/**
  * 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);
 }