Skip to content

Commit

Permalink
Updated the password encode domain object with its related implementa…
Browse files Browse the repository at this point in the history
…tions
  • Loading branch information
benatespina committed Feb 8, 2016
1 parent 9ac8e75 commit 3a5cd2e
Show file tree
Hide file tree
Showing 13 changed files with 84 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
namespace spec\BenGor\User\Application\Service;

use BenGor\User\Application\Service\ChangeUserPasswordRequest;
use BenGor\User\Application\Service\ChangeUserPasswordService;
use BenGor\User\Domain\Model\User;
use BenGor\User\Domain\Model\UserId;
use BenGor\User\Domain\Model\UserPassword;
Expand All @@ -38,7 +39,7 @@ function let(UserRepository $repository)

function it_is_initializable()
{
$this->shouldHaveType('BenGor\User\Application\Service\ChangeUserPasswordService');
$this->shouldHaveType(ChangeUserPasswordService::class);
}

function it_implements_application_service()
Expand All @@ -49,16 +50,13 @@ function it_implements_application_service()
function it_changes_password(UserRepository $repository, User $user)
{
$request = new ChangeUserPasswordRequest('id', 'newPassword', 'oldPassword');

$user->password()->shouldBeCalled()->willReturn(
UserPassword::fromPlain('oldPassword', new DummyUserPasswordEncoder('encodedPassword'))
);
$user->changePassword(
Argument::type(UserPassword::class),
Argument::type(UserPassword::class)
)->shouldBeCalled();
$encoder = new DummyUserPasswordEncoder('encodedPassword');
$oldPassword = UserPassword::fromPlain('oldPassword', $encoder, 'dummy-salt');

$repository->userOfId(Argument::type(UserId::class))->shouldBeCalled()->willReturn($user);
$user->password()->shouldBeCalled()->willReturn($oldPassword);
$user->changePassword(Argument::type(UserPassword::class))->shouldBeCalled();

$repository->persist($user)->shouldBeCalled();

$this->execute($request);
Expand Down
13 changes: 6 additions & 7 deletions spec/BenGor/User/Application/Service/LogInUserServiceSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,16 +96,15 @@ function it_doesnt_log_if_user_does_not_exist(UserRepository $repository, User $

function it_does_not_log_if_user_invalid_password(UserRepository $repository, User $user)
{
$request = new LogInUserRequest('[email protected]', 'plainPassword');
$encoder = new DummyUserPasswordEncoder('otherEncodedPassword', false);
$this->beConstructedWith($repository, $encoder);

$user->login()->shouldNotBeCalled();
$user->isEnabled()->shouldBeCalled()->willReturn(true);
$user->password()->shouldBeCalled()->willReturn(
UserPassword::fromPlain('otherPassword', new DummyUserPasswordEncoder('otherEncodedPassword'))
);
$request = new LogInUserRequest('[email protected]', 'plainPassword');
$password = UserPassword::fromPlain('otherPassword', $encoder);

$repository->userOfEmail(Argument::type(UserEmail::class))->shouldBeCalled()->willReturn($user);
$repository->persist($user)->shouldNotBeCalled();
$user->isEnabled()->shouldBeCalled()->willReturn(true);
$user->password()->shouldBeCalled()->willReturn($password);

$this->shouldThrow(UserPasswordInvalidException::class)->duringExecute($request);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,14 @@ function it_implements_application_service()

function it_does_not_remove_user_password_do_not_match(UserRepository $repository, User $user)
{
$encoder = new DummyUserPasswordEncoder('passwordThatDoesntMatch');
$encoder = new DummyUserPasswordEncoder('encodedPassword', false);
$this->beConstructedWith($repository, $encoder);

$request = new RemoveUserRequest('userID', 'plainPassword');
$password = UserPassword::fromPlain('wrongPassword', $encoder);

$user->password()->willReturn($password);
$repository->userOfId(Argument::type(UserId::class))->shouldBeCalled()->willReturn($user);
$user->password()->shouldBeCalled()->willReturn($password);

$this->shouldThrow(UserPasswordInvalidException::class)->duringExecute($request);
}
Expand All @@ -66,8 +68,8 @@ function it_removes_user(UserRepository $repository, User $user)
$request = new RemoveUserRequest('userID', 'plainPassword');
$password = UserPassword::fromPlain('plainPassword', $encoder);

$user->password()->willReturn($password);
$repository->userOfId(Argument::type(UserId::class))->shouldBeCalled()->willReturn($user);
$user->password()->shouldBeCalled()->willReturn($password);
$repository->remove($user)->shouldBeCalled();

$this->execute($request);
Expand Down
10 changes: 5 additions & 5 deletions spec/BenGor/User/Domain/Model/UserPasswordSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

use BenGor\User\Domain\Model\UserPassword;
use BenGor\User\Domain\Model\UserPasswordEncoder;
use BenGor\User\Infrastructure\Security\Test\DummyUserPasswordEncoder;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;

Expand Down Expand Up @@ -46,7 +47,7 @@ function it_generates_from_plain_password(UserPasswordEncoder $encoder)
$plainPassword = 'secretPassword';
$encodedPassword = 'iudfhiuewhfuiewhiufhewiufewhiufwe';

$encoder->encode($plainPassword, Argument::type('string'))->willReturn($encodedPassword);
$encoder->encode($plainPassword, Argument::type('string'))->shouldBecalled()->willReturn($encodedPassword);

$this->beConstructedFromPlain($plainPassword, $encoder);

Expand All @@ -56,10 +57,9 @@ function it_generates_from_plain_password(UserPasswordEncoder $encoder)

function it_compares_passwords()
{
$encodedPassword = 'ajdqwjnfewnewnfewkjqnfewkjn';
$encoder = new DummyUserPasswordEncoder('ajdqwjnfewnewnfewkjqnfewkjn');
$this->beConstructedFromEncoded('ajdqwjnfewnewnfewkjqnfewkjn', 'thisIsTheSalt');

$this->beConstructedFromEncoded($encodedPassword, 'thisIsTheSalt');

$this->equals(UserPassword::fromEncoded($encodedPassword, 'thisIsTheSalt'))->shouldBe(true);
$this->equals(123456, $encoder)->shouldBe(true);
}
}
2 changes: 1 addition & 1 deletion spec/BenGor/User/Domain/Model/UserSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ function it_changes_password()

$this->rememberPassword();
$this->rememberPasswordToken()->shouldReturnAnInstanceOf(UserToken::class);
$this->changePassword($this->password(), $newPassword);
$this->changePassword($newPassword);
$this->rememberPasswordToken()->shouldReturn(null);
$this->password()->shouldReturn($newPassword);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

namespace BenGor\User\Application\Service;

use BenGor\User\Domain\Model\Exception\UserPasswordInvalidException;
use BenGor\User\Domain\Model\UserId;
use BenGor\User\Domain\Model\UserPassword;
use BenGor\User\Domain\Model\UserPasswordEncoder;
Expand Down Expand Up @@ -62,10 +63,10 @@ public function execute($request = null)
$oldPlainPassword = $request->oldPlainPassword();

$user = $this->repository->userOfId(new UserId($id));
$oldPassword = UserPassword::fromPlain($oldPlainPassword, $this->encoder, $user->password()->salt());
$newPassword = UserPassword::fromPlain($newPlainPassword, $this->encoder);

$user->changePassword($oldPassword, $newPassword);
if (false === $user->password()->equals($oldPlainPassword, $this->encoder)) {
throw new UserPasswordInvalidException();
}
$user->changePassword(UserPassword::fromPlain($newPlainPassword, $this->encoder));

$this->repository->persist($user);
}
Expand Down
7 changes: 2 additions & 5 deletions src/BenGor/User/Application/Service/LogInUserService.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
use BenGor\User\Domain\Model\Exception\UserInactiveException;
use BenGor\User\Domain\Model\Exception\UserPasswordInvalidException;
use BenGor\User\Domain\Model\UserEmail;
use BenGor\User\Domain\Model\UserPassword;
use BenGor\User\Domain\Model\UserPasswordEncoder;
use BenGor\User\Domain\Model\UserRepository;
use Ddd\Application\Service\ApplicationService;
Expand Down Expand Up @@ -70,12 +69,10 @@ public function execute($request = null)
if (false === $user->isEnabled()) {
throw new UserInactiveException();
}

$password = UserPassword::fromPlain($plainPassword, $this->encoder, $user->password()->salt());

if (false === $user->password()->equals($password)) {
if (false === $user->password()->equals($plainPassword, $this->encoder)) {
throw new UserPasswordInvalidException();
}

$user->login();

$this->repository->persist($user);
Expand Down
4 changes: 1 addition & 3 deletions src/BenGor/User/Application/Service/RemoveUserService.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,8 @@ public function execute($request = null)
$id = $request->id();
$plainPassword = $request->password();

$password = UserPassword::fromPlain($plainPassword, $this->encoder);
$user = $this->repository->userOfId(new UserId($id));

if (false === $user->password()->equals($password)) {
if (false === $user->password()->equals($plainPassword, $this->encoder)) {
throw new UserPasswordInvalidException();
}

Expand Down
13 changes: 4 additions & 9 deletions src/BenGor/User/Domain/Model/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
use BenGor\User\Domain\Model\Event\UserRememberPasswordRequested;
use BenGor\User\Domain\Model\Event\UserRoleGranted;
use BenGor\User\Domain\Model\Event\UserRoleRevoked;
use BenGor\User\Domain\Model\Exception\UserPasswordInvalidException;
use BenGor\User\Domain\Model\Exception\UserRoleAlreadyGrantedException;
use BenGor\User\Domain\Model\Exception\UserRoleAlreadyRevokedException;
use BenGor\User\Domain\Model\Exception\UserRoleInvalidException;
Expand Down Expand Up @@ -150,15 +149,11 @@ public function id()
/**
* Updates the user password.
*
* @param UserPassword $anOldPassword The old password
* @param UserPassword $aNewPassword The new password
* @param UserPassword $aPassword The old password
*/
public function changePassword(UserPassword $anOldPassword, UserPassword $aNewPassword)
public function changePassword(UserPassword $aPassword)
{
if (false === $this->password()->equals($anOldPassword)) {
throw new UserPasswordInvalidException();
}
$this->password = $aNewPassword;
$this->password = $aPassword;
$this->rememberPasswordToken = null;
}

Expand Down Expand Up @@ -227,7 +222,7 @@ public function grant(UserRole $aRole)
*/
public function isEnabled()
{
return null === $this->confirmationToken;
return null === $this->confirmationToken || null === $this->confirmationToken->token();
}

/**
Expand Down
7 changes: 4 additions & 3 deletions src/BenGor/User/Domain/Model/UserPassword.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,14 @@ public static function fromPlain($aPlainPassword, UserPasswordEncoder $anEncoder
/**
* Method that checks if the password given is equal to the current.
*
* @param UserPassword $aUserPassword A user password
* @param string $aPlainPassword The plain password
* @param UserPasswordEncoder $anEncoder The encoder
*
* @return bool
*/
public function equals(UserPassword $aUserPassword)
public function equals($aPlainPassword, UserPasswordEncoder $anEncoder)
{
return $this->encodedPassword === $aUserPassword->encodedPassword;
return $anEncoder->isPasswordValid($this, $aPlainPassword);
}

/**
Expand Down
15 changes: 12 additions & 3 deletions src/BenGor/User/Domain/Model/UserPasswordEncoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,22 @@
interface UserPasswordEncoder
{
/**
* Encodes the given plain password with
* salt given returning the encoded password.
* Encodes the plain password.
*
* @param string $aPlainPassword The plain password
* @param string $aPlainPassword A plain password
* @param string $aSalt The salt
*
* @return string
*/
public function encode($aPlainPassword, $aSalt);

/**
* Checks a raw password against an encoded password.
*
* @param UserPassword $anEncoded An encoded domain password
* @param string $aPlainPassword A plain password
*
* @return bool
*/
public function isPasswordValid(UserPassword $anEncoded, $aPlainPassword);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

namespace BenGor\User\Infrastructure\Security\Symfony;

use BenGor\User\Domain\Model\UserPassword;
use BenGor\User\Domain\Model\UserPasswordEncoder;
use Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface;

Expand Down Expand Up @@ -45,12 +46,18 @@ public function __construct(PasswordEncoderInterface $aPasswordEncoder)
*/
public function encode($aPlainPassword, $aSalt)
{
$encodedPassword = $this->passwordEncoder->encodePassword($aPlainPassword, $aSalt);

if (false === $this->passwordEncoder->isPasswordValid($encodedPassword, $aPlainPassword, $aSalt)) {
throw new \Exception('The password is invalid');
}
return $this->passwordEncoder->encodePassword($aPlainPassword, $aSalt);
}

return $encodedPassword;
/**
* {@inheritdoc}
*/
public function isPasswordValid(UserPassword $anEncoded, $aPlainPassword)
{
return $this->passwordEncoder->isPasswordValid(
$anEncoded->encodedPassword(),
$aPlainPassword,
$anEncoded->salt()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

namespace BenGor\User\Infrastructure\Security\Test;

use BenGor\User\Domain\Model\UserPassword;
use BenGor\User\Domain\Model\UserPasswordEncoder;

/**
Expand All @@ -29,14 +30,23 @@ final class DummyUserPasswordEncoder implements UserPasswordEncoder
*/
private $expectedResponse;

/**
* Is password valid boolean.
*
* @var bool
*/
private $isPasswordValid;

/**
* Constructor.
*
* @param string $expectedResponse The expected response
* @param bool $isPasswordValid Is password valid boolean, by default is true
*/
public function __construct($expectedResponse)
public function __construct($expectedResponse, $isPasswordValid = true)
{
$this->expectedResponse = $expectedResponse;
$this->isPasswordValid = $isPasswordValid;
}

/**
Expand All @@ -46,4 +56,12 @@ public function encode($aPlainPassword, $aSalt)
{
return $this->expectedResponse;
}

/**
* {@inheritdoc}
*/
public function isPasswordValid(UserPassword $anEncoded, $aPlainPassword)
{
return $this->isPasswordValid;
}
}

0 comments on commit 3a5cd2e

Please sign in to comment.