From 0b40650ed2d3b5626f1cb010c5d47260022790ed Mon Sep 17 00:00:00 2001 From: Vincent Chalamon <407859+vincentchalamon@users.noreply.github.com> Date: Thu, 23 May 2024 11:25:11 +0200 Subject: [PATCH] feat: introduce TokenGenerator --- config/services.xml | 2 ++ docs/index.md | 8 +++++ docs/use_custom_token_generator.md | 36 +++++++++++++++++++ src/DependencyInjection/Configuration.php | 5 +++ src/Manager/PasswordTokenManager.php | 5 +-- .../Bridge/Bin2HexTokenGenerator.php | 24 +++++++++++++ .../TokenGeneratorInterface.php | 22 ++++++++++++ 7 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 docs/use_custom_token_generator.md create mode 100644 src/TokenGenerator/Bridge/Bin2HexTokenGenerator.php create mode 100644 src/TokenGenerator/TokenGeneratorInterface.php diff --git a/config/services.xml b/config/services.xml index 6cdc5dc..9dfb3d3 100644 --- a/config/services.xml +++ b/config/services.xml @@ -36,6 +36,8 @@ + + diff --git a/docs/index.md b/docs/index.md index 5170941..502d421 100644 --- a/docs/index.md +++ b/docs/index.md @@ -324,3 +324,11 @@ Read full documentation about [usage](usage.md). By default, this bundle works with Doctrine ORM, but you're free to connect with any system. Read full documentation about [how to connect your manager](use_custom_manager.md). + +## Generate your own token + +By default, this bundle works uses [`bin2hex`](https://www.php.net/bin2hex) combined with +[`random_bytes`](https://www.php.net/random_bytes) to generate the token, but you're free to create your own +TokenGenerator to create your token. + +Read full documentation about [how to generate your own token](use_custom_token_generator.md). diff --git a/docs/use_custom_token_generator.md b/docs/use_custom_token_generator.md new file mode 100644 index 0000000..708c869 --- /dev/null +++ b/docs/use_custom_token_generator.md @@ -0,0 +1,36 @@ +# Use custom token generator + +By default, this bundle works uses [`bin2hex`](https://www.php.net/bin2hex) combined with +[`random_bytes`](https://www.php.net/random_bytes) to generate the token, but you're free to create your own +TokenGenerator to create your token. + +## Create your custom token generator + +Supposing you want to generate your own token, you'll have to create a service that will implement +`CoopTilleuls\ForgotPasswordBundle\TokenGenerator\TokenGeneratorInterface`: + +```php +// src/TokenGenerator/FooTokenGenerator.php +namespace App\TokenGenerator; + +use CoopTilleuls\ForgotPasswordBundle\TokenGenerator\TokenGeneratorInterface; + +final class FooTokenGenerator implements TokenGeneratorInterface +{ + public function generate(): string + { + // generate your own token and return it as string + } +} +``` + +## Update configuration + +Update your configuration to set your service as default one to use by this bundle: + +```yaml +# config/packages/coop_tilleuls_forgot_password.yaml +coop_tilleuls_forgot_password: + # ... + token_generator: 'App\TokenGenerator\FooTokenGenerator' +``` diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index c67e5cf..177e2dd 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -134,6 +134,11 @@ public function getConfigTreeBuilder(): TreeBuilder ->booleanNode('use_jms_serializer') ->defaultFalse() ->end() + ->scalarNode('token_generator') + ->defaultValue('coop_tilleuls_forgot_password.token_generator.bin2hex') + ->cannotBeEmpty() + ->info('Persistence manager service to handle the token storage.') + ->end() ->end(); return $treeBuilder; diff --git a/src/Manager/PasswordTokenManager.php b/src/Manager/PasswordTokenManager.php index 1709ace..258c3ff 100644 --- a/src/Manager/PasswordTokenManager.php +++ b/src/Manager/PasswordTokenManager.php @@ -17,13 +17,14 @@ use CoopTilleuls\ForgotPasswordBundle\Provider\Provider; use CoopTilleuls\ForgotPasswordBundle\Provider\ProviderChainInterface; use CoopTilleuls\ForgotPasswordBundle\Provider\ProviderInterface; +use CoopTilleuls\ForgotPasswordBundle\TokenGenerator\TokenGeneratorInterface; /** * @author Vincent CHALAMON */ class PasswordTokenManager { - public function __construct(private readonly ProviderChainInterface $providerChain) + public function __construct(private readonly ProviderChainInterface $providerChain, private readonly TokenGeneratorInterface $tokenGenerator) { } @@ -47,7 +48,7 @@ public function createPasswordToken($user, ?\DateTime $expiresAt = null, ?Provid /** @var AbstractPasswordToken $passwordToken */ $passwordToken = new $tokenClass(); - $passwordToken->setToken(bin2hex(random_bytes(25))); + $passwordToken->setToken($this->tokenGenerator->generate()); $passwordToken->setUser($user); $passwordToken->setExpiresAt($expiresAt); $provider->getManager()->persist($passwordToken); diff --git a/src/TokenGenerator/Bridge/Bin2HexTokenGenerator.php b/src/TokenGenerator/Bridge/Bin2HexTokenGenerator.php new file mode 100644 index 0000000..a1d9fa4 --- /dev/null +++ b/src/TokenGenerator/Bridge/Bin2HexTokenGenerator.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace CoopTilleuls\ForgotPasswordBundle\TokenGenerator\Bridge; + +use CoopTilleuls\ForgotPasswordBundle\TokenGenerator\TokenGeneratorInterface; + +final class Bin2HexTokenGenerator implements TokenGeneratorInterface +{ + public function generate(): string + { + return bin2hex(random_bytes(25)); + } +} diff --git a/src/TokenGenerator/TokenGeneratorInterface.php b/src/TokenGenerator/TokenGeneratorInterface.php new file mode 100644 index 0000000..79da083 --- /dev/null +++ b/src/TokenGenerator/TokenGeneratorInterface.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace CoopTilleuls\ForgotPasswordBundle\TokenGenerator; + +/** + * @author Vincent CHALAMON + */ +interface TokenGeneratorInterface +{ + public function generate(): string; +}