diff --git a/src/wp-admin/css/forms.css b/src/wp-admin/css/forms.css index 5693c9f541..807b06bd80 100644 --- a/src/wp-admin/css/forms.css +++ b/src/wp-admin/css/forms.css @@ -401,6 +401,11 @@ input[type="number"].small-text { color: #777; } +button.wp-hide-pw > .dashicons { + position: relative; + top: 3px; +} + label, #your-profile label + a { vertical-align: middle; @@ -434,34 +439,58 @@ fieldset label, #pass-strength-result { background-color: #eee; border: 1px solid #ddd; - float: left; - margin: 13px 5px 5px 1px; + margin: -2px 5px 5px 1px; padding: 3px 5px; text-align: center; - width: 200px; - display: none; + width: 25em; + box-sizing: border-box; + opacity: 0; } #pass-strength-result.short { + opacity: 1; background-color: #ffa0a0; border-color: #f04040; } #pass-strength-result.bad { + opacity: 1; background-color: #ffb78c; border-color: #ff853c; } #pass-strength-result.good { + opacity: 1; background-color: #ffec8b; border-color: #fc0; } #pass-strength-result.strong { + opacity: 1; background-color: #c3ff88; border-color: #8dff1c; } +#pass1.short { + border-color: #f04040; +} + +#pass1.bad { + border-color: #ff853c; +} + +#pass1.good { + border-color: #fc0; +} + +#pass1.strong { + border-color: #8dff1c; +} + +.pw-weak{ + display:none; +} + .indicator-hint { padding-top: 8px; } diff --git a/src/wp-admin/includes/user.php b/src/wp-admin/includes/user.php index 901f437553..8304314948 100644 --- a/src/wp-admin/includes/user.php +++ b/src/wp-admin/includes/user.php @@ -176,7 +176,7 @@ function edit_user( $user_id = 0 ) { $user_id = wp_update_user( $user ); } else { $user_id = wp_insert_user( $user ); - wp_new_user_notification( $user_id, isset( $_POST['send_password'] ) ? wp_unslash( $pass1 ) : '' ); + wp_new_user_notification( $user_id ); } return $user_id; } diff --git a/src/wp-admin/js/user-profile.js b/src/wp-admin/js/user-profile.js index 72a2465c56..cf01199b5d 100644 --- a/src/wp-admin/js/user-profile.js +++ b/src/wp-admin/js/user-profile.js @@ -1,5 +1,110 @@ /* global ajaxurl, pwsL10n */ (function($){ + $(function(){ + var pw_new = $('.user-pass1-wrap'), + pw_line = pw_new.find('.wp-pwd'), + pw_field = $('#pass1'), + pw_field2 = $('#pass2'), + pw_togglebtn = pw_new.find('.wp-hide-pw'), + pw_generatebtn = pw_new.find('button.wp-generate-pw'), + pw_2 = $('.user-pass2-wrap'), + parentform = pw_new.closest('form'), + pw_strength = $('#pass-strength-result'), + pw_submitbtn_edit = $('#submit'), + pw_submitbtn_new = $( '#createusersub' ), + pw_checkbox = $('.pw-checkbox'), + pw_weak = $('.pw-weak') + ; + + generatePassword = function() { + pw_field.val( pw_field.data( 'pw' ) ); + pw_field.trigger( 'propertychange' ); + pw_field.attr( 'type', 'text' ).focus(); + pw_field[0].setSelectionRange(100, 100); + }; + + pw_2.hide(); + pw_line.hide(); + pw_togglebtn.show(); + pw_generatebtn.show(); + + if ( pw_field.data( 'reveal' ) == 1 ) { + generatePassword(); + } + + parentform.on('submit', function(){ + pw_field2.val( pw_field.val() ); + pw_field.attr('type', 'password'); + }); + + + pw_field.on('input propertychange', function(){ + setTimeout( function(){ + var cssClass = pw_strength.attr('class'); + pw_field.removeClass( 'short bad good strong' ); + if ( 'undefined' !== typeof cssClass ) { + pw_field.addClass( cssClass ); + if ( cssClass == 'short' || cssClass == 'bad' ) { + if ( ! pw_checkbox.attr( 'checked' ) ) { + pw_submitbtn_new.attr( 'disabled','disabled' ); + pw_submitbtn_edit.attr( 'disabled','disabled' ); + } + pw_weak.show(); + } else { + pw_submitbtn_new.removeAttr( 'disabled' ); + pw_submitbtn_edit.removeAttr( 'disabled' ); + pw_weak.hide(); + } + } + }, 1 ); + } ); + + pw_checkbox.change( function() { + if ( pw_checkbox.attr( 'checked' ) ) { + pw_submitbtn_new.removeAttr( 'disabled' ); + pw_submitbtn_edit.removeAttr( 'disabled' ); + } else { + pw_submitbtn_new.attr( 'disabled','disabled' ); + pw_submitbtn_edit.attr( 'disabled','disabled' ); + } + } ); + + /** + * Fix a LastPass mismatch issue, LastPass only changes pass2. + * + * This fixes the issue by copying any changes from the hidden + * pass2 field to the pass1 field. + */ + pw_field2.on( 'input propertychange', function() { + pw_field.val( pw_field2.val() ); + pw_field.trigger( 'propertychange' ); + } ); + + pw_new.on( 'click', 'button.wp-generate-pw', function(){ + pw_generatebtn.hide(); + pw_line.show(); + generatePassword(); + }); + + pw_togglebtn.on( 'click', function() { + var show = pw_togglebtn.attr( 'data-toggle' ); + if ( show == 1 ) { + pw_field.attr( 'type', 'text' ); + pw_togglebtn.attr( 'data-toggle', 0 ) + .find( '.text' ) + .text( 'hide' ) + ; + } else { + pw_field.attr( 'type', 'password' ); + pw_togglebtn.attr( 'data-toggle', 1 ) + .find( '.text' ) + .text( 'show' ) + ; + } + pw_field.focus(); + pw_field[0].setSelectionRange(100, 100); + }); + }); function check_pass_strength() { var pass1 = $('#pass1').val(), pass2 = $('#pass2').val(), strength; diff --git a/src/wp-admin/user-edit.php b/src/wp-admin/user-edit.php index 061f190067..bbf431d211 100644 --- a/src/wp-admin/user-edit.php +++ b/src/wp-admin/user-edit.php @@ -462,27 +462,33 @@ if ( $show_password_fields ) : - -

+ +
+ + + +
- + - +

-
-
-

+ + + + + + + - - get_all() ) === 1 ) : ?> diff --git a/src/wp-admin/user-new.php b/src/wp-admin/user-new.php index 5b8a2847a0..a9a488f6b5 100644 --- a/src/wp-admin/user-new.php +++ b/src/wp-admin/user-new.php @@ -190,7 +190,7 @@ get_current_screen()->set_help_sidebar( ); wp_enqueue_script('wp-ajax-response'); -wp_enqueue_script('user-profile'); +wp_enqueue_script( 'user-profile' ); /** * Filter whether to enable user auto-complete for non-super admins in Multisite. @@ -355,7 +355,7 @@ $new_user_lastname = $creating && isset( $_POST['last_name'] ) ? wp_unslash( $_P $new_user_email = $creating && isset( $_POST['email'] ) ? wp_unslash( $_POST['email'] ) : ''; $new_user_uri = $creating && isset( $_POST['url'] ) ? wp_unslash( $_POST['url'] ) : ''; $new_user_role = $creating && isset( $_POST['role'] ) ? wp_unslash( $_POST['role'] ) : ''; -$new_user_send_password = $creating && isset( $_POST['send_password'] ) ? wp_unslash( $_POST['send_password'] ) : ''; +$new_user_send_password = $creating && isset( $_POST['send_password'] ) ? wp_unslash( $_POST['send_password'] ) : true; $new_user_ignore_pass = $creating && isset( $_POST['noconfirmation'] ) ? wp_unslash( $_POST['noconfirmation'] ) : ''; ?> @@ -390,25 +390,40 @@ $new_user_ignore_pass = $creating && isset( $_POST['noconfirmation'] ) ? wp_unsl * @param bool $show Whether to show the password fields. Default true. */ if ( apply_filters( 'show_password_fields', true ) ) : ?> - - + + + + - + +
+ + + + +
+

