User registration & user profile – Profile Builder - Version 3.5.4

Version Description

  • Feature: Improved login error when an user with an unconfirmed email address is trying to login
  • Feature: Added the ability resend the email confirmation from the login error message
Download this release

Release Info

Developer raster02
Plugin Icon 128x128 User registration & user profile – Profile Builder
Version 3.5.4
Comparing to
See all releases

Code changes from version 3.5.3 to 3.5.4

admin/manage-fields.php CHANGED
@@ -193,7 +193,7 @@ function wppb_populate_manage_fields(){
193
  array( 'type' => 'checkbox', 'slug' => 'simple-upload', 'title' => __( 'Use Simple Upload', 'profile-builder' ), 'options' => array( '%'.__('Yes','profile-builder').'%'.'yes' ), 'description' => __( 'Use a simple upload field instead of the WordPress upload', 'profile-builder' ) ),
194
  array( 'type' => 'text', 'slug' => 'allowed-upload-extensions', 'title' => __( 'Allowed Upload Extensions', 'profile-builder' ), 'default' => '.*', 'description' => __( 'Specify the extension(s) you want to limit to upload<br/>Example: .ext1,.ext2,.ext3<br/>If not specified, defaults to all WordPress allowed file extensions (.*)', 'profile-builder' ) ),
195
  array( 'type' => 'text', 'slug' => 'avatar-size', 'title' => __( 'Avatar Size', 'profile-builder' ), 'default' => 100, 'description' => __( "Enter a value (between 20 and 200) for the size of the 'Avatar'<br/>If not specified, defaults to 100", 'profile-builder' ) ),
196
- array( 'type' => 'text', 'slug' => 'date-format', 'title' => __( 'Date-format', 'profile-builder' ), 'default' => 'mm/dd/yy', 'description' => __( 'Specify the format of the date when using Datepicker<br/>Valid options: mm/dd/yy, mm/yy/dd, dd/yy/mm, dd/mm/yy, yy/dd/mm, yy/mm/dd, mm-dd-yy, yy-mm-dd, D, dd M yy, D, d M y, DD, dd-M-y, D, d M yy, mm/yy, mm/dd, dd/mm, @<br/>If not specified, defaults to mm/dd/yy', 'profile-builder' ) ),
197
  array( 'type' => 'textarea', 'slug' => 'terms-of-agreement', 'title' => __( 'Terms of Agreement', 'profile-builder' ), 'description' => __( 'Enter a detailed description of the terms of agreement for the user to read.<br/>Links can be inserted by using standard HTML syntax: &lt;a href="custom_url"&gt;custom_text&lt;/a&gt;', 'profile-builder' ) ),
198
  array( 'type' => 'text', 'slug' => 'options', 'title' => __( 'Options', 'profile-builder' ), 'description' => __( "Enter a comma separated list of values<br/>This can be anything, as it is hidden from the user, but should not contain special characters or apostrophes", 'profile-builder' ) ),
199
  array( 'type' => 'text', 'slug' => 'labels', 'title' => __( 'Labels', 'profile-builder' ), 'description' => __( "Enter a comma separated list of labels<br/>Visible for the user", 'profile-builder' ) ),
193
  array( 'type' => 'checkbox', 'slug' => 'simple-upload', 'title' => __( 'Use Simple Upload', 'profile-builder' ), 'options' => array( '%'.__('Yes','profile-builder').'%'.'yes' ), 'description' => __( 'Use a simple upload field instead of the WordPress upload', 'profile-builder' ) ),
194
  array( 'type' => 'text', 'slug' => 'allowed-upload-extensions', 'title' => __( 'Allowed Upload Extensions', 'profile-builder' ), 'default' => '.*', 'description' => __( 'Specify the extension(s) you want to limit to upload<br/>Example: .ext1,.ext2,.ext3<br/>If not specified, defaults to all WordPress allowed file extensions (.*)', 'profile-builder' ) ),
195
  array( 'type' => 'text', 'slug' => 'avatar-size', 'title' => __( 'Avatar Size', 'profile-builder' ), 'default' => 100, 'description' => __( "Enter a value (between 20 and 200) for the size of the 'Avatar'<br/>If not specified, defaults to 100", 'profile-builder' ) ),
196
+ array( 'type' => 'text', 'slug' => 'date-format', 'title' => __( 'Date-format', 'profile-builder' ), 'default' => 'mm/dd/yy', 'description' => __( 'Specify the format of the date when using Datepicker<br/>Valid options: mm/dd/yy, mm/yy/dd, dd/yy/mm, dd/mm/yy, yy/dd/mm, yy/mm/dd, mm-dd-yy, yy-mm-dd, D, dd M yy, D, d M y, DD, dd-M-y, D, d M yy, mm/yy, mm/dd, dd/mm, @<br/>If not specified, defaults to mm/dd/yy<br/>ATTENTION: if you plan to use this field for sorting, please make sure to use year first, then month, and day last.', 'profile-builder' ) ),
197
  array( 'type' => 'textarea', 'slug' => 'terms-of-agreement', 'title' => __( 'Terms of Agreement', 'profile-builder' ), 'description' => __( 'Enter a detailed description of the terms of agreement for the user to read.<br/>Links can be inserted by using standard HTML syntax: &lt;a href="custom_url"&gt;custom_text&lt;/a&gt;', 'profile-builder' ) ),
198
  array( 'type' => 'text', 'slug' => 'options', 'title' => __( 'Options', 'profile-builder' ), 'description' => __( "Enter a comma separated list of values<br/>This can be anything, as it is hidden from the user, but should not contain special characters or apostrophes", 'profile-builder' ) ),
199
  array( 'type' => 'text', 'slug' => 'labels', 'title' => __( 'Labels', 'profile-builder' ), 'description' => __( "Enter a comma separated list of labels<br/>Visible for the user", 'profile-builder' ) ),
assets/misc/elementor/widgets/class-pb-widget-base.php CHANGED
@@ -319,7 +319,7 @@ abstract class PB_Elementor_Widget extends \Elementor\Widget_Base {
319
  case 'ul':
320
  include_once( WPPB_PLUGIN_DIR.'/add-ons/user-listing/userlisting.php' );
321
  $atts = [
322
- 'name' => $settings['pb_name'] === '' ? 'userlisting' : $settings['pb_name'],
323
  'single' => $settings['pb_single'] === 'yes',
324
  'meta_key' => $settings['pb_meta_key'],
325
  'meta_value' => $settings['pb_meta_value'],
319
  case 'ul':
320
  include_once( WPPB_PLUGIN_DIR.'/add-ons/user-listing/userlisting.php' );
321
  $atts = [
322
+ 'name' => $settings['pb_name'],
323
  'single' => $settings['pb_single'] === 'yes',
324
  'meta_key' => $settings['pb_meta_key'],
325
  'meta_value' => $settings['pb_meta_value'],
assets/misc/elementor/widgets/class-pb-widget-ul.php CHANGED
@@ -78,13 +78,24 @@ class PB_Elementor_User_Listing_Widget extends PB_Elementor_Widget {
78
  )
79
  );
80
 
 
 
 
 
 
 
 
 
 
 
 
81
  $this->add_control(
82
  'pb_name',
83
  array(
84
- 'label' => __( 'Name', 'profile-builder' ),
85
- 'type' => \Elementor\Controls_Manager::TEXT,
86
- 'placeholder' => __( 'Enter Name', 'profile-builder' ),
87
- 'default' => 'userlisting',
88
  )
89
  );
90
 
@@ -176,17 +187,5 @@ class PB_Elementor_User_Listing_Widget extends PB_Elementor_Widget {
176
  protected function render() {
177
  $output = $this->render_widget( 'ul' );
178
  echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
179
-
180
- // check if the form is being displayed in the Elementor editor
181
- $is_elementor_edit_mode = false;
182
- if( class_exists ( '\Elementor\Plugin' ) ){
183
- $is_elementor_edit_mode = \Elementor\Plugin::$instance->editor->is_edit_mode();
184
- }
185
-
186
- if ($is_elementor_edit_mode && !empty($output)) {
187
- echo '
188
- ';
189
- }
190
  }
191
-
192
  }
78
  )
79
  );
80
 
81
+ $ul_names = array();
82
+ $userlisting_posts = get_posts( array( 'posts_per_page' => -1, 'post_status' =>'publish', 'post_type' => 'wppb-ul-cpt', 'orderby' => 'post_date', 'order' => 'ASC' ) );
83
+ if( !empty( $userlisting_posts ) ){
84
+ foreach ( $userlisting_posts as $post ){
85
+ $ul_names[ $post->post_name ] = $post->post_title;
86
+ }
87
+ }
88
+
89
+ reset($ul_names);
90
+ $default_key = is_null( key($ul_names) ) ? '' : key($ul_names);
91
+
92
  $this->add_control(
93
  'pb_name',
94
  array(
95
+ 'label' => __( 'User Listing', 'profile-builder' ),
96
+ 'type' => \Elementor\Controls_Manager::SELECT,
97
+ 'options' => $ul_names,
98
+ 'default' => $default_key,
99
  )
100
  );
101
 
187
  protected function render() {
188
  $output = $this->render_widget( 'ul' );
189
  echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
 
 
 
 
 
 
 
 
 
 
 
190
  }
 
191
  }
