Skip to content

Commit 73d55cf

Browse files
committed
feature #143 helper methods for storing ResetPasswordToken in session (jrushlow)
This PR was squashed before being merged into the master branch. Discussion ---------- helper methods for storing ResetPasswordToken in session It is more desireable to store the `ResetPasswordToken::class` object in the session after it has been generated by the helper vs storing individual properties of the token class in the session. Adds the following `ResetPasswordControllerTrait::class` methods: - `setTokenObjectInSession(ResetPasswordToken $token): void` - `getTokenObjectFromSession(): ?ResetPasswordToken` Deprecates the following `ResetPasswordControllerTrait:class` methods: - `setCanCheckEmailInSession()` - `canCheckEmail()` These will be removed in version `2.0` of this bundle. refs #142 Commits ------- ebbb9ef helper methods for storing ResetPasswordToken in session
2 parents 7de0693 + ebbb9ef commit 73d55cf

File tree

5 files changed

+112
-3
lines changed

5 files changed

+112
-3
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ find a change that break's semver, please create an issue.*
55

66
## NEXT
77

8+
- [#143](https://github.com/SymfonyCasts/reset-password-bundle/pull/143) Adds controller trait methods to set/get the
9+
`ResetPasswordToken::class` object in the session. The following `ResetPasswordControllerTrait::class` methods have been deprecated:
10+
`setCanCheckEmailInSession()`, `canCheckEmail()`
11+
812
## v1.2.2
913

1014
- [#139](https://github.com/SymfonyCasts/reset-password-bundle/pull/139) Fixed regression

src/Controller/ResetPasswordControllerTrait.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
use Symfony\Component\HttpFoundation\Request;
1313
use Symfony\Component\HttpFoundation\Session\SessionInterface;
14+
use SymfonyCasts\Bundle\ResetPassword\Model\ResetPasswordToken;
1415

1516
/**
1617
* Provides useful methods to a "reset password controller".
@@ -23,13 +24,31 @@
2324
*/
2425
trait ResetPasswordControllerTrait
2526
{
27+
/**
28+
* @deprecated since 1.3.0, use ResetPasswordControllerTrait::setTokenObjectInSession() instead.
29+
*/
2630
private function setCanCheckEmailInSession(): void
2731
{
32+
trigger_deprecation(
33+
'symfonycasts/reset-password-bundle',
34+
'1.3.0',
35+
'Storing the ResetPasswordToken object in the session is more desirable, use ResetPasswordControllerTrait::setTokenObjectInSession() instead.'
36+
);
37+
2838
$this->getSessionService()->set('ResetPasswordCheckEmail', true);
2939
}
3040

41+
/**
42+
* @deprecated since 1.3.0, use ResetPasswordControllerTrait::getTokenObjectFromSession() instead.
43+
*/
3144
private function canCheckEmail(): bool
3245
{
46+
trigger_deprecation(
47+
'symfonycasts/reset-password-bundle',
48+
'1.3.0',
49+
'Storing the ResetPasswordToken object in the session is more desirable, use ResetPasswordControllerTrait::getTokenObjectFromSession() instead.'
50+
);
51+
3352
return $this->getSessionService()->has('ResetPasswordCheckEmail');
3453
}
3554

@@ -43,12 +62,25 @@ private function getTokenFromSession(): ?string
4362
return $this->getSessionService()->get('ResetPasswordPublicToken');
4463
}
4564

65+
private function setTokenObjectInSession(ResetPasswordToken $token): void
66+
{
67+
$token->clearToken();
68+
69+
$this->getSessionService()->set('ResetPasswordToken', $token);
70+
}
71+
72+
private function getTokenObjectFromSession(): ?ResetPasswordToken
73+
{
74+
return $this->getSessionService()->get('ResetPasswordToken');
75+
}
76+
4677
private function cleanSessionAfterReset(): void
4778
{
4879
$session = $this->getSessionService();
4980

5081
$session->remove('ResetPasswordPublicToken');
5182
$session->remove('ResetPasswordCheckEmail');
83+
$session->remove('ResetPasswordToken');
5284
}
5385

5486
private function getSessionService(): SessionInterface

src/Model/ResetPasswordToken.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
final class ResetPasswordToken
1717
{
1818
/**
19-
* @var string selector + non-hashed verifier token
19+
* @var string|null selector + non-hashed verifier token
2020
*/
2121
private $token;
2222

@@ -55,9 +55,21 @@ public function __construct(string $token, \DateTimeInterface $expiresAt, int $g
5555
*/
5656
public function getToken(): string
5757
{
58+
if (null === $this->token) {
59+
throw new \RuntimeException('The token property is not set. Calling getToken() after calling clearToken() is not allowed.');
60+
}
61+
5862
return $this->token;
5963
}
6064

65+
/**
66+
* Allow the token object to be safely persisted in a session.
67+
*/
68+
public function clearToken(): void
69+
{
70+
$this->token = null;
71+
}
72+
6173
public function getExpiresAt(): \DateTimeInterface
6274
{
6375
return $this->expiresAt;

tests/UnitTests/Controller/ResetPasswordControllerTraitTest.php

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Symfony\Component\HttpFoundation\RequestStack;
1717
use Symfony\Component\HttpFoundation\Session\SessionInterface;
1818
use SymfonyCasts\Bundle\ResetPassword\Controller\ResetPasswordControllerTrait;
19+
use SymfonyCasts\Bundle\ResetPassword\Model\ResetPasswordToken;
1920

2021
/**
2122
* @author Jesse Rushlow <jr@rushlow.dev>
@@ -25,6 +26,7 @@ class ResetPasswordControllerTraitTest extends TestCase
2526
{
2627
private const EMAIL_KEY = 'ResetPasswordCheckEmail';
2728
private const TOKEN_KEY = 'ResetPasswordPublicToken';
29+
private const TOKEN_OBJECT_KEY = 'ResetPasswordToken';
2830

2931
/**
3032
* @var MockObject|SessionInterface
@@ -64,6 +66,9 @@ public function testGetsTokenFromSession(): void
6466
$fixture->getToken();
6567
}
6668

69+
/**
70+
* @group legacy
71+
*/
6772
public function testSetsEmailFlagInSession(): void
6873
{
6974
$this->mockSession
@@ -76,6 +81,9 @@ public function testSetsEmailFlagInSession(): void
7681
$fixture->setEmail();
7782
}
7883

84+
/**
85+
* @group legacy
86+
*/
7987
public function testCanCheckEmailUsesCorrectKey(): void
8088
{
8189
$this->mockSession
@@ -89,12 +97,43 @@ public function testCanCheckEmailUsesCorrectKey(): void
8997
$fixture->getEmail();
9098
}
9199

100+
public function testSetsResetTokenInSession(): void
101+
{
102+
$token = new ResetPasswordToken('1234', new \DateTimeImmutable(), 1234);
103+
104+
$this->mockSession
105+
->expects($this->once())
106+
->method('set')
107+
->with(self::TOKEN_OBJECT_KEY, $token)
108+
;
109+
110+
$fixture = $this->getFixture();
111+
$fixture->storeResetPasswordToken($token);
112+
}
113+
114+
public function testGetsResetTokenFromSession(): void
115+
{
116+
$token = new ResetPasswordToken('1234', new \DateTimeImmutable(), 1234);
117+
118+
$this->mockSession
119+
->expects($this->once())
120+
->method('get')
121+
->with(self::TOKEN_OBJECT_KEY)
122+
->willReturn($token)
123+
;
124+
125+
$fixture = $this->getFixture();
126+
$result = $fixture->getResetPasswordToken();
127+
128+
self::assertSame($token, $result);
129+
}
130+
92131
public function testCleanSessionAfterServiceRemovesByTokenAndEmailKeys(): void
93132
{
94133
$this->mockSession
95-
->expects($this->exactly(2))
134+
->expects($this->exactly(3))
96135
->method('remove')
97-
->withConsecutive([self::TOKEN_KEY], [self::EMAIL_KEY])
136+
->withConsecutive([self::TOKEN_KEY], [self::EMAIL_KEY], [self::TOKEN_OBJECT_KEY])
98137
;
99138

100139
$fixture = $this->getFixture();
@@ -165,6 +204,16 @@ public function getToken(): string
165204
return $this->getTokenFromSession();
166205
}
167206

207+
public function storeResetPasswordToken(ResetPasswordToken $token): void
208+
{
209+
$this->setTokenObjectInSession($token);
210+
}
211+
212+
public function getResetPasswordToken(): ?ResetPasswordToken
213+
{
214+
return $this->getTokenObjectFromSession();
215+
}
216+
168217
public function clearSession(): void
169218
{
170219
$this->cleanSessionAfterReset();

tests/UnitTests/Model/ResetPasswordTokenTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,18 @@
1717
*/
1818
class ResetPasswordTokenTest extends TestCase
1919
{
20+
public function testTokenValueIsSafeForStorage(): void
21+
{
22+
$token = new ResetPasswordToken('1234', new \DateTimeImmutable(), \time());
23+
24+
$token->clearToken();
25+
26+
$this->expectException(\RuntimeException::class);
27+
$this->expectExceptionMessage('The token property is not set. Calling getToken() after calling clearToken() is not allowed.');
28+
29+
self::assertSame('void', $token->getToken());
30+
}
31+
2032
/**
2133
* @dataProvider translationIntervalDataProvider
2234
*/

0 commit comments

Comments
 (0)