- - + + -
-
-

- - - + + + + + + diff --git a/src/wp-includes/default-constants.php b/src/wp-includes/default-constants.php index f265e31a51..7325845966 100644 --- a/src/wp-includes/default-constants.php +++ b/src/wp-includes/default-constants.php @@ -92,6 +92,9 @@ function wp_initial_constants() { if ( !defined('SHORTINIT') ) define('SHORTINIT', false); + // Constants for features added to WP that should short-circuit their plugin implementations + define( 'WP_FEATURE_BETTER_PASSWORDS', true ); + // Constants for expressing human-readable intervals // in their respective number of seconds. define( 'MINUTE_IN_SECONDS', 60 ); diff --git a/src/wp-includes/pluggable.php b/src/wp-includes/pluggable.php index 1295282790..5f35ece004 100644 --- a/src/wp-includes/pluggable.php +++ b/src/wp-includes/pluggable.php @@ -1690,9 +1690,9 @@ if ( !function_exists('wp_new_user_notification') ) : * @since 2.0.0 * * @param int $user_id User ID. - * @param string $plaintext_pass Optional. The user's plaintext password. Default empty. */ -function wp_new_user_notification($user_id, $plaintext_pass = '') { +function wp_new_user_notification($user_id) { + global $wpdb; $user = get_userdata( $user_id ); // The blogname option is escaped with esc_html on the way into the database in sanitize_option @@ -1705,14 +1705,26 @@ function wp_new_user_notification($user_id, $plaintext_pass = '') { @wp_mail(get_option('admin_email'), sprintf(__('[%s] New User Registration'), $blogname), $message); - if ( empty($plaintext_pass) ) - return; + // Generate something random for a password reset key. + $key = wp_generate_password( 20, false ); + + do_action( 'retrieve_password_key', $user->user_login, $key ); + + // Now insert the key, hashed, into the DB. + if ( empty( $wp_hasher ) ) { + require_once ABSPATH . WPINC . '/class-phpass.php'; + $wp_hasher = new PasswordHash( 8, true ); + } + $hashed = time() . ':' . $wp_hasher->HashPassword( $key ); + $wpdb->update( $wpdb->users, array( 'user_activation_key' => $hashed ), array( 'user_login' => $user->user_login ) ); + + $message = sprintf(__('Username: %s'), $user->user_login) . "\r\n\r\n"; + $message .= __('To set your password, visit the following address:') . "\r\n\r\n"; + $message .= '<' . network_site_url("wp-login.php?action=rp&key=$key&login=" . rawurlencode($user->user_login), 'login') . ">\r\n\r\n"; - $message = sprintf(__('Username: %s'), $user->user_login) . "\r\n"; - $message .= sprintf(__('Password: %s'), $plaintext_pass) . "\r\n"; $message .= wp_login_url() . "\r\n"; - wp_mail($user->user_email, sprintf(__('[%s] Your username and password'), $blogname), $message); + wp_mail($user->user_email, sprintf(__('[%s] Your username and password info'), $blogname), $message); } endif; diff --git a/src/wp-includes/script-loader.php b/src/wp-includes/script-loader.php index 79d060136d..3e55a11c4f 100644 --- a/src/wp-includes/script-loader.php +++ b/src/wp-includes/script-loader.php @@ -365,7 +365,7 @@ function wp_default_scripts( &$scripts ) { $scripts->add( 'password-strength-meter', "/wp-admin/js/password-strength-meter$suffix.js", array( 'jquery', 'zxcvbn-async' ), false, 1 ); did_action( 'init' ) && $scripts->localize( 'password-strength-meter', 'pwsL10n', array( - 'empty' => __('Strength indicator'), + 'empty' => __(' '), 'short' => __('Very weak'), 'bad' => __('Weak'), /* translators: password strength */ diff --git a/src/wp-includes/user.php b/src/wp-includes/user.php index a1c12cdb01..1c8a5b36d4 100644 --- a/src/wp-includes/user.php +++ b/src/wp-includes/user.php @@ -2409,7 +2409,7 @@ function _wp_get_user_contactmethods( $user = null ) { * @return string The password hint text. */ function wp_get_password_hint() { - $hint = __( 'Hint: The password should be at least seven characters long. To make it stronger, use upper and lower case letters, numbers, and symbols like ! " ? $ % ^ & ).' ); + $hint = __( 'Hint: The password should be at least twelve characters long. To make it stronger, use upper and lower case letters, numbers, and symbols like ! " ? $ % ^ & ).' ); /** * Filter the text describing the site's password complexity policy. @@ -2615,7 +2615,7 @@ function register_new_user( $user_login, $user_email ) { update_user_option( $user_id, 'default_password_nag', true, true ); //Set up the Password change nag. - wp_new_user_notification( $user_id, $user_pass ); + wp_new_user_notification( $user_id ); return $user_id; } diff --git a/src/wp-login.php b/src/wp-login.php index 080322cc09..c40c9b4d3d 100644 --- a/src/wp-login.php +++ b/src/wp-login.php @@ -652,13 +652,15 @@ case 'rp' :
-

- +

+
+

+ +

-

- +

+
+