Make WordPress Core


Ignore:
Timestamp:
02/01/2021 10:11:46 PM (6 years ago)
Author:
adamsilverstein
Message:

Users: enable admins to send users a reset password link.

Add a feature so Admins can send users a 'password reset' email. This doesn't change the password or force a password change. It only emails the user the password reset link.

The feature appears in several places:

  • A "Send Reset Link" button on user profile screen.
  • A "Send password reset" option in the user list bulk action dropdown.
  • A "Send password reset" quick action when hovering over a username in the user list.

Props Ipstenu, DrewAPicture, eventualo, wonderboymusic, knutsp, ericlewis, afercia, JoshuaWold, johnbillion, paaljoachim, hedgefield.
Fixes #34281.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-login.php

    r50117 r50129  
    359359        <meta name="viewport" content="width=device-width" />
    360360        <?php
    361 }
    362 
    363 /**
    364  * Handles sending a password retrieval email to a user.
    365  *
    366  * @since 2.5.0
    367  *
    368  * @return true|WP_Error True when finished, WP_Error object on error.
    369  */
    370 function retrieve_password() {
    371         $errors    = new WP_Error();
    372         $user_data = false;
    373 
    374         if ( empty( $_POST['user_login'] ) || ! is_string( $_POST['user_login'] ) ) {
    375                 $errors->add( 'empty_username', __( '<strong>Error</strong>: Please enter a username or email address.' ) );
    376         } elseif ( strpos( $_POST['user_login'], '@' ) ) {
    377                 $user_data = get_user_by( 'email', trim( wp_unslash( $_POST['user_login'] ) ) );
    378                 if ( empty( $user_data ) ) {
    379                         $errors->add( 'invalid_email', __( '<strong>Error</strong>: There is no account with that username or email address.' ) );
    380                 }
    381         } else {
    382                 $login     = trim( wp_unslash( $_POST['user_login'] ) );
    383                 $user_data = get_user_by( 'login', $login );
    384         }
    385 
    386         /**
    387          * Filters the user data during a password reset request.
    388          *
    389          * Allows, for example, custom validation using data other than username or email address.
    390          *
    391          * @since 5.7.0
    392          *
    393          * @param WP_User|false $user_data WP_User object if found, false if the user does not exist.
    394          * @param WP_Error      $errors    A WP_Error object containing any errors generated
    395          *                                 by using invalid credentials.
    396          */
    397         $user_data = apply_filters( 'lostpassword_user_data', $user_data, $errors );
    398 
    399         /**
    400          * Fires before errors are returned from a password reset request.
    401          *
    402          * @since 2.1.0
    403          * @since 4.4.0 Added the `$errors` parameter.
    404          * @since 5.4.0 Added the `$user_data` parameter.
    405          *
    406          * @param WP_Error      $errors    A WP_Error object containing any errors generated
    407          *                                 by using invalid credentials.
    408          * @param WP_User|false $user_data WP_User object if found, false if the user does not exist.
    409          */
    410         do_action( 'lostpassword_post', $errors, $user_data );
    411 
    412         /**
    413          * Filters the errors encountered on a password reset request.
    414          *
    415          * The filtered WP_Error object may, for example, contain errors for an invalid
    416          * username or email address. A WP_Error object should always be returned,
    417          * but may or may not contain errors.
    418          *
    419          * If any errors are present in $errors, this will abort the password reset request.
    420          *
    421          * @since 5.5.0
    422          *
    423          * @param WP_Error      $errors    A WP_Error object containing any errors generated
    424          *                                 by using invalid credentials.
    425          * @param WP_User|false $user_data WP_User object if found, false if the user does not exist.
    426          */
    427         $errors = apply_filters( 'lostpassword_errors', $errors, $user_data );
    428 
    429         if ( $errors->has_errors() ) {
    430                 return $errors;
    431         }
    432 
    433         if ( ! $user_data ) {
    434                 $errors->add( 'invalidcombo', __( '<strong>Error</strong>: There is no account with that username or email address.' ) );
    435                 return $errors;
    436         }
    437 
    438         // Redefining user_login ensures we return the right case in the email.
    439         $user_login = $user_data->user_login;
    440         $user_email = $user_data->user_email;
    441         $key        = get_password_reset_key( $user_data );
    442 
    443         if ( is_wp_error( $key ) ) {
    444                 return $key;
    445         }
    446 
    447         if ( is_multisite() ) {
    448                 $site_name = get_network()->site_name;
    449         } else {
    450                 /*
    451                  * The blogname option is escaped with esc_html on the way into the database
    452                  * in sanitize_option. We want to reverse this for the plain text arena of emails.
    453                  */
    454                 $site_name = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
    455         }
    456 
    457         $message = __( 'Someone has requested a password reset for the following account:' ) . "\r\n\r\n";
    458         /* translators: %s: Site name. */
    459         $message .= sprintf( __( 'Site Name: %s' ), $site_name ) . "\r\n\r\n";
    460         /* translators: %s: User login. */
    461         $message .= sprintf( __( 'Username: %s' ), $user_login ) . "\r\n\r\n";
    462         $message .= __( 'If this was a mistake, ignore this email and nothing will happen.' ) . "\r\n\r\n";
    463         $message .= __( 'To reset your password, visit the following address:' ) . "\r\n\r\n";
    464         $message .= network_site_url( "wp-login.php?action=rp&key=$key&login=" . rawurlencode( $user_login ), 'login' ) . "\r\n\r\n";
    465 
    466         $requester_ip = $_SERVER['REMOTE_ADDR'];
    467         if ( $requester_ip ) {
    468                 $message .= sprintf(
    469                         /* translators: %s: IP address of password reset requester. */
    470                         __( 'This password reset request originated from the IP address %s.' ),
    471                         $requester_ip
    472                 ) . "\r\n";
    473         }
    474 
    475         /* translators: Password reset notification email subject. %s: Site title. */
    476         $title = sprintf( __( '[%s] Password Reset' ), $site_name );
    477 
    478         /**
    479          * Filters the subject of the password reset email.
    480          *
    481          * @since 2.8.0
    482          * @since 4.4.0 Added the `$user_login` and `$user_data` parameters.
    483          *
    484          * @param string  $title      Email subject.
    485          * @param string  $user_login The username for the user.
    486          * @param WP_User $user_data  WP_User object.
    487          */
    488         $title = apply_filters( 'retrieve_password_title', $title, $user_login, $user_data );
    489 
    490         /**
    491          * Filters the message body of the password reset mail.
    492          *
    493          * If the filtered message is empty, the password reset email will not be sent.
    494          *
    495          * @since 2.8.0
    496          * @since 4.1.0 Added `$user_login` and `$user_data` parameters.
    497          *
    498          * @param string  $message    Email message.
    499          * @param string  $key        The activation key.
    500          * @param string  $user_login The username for the user.
    501          * @param WP_User $user_data  WP_User object.
    502          */
    503         $message = apply_filters( 'retrieve_password_message', $message, $key, $user_login, $user_data );
    504 
    505         if ( $message && ! wp_mail( $user_email, wp_specialchars_decode( $title ), $message ) ) {
    506                 $errors->add(
    507                         'retrieve_password_email_failure',
    508                         sprintf(
    509                                 /* translators: %s: Documentation URL. */
    510                                 __( '<strong>Error</strong>: The email could not be sent. Your site may not be correctly configured to send emails. <a href="%s">Get support for resetting your password</a>.' ),
    511                                 esc_url( __( 'https://wordpress.org/support/article/resetting-your-password/' ) )
    512                         )
    513                 );
    514                 return $errors;
    515         }
    516 
    517         return true;
    518361}
    519362
Note: See TracChangeset for help on using the changeset viewer.