/** * Log a password change from the given member. * Call MemberPassword::log($this) from within Member whenever the password is changed. * * @param Member $member */ public static function log($member) { $record = new MemberPassword(); $record->MemberID = $member->ID; $record->Password = $member->Password; $record->PasswordEncryption = $member->PasswordEncryption; $record->Salt = $member->Salt; $record->write(); }
/** * @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; }
public function onAfterWrite() { parent::onAfterWrite(); Permission::flush_permission_cache(); if ($this->isChanged('Password')) { MemberPassword::log($this); } }
/** * Test that password changes are logged properly */ public function testPasswordChangeLogging() { $member = $this->objFromFixture('SilverStripe\\Security\\Member', 'test'); $this->assertNotNull($member); $member->Password = "******"; $member->write(); $member->Password = "******"; $member->write(); $member->Password = "******"; $member->write(); $passwords = DataObject::get("SilverStripe\\Security\\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('SilverStripe\\ORM\\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); }