diff --git a/core/modules/user/lib/Drupal/user/UserPasswordController.php b/core/modules/user/lib/Drupal/user/UserPasswordController.php new file mode 100644 index 0000000..67985b5 --- /dev/null +++ b/core/modules/user/lib/Drupal/user/UserPasswordController.php @@ -0,0 +1,137 @@ +entityManager = $entity_manager; + $this->userStorageController = $entity_manager->getStorageController('user'); + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static($container->get('plugin.manager.entity')); + } + + /** + * Menu callback; process one time login link and redirects to the user page on success. + */ + function reset($form, &$form_state, $uid, $timestamp, $hashed_pass, $action = NULL) { + global $user; + + // When processing the one-time login link, we have to make sure that a user + // isn't already logged in. + if ($user->uid) { + // The existing user is already logged in. + if ($user->uid == $uid) { + drupal_set_message(t('You are logged in as %user. Change your password.', array('%user' => $user->name, '!user_edit' => url("user/$user->uid/edit")))); + } + // A different user is already logged in on the computer. + else { + $reset_link_account = $this->userStorageController->loadByProperties(array('uid' => $uid)); + if (!empty($reset_link_account)) { + drupal_set_message(t('Another user (%other_user) is already logged into the site on this computer, but you tried to use a one-time link for user %resetting_user. Please logout and try using the link again.', + array('%other_user' => $user->name, '%resetting_user' => $reset_link_account->name, '!logout' => url('user/logout')))); + } else { + // Invalid one-time link specifies an unknown user. + drupal_set_message(t('The one-time login link you clicked is invalid.')); + } + } + return new RedirectResponse(); + } + else { + // Time out, in seconds, until login URL expires. + $timeout = $this->entityManager + ->getStorageController('user.settings') + ->get('password_reset_timeout'); + $current = REQUEST_TIME; + $account = $this->userStorageController->loadByProperties(array('uid' => $uid)); + // Verify that the user exists and is active. + if ($timestamp <= $current && $account && $account->status) { + // No time out for first time login. + if ($account->login && $current - $timestamp > $timeout) { + drupal_set_message(t('You have tried to use a one-time login link that has expired. Please request a new one using the form below.')); + return new RedirectResponse('user/password'); + } + elseif ($account->uid && $timestamp >= $account->login && $timestamp <= $current && $hashed_pass == user_pass_rehash($account->pass, $timestamp, $account->login)) { + // First stage is a confirmation form, then login + if ($action == 'login') { + // Set the new user. + $user = $account; + // user_login_finalize() also updates the login timestamp of the + // user, which invalidates further use of the one-time login link. + user_login_finalize(); + watchdog('user', 'User %name used one-time login link at time %timestamp.', array('%name' => $account->name, '%timestamp' => $timestamp)); + drupal_set_message(t('You have just used your one-time login link. It is no longer necessary to use this link to log in. Please change your password.')); + // Let the user's password be changed without the current password check. + $token = Crypt::randomStringHashed(55); + $_SESSION['pass_reset_' . $user->uid] = $token; + return new RedirectResponse('user/' . $user->uid . '/edit', array( + 'query' => array( + 'pass-reset-token' => $token + ))); + } + else { + if (!$account->login) { + // No expiration for first time login. + $form['message'] = array('#markup' => t('

This is a one-time login for %user_name.

Click on this button to log in to the site and change your password.

', array('%user_name' => $account->name))); + } + else { + $form['message'] = array('#markup' => t('

This is a one-time login for %user_name and will expire on %expiration_date.

Click on this button to log in to the site and change your password.

', array('%user_name' => $account->name, '%expiration_date' => format_date($timestamp + $timeout)))); + } + $form['help'] = array('#markup' => '

' . t('This login can be used only once.') . '

'); + $form['actions'] = array('#type' => 'actions'); + $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Log in')); + $form['#action'] = url("user/reset/$uid/$timestamp/$hashed_pass/login"); + return $form; + } + } + else { + drupal_set_message(t('You have tried to use a one-time login link that has either been used or is no longer valid. Please request a new one using the form below.')); + return new RedirectResponse('user/password'); + } + } + else { + // Deny access, no more clues. + // Everything will be in the watchdog's URL for the administrator to check. + throw new AccessDeniedHttpException(); + } + } + } + +} diff --git a/core/modules/user/user.module b/core/modules/user/user.module index 322311f..58caee6 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -895,13 +895,11 @@ function user_menu() { 'type' => MENU_LOCAL_TASK, 'file' => 'user.pages.inc', ); + $items['user/reset/%/%/%'] = array( 'title' => 'Reset password', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('user_pass_reset', 2, 3, 4), - 'access callback' => TRUE, 'type' => MENU_CALLBACK, - 'file' => 'user.pages.inc', + 'route_name' => 'user_pass_reset', ); $items['user/logout'] = array( diff --git a/core/modules/user/user.pages.inc b/core/modules/user/user.pages.inc index 5f0cfab..676c9ce 100644 --- a/core/modules/user/user.pages.inc +++ b/core/modules/user/user.pages.inc @@ -82,87 +82,6 @@ function user_pass_submit($form, &$form_state) { } /** - * Menu callback; process one time login link and redirects to the user page on success. - */ -function user_pass_reset($form, &$form_state, $uid, $timestamp, $hashed_pass, $action = NULL) { - global $user; - - // When processing the one-time login link, we have to make sure that a user - // isn't already logged in. - if ($user->uid) { - // The existing user is already logged in. - if ($user->uid == $uid) { - drupal_set_message(t('You are logged in as %user. Change your password.', array('%user' => $user->name, '!user_edit' => url("user/$user->uid/edit")))); - } - // A different user is already logged in on the computer. - else { - $reset_link_account = user_load($uid); - if (!empty($reset_link_account)) { - drupal_set_message(t('Another user (%other_user) is already logged into the site on this computer, but you tried to use a one-time link for user %resetting_user. Please logout and try using the link again.', - array('%other_user' => $user->name, '%resetting_user' => $reset_link_account->name, '!logout' => url('user/logout')))); - } else { - // Invalid one-time link specifies an unknown user. - drupal_set_message(t('The one-time login link you clicked is invalid.')); - } - } - drupal_goto(); - } - else { - // Time out, in seconds, until login URL expires. - $timeout = config('user.settings')->get('password_reset_timeout'); - $current = REQUEST_TIME; - $account = user_load($uid); - // Verify that the user exists and is active. - if ($timestamp <= $current && $account && $account->status) { - // No time out for first time login. - if ($account->login && $current - $timestamp > $timeout) { - drupal_set_message(t('You have tried to use a one-time login link that has expired. Please request a new one using the form below.')); - drupal_goto('user/password'); - } - elseif ($account->uid && $timestamp >= $account->login && $timestamp <= $current && $hashed_pass == user_pass_rehash($account->pass, $timestamp, $account->login)) { - // First stage is a confirmation form, then login - if ($action == 'login') { - // Set the new user. - $user = $account; - // user_login_finalize() also updates the login timestamp of the - // user, which invalidates further use of the one-time login link. - user_login_finalize(); - watchdog('user', 'User %name used one-time login link at time %timestamp.', array('%name' => $account->name, '%timestamp' => $timestamp)); - drupal_set_message(t('You have just used your one-time login link. It is no longer necessary to use this link to log in. Please change your password.')); - // Let the user's password be changed without the current password check. - $token = Crypt::randomStringHashed(55); - $_SESSION['pass_reset_' . $user->uid] = $token; - drupal_goto('user/' . $user->uid . '/edit', array('query' => array('pass-reset-token' => $token))); - } - else { - if (!$account->login) { - // No expiration for first time login. - $form['message'] = array('#markup' => t('

This is a one-time login for %user_name.

Click on this button to log in to the site and change your password.

', array('%user_name' => $account->name))); - } - else { - $form['message'] = array('#markup' => t('

This is a one-time login for %user_name and will expire on %expiration_date.

Click on this button to log in to the site and change your password.

', array('%user_name' => $account->name, '%expiration_date' => format_date($timestamp + $timeout)))); - } - $form['help'] = array('#markup' => '

' . t('This login can be used only once.') . '

'); - $form['actions'] = array('#type' => 'actions'); - $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Log in')); - $form['#action'] = url("user/reset/$uid/$timestamp/$hashed_pass/login"); - return $form; - } - } - else { - drupal_set_message(t('You have tried to use a one-time login link that has either been used or is no longer valid. Please request a new one using the form below.')); - drupal_goto('user/password'); - } - } - else { - // Deny access, no more clues. - // Everything will be in the watchdog's URL for the administrator to check. - throw new AccessDeniedHttpException(); - } - } -} - -/** * Menu callback; logs the current user out, and redirects to the home page. */ function user_logout() { diff --git a/core/modules/user/user.routing.yml b/core/modules/user/user.routing.yml index 409b033..64eb12b 100644 --- a/core/modules/user/user.routing.yml +++ b/core/modules/user/user.routing.yml @@ -54,3 +54,10 @@ user_role_delete: _form: '\Drupal\user\Form\UserRoleDelete' requirements: _entity_access: user_role.delete + +user_pass_reset: + pattern: 'user/reset/{user}/{timestamp}/{hashed_pass}' + defaults: + _form: '\Drupal\user\UserPasswordController::reset' + requirements: + _access: 'TRUE'