front-end/login.php CHANGED
@@ -248,6 +248,67 @@ function wppb_change_login_with_email(){
248
  }
249
  add_action( 'login_init', 'wppb_change_login_with_email' );
250
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
251
  /**
252
  * Remove email login when username login is selected
253
  * inspiration from https://wordpress.org/plugins/no-login-by-email-address/
@@ -346,15 +407,17 @@ function wppb_login_redirect( $redirect_to, $requested_redirect_to, $user ){
346
  }
347
 
348
  if ($user->get_error_code() == 'invalid_username') {
349
- if ($wppb_generalSettings['loginWith'] == 'email')// if login with email is enabled change the word username with email
350
- $error_string .= __('Invalid email.', 'profile-builder') . ' ';
351
- else if( $wppb_generalSettings['loginWith'] == 'usernameemail' )// if login with username and email is enabled change the word username with username or email
352
- $error_string .= __('Invalid username or email.', 'profile-builder') . ' ';
353
- else
354
- $error_string .= __('Invalid username.', 'profile-builder') . ' ';
 
 
355
  }
356
 
357
- if( $user->get_error_code() == 'incorrect_password' || $user->get_error_code() == 'invalid_username' )
358
  $error_string .= '<a href="' . esc_url( $lost_pass_url ) . '" title="' . __('Password Lost and Found.', 'profile-builder') . '">' . __('Lost your password?', 'profile-builder') . '</a>';
359
 
360
  }
@@ -366,7 +429,7 @@ function wppb_login_redirect( $redirect_to, $requested_redirect_to, $user ){
366
  }
367
 
368
  $error_string = apply_filters('wppb_login_wp_error_message', $error_string, $user);
369
- $wppb_error_string_nonce = wp_create_nonce( 'wppb_login_error_'. $error_string );
370
 
371
  // encode the error string and send it as a GET parameter
372
  if ( isset($_POST['wppb_referer_url']) && $_POST['wppb_referer_url'] !== '' ) {
@@ -397,7 +460,11 @@ function wppb_login_redirect( $redirect_to, $requested_redirect_to, $user ){
397
  }
398
  }
399
 
400
- return $redirect_to;
 
 
 
 
401
  }
402
  add_filter( 'login_redirect', 'wppb_login_redirect', 20, 3 );
403
 
@@ -454,15 +521,11 @@ function wppb_front_end_login( $atts ){
454
 
455
  // Check if 2fa is required
456
  if( class_exists( 'WPPB_Two_Factor_Authenticator' ) ){
457
- $wppb_google_auth = new WPPB_Two_Factor_Authenticator;
458
  $wppb_two_factor_authentication_settings = get_option( 'wppb_two_factor_authentication_settings', 'not_found' );
459
- if ( ( isset( $_GET['login_auth'] ) && $_GET['login_auth'] === 'true' ) || (
460
- ( isset($wppb_two_factor_authentication_settings['enabled']) && $wppb_two_factor_authentication_settings['enabled'] === 'yes' ) &&
461
- ( ( isset($wppb_two_factor_authentication_settings['show_code_field']) && (
462
- $wppb_two_factor_authentication_settings['show_code_field'] === 'everywhere' ||
463
- $wppb_two_factor_authentication_settings['show_code_field'] === 'frontend' ) ) ||
464
- $show_2fa_field === 'yes' ) ) ){
465
- add_action( 'login_form_middle', array( $wppb_google_auth, 'auth_code_field') );
466
  }
467
  }
468
 
@@ -473,7 +536,10 @@ function wppb_front_end_login( $atts ){
473
  if( ( isset( $_GET['loginerror'] ) || isset( $_POST['loginerror'] ) ) && isset( $_GET['_wpnonce'] ) ){
474
  $error_string = urldecode( base64_decode( isset( $_GET['loginerror'] ) ? sanitize_text_field( $_GET['loginerror'] ) : sanitize_text_field( $_POST['loginerror'] ) ) );
475
  if( wp_verify_nonce( sanitize_text_field( $_GET['_wpnonce'] ), 'wppb_login_error_'. $error_string ) ) {
476
- $loginerror = '<p class="wppb-error">' . wp_kses_post($error_string) . '</p><!-- .error -->';
 
 
 
477
  if (isset($_GET['request_form_location'])) {
478
  if ($_GET['request_form_location'] === 'widget' && !in_the_loop()) {
479
  $login_form .= $loginerror;
248
  }
249
  add_action( 'login_init', 'wppb_change_login_with_email' );
250
 
251
+ function wppb_resend_confirmation_email() {
252
+ if( !isset( $_GET['wppb-action'] ) || $_GET['wppb-action'] != 'resend_email_confirmation' || !isset( $_GET['email'] ))
253
+ return;
254
+
255
+ $transient_check_key = Wordpress_Creation_Kit_PB::wck_generate_slug( sanitize_email( $_GET['email'] ));
256
+ $transient_check = get_transient('wppb_confirmation_email_already_sent_'.$transient_check_key);
257
+
258
+ if ( $transient_check === false ) {
259
+
260
+ if ( !isset( $_GET['_wpnonce'] ) || !wp_verify_nonce(sanitize_text_field( $_GET['_wpnonce'] ), 'wppb_confirmation_url_nonce' ))
261
+ return;
262
+
263
+ include_once(plugin_dir_path(__FILE__) . '../features/email-confirmation/email-confirmation.php');
264
+ if ( !class_exists('PB_Mustache_Generate_Template'))
265
+ include_once(plugin_dir_path(__FILE__) . '../assets/lib/class-mustache-templates/class-mustache-templates.php');
266
+ global $wpdb;
267
+ $sql_result = $wpdb->get_row( $wpdb->prepare("SELECT * FROM " . $wpdb->base_prefix . "signups WHERE user_email = %s", sanitize_email( $_GET['email'] )), ARRAY_A );
268
+
269
+ // if the email address exists in wp_signups table, resend Confirmation Email and redirect to display notification
270
+ if ( $sql_result ) {
271
+ wppb_signup_user_notification( sanitize_text_field( $sql_result['user_login'] ), sanitize_email( $sql_result['user_email'] ), $sql_result['activation_key'], $sql_result['meta'] );
272
+ $transient_key = Wordpress_Creation_Kit_PB::wck_generate_slug( sanitize_email( $_GET['email'] ));
273
+ set_transient('wppb_confirmation_email_already_sent_' . $transient_key, true, 900 );
274
+ $error_string = '<strong>' . __('SUCCESS', 'profile-builder') . '</strong>: ' . sprintf( __( 'Activation email sent to %s', 'profile-builder' ), sanitize_email( $_GET['email'] ));
275
+ $wppb_success_message_nonce = wp_create_nonce( 'wppb_login_error_'.$error_string);
276
+ $current_url = wppb_curpageurl();
277
+ $arr_params = array('loginerror' => urlencode(base64_encode($error_string)), '_wpnonce' => $wppb_success_message_nonce, 'request_form_location' => 'page', 'wppb_message_type' => 'success');
278
+ $redirect_to = add_query_arg($arr_params, $current_url);
279
+ wp_safe_redirect($redirect_to);
280
+ exit();
281
+ }
282
+
283
+ }
284
+ }
285
+ add_action('init', 'wppb_resend_confirmation_email');
286
+
287
+ function wppb_change_error_message($error_message) {
288
+ global $wpdb;
289
+ $check_user = $_REQUEST['log'];
290
+
291
+ if ( is_email($check_user) )
292
+ $sql_result = $wpdb->get_row( $wpdb->prepare("SELECT * FROM " . $wpdb->base_prefix . "signups WHERE user_email = %s", sanitize_email( $check_user )), ARRAY_A );
293
+ else {
294
+ $sql_result = $wpdb->get_row( $wpdb->prepare("SELECT * FROM " . $wpdb->base_prefix . "signups WHERE user_login = %s", sanitize_user( $check_user )), ARRAY_A );
295
+ if ( $sql_result )
296
+ $check_user = $sql_result['user_email'];
297
+ }
298
+
299
+ // if the email address exists in wp_signups table, display message and link to resend Confirmation Email
300
+ if ( isset($sql_result) ) {
301
+ $confirmation_url_nonce = wp_create_nonce( 'wppb_confirmation_url_nonce' );
302
+ $current_url = wppb_curpageurl();
303
+ $arr_params = array('email' => sanitize_email( $check_user ), 'wppb-action' => 'resend_email_confirmation', '_wpnonce' => $confirmation_url_nonce);
304
+ $confirmation_url = add_query_arg($arr_params, $current_url);
305
+ $error_message = '<strong>' . __('ERROR', 'profile-builder') . '</strong>: ' . sprintf( __( 'You need to confirm your Email Address before logging in! To resend the Confirmation Email %1$sclick here%2$s', 'profile-builder' ), '<a href="' . esc_url( $confirmation_url ) . '" title="Resend Confirmation Email">', '</a>.' );
306
+ }
307
+
308
+ return $error_message;
309
+ }
310
+ add_filter('wppb_login_invalid_username_error_message', 'wppb_change_error_message');
311
+
312
  /**
313
  * Remove email login when username login is selected
314
  * inspiration from https://wordpress.org/plugins/no-login-by-email-address/
407
  }
408
 
409
  if ($user->get_error_code() == 'invalid_username') {
410
+ if ($wppb_generalSettings['loginWith'] == 'email')// if login with email is enabled change the word username with email
411
+ $error_string .= __('Invalid email.', 'profile-builder') . ' ';
412
+ else if( $wppb_generalSettings['loginWith'] == 'usernameemail' )// if login with username and email is enabled change the word username with username or email
413
+ $error_string .= __('Invalid username or email.', 'profile-builder') . ' ';
414
+ else
415
+ $error_string .= __('Invalid username.', 'profile-builder') . ' ';
416
+
417
+ $error_string = apply_filters('wppb_login_invalid_username_error_message', $error_string);
418
  }
419
 
420
+ if( $user->get_error_code() == 'incorrect_password' || $user->get_error_code() == 'invalid_username' && empty( $message_check = apply_filters('wppb_login_invalid_username_error_message', '' )))
421
  $error_string .= '<a href="' . esc_url( $lost_pass_url ) . '" title="' . __('Password Lost and Found.', 'profile-builder') . '">' . __('Lost your password?', 'profile-builder') . '</a>';
422
 
423
  }
429
  }
430
 
431
  $error_string = apply_filters('wppb_login_wp_error_message', $error_string, $user);
432
+ $wppb_error_string_nonce = wp_create_nonce( 'wppb_login_error_'.$error_string );
433
 
434
  // encode the error string and send it as a GET parameter
435
  if ( isset($_POST['wppb_referer_url']) && $_POST['wppb_referer_url'] !== '' ) {
460
  }
461
  }
462
 
463
+ // if "wppb_message_type = success" is present the message will show up in a green box instead of red
464
+ if ( isset( $_GET['wppb_message_type'] ) && $_GET['wppb_message_type'] == 'success' )
465
+ $redirect_to = remove_query_arg( 'wppb_message_type', $redirect_to );
466
+
467
+ return $redirect_to;
468
  }
469
  add_filter( 'login_redirect', 'wppb_login_redirect', 20, 3 );
470
 
521
 
522
  // Check if 2fa is required
523
  if( class_exists( 'WPPB_Two_Factor_Authenticator' ) ){
524
+ $wppb_auth = new WPPB_Two_Factor_Authenticator;
525
  $wppb_two_factor_authentication_settings = get_option( 'wppb_two_factor_authentication_settings', 'not_found' );
526
+ if ( ( isset( $_GET['login_auth'] ) && $_GET['login_auth'] === 'true' ) ||
527
+ ( ( isset($wppb_two_factor_authentication_settings['enabled']) && $wppb_two_factor_authentication_settings['enabled'] === 'yes' ) && $show_2fa_field === 'yes' ) ){
528
+ add_action( 'login_form_middle', array( $wppb_auth, 'auth_code_field') );
 
 
 
 
529
  }
530
  }
531
 
536
  if( ( isset( $_GET['loginerror'] ) || isset( $_POST['loginerror'] ) ) && isset( $_GET['_wpnonce'] ) ){
537
  $error_string = urldecode( base64_decode( isset( $_GET['loginerror'] ) ? sanitize_text_field( $_GET['loginerror'] ) : sanitize_text_field( $_POST['loginerror'] ) ) );
538
  if( wp_verify_nonce( sanitize_text_field( $_GET['_wpnonce'] ), 'wppb_login_error_'. $error_string ) ) {
539
+ if ( isset( $_GET['wppb_message_type'] ) && $_GET['wppb_message_type'] == 'success' )
540
+ $message_type = 'wppb-success';
541
+ else $message_type = 'wppb-error';
542
+ $loginerror = '<p class="'. $message_type .'">' . wp_kses_post($error_string) . '</p><!-- .error -->';
543
  if (isset($_GET['request_form_location'])) {
544
  if ($_GET['request_form_location'] === 'widget' && !in_the_loop()) {
545
  $login_form .= $loginerror;
index.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Profile Builder
4
  Plugin URI: https://www.cozmoslabs.com/wordpress-profile-builder/
5
  Description: Login, registration and edit profile shortcodes for the front-end. Also you can choose what fields should be displayed or add new (custom) ones both in the front-end and in the dashboard.
6
- Version: 3.5.3
7
  Author: Cozmoslabs
8
  Author URI: https://www.cozmoslabs.com/
9
  Text Domain: profile-builder
@@ -70,7 +70,7 @@ function wppb_free_plugin_init() {
70
  *
71
  *
72
  */
