diff --git a/plugins/constraint/delay.inc b/plugins/constraint/delay.inc index 600b037..68812dc 100644 --- a/plugins/constraint/delay.inc +++ b/plugins/constraint/delay.inc @@ -11,6 +11,7 @@ $plugin = array( 'prime value' => 'delay', 'config' => array( 'delay' => NULL, + 'threshold' => NULL, ), ); @@ -28,6 +29,13 @@ function password_policy_delay_admin_form($form, &$form_state, $constraint) { '#default_value' => $constraint->config['delay'], '#description' => t('Password cannot be changed until this much time has passed since the last password change (use normal English, like 1 week or 24 hours).'), ); + $sub_form['delay_fieldset']['threshold'] = array( + '#type' => 'textfield', + '#title' => t('Maximum number of times password can be changed'), + '#default_value' => $constraint->config['threshold'], + '#description' => t('Password can be changed this many times in a period above (if not defined 1 time).'), + '#element_validate' => array('element_validate_integer_positive'), + ); return $sub_form; } @@ -41,13 +49,6 @@ function password_policy_delay_constraint($password, $account, $constraint) { $account = $user; } - // To skip the delay constraint, the user must have logged in via a - // one-time link and have the token in the URL. - if (isset($_SESSION['pass_reset_' . $account->uid], $_GET['pass-reset-token']) && ($_GET['pass-reset-token'] === $_SESSION['pass_reset_' . $account->uid])) { - // Don't apply constraint on password reset. - return TRUE; - } - // @TODO Find out why the hook_user_load is not running correctly. if (!isset($account->password_history)) { password_policy_user_load(array($account->uid => $account)); @@ -58,6 +59,24 @@ function password_policy_delay_constraint($password, $account, $constraint) { return TRUE; } - // Apply constraint if most recent password change happened too recently. - return $account->password_history[0]->created <= strtotime('-' . $constraint->config['delay']); + // If user has only system-generated password, uses one-time link + // and have the token in the URL, don't apply constraint. + $is_password_generated = variable_get('user_email_verification', TRUE) && count($account->password_history) == 1; + $is_one_time_login = isset($_SESSION['pass_reset_' . $account->uid], $_GET['pass-reset-token']) && $_GET['pass-reset-token'] === $_SESSION['pass_reset_' . $account->uid]; + if ($is_password_generated && $is_one_time_login) { + return TRUE; + } + + $period_start = strtotime('-' . $constraint->config['delay']); + $password_index = !empty($constraint->config['threshold']) ? $constraint->config['threshold'] - 1 : 0; + + // If password has been changed less times than allowed by threshold, + // don't apply constraint. + if (!isset($account->password_history[$password_index])) { + return TRUE; + } + + // Apply constraint if last number of password changes defined by threshold + // happened too recently. + return $account->password_history[$password_index]->created <= $period_start; }