/** * @param String $password * @param Member $member * @return ValidationResult */ public function validate($password, $member) { $valid = ValidationResult::create(); if ($this->minLength) { if (strlen($password) < $this->minLength) { $valid->error(sprintf(_t('PasswordValidator.TOOSHORT', 'Password is too short, it must be %s or more characters long'), $this->minLength), 'TOO_SHORT'); } } if ($this->minScore) { $score = 0; $missedTests = array(); foreach ($this->testNames as $name) { if (preg_match(self::config()->character_strength_tests[$name], $password)) { $score++; } else { $missedTests[] = _t('PasswordValidator.STRENGTHTEST' . strtoupper($name), $name, 'The user needs to add this to their password for more complexity'); } } if ($score < $this->minScore) { $valid->error(sprintf(_t('PasswordValidator.LOWCHARSTRENGTH', 'Please increase password strength by adding some of the following characters: %s'), implode(', ', $missedTests)), 'LOW_CHARACTER_STRENGTH'); } } if ($this->historicalPasswordCount) { $previousPasswords = MemberPassword::get()->where(array('"MemberPassword"."MemberID"' => $member->ID))->sort('"Created" DESC, "ID" DESC')->limit($this->historicalPasswordCount); if ($previousPasswords) { foreach ($previousPasswords as $previousPasswords) { if ($previousPasswords->checkPassword($password)) { $valid->error(_t('PasswordValidator.PREVPASSWORD', 'You\'ve already used that password in the past, please choose a new password'), 'PREVIOUS_PASSWORD'); break; } } } } return $valid; }
/** * Test that password changes are logged properly */ public function testPasswordChangeLogging() { $member = $this->objFromFixture('Member', 'test'); $this->assertNotNull($member); $member->Password = "******"; $member->write(); $member->Password = "******"; $member->write(); $member->Password = "******"; $member->write(); $passwords = DataObject::get("MemberPassword", "\"MemberID\" = {$member->ID}", "\"Created\" DESC, \"ID\" DESC")->getIterator(); $this->assertNotNull($passwords); $passwords->rewind(); $this->assertTrue($passwords->current()->checkPassword('test3'), "Password test3 not found in MemberRecord"); $passwords->next(); $this->assertTrue($passwords->current()->checkPassword('test2'), "Password test2 not found in MemberRecord"); $passwords->next(); $this->assertTrue($passwords->current()->checkPassword('test1'), "Password test1 not found in MemberRecord"); $passwords->next(); $this->assertInstanceOf('DataObject', $passwords->current()); $this->assertTrue($passwords->current()->checkPassword('1nitialPassword'), "Password 1nitialPassword not found in MemberRecord"); //check we don't retain orphaned records when a member is deleted $member->delete(); $passwords = MemberPassword::get()->filter('MemberID', $member->OldID); $this->assertCount(0, $passwords); }