diff --git a/modules/user/user.pages.inc b/modules/user/user.pages.inc index 2d3c13d..149a37c 100644 --- a/modules/user/user.pages.inc +++ b/modules/user/user.pages.inc @@ -98,7 +98,15 @@ function user_pass_reset($form, &$form_state, $uid, $timestamp, $hashed_pass, $a 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")))); + watchdog('user', 'Session closed for %name.', array('%name' => $user->name)); + + module_invoke_all('user_logout', $user); + // Destroy the current session, and reset $user to the anonymous user. + session_destroy(); + + if ($action === 'login') { + drupal_goto("user/reset/$uid/$timestamp/$hashed_pass/login"); + } } // A different user is already logged in on the computer. else { @@ -110,58 +118,56 @@ function user_pass_reset($form, &$form_state, $uid, $timestamp, $hashed_pass, $a // Invalid one-time link specifies an unknown user. drupal_set_message(t('The one-time login link you clicked is invalid.'), 'error'); } + drupal_goto(); } - drupal_goto(); } - else { - // Time out, in seconds, until login URL expires. Defaults to 24 hours = - // 86400 seconds. - $timeout = variable_get('user_password_reset_timeout', 86400); - $current = REQUEST_TIME; - // Some redundant checks for extra security ? - $users = user_load_multiple(array($uid), array('status' => '1')); - if ($timestamp <= $current && $account = reset($users)) { - // 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.'), 'error'); - drupal_goto('user/password'); - } - elseif ($account->uid && $timestamp >= $account->login && $timestamp <= $current && $hashed_pass == user_pass_rehash($account->pass, $timestamp, $account->login, $account->uid)) { - // 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 = drupal_random_key(); - $_SESSION['pass_reset_' . $user->uid] = $token; - drupal_goto('user/' . $user->uid . '/edit', array('query' => array('pass-reset-token' => $token))); - } - 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; - } + // Time out, in seconds, until login URL expires. Defaults to 24 hours = + // 86400 seconds. + $timeout = variable_get('user_password_reset_timeout', 86400); + $current = REQUEST_TIME; + // Some redundant checks for extra security ? + $users = user_load_multiple(array($uid), array('status' => '1')); + if ($timestamp <= $current && $account = reset($users)) { + // 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.'), 'error'); + drupal_goto('user/password'); + } + elseif ($account->uid && $timestamp >= $account->login && $timestamp <= $current && $hashed_pass == user_pass_rehash($account->pass, $timestamp, $account->login, $account->uid)) { + // 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 = drupal_random_key(); + $_SESSION['pass_reset_' . $user->uid] = $token; + drupal_goto('user/' . $user->uid . '/edit', array('query' => array('pass-reset-token' => $token))); } 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.'), 'error'); - drupal_goto('user/password'); + $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 { - // Deny access, no more clues. - // Everything will be in the watchdog's URL for the administrator to check. - drupal_access_denied(); - drupal_exit(); + 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.'), 'error'); + drupal_goto('user/password'); } } + else { + // Deny access, no more clues. + // Everything will be in the watchdog's URL for the administrator to check. + drupal_access_denied(); + drupal_exit(); + } } /** diff --git a/modules/user/user.test b/modules/user/user.test index 97d23b4..2393c3a 100644 --- a/modules/user/user.test +++ b/modules/user/user.test @@ -481,6 +481,34 @@ class UserPasswordResetTestCase extends DrupalWebTestCase { } /** + * Test user password reset while logged in. + */ + function testUserPasswordResetLoggedIn() { + $account = $this->drupalCreateUser(); + $this->drupalLogin($account); + // Make sure the test account has a valid password. + user_save($account, array('pass' => user_password())); + + // Generate one time login link. + $reset_url = user_pass_reset_url($account); + $this->drupalGet($reset_url); + + $this->assertText('Reset password'); + $this->drupalPost(NULL, NULL, t('Log in')); + + $this->assertText('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.'); + + $pass = user_password(); + $edit = array( + 'pass[pass1]' => $pass, + 'pass[pass2]' => $pass, + ); + $this->drupalPost(NULL, $edit, t('Save')); + + $this->assertText('The changes have been saved.'); + } + + /** * Attempts login using an expired password reset link. */ function testUserPasswordResetExpired() {