=== modified file 'modules/user/user.pages.inc' --- modules/user/user.pages.inc 2009-07-31 19:01:01 +0000 +++ modules/user/user.pages.inc 2009-08-09 05:04:07 +0000 @@ -75,7 +75,7 @@ function user_pass_submit($form, &$form_ /** * Menu callback; process one time login link and redirects to the user page on success. */ -function user_pass_reset(&$form_state, $uid, $timestamp, $hashed_pass, $action = NULL) { +function user_pass_reset(&$form_state, $uid, $timestamp, $hashed_pass) { global $user; // Check if the user is already logged in. The back button is often the culprit here. @@ -96,24 +96,7 @@ function user_pass_reset(&$form_state, $ 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') { - watchdog('user', 'User %name used one-time login link at time %timestamp.', array('%name' => $account->name, '%timestamp' => $timestamp)); - // 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(); - drupal_set_message(t('You have just used your one-time login link. It is no longer necessary to use this link to login. Please change your password.')); - drupal_goto('user/' . $user->uid . '/edit'); - } - 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 login 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['submit'] = array('#type' => 'submit', '#value' => t('Log in')); - $form['#action'] = url("user/reset/$uid/$timestamp/$hashed_pass/login"); - return $form; - } + return _user_pass_reset_form($account, $timestamp); } else { drupal_set_message(t('You have tried to use a one-time login link which has either been used or is no longer valid. Please request a new one using the form below.')); @@ -129,6 +112,40 @@ function user_pass_reset(&$form_state, $ } /** + * Generate the form to change password and log in using a one-time login link. + * + * @param stdClass $account + * This account will be logged in after a password change. + * @param $expire + * The timestamp when the login link expires. Used only to display. + */ +function _user_pass_reset_form($account, $expire) { + $form['message'] = array('#markup' => t('

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

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

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

'); + $form['pass'] = array('#type' => 'password_confirm', '#required' => TRUE); + $form['submit'] = array('#type' => 'submit', '#value' => t('Change password and log in')); + $form['#account'] = $account; + $form['#redirect'] = "user/$account->uid"; + return $form; +} + +/** + * Change password and log in the user. + */ +function user_pass_reset_submit($form, $form_state) { + global $user; + watchdog('user', 'User %name used one-time login link at time %timestamp.', array('%name' => $form['#account']->name, '%timestamp' => REQUEST_TIME)); + drupal_set_message(t('You have just used your one-time login link. It is no longer possible to use this link to login.')); + // Set the new user. + $user = $form['#account']; + user_save($user, array('pass' => $form_state['values']['pass'])); + drupal_set_message(t('Password changed.')); + // user_login_finalize() also updates the login timestamp of the + // user, which invalidates further use of the one-time login link. + user_login_finalize(); +} + +/** * Menu callback; logs the current user out, and redirects to the home page. */ function user_logout() { === modified file 'modules/user/user.test' --- modules/user/user.test 2009-07-31 21:14:01 +0000 +++ modules/user/user.test 2009-08-09 05:07:53 +0000 @@ -59,29 +59,27 @@ class UserRegistrationTestCase extends D $url = user_pass_reset_url($user); $this->drupalGet($url); $this->assertText(t('This login can be used only once.'), t('Login can be used only once.')); - - $this->drupalPost(NULL, NULL, t('Log in')); - $this->assertText(t('You have just used your one-time login link. It is no longer necessary to use this link to login. Please change your password.'), t('This link is no longer valid.')); - + // This should not succeed. + $this->drupalPost(NULL, array(), t('Change password and log in')); + $this->assertText(t('This login can be used only once.'), t('Login can be used only once.')); // Check password type validation $edit = array(); $edit['pass[pass1]'] = '99999.0'; $edit['pass[pass2]'] = '99999'; - $this->drupalPost(NULL, $edit, t('Save')); + $this->drupalPost(NULL, $edit, t('Change password and log in')); $this->assertText(t('The specified passwords do not match.'), t('Type mismatched passwords display an error message.')); - $this->assertNoText(t('The changes have been saved.'), t('Save user password with mismatched type in password confirm.')); - + $this->assertText(t('This login can be used only once.'), t('Login can be used only once.')); // Change user password. $new_pass = user_password(); $edit = array(); $edit['pass[pass1]'] = $new_pass; $edit['pass[pass2]'] = $new_pass; - $this->drupalPost(NULL, $edit, t('Save')); - $this->assertText(t('The changes have been saved.'), t('Password changed to @password', array('@password' => $new_pass))); - + $this->drupalPost(NULL, $edit, t('Change password and log in')); + file_put_contents('/tmp/log.htm', $this->content); + $this->assertText(t('You have just used your one-time login link. It is no longer possible to use this link to login.'), t('This link is no longer valid.')); + $this->assertText(t('Password changed.'), t('Password changed.')); // Make sure password changes are present in database. require_once DRUPAL_ROOT . '/' . variable_get('password_inc', 'includes/password.inc'); - $user = user_load($user->uid, TRUE); $this->assertTrue(user_check_password($new_pass, $user), t('Correct password in database.'));