diff --git a/src/Illuminate/Validation/Concerns/ValidatesAttributes.php b/src/Illuminate/Validation/Concerns/ValidatesAttributes.php index 35dff99f1c92..ecf5049d286e 100644 --- a/src/Illuminate/Validation/Concerns/ValidatesAttributes.php +++ b/src/Illuminate/Validation/Concerns/ValidatesAttributes.php @@ -348,6 +348,28 @@ public function validateConfirmed($attribute, $value) return $this->validateSame($attribute, $value, [$attribute.'_confirmation']); } + /** + * Validate that the password of the currently authenticated user matches the given value. + * + * @param string $attribute + * @param mixed $value + * @param array $parameters + * @return bool + */ + protected function validateCurrentPassword($attribute, $value, $parameters) + { + $auth = $this->container->make('auth'); + $hasher = $this->container->make('hash'); + + $guard = $auth->guard(Arr::first($parameters)); + + if ($guard->guest()) { + return false; + } + + return $hasher->check($value, $guard->user()->getAuthPassword()); + } + /** * Validate that an attribute is a valid date. * @@ -1325,7 +1347,7 @@ public function validateNumeric($attribute, $value) } /** - * Validate that the current logged in user's password matches the given value. + * Validate that the password of the currently authenticated user matches the given value. * * @param string $attribute * @param mixed $value @@ -1334,16 +1356,7 @@ public function validateNumeric($attribute, $value) */ protected function validatePassword($attribute, $value, $parameters) { - $auth = $this->container->make('auth'); - $hasher = $this->container->make('hash'); - - $guard = $auth->guard(Arr::first($parameters)); - - if ($guard->guest()) { - return false; - } - - return $hasher->check($value, $guard->user()->getAuthPassword()); + return $this->validateCurrentPassword($attribute, $value, $parameters); } /** diff --git a/tests/Validation/ValidationValidatorTest.php b/tests/Validation/ValidationValidatorTest.php index 4064290aa16b..992aa3f0dae1 100755 --- a/tests/Validation/ValidationValidatorTest.php +++ b/tests/Validation/ValidationValidatorTest.php @@ -718,6 +718,100 @@ public function testValidateArrayKeys() $this->assertFalse($v->passes()); } + public function testValidateCurrentPassword() + { + // Fails when user is not logged in. + $auth = m::mock(Guard::class); + $auth->shouldReceive('guard')->andReturn($auth); + $auth->shouldReceive('guest')->andReturn(true); + + $hasher = m::mock(Hasher::class); + + $container = m::mock(Container::class); + $container->shouldReceive('make')->with('auth')->andReturn($auth); + $container->shouldReceive('make')->with('hash')->andReturn($hasher); + + $trans = $this->getTranslator(); + $trans->shouldReceive('get')->andReturnArg(0); + + $v = new Validator($trans, ['password' => 'foo'], ['password' => 'current_password']); + $v->setContainer($container); + + $this->assertFalse($v->passes()); + + // Fails when password is incorrect. + $user = m::mock(Authenticatable::class); + $user->shouldReceive('getAuthPassword'); + + $auth = m::mock(Guard::class); + $auth->shouldReceive('guard')->andReturn($auth); + $auth->shouldReceive('guest')->andReturn(false); + $auth->shouldReceive('user')->andReturn($user); + + $hasher = m::mock(Hasher::class); + $hasher->shouldReceive('check')->andReturn(false); + + $container = m::mock(Container::class); + $container->shouldReceive('make')->with('auth')->andReturn($auth); + $container->shouldReceive('make')->with('hash')->andReturn($hasher); + + $trans = $this->getTranslator(); + $trans->shouldReceive('get')->andReturnArg(0); + + $v = new Validator($trans, ['password' => 'foo'], ['password' => 'current_password']); + $v->setContainer($container); + + $this->assertFalse($v->passes()); + + // Succeeds when password is correct. + $user = m::mock(Authenticatable::class); + $user->shouldReceive('getAuthPassword'); + + $auth = m::mock(Guard::class); + $auth->shouldReceive('guard')->andReturn($auth); + $auth->shouldReceive('guest')->andReturn(false); + $auth->shouldReceive('user')->andReturn($user); + + $hasher = m::mock(Hasher::class); + $hasher->shouldReceive('check')->andReturn(true); + + $container = m::mock(Container::class); + $container->shouldReceive('make')->with('auth')->andReturn($auth); + $container->shouldReceive('make')->with('hash')->andReturn($hasher); + + $trans = $this->getTranslator(); + $trans->shouldReceive('get')->andReturnArg(0); + + $v = new Validator($trans, ['password' => 'foo'], ['password' => 'current_password']); + $v->setContainer($container); + + $this->assertTrue($v->passes()); + + // We can use a specific guard. + $user = m::mock(Authenticatable::class); + $user->shouldReceive('getAuthPassword'); + + $auth = m::mock(Guard::class); + $auth->shouldReceive('guard')->with('custom')->andReturn($auth); + $auth->shouldReceive('guest')->andReturn(false); + $auth->shouldReceive('user')->andReturn($user); + + $hasher = m::mock(Hasher::class); + $hasher->shouldReceive('check')->andReturn(true); + + $container = m::mock(Container::class); + $container->shouldReceive('make')->with('auth')->andReturn($auth); + $container->shouldReceive('make')->with('hash')->andReturn($hasher); + + $trans = $this->getTranslator(); + $trans->shouldReceive('get')->andReturnArg(0); + + $v = new Validator($trans, ['password' => 'foo'], ['password' => 'current_password:custom']); + $v->setContainer($container); + + $this->assertTrue($v->passes()); + } + public function testValidateFilled() { $trans = $this->getIlluminateArrayTranslator();