From f83840f12e92bbea1380d58bd1cbdef1b22f7b59 Mon Sep 17 00:00:00 2001 From: Kevin Kaniaburka Date: Thu, 17 Mar 2022 10:56:58 +0100 Subject: [PATCH 1/2] [Maintenance][API] Decouple resource metadata from ResetPasswordHandler --- .../Account/ResetPasswordHandler.php | 8 ++-- .../config/services/command_handlers.xml | 7 +-- .../Account/ResetPasswordHandlerSpec.php | 10 +--- .../SyliusUserExtension.php | 13 +++++ .../SyliusUserExtensionTest.php | 48 +++++++++++++++++++ 5 files changed, 66 insertions(+), 20 deletions(-) diff --git a/src/Sylius/Bundle/ApiBundle/CommandHandler/Account/ResetPasswordHandler.php b/src/Sylius/Bundle/ApiBundle/CommandHandler/Account/ResetPasswordHandler.php index e0c9bca824b..47aa0c61a62 100644 --- a/src/Sylius/Bundle/ApiBundle/CommandHandler/Account/ResetPasswordHandler.php +++ b/src/Sylius/Bundle/ApiBundle/CommandHandler/Account/ResetPasswordHandler.php @@ -15,7 +15,6 @@ use Sylius\Bundle\ApiBundle\Command\Account\ResetPassword; use Sylius\Component\Core\Model\ShopUserInterface; -use Sylius\Component\Resource\Metadata\MetadataInterface; use Sylius\Component\User\Repository\UserRepositoryInterface; use Sylius\Component\User\Security\PasswordUpdaterInterface; use Symfony\Component\Messenger\Handler\MessageHandlerInterface; @@ -26,8 +25,8 @@ final class ResetPasswordHandler implements MessageHandlerInterface { public function __construct( private UserRepositoryInterface $userRepository, - private MetadataInterface $metadata, - private PasswordUpdaterInterface $passwordUpdater + private PasswordUpdaterInterface $passwordUpdater, + private string $tokenTtl ) { } @@ -38,8 +37,7 @@ public function __invoke(ResetPassword $command): void Assert::notNull($user, 'No user found with reset token: ' . $command->resetPasswordToken); - $resetting = $this->metadata->getParameter('resetting'); - $lifetime = new \DateInterval($resetting['token']['ttl']); + $lifetime = new \DateInterval($this->tokenTtl); if (!$user->isPasswordRequestNonExpired($lifetime)) { throw new \InvalidArgumentException('Password reset token has expired'); diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/services/command_handlers.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/services/command_handlers.xml index c3c5ae8d3e3..9cfd4bbe87a 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/services/command_handlers.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/services/command_handlers.xml @@ -160,13 +160,8 @@ - - - - sylius.shop_user - - + %sylius.shop_user.token.password_reset.ttl% diff --git a/src/Sylius/Bundle/ApiBundle/spec/CommandHandler/Account/ResetPasswordHandlerSpec.php b/src/Sylius/Bundle/ApiBundle/spec/CommandHandler/Account/ResetPasswordHandlerSpec.php index ad672fecd5b..5b28c17f2db 100644 --- a/src/Sylius/Bundle/ApiBundle/spec/CommandHandler/Account/ResetPasswordHandlerSpec.php +++ b/src/Sylius/Bundle/ApiBundle/spec/CommandHandler/Account/ResetPasswordHandlerSpec.php @@ -17,7 +17,6 @@ use Prophecy\Argument; use Sylius\Bundle\ApiBundle\Command\Account\ResetPassword; use Sylius\Component\Core\Model\ShopUserInterface; -use Sylius\Component\Resource\Metadata\MetadataInterface; use Sylius\Component\User\Repository\UserRepositoryInterface; use Sylius\Component\User\Security\PasswordUpdaterInterface; use Symfony\Component\Messenger\Handler\MessageHandlerInterface; @@ -26,10 +25,9 @@ final class ResetPasswordHandlerSpec extends ObjectBehavior { function let( UserRepositoryInterface $userRepository, - MetadataInterface $metadata, PasswordUpdaterInterface $passwordUpdater ): void { - $this->beConstructedWith($userRepository, $metadata, $passwordUpdater); + $this->beConstructedWith($userRepository, $passwordUpdater, 'P5D'); } function it_is_a_message_handler(): void @@ -40,11 +38,9 @@ function it_is_a_message_handler(): void function it_resets_password( UserRepositoryInterface $userRepository, ShopUserInterface $shopUser, - MetadataInterface $metadata, PasswordUpdaterInterface $passwordUpdater ): void { $userRepository->findOneBy(['passwordResetToken' => 'TOKEN'])->willReturn($shopUser); - $metadata->getParameter('resetting')->willReturn(['token' => ['ttl' => 'P5D']]); $shopUser->isPasswordRequestNonExpired(Argument::that(function (\DateInterval $dateInterval) { return $dateInterval->format('%d') === '5'; @@ -66,11 +62,9 @@ function it_resets_password( function it_throws_exception_if_token_is_expired( UserRepositoryInterface $userRepository, ShopUserInterface $shopUser, - MetadataInterface $metadata, PasswordUpdaterInterface $passwordUpdater ): void { $userRepository->findOneBy(['passwordResetToken' => 'TOKEN'])->willReturn($shopUser); - $metadata->getParameter('resetting')->willReturn(['token' => ['ttl' => 'P5D']]); $shopUser->isPasswordRequestNonExpired(Argument::that(function (\DateInterval $dateInterval) { return $dateInterval->format('%d') === '5'; @@ -93,11 +87,9 @@ function it_throws_exception_if_token_is_expired( function it_throws_exception_if_tokens_are_not_exact( UserRepositoryInterface $userRepository, ShopUserInterface $shopUser, - MetadataInterface $metadata, PasswordUpdaterInterface $passwordUpdater ): void { $userRepository->findOneBy(['passwordResetToken' => 'TOKEN'])->willReturn($shopUser); - $metadata->getParameter('resetting')->willReturn(['token' => ['ttl' => 'P5D']]); $shopUser->isPasswordRequestNonExpired(Argument::that(function (\DateInterval $dateInterval) { return $dateInterval->format('%d') === '5'; diff --git a/src/Sylius/Bundle/UserBundle/DependencyInjection/SyliusUserExtension.php b/src/Sylius/Bundle/UserBundle/DependencyInjection/SyliusUserExtension.php index 3543592f1e6..f215bb35930 100644 --- a/src/Sylius/Bundle/UserBundle/DependencyInjection/SyliusUserExtension.php +++ b/src/Sylius/Bundle/UserBundle/DependencyInjection/SyliusUserExtension.php @@ -48,6 +48,7 @@ public function load(array $configs, ContainerBuilder $container): void $loader->load('services.xml'); + $this->createParameters($config['resources'], $container); $this->createServices($config['resources'], $container); $this->loadEncodersAwareServices($config['encoder'], $config['resources'], $container); } @@ -81,6 +82,13 @@ private function createServices(array $resources, ContainerBuilder $container): } } + private function createParameters(array $resources, ContainerBuilder $container): void + { + foreach ($resources as $userType => $config) { + $this->createResettingTokenParameters($userType, $config['user'], $container); + } + } + private function loadEncodersAwareServices(?string $globalEncoder, array $resources, ContainerBuilder $container): void { foreach ($resources as $userType => $config) { @@ -274,4 +282,9 @@ private function registerUpdateUserEncoderListener(ContainerBuilder $container, $updateUserEncoderListenerDefinition ); } + + private function createResettingTokenParameters(string $userType, array $config, ContainerBuilder $container) + { + $container->setParameter(sprintf('sylius.%s_user.token.password_reset.ttl', $userType), $config['resetting']['token']['ttl']); + } } diff --git a/src/Sylius/Bundle/UserBundle/Tests/DependencyInjection/SyliusUserExtensionTest.php b/src/Sylius/Bundle/UserBundle/Tests/DependencyInjection/SyliusUserExtensionTest.php index 72c8b7eeaca..df3c1df5728 100644 --- a/src/Sylius/Bundle/UserBundle/Tests/DependencyInjection/SyliusUserExtensionTest.php +++ b/src/Sylius/Bundle/UserBundle/Tests/DependencyInjection/SyliusUserExtensionTest.php @@ -133,6 +133,54 @@ public function it_creates_a_update_user_encoder_listener_for_each_user_type(): Assert::assertSame('_password', $shopUserListenerDefinition->getArgument(4)); } + /** @test */ + public function it_creates_default_resetting_token_parameters_for_each_user_type(): void + { + $this->load([ + 'resources' => [ + 'admin' => [ + 'user' => [], + ], + 'shop' => [ + 'user' => [], + ], + ], + ]); + + Assert::assertSame('P1D', $this->container->getParameter('sylius.admin_user.token.password_reset.ttl')); + Assert::assertSame('P1D', $this->container->getParameter('sylius.shop_user.token.password_reset.ttl')); + } + + /** @test */ + public function it_creates_custom_resetting_token_parameters_for_each_user_type(): void + { + $this->load([ + 'resources' => [ + 'admin' => [ + 'user' => [ + 'resetting' => [ + 'token' => [ + 'ttl' => 'P5D', + ], + ], + ], + ], + 'shop' => [ + 'user' => [ + 'resetting' => [ + 'token' => [ + 'ttl' => 'P2D', + ], + ], + ], + ], + ], + ]); + + Assert::assertSame('P5D', $this->container->getParameter('sylius.admin_user.token.password_reset.ttl')); + Assert::assertSame('P2D', $this->container->getParameter('sylius.shop_user.token.password_reset.ttl')); + } + protected function getContainerExtensions(): array { return [ From c343e28265d67cba90629bb407ca5018fa7d8623 Mon Sep 17 00:00:00 2001 From: Kevin Kaniaburka Date: Thu, 17 Mar 2022 13:45:58 +0100 Subject: [PATCH 2/2] [Maintenance][API] Update UPGRADE-API-1.12.md --- UPGRADE-API-1.12.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/UPGRADE-API-1.12.md b/UPGRADE-API-1.12.md index a36464d00a1..8804b1600de 100644 --- a/UPGRADE-API-1.12.md +++ b/UPGRADE-API-1.12.md @@ -69,3 +69,5 @@ Here is how the response looks like: 1. The `GET` `api/v2/shop/orders/{tokenValue}/payments/{payments}/methods` and `api/v2/shop/payments/{id}/methods` endpoints have been removed and changed into collection request with 2 parameters `api/v2/shop/payment-methods?paymentId={id}&orderToken={token}`. Now when we do not provide parameters in response it returns all available `paymentMethods` in channel. Wrong parameters otherwise cause empty array `[]` in response and correct parameters return `paymentMethods` available for your `payment`. + +1. The 2nd parameter `MetadataInterface` has been removed from `src/Sylius/Bundle/ApiBundle/CommandHandler/Account/ResetPasswordHandler` and a token TTL value must be used instead as the 3rd parameter.