Skip to content

Commit

Permalink
[8.x] Copy password rule to current_password (#37650)
Browse files Browse the repository at this point in the history
* Rename validation and add alias

* Add test for renamed rule

* Update ValidatesAttributes.php

Co-authored-by: Taylor Otwell <[email protected]>
  • Loading branch information
netpok and taylorotwell authored Jun 11, 2021
1 parent 0b1610f commit e886360
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 11 deletions.
35 changes: 24 additions & 11 deletions src/Illuminate/Validation/Concerns/ValidatesAttributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down Expand Up @@ -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
Expand All @@ -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);
}

/**
Expand Down
94 changes: 94 additions & 0 deletions tests/Validation/ValidationValidatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down

0 comments on commit e886360

Please sign in to comment.