73
- define('PROFILE_BUILDER_VERSION', '3.5.3' );
74
  define('WPPB_PLUGIN_DIR', plugin_dir_path(__FILE__));
75
  define('WPPB_PLUGIN_URL', plugin_dir_url(__FILE__));
76
  define('WPPB_PLUGIN_BASENAME', plugin_basename(__FILE__));
3
  Plugin Name: Profile Builder
4
  Plugin URI: https://www.cozmoslabs.com/wordpress-profile-builder/
5
  Description: Login, registration and edit profile shortcodes for the front-end. Also you can choose what fields should be displayed or add new (custom) ones both in the front-end and in the dashboard.
6
+ Version: 3.5.4
7
  Author: Cozmoslabs
8
  Author URI: https://www.cozmoslabs.com/
9
  Text Domain: profile-builder
70
  *
71
  *
72
  */
73
+ define('PROFILE_BUILDER_VERSION', '3.5.4' );
74
  define('WPPB_PLUGIN_DIR', plugin_dir_path(__FILE__));
75
  define('WPPB_PLUGIN_URL', plugin_dir_url(__FILE__));
76
  define('WPPB_PLUGIN_BASENAME', plugin_basename(__FILE__));
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: http://www.cozmoslabs.com/wordpress-profile-builder/
4
  Tags: user registration, user profile, registration, profile, user registration form, user fields, edit profile, user custom fields, front-end login, front-end edit profile, front-end user registration, email confirmation, login form, content restriction, restrict content
5
  Requires at least: 3.1
6
  Tested up to: 5.8.0
7
- Stable tag: 3.5.3
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -176,6 +176,10 @@ This plugin adds/removes user fields in the front-end. Both default and extra pr
176
  15. Edit or Add New User Role
177
 
178
  == Changelog ==
 
 
 
 
179
  = 3.5.3 =
180
  * Feature: Added option to display Elementor sections and widgets to logged out users
181
  * Fix: Position of password strength on the reset password form
4
  Tags: user registration, user profile, registration, profile, user registration form, user fields, edit profile, user custom fields, front-end login, front-end edit profile, front-end user registration, email confirmation, login form, content restriction, restrict content
5
  Requires at least: 3.1
6
  Tested up to: 5.8.0
7
+ Stable tag: 3.5.4
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
176
  15. Edit or Add New User Role
177
 
178
  == Changelog ==
179
+ = 3.5.4 =
180
+ * Feature: Improved login error when an user with an unconfirmed email address is trying to login
181
+ * Feature: Added the ability resend the email confirmation from the login error message
182
+
183
  = 3.5.3 =
184
  * Feature: Added option to display Elementor sections and widgets to logged out users
185
  * Fix: Position of password strength on the reset password form