You are here

prlp.module in Password Reset Landing Page (PRLP) 7.x

Same filename and directory in other branches
  1. 8 prlp.module
  2. 6 prlp.module
  3. 7 prlp.module

File

prlp.module
View source
<?php

/**
 * Alters the user password reset landing page so that user can enter new
 * password directly on the landing page, and the submit handler can save it.
 */
function prlp_form_user_pass_reset_alter(&$form, &$form_state) {
  @(list($uid, $timestamp, $hashed_pass, $action) = $form_state['build_info']['args']);
  if ($uid) {
    $form['#user'] = user_load($uid);

    // Do this only
    if (empty($action)) {

      // Inject the username/password change form into the current form.
      user_account_form($form, $form_state);

      // ???
      $form['#user_category'] = 'account';

      // Hide email and picture fields.
      $form['account']['mail']['#access'] = FALSE;
      $form['picture']['#access'] = FALSE;

      // Unset $form['#action'] so that the form doesn't get submitted to the
      // user profile edit page. Instead it gets submitted to self.
      unset($form['#action']);

      // Append our own submit handler so we can save the password change
      // before sending the user to user profile edit form.
      $form['#submit'][] = 'prlp_user_pass_reset_submit';
    }
  }
}

/**
 * This function is almost a direct copy of 'user_pass_reset' function, with a
 * couple of significant changes. It saves the password or username changes.
 * 
 * Also, Unlike that function, this one is a form submit handler.
 */
function prlp_user_pass_reset_submit($form, &$form_state) {
  global $user;
  @(list($uid, $timestamp, $hashed_pass, $action) = $form_state['build_info']['args']);

  // 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. <a href="!user_edit">Change your password.</a>', array(
        '%user' => $user->name,
        '!user_edit' => url("user/{$user->uid}/edit"),
      )));
    }
    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 <a href="!logout">logout</a> 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. 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.'));
        drupal_goto('user/password');
      }
      elseif ($account->uid && $timestamp >= $account->login && $timestamp <= $current && $hashed_pass == user_pass_rehash($account->pass, $timestamp, $account->login)) {

        /*
         * BEGIN: CHANGED from user_pass_reset.
         */
        $form_state['user'] = $account;

        // If I don't do this, I get a notice from line 324 in DRUPAL_ROOT/modules/user/user.pages.inc
        if (!isset($_SESSION)) {
          $_SESSION = array();
        }
        user_profile_form_submit($form, $form_state);

        /*
         * END: CHANGED from user_pass_reset.
         */

        // First stage is a confirmation form, then 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 log in. Please change your password.'));

        // Let the user's password be changed without the current password check.
        $token = drupal_hash_base64(drupal_random_bytes(55));
        $_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.'));
        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();
    }
  }
}

Functions

Namesort descending Description
prlp_form_user_pass_reset_alter Alters the user password reset landing page so that user can enter new password directly on the landing page, and the submit handler can save it.
prlp_user_pass_reset_submit This function is almost a direct copy of 'user_pass_reset' function, with a couple of significant changes. It saves the password or username changes.