diff --git a/password_strength.install b/password_strength.install index fe86c19..b02687b 100644 --- a/password_strength.install +++ b/password_strength.install @@ -66,3 +66,10 @@ function password_strength_schema() { return $schema; } + +/** + * Install password_strength DB schema. + */ +function password_strength_update_7000() { + drupal_install_schema('password_strength'); +} diff --git a/password_strength.module b/password_strength.module index d7db2bd..7d2efc2 100644 --- a/password_strength.module +++ b/password_strength.module @@ -31,18 +31,6 @@ function password_strength_init() { } /** - * Implements hook_user_login(). - */ -function password_strength_user_login(&$edit, $account) { - global $user; - - // Check password strength score and force a reset if needed. - if ((int)password_strength_get_user_score($user->uid) < password_strength_required_score($user)) { - $_SESSION['password_strength_force_password_reset'] = TRUE; - } -} - -/** * Implements hook_xautoload(). */ function password_strength_xautoload($api) { @@ -94,6 +82,12 @@ function password_strength_check_strength($account = NULL) { */ function password_strength_form_alter(&$form, &$form_state, $form_id) { switch ($form_id) { + case 'user_login_block': + case 'user_login': + // Run user_login_submit handler after others. + $form['#submit'] = array_merge($form['#submit'], array('password_strength_form_user_login_submit')); + break; + case 'user_register_form': // Include password strength JS check and validation handler. if (array_key_exists('pass', $form['account']) && password_strength_check_strength()) { @@ -216,7 +210,7 @@ function password_strength_form_password_submit($form, &$form_state) { } list($account, $strength) = _password_strength_form_helper($form, $form_state); // We need to store the password strength before the raw password gets hashed - // by user_saved() in user_register_submit(). This ensures that the password + // by user_save() in user_register_submit(). This ensures that the password // strength is available in hook_user_insert(). $form_state['values']['password_strength_score'] = $strength; // Password has passed validation. Save strength and report change. @@ -229,6 +223,23 @@ function password_strength_form_password_submit($form, &$form_state) { } /** + * Submission handler for user login form. + */ +function password_strength_form_user_login_submit($form, &$form_state) { + list($account, $strength) = _password_strength_form_helper($form, $form_state); + + // Set password strength for this user account upon successful login. + if (password_strength_get_user_score($account->uid) != $strength['score']) { + password_strength_set_user_score($account->uid, $strength['score']); + } + + // Check password strength score and force a password change if needed. + if ((int) password_strength_get_user_score($account->uid) < password_strength_required_score($account)) { + $_SESSION['password_strength_force_password_reset'] = TRUE; + } +} + +/** * Internal helper gets pass and account from form and calls strength check. * * @param array $form diff --git a/tests/password_strength.test b/tests/password_strength.test index 0266c3b..2263266 100644 --- a/tests/password_strength.test +++ b/tests/password_strength.test @@ -52,9 +52,62 @@ class PasswordStrengthTestCase extends DrupalWebTestCase { $this->changePassword($this->web_user, 'Password1', TRUE); $this->assertTrue(password_strength_get_user_score($this->web_user->uid) === 4, t('User password score remains the same.')); $this->changePassword($this->web_user, '35qzYI^HUbAZ'); - $this->assertTrue(password_strength_get_user_score($this->web_user->uid) === 4, t('User password score set.')); + $this->assertTrue(password_strength_get_user_score($this->web_user->uid) === 4, t('User password score remains the same.')); + + } + + /** + * Tests force password change on login. + */ + public function testForcePasswordChange() { + // Verify that a password change is not forced on login if no strength + // requirement is set, or if the user password is equal to or stronger than + // the required strength. + foreach (array('0', '1', '2') as $minimum_strength) { + $this->setRequiredScore('0'); + // Set password to strength 2 (good) password. + $this->changePassword($this->web_user, 'demodemo12'); + $this->setRequiredScore($minimum_strength); + $this->drupalLogin($this->web_user); + $this->assertNoText(t("Your password does not meet the minimum complexity requirement. You must change your password to proceed on the site."), 'Force password change message is not displayed'); + // Test that the user can browse the site. + $this->drupalGet('node'); + $this->assertEqual($this->getUrl(), url('node', array('absolute' => TRUE)), 'The user was not redirected to the password form'); + $this->drupalLogout(); + } - // Delete web user and verify password score gets cleaned up. + // Verify that a password change is forced on login if the required strength + // is higher than the user password. + $this->setRequiredScore('0'); + $this->changePassword($this->web_user, 'Password1'); + $this->setRequiredScore('4'); + $this->drupalLogin($this->web_user); + $this->assertEqual($this->getUrl(), url("user/{$this->web_user->uid}/edit", array('query' => array('destination' => "user/{$this->web_user->uid}"), 'absolute' => TRUE)), 'The user was redirected to the password form'); + $this->assertText(t("Your password does not meet the minimum complexity requirement. You must change your password to proceed on the site."), 'Force password change message is displayed'); + + // Test that the user cannot browse the site. + $this->drupalGet('node'); + $this->assertEqual($this->getUrl(), url("user/{$this->web_user->uid}/edit", array('query' => array('destination' => 'node'), 'absolute' => TRUE)), 'The user was redirected to the password form'); + + // Test that the password can be set to the stronger password. + $edit = array(); + $edit['current_pass'] = 'Password1'; + $edit['pass[pass1]'] = '35qzYI^HUbAZ'; + $edit['pass[pass2]'] = '35qzYI^HUbAZ'; + $this->drupalPost("user/{$this->web_user->uid}/edit", $edit, t('Save')); + + // Make sure the user can log in with their new password. + $this->drupalLogout(); + $this->web_user->pass_raw = '35qzYI^HUbAZ'; + $this->drupalLogin($this->web_user); + $this->drupalLogout(); + } + + /** + * Tests user deletion. + */ + public function testUserDeletion() { + // Delete web_user and verify password score gets cleaned up. variable_set('user_cancel_method', 'user_cancel_reassign'); variable_set('password_strength_default_required_score', '0'); $this->drupalLogin($this->admin_user);