Skip to content

Commit

Permalink
fix #37, allow resending an unexpired token (#41)
Browse files Browse the repository at this point in the history
  • Loading branch information
gorghoa authored and vincentchalamon committed Jul 5, 2018
1 parent c043b9e commit 65338d6
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 39 deletions.
25 changes: 0 additions & 25 deletions Exception/UnexpiredTokenHttpException.php

This file was deleted.

8 changes: 4 additions & 4 deletions Manager/ForgotPasswordManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

use CoopTilleuls\ForgotPasswordBundle\Entity\AbstractPasswordToken;
use CoopTilleuls\ForgotPasswordBundle\Event\ForgotPasswordEvent;
use CoopTilleuls\ForgotPasswordBundle\Exception\UnexpiredTokenHttpException;
use CoopTilleuls\ForgotPasswordBundle\Exception\UserNotFoundHttpException;
use CoopTilleuls\ForgotPasswordBundle\Manager\Bridge\ManagerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
Expand Down Expand Up @@ -61,15 +60,16 @@ public function resetPassword($username)
}

$token = $this->passwordTokenManager->findOneByUser($user);

// A token already exists and has not expired
if (null !== $token && !$token->isExpired()) {
throw new UnexpiredTokenHttpException();
if (null === $token || $token->isExpired()) {
$token = $this->passwordTokenManager->createPasswordToken($user);
}

// Generate password token
$this->dispatcher->dispatch(
ForgotPasswordEvent::CREATE_TOKEN,
new ForgotPasswordEvent($this->passwordTokenManager->createPasswordToken($user))
new ForgotPasswordEvent($token)
);
}

Expand Down
4 changes: 2 additions & 2 deletions features/forgotPassword.feature
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ Feature: I need to be able to reset my password
When I reset my password
Then I should receive an email

Scenario: I can't reset my password if I already request a token
Scenario: I can reset my password even if I have already requested a token and this token has not expired yet
Given I have a valid token
When I reset my password
Then the request should be invalid with message 'An unexpired token already exists for this user.'
Then I should receive an email

Scenario: I can reset my password if I already request a token but it has expired
Given I have an expired token
Expand Down
42 changes: 34 additions & 8 deletions tests/Manager/ForgotPasswordManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,20 +65,21 @@ public function testResetPasswordUserNotFoundHttpException()
$this->manager->resetPassword('[email protected]');
}

/**
* @expectedException \CoopTilleuls\ForgotPasswordBundle\Exception\UnexpiredTokenHttpException
* @expectedExceptionMessage An unexpired token already exists for this user.
*/
public function testResetPasswordUnexpiredTokenHttpException()
public function testResetPasswordWithNoPreviousToken()
{
$tokenMock = $this->prophesize(AbstractPasswordToken::class);

$this->managerMock->findOneBy('App\Entity\User', ['email' => '[email protected]'])->willReturn($this->userMock->reveal())->shouldBeCalledTimes(1);
$this->passwordManagerMock->findOneByUser($this->userMock->reveal())->willReturn($this->tokenMock->reveal())->shouldBeCalledTimes(1);
$this->tokenMock->isExpired()->willReturn(false)->shouldBeCalledTimes(1);
$this->passwordManagerMock->findOneByUser($this->userMock->reveal())->willReturn(null)->shouldBeCalledTimes(1);
$this->passwordManagerMock->createPasswordToken($this->userMock->reveal())->willReturn($tokenMock->reveal())->shouldBeCalledTimes(1);
$this->eventDispatcherMock->dispatch(ForgotPasswordEvent::CREATE_TOKEN, Argument::that(function ($event) use ($tokenMock) {
return $event instanceof ForgotPasswordEvent && is_null($event->getPassword()) && $tokenMock->reveal() === $event->getPasswordToken();
}))->shouldBeCalledTimes(1);

$this->manager->resetPassword('[email protected]');
}

public function testResetPassword()
public function testResetPasswordWithExpiredPreviousToken()
{
$tokenMock = $this->prophesize(AbstractPasswordToken::class);

Expand All @@ -93,6 +94,31 @@ public function testResetPassword()
$this->manager->resetPassword('[email protected]');
}

/**
* @see https://github.com/coopTilleuls/CoopTilleulsForgotPasswordBundle/issues/37
*/
public function testResetPasswordWithUnexpiredTokenHttp()
{
$tokenMock = $this->prophesize(AbstractPasswordToken::class);

$tokenMock
->isExpired()
->willReturn(false)
->shouldBeCalledTimes(1)
;

$token = $tokenMock->reveal();

$this->managerMock->findOneBy('App\Entity\User', ['email' => '[email protected]'])->willReturn($this->userMock->reveal())->shouldBeCalledTimes(1);
$this->passwordManagerMock->findOneByUser($this->userMock->reveal())->willReturn($token)->shouldBeCalledTimes(1);

$this->eventDispatcherMock->dispatch(ForgotPasswordEvent::CREATE_TOKEN, Argument::that(function ($event) use ($token) {
return $event instanceof ForgotPasswordEvent && is_null($event->getPassword()) && $token === $event->getPasswordToken();
}))->shouldBeCalledTimes(1);

$this->manager->resetPassword('[email protected]');
}

public function testUpdatePassword()
{
$token = $this->tokenMock->reveal();
Expand Down

0 comments on commit 65338d6

Please sign in to comment.