From 0ce0173c662ea2c697affd835c32929ea30ef458 Mon Sep 17 00:00:00 2001 From: arti0090 Date: Wed, 17 Feb 2021 08:56:03 +0100 Subject: [PATCH 01/15] [API] Password reset --- features/account/resetting_password.feature | 2 +- .../Client/ApiPlatformSecurityClient.php | 37 +++++++++++--- .../Client/ApiSecurityClientInterface.php | 8 +++ src/Sylius/Behat/Context/Api/EmailContext.php | 44 ++++++++++++++++ .../Behat/Context/Api/Shop/LoginContext.php | 26 ++++++++++ .../config/services/contexts/api.xml | 1 + .../config/services/contexts/api/email.xml | 22 ++++++++ .../config/suites/api/account/login.yml | 6 +++ .../Command/LocaleCodeAwareInterface.php | 12 +++++ .../Command/ResetPasswordRequest.php | 47 +++++++++++++++++ .../Command/SendResetPasswordEmail.php | 42 +++++++++++++++ .../ResetPasswordRequestHandler.php | 51 +++++++++++++++++++ .../SendResetPasswordEmailHandler.php | 49 ++++++++++++++++++ ...leCodeAwareInputCommandDataTransformer.php | 34 +++++++++++++ .../Event/ResetPasswordRequested.php | 42 +++++++++++++++ .../ResetPasswordRequestedHandler.php | 31 +++++++++++ .../config/api_resources/ShopUser.xml | 45 ++++++++++++++++ .../ApiBundle/Resources/config/services.xml | 5 ++ .../config/services/command_handlers.xml | 14 +++++ .../config/services/event_handlers.xml | 5 ++ .../Bundle/CoreBundle/Mailer/Emails.php | 2 + .../config/app/sylius/sylius_mailer.yml | 3 ++ .../views/Email/passwordReset.html.twig | 22 ++++++++ 23 files changed, 541 insertions(+), 9 deletions(-) create mode 100644 src/Sylius/Behat/Context/Api/EmailContext.php create mode 100644 src/Sylius/Behat/Resources/config/services/contexts/api/email.xml create mode 100644 src/Sylius/Bundle/ApiBundle/Command/LocaleCodeAwareInterface.php create mode 100644 src/Sylius/Bundle/ApiBundle/Command/ResetPasswordRequest.php create mode 100644 src/Sylius/Bundle/ApiBundle/Command/SendResetPasswordEmail.php create mode 100644 src/Sylius/Bundle/ApiBundle/CommandHandler/ResetPasswordRequestHandler.php create mode 100644 src/Sylius/Bundle/ApiBundle/CommandHandler/SendResetPasswordEmailHandler.php create mode 100644 src/Sylius/Bundle/ApiBundle/DataTransformer/LocaleCodeAwareInputCommandDataTransformer.php create mode 100644 src/Sylius/Bundle/ApiBundle/Event/ResetPasswordRequested.php create mode 100644 src/Sylius/Bundle/ApiBundle/EventHandler/ResetPasswordRequestedHandler.php create mode 100644 src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/ShopUser.xml create mode 100644 src/Sylius/Bundle/CoreBundle/Resources/views/Email/passwordReset.html.twig diff --git a/features/account/resetting_password.feature b/features/account/resetting_password.feature index e381cd3c31f..6d816bcc227 100644 --- a/features/account/resetting_password.feature +++ b/features/account/resetting_password.feature @@ -9,7 +9,7 @@ Feature: Resetting a password And that channel allows to shop using "English (United States)" and "Polish (Poland)" locales And there is a user "goodman@example.com" identified by "heisenberg" - @ui @email + @ui @email @api Scenario: Resetting an account password When I want to reset password And I specify the email as "goodman@example.com" diff --git a/src/Sylius/Behat/Client/ApiPlatformSecurityClient.php b/src/Sylius/Behat/Client/ApiPlatformSecurityClient.php index a08f5a42970..6a4f7540792 100644 --- a/src/Sylius/Behat/Client/ApiPlatformSecurityClient.php +++ b/src/Sylius/Behat/Client/ApiPlatformSecurityClient.php @@ -44,6 +44,12 @@ public function prepareLoginRequest(): void $this->request['method'] = 'POST'; } + public function preparePasswordResetRequest(): void + { + $this->request['url'] = sprintf('/api/v2/%s/password-reset-request', $this->section); + $this->request['method'] = 'POST'; + } + public function setEmail(string $email): void { $this->request['body']['email'] = $email; @@ -56,14 +62,7 @@ public function setPassword(string $password): void public function call(): void { - $this->client->request( - $this->request['method'], - $this->request['url'], - [], - [], - ['CONTENT_TYPE' => 'application/json', 'HTTP_ACCEPT' => 'application/json'], - json_encode($this->request['body']) - ); + $this->callRequest(); $response = $this->client->getResponse(); $content = json_decode($response->getContent(), true); @@ -97,4 +96,26 @@ public function logOut(): void $this->sharedStorage->set('cart_token', null); } } + + public function resetPassword(): void + { + $this->callRequest(); + } + + private function callRequest(): void + { + $this->client->request( + $this->request['method'], + $this->request['url'], + [], + [], + ['CONTENT_TYPE' => 'application/json', 'HTTP_ACCEPT' => 'application/json'], + json_encode($this->request['body']) + ); + } + + public function getLastResponse(): Response + { + return $this->client->getResponse(); + } } diff --git a/src/Sylius/Behat/Client/ApiSecurityClientInterface.php b/src/Sylius/Behat/Client/ApiSecurityClientInterface.php index d7d43f2b7bd..fac37d4de78 100644 --- a/src/Sylius/Behat/Client/ApiSecurityClientInterface.php +++ b/src/Sylius/Behat/Client/ApiSecurityClientInterface.php @@ -13,10 +13,14 @@ namespace Sylius\Behat\Client; +use Symfony\Component\HttpFoundation\Response; + interface ApiSecurityClientInterface { public function prepareLoginRequest(): void; + public function preparePasswordResetRequest(): void; + public function setEmail(string $email): void; public function setPassword(string $password): void; @@ -28,4 +32,8 @@ public function isLoggedIn(): bool; public function getErrorMessage(): string; public function logOut(): void; + + public function resetPassword(): void; + + public function getLastResponse(): Response; } diff --git a/src/Sylius/Behat/Context/Api/EmailContext.php b/src/Sylius/Behat/Context/Api/EmailContext.php new file mode 100644 index 00000000000..f142ec9d3c6 --- /dev/null +++ b/src/Sylius/Behat/Context/Api/EmailContext.php @@ -0,0 +1,44 @@ +emailChecker = $emailChecker; + $this->translator = $translator; + } + + /** + * @Then an email with reset token should be sent to :recipient + * @Then an email with reset token should be sent to :recipient in :localeCode locale + */ + public function anEmailWithResetTokenShouldBeSentTo(string $recipient, string $localeCode = 'en_US'): void + { + $this->assertEmailContainsMessageTo( + $this->translator->trans('sylius.email.password_reset.reset_your_password', [], null, $localeCode), + $recipient + ); + } + + private function assertEmailContainsMessageTo(string $message, string $recipient): void + { + Assert::true($this->emailChecker->hasMessageTo($message, $recipient)); + } +} diff --git a/src/Sylius/Behat/Context/Api/Shop/LoginContext.php b/src/Sylius/Behat/Context/Api/Shop/LoginContext.php index a8779db0e90..80a227ba144 100644 --- a/src/Sylius/Behat/Context/Api/Shop/LoginContext.php +++ b/src/Sylius/Behat/Context/Api/Shop/LoginContext.php @@ -43,8 +43,25 @@ public function iWantToLogIn(): void $this->client->prepareLoginRequest(); } + /** + * @When I want to reset password + */ + public function iWantToResetPassword(): void + { + $this->client->preparePasswordResetRequest(); + } + + /** + * @When I reset it + */ + public function iResetIt(): void + { + $this->client->resetPassword(); + } + /** * @When I specify the username as :username + * @When I specify the email as :username */ public function iSpecifyTheUsername(string $username): void { @@ -111,4 +128,13 @@ public function iShouldBeNotifiedAboutBadCredentials(): void { Assert::same($this->client->getErrorMessage(), 'Invalid credentials.'); } + + /** + * @Then I should be notified that email with reset instruction has been sent + */ + public function iShouldBeNotifiedThatEmailWithResetInstructionWasSent(): void + { + $response = $this->client->getLastResponse(); + Assert::same($response->getStatusCode(), 202); + } } diff --git a/src/Sylius/Behat/Resources/config/services/contexts/api.xml b/src/Sylius/Behat/Resources/config/services/contexts/api.xml index 2f013ad0ffe..8c4266275f9 100644 --- a/src/Sylius/Behat/Resources/config/services/contexts/api.xml +++ b/src/Sylius/Behat/Resources/config/services/contexts/api.xml @@ -18,5 +18,6 @@ + diff --git a/src/Sylius/Behat/Resources/config/services/contexts/api/email.xml b/src/Sylius/Behat/Resources/config/services/contexts/api/email.xml new file mode 100644 index 00000000000..c4a1f219ef1 --- /dev/null +++ b/src/Sylius/Behat/Resources/config/services/contexts/api/email.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + diff --git a/src/Sylius/Behat/Resources/config/suites/api/account/login.yml b/src/Sylius/Behat/Resources/config/suites/api/account/login.yml index d0eb5d0ed77..3c139f9c72e 100644 --- a/src/Sylius/Behat/Resources/config/suites/api/account/login.yml +++ b/src/Sylius/Behat/Resources/config/suites/api/account/login.yml @@ -6,13 +6,19 @@ default: api_customer_login: contexts: - sylius.behat.context.hook.doctrine_orm + - sylius.behat.context.hook.email_spool + - sylius.behat.context.transform.locale + - sylius.behat.context.transform.shared_storage - sylius.behat.context.transform.user - sylius.behat.context.setup.channel + - sylius.behat.context.setup.locale - sylius.behat.context.setup.user + - sylius.behat.context.api.email - sylius.behat.context.api.shop.login + filters: tags: "@customer_login && @api" diff --git a/src/Sylius/Bundle/ApiBundle/Command/LocaleCodeAwareInterface.php b/src/Sylius/Bundle/ApiBundle/Command/LocaleCodeAwareInterface.php new file mode 100644 index 00000000000..2599be8a758 --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/Command/LocaleCodeAwareInterface.php @@ -0,0 +1,12 @@ +email = $email; + } + + public function getEmail(): string + { + return $this->email; + } + + public function getChannelCode(): ?string + { + return $this->channelCode; + } + + public function setChannelCode(?string $channelCode): void + { + $this->channelCode = $channelCode; + } + + public function getLocaleCode(): ?string + { + return $this->localeCode; + } + + public function setLocaleCode(?string $localeCode): void + { + $this->localeCode = $localeCode; + } +} diff --git a/src/Sylius/Bundle/ApiBundle/Command/SendResetPasswordEmail.php b/src/Sylius/Bundle/ApiBundle/Command/SendResetPasswordEmail.php new file mode 100644 index 00000000000..1c0501b1168 --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/Command/SendResetPasswordEmail.php @@ -0,0 +1,42 @@ +email = $email; + $this->channelCode = $channelCode; + $this->localeCode = $localeCode; + } + + public function email(): string + { + return $this->email; + } + + public function channelCode(): string + { + return $this->channelCode; + } + + public function localeCode(): string + { + return $this->localeCode; + } +} diff --git a/src/Sylius/Bundle/ApiBundle/CommandHandler/ResetPasswordRequestHandler.php b/src/Sylius/Bundle/ApiBundle/CommandHandler/ResetPasswordRequestHandler.php new file mode 100644 index 00000000000..3d007110394 --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/CommandHandler/ResetPasswordRequestHandler.php @@ -0,0 +1,51 @@ +userRepository = $userRepository; + $this->eventBus = $eventBus; + $this->generator = $generator; + } + + public function __invoke(ResetPasswordRequest $command): void + { + $user = $this->userRepository->findOneByEmail($command->getEmail()); + Assert::notNull($user); + + $user->setPasswordResetToken($this->generator->generate()); + $user->setPasswordRequestedAt(new \DateTime()); + + $this->eventBus->dispatch( + new ResetPasswordRequested($command->getEmail(), $command->getChannelCode(), $command->getLocaleCode()), + [new DispatchAfterCurrentBusStamp() + ]); + + + } +} diff --git a/src/Sylius/Bundle/ApiBundle/CommandHandler/SendResetPasswordEmailHandler.php b/src/Sylius/Bundle/ApiBundle/CommandHandler/SendResetPasswordEmailHandler.php new file mode 100644 index 00000000000..7457d4a1a5e --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/CommandHandler/SendResetPasswordEmailHandler.php @@ -0,0 +1,49 @@ +emailSender = $emailSender; + $this->channelRepository = $channelRepository; + $this->userRepository = $userRepository; + } + + public function __invoke(SendResetPasswordEmail $command) + { + $user = $this->userRepository->findOneByEmail($command->email); + $channel = $this->channelRepository->findOneByCode($command->channelCode()); + + $this->emailSender->send( + Emails::PASSWORD_RESET, + [$command->email], + [ + 'user' => $user, + 'localeCode' => $command->localeCode(), + 'channel' => $channel + ] + ); + } +} diff --git a/src/Sylius/Bundle/ApiBundle/DataTransformer/LocaleCodeAwareInputCommandDataTransformer.php b/src/Sylius/Bundle/ApiBundle/DataTransformer/LocaleCodeAwareInputCommandDataTransformer.php new file mode 100644 index 00000000000..50c926bd168 --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/DataTransformer/LocaleCodeAwareInputCommandDataTransformer.php @@ -0,0 +1,34 @@ +localeContext = $localeContext; + } + + public function transform($object, string $to, array $context = []) + { + $localeCode = $this->localeContext->getLocaleCode(); + + $object->setLocaleCode($localeCode); + + return $object; + } + + public function supportsTransformation($object): bool + { + return $object instanceof LocaleCodeAwareInterface; + } +} diff --git a/src/Sylius/Bundle/ApiBundle/Event/ResetPasswordRequested.php b/src/Sylius/Bundle/ApiBundle/Event/ResetPasswordRequested.php new file mode 100644 index 00000000000..cebc00a9243 --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/Event/ResetPasswordRequested.php @@ -0,0 +1,42 @@ +email = $email; + $this->channelCode = $channelCode; + $this->localeCode = $localeCode; + } + + public function email(): string + { + return $this->email; + } + + public function channelCode(): string + { + return $this->channelCode; + } + + public function localeCode(): string + { + return $this->localeCode; + } +} diff --git a/src/Sylius/Bundle/ApiBundle/EventHandler/ResetPasswordRequestedHandler.php b/src/Sylius/Bundle/ApiBundle/EventHandler/ResetPasswordRequestedHandler.php new file mode 100644 index 00000000000..ee21ebfca40 --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/EventHandler/ResetPasswordRequestedHandler.php @@ -0,0 +1,31 @@ +commandBus = $commandBus; + } + + public function __invoke(ResetPasswordRequested $resetPasswordRequested): void + { + $this->commandBus->dispatch( + new SendResetPasswordEmail( + $resetPasswordRequested->email, + $resetPasswordRequested->channelCode(), + $resetPasswordRequested->localeCode() + ) + ); + } +} diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/ShopUser.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/ShopUser.xml new file mode 100644 index 00000000000..d3f79f13150 --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/ShopUser.xml @@ -0,0 +1,45 @@ + + + + + + + sylius + + + + POST + shop/password-reset-request + input + Sylius\Bundle\ApiBundle\Command\ResetPasswordRequest + false + 202 + + sylius + sylius_shop_password_reset + + + shop:shop_user:password_reset + + + Request password reset + + + + + + + + diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/services.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/services.xml index 3651a1dfde9..92bf8566e51 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/services.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/services.xml @@ -109,6 +109,11 @@ + + + + + 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 94d47258b02..46747cd6a15 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/services/command_handlers.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/services/command_handlers.xml @@ -102,6 +102,13 @@ + + + + + + + @@ -114,5 +121,12 @@ + + + + + + + diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/services/event_handlers.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/services/event_handlers.xml index 8ad82cce7ce..492ccf5c218 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/services/event_handlers.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/services/event_handlers.xml @@ -21,5 +21,10 @@ + + + + + diff --git a/src/Sylius/Bundle/CoreBundle/Mailer/Emails.php b/src/Sylius/Bundle/CoreBundle/Mailer/Emails.php index b65e5e7a175..78135590602 100644 --- a/src/Sylius/Bundle/CoreBundle/Mailer/Emails.php +++ b/src/Sylius/Bundle/CoreBundle/Mailer/Emails.php @@ -24,4 +24,6 @@ interface Emails public const SHIPMENT_CONFIRMATION = 'shipment_confirmation'; public const USER_REGISTRATION = 'user_registration'; + + public const PASSWORD_RESET = 'password_reset'; } diff --git a/src/Sylius/Bundle/CoreBundle/Resources/config/app/sylius/sylius_mailer.yml b/src/Sylius/Bundle/CoreBundle/Resources/config/app/sylius/sylius_mailer.yml index b2cfe7b61c3..370c8f14ef2 100644 --- a/src/Sylius/Bundle/CoreBundle/Resources/config/app/sylius/sylius_mailer.yml +++ b/src/Sylius/Bundle/CoreBundle/Resources/config/app/sylius/sylius_mailer.yml @@ -9,3 +9,6 @@ sylius_mailer: order_confirmation: subject: sylius.emails.order_confirmation.subject template: "@SyliusCore/Email/orderConfirmation.html.twig" + password_reset: + subject: sylius.emails.user.password_reset.subject + template: "@SyliusCore/Email/passwordReset.html.twig" diff --git a/src/Sylius/Bundle/CoreBundle/Resources/views/Email/passwordReset.html.twig b/src/Sylius/Bundle/CoreBundle/Resources/views/Email/passwordReset.html.twig new file mode 100644 index 00000000000..3122c50a517 --- /dev/null +++ b/src/Sylius/Bundle/CoreBundle/Resources/views/Email/passwordReset.html.twig @@ -0,0 +1,22 @@ +{% extends '@SyliusCore/Email/layout.html.twig' %} + +{% block subject %} + {{ 'sylius.email.password_reset.subject'|trans({}, null, localeCode) }} +{% endblock %} + +{% block content %} + {% set url = channel.hostname is not null ? 'http://' ~ channel.hostname ~ path('sylius_shop_password_reset', { 'token': user.passwordResetToken}) : url('sylius_shop_password_reset', { 'token': user.passwordResetToken}) %} + +
+
+ {{ 'sylius.email.password_reset.hello'|trans({}, null, localeCode) }} {{ user.username }}
+
+ {{ 'sylius.email.password_reset.to_reset_your_password'|trans({}, null, localeCode) }}: +
+ +
+ + {{ 'sylius.email.password_reset.reset_your_password'|trans({}, null, localeCode) }} + +
+{% endblock %} From 9740b923aaf5f3def48dea32d1f44192d6e96afb Mon Sep 17 00:00:00 2001 From: arti0090 Date: Wed, 17 Feb 2021 09:16:32 +0100 Subject: [PATCH 02/15] change email templates --- .../views/Email/passwordReset.html.twig | 23 +------------------ 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/src/Sylius/Bundle/ShopBundle/Resources/views/Email/passwordReset.html.twig b/src/Sylius/Bundle/ShopBundle/Resources/views/Email/passwordReset.html.twig index 57f99bcec7b..207f739cf25 100644 --- a/src/Sylius/Bundle/ShopBundle/Resources/views/Email/passwordReset.html.twig +++ b/src/Sylius/Bundle/ShopBundle/Resources/views/Email/passwordReset.html.twig @@ -1,22 +1 @@ -{% extends '@SyliusShop/Email/layout.html.twig' %} - -{% block subject %} - {{ 'sylius.email.password_reset.subject'|trans({}, null, localeCode) }} -{% endblock %} - -{% block content %} - {% set url = channel.hostname is not null ? 'http://' ~ channel.hostname ~ path('sylius_shop_password_reset', { 'token': user.passwordResetToken}) : url('sylius_shop_password_reset', { 'token': user.passwordResetToken}) %} - -
-
- {{ 'sylius.email.password_reset.hello'|trans({}, null, localeCode) }} {{ user.username }}
-
- {{ 'sylius.email.password_reset.to_reset_your_password'|trans({}, null, localeCode) }}: -
- - -{% endblock %} +{% include '@SyliusCore/Email/passwordReset.html.twig' %} From 6d453ce8227db1e629e6fc238792915fd450fb5b Mon Sep 17 00:00:00 2001 From: arti0090 Date: Thu, 18 Feb 2021 08:20:43 +0100 Subject: [PATCH 03/15] fixes, revert ApiPlatformSecurityClient and use ApiClient instead in behat --- .../Client/ApiPlatformSecurityClient.php | 37 ++++----------- .../Client/ApiSecurityClientInterface.php | 6 --- src/Sylius/Behat/Context/Api/EmailContext.php | 6 +-- .../Behat/Context/Api/Shop/LoginContext.php | 22 +++++++-- .../config/services/contexts/api/shop.xml | 1 + ...tPasswordRequest.php => ResetPassword.php} | 2 +- ...stHandler.php => ResetPasswordHandler.php} | 8 ++-- .../Event/ResetPasswordRequested.php | 2 +- .../ResetPasswordRequestedHandler.php | 2 +- .../config/api_resources/Customer.xml | 19 ++++++++ .../config/api_resources/ShopUser.xml | 45 ------------------- .../config/services/command_handlers.xml | 2 +- 12 files changed, 56 insertions(+), 96 deletions(-) rename src/Sylius/Bundle/ApiBundle/Command/{ResetPasswordRequest.php => ResetPassword.php} (90%) rename src/Sylius/Bundle/ApiBundle/CommandHandler/{ResetPasswordRequestHandler.php => ResetPasswordHandler.php} (89%) delete mode 100644 src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/ShopUser.xml diff --git a/src/Sylius/Behat/Client/ApiPlatformSecurityClient.php b/src/Sylius/Behat/Client/ApiPlatformSecurityClient.php index 6a4f7540792..a08f5a42970 100644 --- a/src/Sylius/Behat/Client/ApiPlatformSecurityClient.php +++ b/src/Sylius/Behat/Client/ApiPlatformSecurityClient.php @@ -44,12 +44,6 @@ public function prepareLoginRequest(): void $this->request['method'] = 'POST'; } - public function preparePasswordResetRequest(): void - { - $this->request['url'] = sprintf('/api/v2/%s/password-reset-request', $this->section); - $this->request['method'] = 'POST'; - } - public function setEmail(string $email): void { $this->request['body']['email'] = $email; @@ -62,7 +56,14 @@ public function setPassword(string $password): void public function call(): void { - $this->callRequest(); + $this->client->request( + $this->request['method'], + $this->request['url'], + [], + [], + ['CONTENT_TYPE' => 'application/json', 'HTTP_ACCEPT' => 'application/json'], + json_encode($this->request['body']) + ); $response = $this->client->getResponse(); $content = json_decode($response->getContent(), true); @@ -96,26 +97,4 @@ public function logOut(): void $this->sharedStorage->set('cart_token', null); } } - - public function resetPassword(): void - { - $this->callRequest(); - } - - private function callRequest(): void - { - $this->client->request( - $this->request['method'], - $this->request['url'], - [], - [], - ['CONTENT_TYPE' => 'application/json', 'HTTP_ACCEPT' => 'application/json'], - json_encode($this->request['body']) - ); - } - - public function getLastResponse(): Response - { - return $this->client->getResponse(); - } } diff --git a/src/Sylius/Behat/Client/ApiSecurityClientInterface.php b/src/Sylius/Behat/Client/ApiSecurityClientInterface.php index fac37d4de78..a570ea75388 100644 --- a/src/Sylius/Behat/Client/ApiSecurityClientInterface.php +++ b/src/Sylius/Behat/Client/ApiSecurityClientInterface.php @@ -19,8 +19,6 @@ interface ApiSecurityClientInterface { public function prepareLoginRequest(): void; - public function preparePasswordResetRequest(): void; - public function setEmail(string $email): void; public function setPassword(string $password): void; @@ -32,8 +30,4 @@ public function isLoggedIn(): bool; public function getErrorMessage(): string; public function logOut(): void; - - public function resetPassword(): void; - - public function getLastResponse(): Response; } diff --git a/src/Sylius/Behat/Context/Api/EmailContext.php b/src/Sylius/Behat/Context/Api/EmailContext.php index f142ec9d3c6..2922ac8342f 100644 --- a/src/Sylius/Behat/Context/Api/EmailContext.php +++ b/src/Sylius/Behat/Context/Api/EmailContext.php @@ -17,10 +17,8 @@ class EmailContext implements Context /** @var TranslatorInterface */ private $translator; - public function __construct( - EmailCheckerInterface $emailChecker, - TranslatorInterface $translator - ) { + public function __construct(EmailCheckerInterface $emailChecker, TranslatorInterface $translator) + { $this->emailChecker = $emailChecker; $this->translator = $translator; } diff --git a/src/Sylius/Behat/Context/Api/Shop/LoginContext.php b/src/Sylius/Behat/Context/Api/Shop/LoginContext.php index 80a227ba144..c2c7316ed18 100644 --- a/src/Sylius/Behat/Context/Api/Shop/LoginContext.php +++ b/src/Sylius/Behat/Context/Api/Shop/LoginContext.php @@ -14,14 +14,23 @@ namespace Sylius\Behat\Context\Api\Shop; use Behat\Behat\Context\Context; +use Sylius\Behat\Client\ApiClientInterface; use Sylius\Behat\Client\ApiSecurityClientInterface; +use Sylius\Behat\Client\Request; use Webmozart\Assert\Assert; +use \Symfony\Component\HttpFoundation\Request as HTTPRequest; final class LoginContext implements Context { /** @var ApiSecurityClientInterface */ private $client; + /** @var ApiClientInterface */ + private $apiClient; + + /** @var Request */ + private $request; + public function __construct(ApiSecurityClientInterface $client) { $this->client = $client; @@ -48,7 +57,7 @@ public function iWantToLogIn(): void */ public function iWantToResetPassword(): void { - $this->client->preparePasswordResetRequest(); + $this->request = Request::custom('shop/password-reset-request', HTTPRequest::METHOD_POST); } /** @@ -56,18 +65,25 @@ public function iWantToResetPassword(): void */ public function iResetIt(): void { - $this->client->resetPassword(); + $this->apiClient->executeCustomRequest($this->request); } /** * @When I specify the username as :username - * @When I specify the email as :username */ public function iSpecifyTheUsername(string $username): void { $this->client->setEmail($username); } + /** + * @When I specify the email as :email + */ + public function iSpecifyTheEmail(string $email): void + { + $this->request->setContent(['email' => $email]); + } + /** * @When I specify the password as :password */ diff --git a/src/Sylius/Behat/Resources/config/services/contexts/api/shop.xml b/src/Sylius/Behat/Resources/config/services/contexts/api/shop.xml index 90d3a893771..45f46cbba1e 100644 --- a/src/Sylius/Behat/Resources/config/services/contexts/api/shop.xml +++ b/src/Sylius/Behat/Resources/config/services/contexts/api/shop.xml @@ -74,6 +74,7 @@ + diff --git a/src/Sylius/Bundle/ApiBundle/Command/ResetPasswordRequest.php b/src/Sylius/Bundle/ApiBundle/Command/ResetPassword.php similarity index 90% rename from src/Sylius/Bundle/ApiBundle/Command/ResetPasswordRequest.php rename to src/Sylius/Bundle/ApiBundle/Command/ResetPassword.php index 5a5250846ec..3b2fd696673 100644 --- a/src/Sylius/Bundle/ApiBundle/Command/ResetPasswordRequest.php +++ b/src/Sylius/Bundle/ApiBundle/Command/ResetPassword.php @@ -4,7 +4,7 @@ namespace Sylius\Bundle\ApiBundle\Command; -class ResetPasswordRequest implements ChannelCodeAwareInterface, LocaleCodeAwareInterface +class ResetPassword implements ChannelCodeAwareInterface, LocaleCodeAwareInterface { /** @var string */ public $email; diff --git a/src/Sylius/Bundle/ApiBundle/CommandHandler/ResetPasswordRequestHandler.php b/src/Sylius/Bundle/ApiBundle/CommandHandler/ResetPasswordHandler.php similarity index 89% rename from src/Sylius/Bundle/ApiBundle/CommandHandler/ResetPasswordRequestHandler.php rename to src/Sylius/Bundle/ApiBundle/CommandHandler/ResetPasswordHandler.php index 3d007110394..d241786b672 100644 --- a/src/Sylius/Bundle/ApiBundle/CommandHandler/ResetPasswordRequestHandler.php +++ b/src/Sylius/Bundle/ApiBundle/CommandHandler/ResetPasswordHandler.php @@ -4,7 +4,7 @@ namespace Sylius\Bundle\ApiBundle\CommandHandler; -use Sylius\Bundle\ApiBundle\Command\ResetPasswordRequest; +use Sylius\Bundle\ApiBundle\Command\ResetPassword; use Sylius\Bundle\ApiBundle\Event\ResetPasswordRequested; use Sylius\Component\User\Repository\UserRepositoryInterface; use Sylius\Component\User\Security\Generator\GeneratorInterface; @@ -12,7 +12,7 @@ use Symfony\Component\Messenger\Stamp\DispatchAfterCurrentBusStamp; use Webmozart\Assert\Assert; -class ResetPasswordRequestHandler +class ResetPasswordHandler { /** @var UserRepositoryInterface */ private $userRepository; @@ -33,7 +33,7 @@ public function __construct( $this->generator = $generator; } - public function __invoke(ResetPasswordRequest $command): void + public function __invoke(ResetPassword $command): void { $user = $this->userRepository->findOneByEmail($command->getEmail()); Assert::notNull($user); @@ -45,7 +45,5 @@ public function __invoke(ResetPasswordRequest $command): void new ResetPasswordRequested($command->getEmail(), $command->getChannelCode(), $command->getLocaleCode()), [new DispatchAfterCurrentBusStamp() ]); - - } } diff --git a/src/Sylius/Bundle/ApiBundle/Event/ResetPasswordRequested.php b/src/Sylius/Bundle/ApiBundle/Event/ResetPasswordRequested.php index cebc00a9243..dabb8814bef 100644 --- a/src/Sylius/Bundle/ApiBundle/Event/ResetPasswordRequested.php +++ b/src/Sylius/Bundle/ApiBundle/Event/ResetPasswordRequested.php @@ -13,7 +13,7 @@ class ResetPasswordRequested private $channelCode; /** @var string */ - private $localeCode; + protected $localeCode; public function __construct( string $email, diff --git a/src/Sylius/Bundle/ApiBundle/EventHandler/ResetPasswordRequestedHandler.php b/src/Sylius/Bundle/ApiBundle/EventHandler/ResetPasswordRequestedHandler.php index ee21ebfca40..c2cc5171a95 100644 --- a/src/Sylius/Bundle/ApiBundle/EventHandler/ResetPasswordRequestedHandler.php +++ b/src/Sylius/Bundle/ApiBundle/EventHandler/ResetPasswordRequestedHandler.php @@ -22,7 +22,7 @@ public function __invoke(ResetPasswordRequested $resetPasswordRequested): void { $this->commandBus->dispatch( new SendResetPasswordEmail( - $resetPasswordRequested->email, + $resetPasswordRequested->email(), $resetPasswordRequested->channelCode(), $resetPasswordRequested->localeCode() ) diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Customer.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Customer.xml index a4279b8058b..d766585f62d 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Customer.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Customer.xml @@ -33,6 +33,25 @@ Sylius\Bundle\ApiBundle\Command\RegisterShopUser false + + + POST + shop/password-reset-request + input + Sylius\Bundle\ApiBundle\Command\ResetPasswordRequest + false + 202 + + sylius + sylius_shop_password_reset + + + shop:shop_user:password_reset + + + Request password reset + + diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/ShopUser.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/ShopUser.xml deleted file mode 100644 index d3f79f13150..00000000000 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/ShopUser.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - sylius - - - - POST - shop/password-reset-request - input - Sylius\Bundle\ApiBundle\Command\ResetPasswordRequest - false - 202 - - sylius - sylius_shop_password_reset - - - shop:shop_user:password_reset - - - Request password reset - - - - - - - - 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 46747cd6a15..a50dc3c09e2 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/services/command_handlers.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/services/command_handlers.xml @@ -102,7 +102,7 @@ - + From ecadef4ac16226d7d313f41baae9d2862aebdc70 Mon Sep 17 00:00:00 2001 From: arti0090 Date: Thu, 18 Feb 2021 08:36:45 +0100 Subject: [PATCH 04/15] fix config files --- src/Sylius/Behat/Context/Api/Shop/LoginContext.php | 7 ++++--- .../ApiBundle/Resources/config/api_resources/Customer.xml | 4 ++-- .../Resources/config/services/command_handlers.xml | 2 +- .../Resources/views/Email/passwordReset.html.twig | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/Sylius/Behat/Context/Api/Shop/LoginContext.php b/src/Sylius/Behat/Context/Api/Shop/LoginContext.php index c2c7316ed18..ee02274b9b4 100644 --- a/src/Sylius/Behat/Context/Api/Shop/LoginContext.php +++ b/src/Sylius/Behat/Context/Api/Shop/LoginContext.php @@ -31,9 +31,10 @@ final class LoginContext implements Context /** @var Request */ private $request; - public function __construct(ApiSecurityClientInterface $client) + public function __construct(ApiSecurityClientInterface $client, ApiClientInterface $apiClient) { $this->client = $client; + $this->apiClient = $apiClient; } /** @@ -57,7 +58,7 @@ public function iWantToLogIn(): void */ public function iWantToResetPassword(): void { - $this->request = Request::custom('shop/password-reset-request', HTTPRequest::METHOD_POST); + $this->request = Request::create('shop', 'password-reset-request', 'Bearer'); } /** @@ -150,7 +151,7 @@ public function iShouldBeNotifiedAboutBadCredentials(): void */ public function iShouldBeNotifiedThatEmailWithResetInstructionWasSent(): void { - $response = $this->client->getLastResponse(); + $response = $this->apiClient->getLastResponse(); Assert::same($response->getStatusCode(), 202); } } diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Customer.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Customer.xml index d766585f62d..a382012e90b 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Customer.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Customer.xml @@ -33,12 +33,12 @@ Sylius\Bundle\ApiBundle\Command\RegisterShopUser false - + POST shop/password-reset-request input - Sylius\Bundle\ApiBundle\Command\ResetPasswordRequest + Sylius\Bundle\ApiBundle\Command\ResetPassword false 202 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 a50dc3c09e2..ac6bebaec18 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/services/command_handlers.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/services/command_handlers.xml @@ -102,7 +102,7 @@ - + diff --git a/src/Sylius/Bundle/ShopBundle/Resources/views/Email/passwordReset.html.twig b/src/Sylius/Bundle/ShopBundle/Resources/views/Email/passwordReset.html.twig index 207f739cf25..4905c466ffd 100644 --- a/src/Sylius/Bundle/ShopBundle/Resources/views/Email/passwordReset.html.twig +++ b/src/Sylius/Bundle/ShopBundle/Resources/views/Email/passwordReset.html.twig @@ -1 +1 @@ -{% include '@SyliusCore/Email/passwordReset.html.twig' %} +{% extends '@SyliusCore/Email/passwordReset.html.twig' %} From 3759b2bcc4a91d8ca04ff5d237766367cde59c9d Mon Sep 17 00:00:00 2001 From: arti0090 Date: Thu, 18 Feb 2021 10:06:22 +0100 Subject: [PATCH 05/15] validate email --- features/account/resetting_password.feature | 2 +- .../resetting_password_validation.feature | 2 +- .../Behat/Context/Api/Shop/LoginContext.php | 44 +++++++++++++++++-- .../config/services/contexts/api/shop.xml | 1 + ...leCodeAwareInputCommandDataTransformer.php | 4 ++ .../config/api_resources/Customer.xml | 2 +- .../Commands/Account/ResetPassword.xml | 26 +++++++++++ .../config/validation/ResetPassword.xml | 29 ++++++++++++ 8 files changed, 103 insertions(+), 7 deletions(-) create mode 100644 src/Sylius/Bundle/ApiBundle/Resources/config/serialization/Commands/Account/ResetPassword.xml create mode 100644 src/Sylius/Bundle/ApiBundle/Resources/config/validation/ResetPassword.xml diff --git a/features/account/resetting_password.feature b/features/account/resetting_password.feature index 6d816bcc227..822f9a1feeb 100644 --- a/features/account/resetting_password.feature +++ b/features/account/resetting_password.feature @@ -17,7 +17,7 @@ Feature: Resetting a password Then I should be notified that email with reset instruction has been sent And an email with reset token should be sent to "goodman@example.com" - @ui @email + @ui @email @api Scenario: Resetting an account password in different locale than the default one When I reset password for email "goodman@example.com" in "Polish (Poland)" locale Then an email with reset token should be sent to "goodman@example.com" in "Polish (Poland)" locale diff --git a/features/account/resetting_password_validation.feature b/features/account/resetting_password_validation.feature index 2ffba025c65..3f0969e78ca 100644 --- a/features/account/resetting_password_validation.feature +++ b/features/account/resetting_password_validation.feature @@ -8,7 +8,7 @@ Feature: Resetting a password validation Given the store operates on a single channel in "United States" And there is a user "goodman@example.com" identified by "heisenberg" - @ui + @ui @api Scenario: Trying to reset password without specifying email When I want to reset password And I do not specify the email diff --git a/src/Sylius/Behat/Context/Api/Shop/LoginContext.php b/src/Sylius/Behat/Context/Api/Shop/LoginContext.php index ee02274b9b4..25d7952b839 100644 --- a/src/Sylius/Behat/Context/Api/Shop/LoginContext.php +++ b/src/Sylius/Behat/Context/Api/Shop/LoginContext.php @@ -17,8 +17,8 @@ use Sylius\Behat\Client\ApiClientInterface; use Sylius\Behat\Client\ApiSecurityClientInterface; use Sylius\Behat\Client\Request; +use Sylius\Behat\Client\ResponseCheckerInterface; use Webmozart\Assert\Assert; -use \Symfony\Component\HttpFoundation\Request as HTTPRequest; final class LoginContext implements Context { @@ -28,13 +28,20 @@ final class LoginContext implements Context /** @var ApiClientInterface */ private $apiClient; + /** @var ResponseCheckerInterface */ + private $responseChecker; + /** @var Request */ private $request; - public function __construct(ApiSecurityClientInterface $client, ApiClientInterface $apiClient) - { + public function __construct( + ApiSecurityClientInterface $client, + ApiClientInterface $apiClient, + ResponseCheckerInterface $responseChecker + ) { $this->client = $client; $this->apiClient = $apiClient; + $this->responseChecker = $responseChecker; } /** @@ -61,8 +68,20 @@ public function iWantToResetPassword(): void $this->request = Request::create('shop', 'password-reset-request', 'Bearer'); } + /** + * @When I reset password for email :email in :localeCode locale + */ + public function iResetPasswordForEmailInLocale(string $email, string $localeCode): void + { + $this->iWantToResetPassword(); + $this->iSpecifyTheEmail($email); + $this->addLocaleCode($localeCode); + $this->iResetIt(); + } + /** * @When I reset it + * @When I try to reset it */ public function iResetIt(): void { @@ -79,8 +98,9 @@ public function iSpecifyTheUsername(string $username): void /** * @When I specify the email as :email + * @When I do not specify the email */ - public function iSpecifyTheEmail(string $email): void + public function iSpecifyTheEmail(string $email = ''): void { $this->request->setContent(['email' => $email]); } @@ -154,4 +174,20 @@ public function iShouldBeNotifiedThatEmailWithResetInstructionWasSent(): void $response = $this->apiClient->getLastResponse(); Assert::same($response->getStatusCode(), 202); } + + /** + * @Then I should be notified that the :elementName is required + */ + public function iShouldBeNotifiedThatFirstNameIsRequired(string $elementName): void + { + Assert::contains( + $this->responseChecker->getError($this->apiClient->getLastResponse()), + sprintf('Please enter your %s.', $elementName) + ); + } + + private function addLocaleCode(string $localeCode): void + { + $this->request->updateContent(['localeCode' => $localeCode]); + } } diff --git a/src/Sylius/Behat/Resources/config/services/contexts/api/shop.xml b/src/Sylius/Behat/Resources/config/services/contexts/api/shop.xml index 45f46cbba1e..4b63b51dbaa 100644 --- a/src/Sylius/Behat/Resources/config/services/contexts/api/shop.xml +++ b/src/Sylius/Behat/Resources/config/services/contexts/api/shop.xml @@ -75,6 +75,7 @@ + diff --git a/src/Sylius/Bundle/ApiBundle/DataTransformer/LocaleCodeAwareInputCommandDataTransformer.php b/src/Sylius/Bundle/ApiBundle/DataTransformer/LocaleCodeAwareInputCommandDataTransformer.php index 50c926bd168..b0b02027a68 100644 --- a/src/Sylius/Bundle/ApiBundle/DataTransformer/LocaleCodeAwareInputCommandDataTransformer.php +++ b/src/Sylius/Bundle/ApiBundle/DataTransformer/LocaleCodeAwareInputCommandDataTransformer.php @@ -20,6 +20,10 @@ public function __construct(LocaleContextInterface $localeContext) public function transform($object, string $to, array $context = []) { + if ($object->getLocaleCode() !== null) { + return $object; + } + $localeCode = $this->localeContext->getLocaleCode(); $object->setLocaleCode($localeCode); diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Customer.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Customer.xml index a382012e90b..ff8586dc25a 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Customer.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Customer.xml @@ -46,7 +46,7 @@ sylius_shop_password_reset - shop:shop_user:password_reset + shop:customer:password_reset Request password reset diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/serialization/Commands/Account/ResetPassword.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/serialization/Commands/Account/ResetPassword.xml new file mode 100644 index 00000000000..a8f7f064269 --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/serialization/Commands/Account/ResetPassword.xml @@ -0,0 +1,26 @@ + + + + + + + + shop:customer:password_reset + + + shop:customer:password_reset + + + diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/validation/ResetPassword.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/validation/ResetPassword.xml new file mode 100644 index 00000000000..23ab56caa00 --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/validation/ResetPassword.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + From e58e74164198537918844f2735d887fbdf398b5c Mon Sep 17 00:00:00 2001 From: arti0090 Date: Thu, 18 Feb 2021 10:13:20 +0100 Subject: [PATCH 06/15] fix behat step --- features/account/resetting_password.feature | 2 +- src/Sylius/Behat/Context/Api/Shop/LoginContext.php | 2 +- src/Sylius/Behat/Context/Ui/Shop/LoginContext.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/features/account/resetting_password.feature b/features/account/resetting_password.feature index 822f9a1feeb..4c4cd497311 100644 --- a/features/account/resetting_password.feature +++ b/features/account/resetting_password.feature @@ -12,7 +12,7 @@ Feature: Resetting a password @ui @email @api Scenario: Resetting an account password When I want to reset password - And I specify the email as "goodman@example.com" + And I specify customer email as "goodman@example.com" And I reset it Then I should be notified that email with reset instruction has been sent And an email with reset token should be sent to "goodman@example.com" diff --git a/src/Sylius/Behat/Context/Api/Shop/LoginContext.php b/src/Sylius/Behat/Context/Api/Shop/LoginContext.php index 25d7952b839..1534a321612 100644 --- a/src/Sylius/Behat/Context/Api/Shop/LoginContext.php +++ b/src/Sylius/Behat/Context/Api/Shop/LoginContext.php @@ -97,7 +97,7 @@ public function iSpecifyTheUsername(string $username): void } /** - * @When I specify the email as :email + * @When I specify customer email as :email * @When I do not specify the email */ public function iSpecifyTheEmail(string $email = ''): void diff --git a/src/Sylius/Behat/Context/Ui/Shop/LoginContext.php b/src/Sylius/Behat/Context/Ui/Shop/LoginContext.php index 935c281d2b2..e6f07471032 100644 --- a/src/Sylius/Behat/Context/Ui/Shop/LoginContext.php +++ b/src/Sylius/Behat/Context/Ui/Shop/LoginContext.php @@ -119,7 +119,7 @@ public function iSpecifyTheUsername(?string $username = null): void } /** - * @When I specify the email as :email + * @When I specify customer email as :email * @When I do not specify the email */ public function iSpecifyTheEmail(?string $email = null): void From 656719d17ea855ff41596ab8cfdf355d71ca92a7 Mon Sep 17 00:00:00 2001 From: arti0090 Date: Thu, 18 Feb 2021 10:31:09 +0100 Subject: [PATCH 07/15] remove unneded elements --- .../Behat/Client/ApiSecurityClientInterface.php | 2 -- src/Sylius/Behat/Context/Api/Shop/LoginContext.php | 11 ----------- .../Resources/config/suites/api/account/login.yml | 2 +- 3 files changed, 1 insertion(+), 14 deletions(-) diff --git a/src/Sylius/Behat/Client/ApiSecurityClientInterface.php b/src/Sylius/Behat/Client/ApiSecurityClientInterface.php index a570ea75388..d7d43f2b7bd 100644 --- a/src/Sylius/Behat/Client/ApiSecurityClientInterface.php +++ b/src/Sylius/Behat/Client/ApiSecurityClientInterface.php @@ -13,8 +13,6 @@ namespace Sylius\Behat\Client; -use Symfony\Component\HttpFoundation\Response; - interface ApiSecurityClientInterface { public function prepareLoginRequest(): void; diff --git a/src/Sylius/Behat/Context/Api/Shop/LoginContext.php b/src/Sylius/Behat/Context/Api/Shop/LoginContext.php index 1534a321612..cd2a59fab53 100644 --- a/src/Sylius/Behat/Context/Api/Shop/LoginContext.php +++ b/src/Sylius/Behat/Context/Api/Shop/LoginContext.php @@ -175,17 +175,6 @@ public function iShouldBeNotifiedThatEmailWithResetInstructionWasSent(): void Assert::same($response->getStatusCode(), 202); } - /** - * @Then I should be notified that the :elementName is required - */ - public function iShouldBeNotifiedThatFirstNameIsRequired(string $elementName): void - { - Assert::contains( - $this->responseChecker->getError($this->apiClient->getLastResponse()), - sprintf('Please enter your %s.', $elementName) - ); - } - private function addLocaleCode(string $localeCode): void { $this->request->updateContent(['localeCode' => $localeCode]); diff --git a/src/Sylius/Behat/Resources/config/suites/api/account/login.yml b/src/Sylius/Behat/Resources/config/suites/api/account/login.yml index 3c139f9c72e..b77b7b5b554 100644 --- a/src/Sylius/Behat/Resources/config/suites/api/account/login.yml +++ b/src/Sylius/Behat/Resources/config/suites/api/account/login.yml @@ -17,8 +17,8 @@ default: - sylius.behat.context.setup.user - sylius.behat.context.api.email + - sylius.behat.context.api.shop.customer - sylius.behat.context.api.shop.login - filters: tags: "@customer_login && @api" From 5bc148c02feef799497d5251f84499c87ac88bbf Mon Sep 17 00:00:00 2001 From: arti0090 Date: Fri, 19 Feb 2021 09:24:31 +0100 Subject: [PATCH 08/15] add copyright blocks, add phpspec for handler, fix issues --- src/Sylius/Behat/Context/Api/EmailContext.php | 9 +++ .../Behat/Context/Api/Shop/LoginContext.php | 2 +- .../config/services/contexts/api.xml | 4 +- ...word.php => RequestResetPasswordToken.php} | 11 ++- .../Command/SendResetPasswordEmail.php | 9 +++ ...p => RequestResetPasswordTokenHandler.php} | 19 +++-- .../SendResetPasswordEmailHandler.php | 14 +++- .../Event/ResetPasswordRequested.php | 9 +++ .../ResetPasswordRequestedHandler.php | 12 +++- .../config/api_resources/Customer.xml | 6 +- .../Commands/Account/ResetPassword.xml | 4 +- .../config/services/command_handlers.xml | 2 +- .../config/validation/ResetPassword.xml | 2 +- .../SendResetPasswordEmailHandlerSpec.php | 71 +++++++++++++++++++ 14 files changed, 154 insertions(+), 20 deletions(-) rename src/Sylius/Bundle/ApiBundle/Command/{ResetPassword.php => RequestResetPasswordToken.php} (72%) rename src/Sylius/Bundle/ApiBundle/CommandHandler/{ResetPasswordHandler.php => RequestResetPasswordTokenHandler.php} (74%) create mode 100644 src/Sylius/Bundle/ApiBundle/spec/CommandHandler/SendResetPasswordEmailHandlerSpec.php diff --git a/src/Sylius/Behat/Context/Api/EmailContext.php b/src/Sylius/Behat/Context/Api/EmailContext.php index 2922ac8342f..4c68f30034a 100644 --- a/src/Sylius/Behat/Context/Api/EmailContext.php +++ b/src/Sylius/Behat/Context/Api/EmailContext.php @@ -1,5 +1,14 @@ request = Request::create('shop', 'password-reset-request', 'Bearer'); + $this->request = Request::create('shop', 'request-reset-password', 'Bearer'); } /** diff --git a/src/Sylius/Behat/Resources/config/services/contexts/api.xml b/src/Sylius/Behat/Resources/config/services/contexts/api.xml index 8c4266275f9..22594485204 100644 --- a/src/Sylius/Behat/Resources/config/services/contexts/api.xml +++ b/src/Sylius/Behat/Resources/config/services/contexts/api.xml @@ -16,8 +16,6 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd" > - - - + diff --git a/src/Sylius/Bundle/ApiBundle/Command/ResetPassword.php b/src/Sylius/Bundle/ApiBundle/Command/RequestResetPasswordToken.php similarity index 72% rename from src/Sylius/Bundle/ApiBundle/Command/ResetPassword.php rename to src/Sylius/Bundle/ApiBundle/Command/RequestResetPasswordToken.php index 3b2fd696673..9437cb6f8ae 100644 --- a/src/Sylius/Bundle/ApiBundle/Command/ResetPassword.php +++ b/src/Sylius/Bundle/ApiBundle/Command/RequestResetPasswordToken.php @@ -1,10 +1,19 @@ generator = $generator; } - public function __invoke(ResetPassword $command): void + public function __invoke(RequestResetPasswordToken $command): void { $user = $this->userRepository->findOneByEmail($command->getEmail()); Assert::notNull($user); @@ -43,7 +52,7 @@ public function __invoke(ResetPassword $command): void $this->eventBus->dispatch( new ResetPasswordRequested($command->getEmail(), $command->getChannelCode(), $command->getLocaleCode()), - [new DispatchAfterCurrentBusStamp() - ]); + [new DispatchAfterCurrentBusStamp()] + ); } } diff --git a/src/Sylius/Bundle/ApiBundle/CommandHandler/SendResetPasswordEmailHandler.php b/src/Sylius/Bundle/ApiBundle/CommandHandler/SendResetPasswordEmailHandler.php index 7457d4a1a5e..279ceaf480f 100644 --- a/src/Sylius/Bundle/ApiBundle/CommandHandler/SendResetPasswordEmailHandler.php +++ b/src/Sylius/Bundle/ApiBundle/CommandHandler/SendResetPasswordEmailHandler.php @@ -1,5 +1,14 @@ $user, 'localeCode' => $command->localeCode(), - 'channel' => $channel + 'channel' => $channel, ] ); } diff --git a/src/Sylius/Bundle/ApiBundle/Event/ResetPasswordRequested.php b/src/Sylius/Bundle/ApiBundle/Event/ResetPasswordRequested.php index dabb8814bef..bb55a654901 100644 --- a/src/Sylius/Bundle/ApiBundle/Event/ResetPasswordRequested.php +++ b/src/Sylius/Bundle/ApiBundle/Event/ResetPasswordRequested.php @@ -1,5 +1,14 @@ POST - shop/password-reset-request + shop/request-reset-password input - Sylius\Bundle\ApiBundle\Command\ResetPassword + Sylius\Bundle\ApiBundle\Command\RequestResetPasswordToken false 202 @@ -46,7 +46,7 @@ sylius_shop_password_reset - shop:customer:password_reset + shop:password_reset:create Request password reset diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/serialization/Commands/Account/ResetPassword.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/serialization/Commands/Account/ResetPassword.xml index a8f7f064269..194ac5cd5b9 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/serialization/Commands/Account/ResetPassword.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/serialization/Commands/Account/ResetPassword.xml @@ -17,10 +17,10 @@ > - shop:customer:password_reset + shop:password_reset:create - shop:customer:password_reset + shop:password_reset:create 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 ac6bebaec18..531d285161e 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/services/command_handlers.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/services/command_handlers.xml @@ -102,7 +102,7 @@ - + diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/validation/ResetPassword.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/validation/ResetPassword.xml index 23ab56caa00..e22a04d6c04 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/validation/ResetPassword.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/validation/ResetPassword.xml @@ -15,7 +15,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/services/constraint-mapping-1.0.xsd"> - + diff --git a/src/Sylius/Bundle/ApiBundle/spec/CommandHandler/SendResetPasswordEmailHandlerSpec.php b/src/Sylius/Bundle/ApiBundle/spec/CommandHandler/SendResetPasswordEmailHandlerSpec.php new file mode 100644 index 00000000000..10ff2de8882 --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/spec/CommandHandler/SendResetPasswordEmailHandlerSpec.php @@ -0,0 +1,71 @@ +beConstructedWith($emailSender, $channelRepository, $userRepository); + } + + function it_is_a_message_handler(): void + { + $this->shouldImplement(MessageHandlerInterface::class); + } + + function it_sends_message_with_reset_password_token( + SenderInterface $sender, + UserRepositoryInterface $userRepository, + SendResetPasswordEmail $sendResetPasswordEmail, + UserInterface $user, + ChannelRepositoryInterface $channelRepository, + ChannelInterface $channel + ): void { + $sendResetPasswordEmail->email()->willReturn('iAmAnEmail@spaghettiCode.php'); + + $userRepository->findOneByEmail('iAmAnEmail@spaghettiCode.php')->willReturn($user); + + $sendResetPasswordEmail->channelCode()->willReturn('WEB'); + + $channelRepository->findOneByCode('WEB')->willReturn($channel); + + $sendResetPasswordEmail->localeCode()->willReturn('en_US'); + + $sender->send( + Emails::PASSWORD_RESET, + ['iAmAnEmail@spaghettiCode.php'], + [ + 'user' => $user->getWrappedObject(), + 'localeCode' => 'en_US', + 'channel' => $channel->getWrappedObject(), + ] + ); + + $this(new SendResetPasswordEmail('iAmAnEmail@spaghettiCode.php', 'WEB', 'en_US')); + } +} From 1ecde8f19b4ac44181d32e185156a0888a67e8d5 Mon Sep 17 00:00:00 2001 From: arti0090 Date: Fri, 19 Feb 2021 11:26:00 +0100 Subject: [PATCH 09/15] change access modifiers --- src/Sylius/Behat/Context/Api/EmailContext.php | 2 +- .../Bundle/ApiBundle/Command/RequestResetPasswordToken.php | 4 ++-- .../Bundle/ApiBundle/Command/SendResetPasswordEmail.php | 4 ++-- src/Sylius/Bundle/ApiBundle/Event/ResetPasswordRequested.php | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Sylius/Behat/Context/Api/EmailContext.php b/src/Sylius/Behat/Context/Api/EmailContext.php index 4c68f30034a..dd86e5aef8f 100644 --- a/src/Sylius/Behat/Context/Api/EmailContext.php +++ b/src/Sylius/Behat/Context/Api/EmailContext.php @@ -18,7 +18,7 @@ use Symfony\Contracts\Translation\TranslatorInterface; use Webmozart\Assert\Assert; -class EmailContext implements Context +final class EmailContext implements Context { /** @var EmailCheckerInterface */ private $emailChecker; diff --git a/src/Sylius/Bundle/ApiBundle/Command/RequestResetPasswordToken.php b/src/Sylius/Bundle/ApiBundle/Command/RequestResetPasswordToken.php index 9437cb6f8ae..615078b54e0 100644 --- a/src/Sylius/Bundle/ApiBundle/Command/RequestResetPasswordToken.php +++ b/src/Sylius/Bundle/ApiBundle/Command/RequestResetPasswordToken.php @@ -19,10 +19,10 @@ class RequestResetPasswordToken implements ChannelCodeAwareInterface, LocaleCode public $email; /** @var string|null */ - private $channelCode; + public $channelCode; /** @var string|null */ - private $localeCode; + public $localeCode; public function __construct(string $email) { diff --git a/src/Sylius/Bundle/ApiBundle/Command/SendResetPasswordEmail.php b/src/Sylius/Bundle/ApiBundle/Command/SendResetPasswordEmail.php index 4a6ee777204..a243a120eba 100644 --- a/src/Sylius/Bundle/ApiBundle/Command/SendResetPasswordEmail.php +++ b/src/Sylius/Bundle/ApiBundle/Command/SendResetPasswordEmail.php @@ -19,10 +19,10 @@ class SendResetPasswordEmail public $email; /** @var string */ - private $channelCode; + public $channelCode; /** @var string */ - private $localeCode; + public $localeCode; public function __construct( string $email, diff --git a/src/Sylius/Bundle/ApiBundle/Event/ResetPasswordRequested.php b/src/Sylius/Bundle/ApiBundle/Event/ResetPasswordRequested.php index bb55a654901..1cb8d9f990f 100644 --- a/src/Sylius/Bundle/ApiBundle/Event/ResetPasswordRequested.php +++ b/src/Sylius/Bundle/ApiBundle/Event/ResetPasswordRequested.php @@ -19,10 +19,10 @@ class ResetPasswordRequested public $email; /** @var string */ - private $channelCode; + public $channelCode; /** @var string */ - protected $localeCode; + public $localeCode; public function __construct( string $email, From 66d5b0d7279a278898ec2f91e6e2edc04aeb9da1 Mon Sep 17 00:00:00 2001 From: arti0090 Date: Tue, 23 Feb 2021 12:59:07 +0100 Subject: [PATCH 10/15] decouple mail --- .../Resources/views/Email/passwordReset.html.twig | 13 +++++++++++-- .../Resources/translations/messages.en.yml | 2 ++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Sylius/Bundle/CoreBundle/Resources/views/Email/passwordReset.html.twig b/src/Sylius/Bundle/CoreBundle/Resources/views/Email/passwordReset.html.twig index 3122c50a517..f696ebd2806 100644 --- a/src/Sylius/Bundle/CoreBundle/Resources/views/Email/passwordReset.html.twig +++ b/src/Sylius/Bundle/CoreBundle/Resources/views/Email/passwordReset.html.twig @@ -5,18 +5,27 @@ {% endblock %} {% block content %} - {% set url = channel.hostname is not null ? 'http://' ~ channel.hostname ~ path('sylius_shop_password_reset', { 'token': user.passwordResetToken}) : url('sylius_shop_password_reset', { 'token': user.passwordResetToken}) %} - + {% if sylius_bundle_loaded_checker('SyliusShopBundle') %} + {% set url = channel.hostname is not null ? 'http://' ~ channel.hostname ~ path('sylius_shop_password_reset', { 'token': user.passwordResetToken}) : url('sylius_shop_password_reset', { 'token': user.passwordResetToken}) %} + {% endif %}
{{ 'sylius.email.password_reset.hello'|trans({}, null, localeCode) }} {{ user.username }}
+ {% if sylius_bundle_loaded_checker('SyliusShopBundle') %} {{ 'sylius.email.password_reset.to_reset_your_password'|trans({}, null, localeCode) }}: + {% else %} + {{ 'sylius.email.password_reset.to_reset_your_password'|trans({}, null, localeCode) }}: + {% endif %}
+ {% if sylius_bundle_loaded_checker('SyliusShopBundle') %} {{ 'sylius.email.password_reset.reset_your_password'|trans({}, null, localeCode) }} + {% else %} + {{ 'sylius.email.password_reset.token'|trans({}, null, localeCode) }}: {{ user.passwordResetToken }} + {% endif %}
{% endblock %} diff --git a/src/Sylius/Bundle/ShopBundle/Resources/translations/messages.en.yml b/src/Sylius/Bundle/ShopBundle/Resources/translations/messages.en.yml index 005ac51051e..59ff57ec43d 100644 --- a/src/Sylius/Bundle/ShopBundle/Resources/translations/messages.en.yml +++ b/src/Sylius/Bundle/ShopBundle/Resources/translations/messages.en.yml @@ -18,6 +18,8 @@ sylius: reset_your_password: 'Reset your password' subject: 'Password reset' to_reset_your_password: 'To reset your password - click the link below' + to_reset_your_password_token: 'To reset your password - use the token below' + token: 'Your password reset token is' user_registration: start_shopping: 'Start shopping' subject: 'User registration' From f575fa38e91e2d31f006c732f1540546d8362c32 Mon Sep 17 00:00:00 2001 From: arti0090 Date: Tue, 23 Feb 2021 13:10:53 +0100 Subject: [PATCH 11/15] remove events --- .../RequestResetPasswordTokenHandler.php | 8 ++- .../Event/ResetPasswordRequested.php | 51 ------------------- .../ResetPasswordRequestedHandler.php | 41 --------------- .../config/services/command_handlers.xml | 2 +- .../config/services/event_handlers.xml | 5 -- 5 files changed, 7 insertions(+), 100 deletions(-) delete mode 100644 src/Sylius/Bundle/ApiBundle/Event/ResetPasswordRequested.php delete mode 100644 src/Sylius/Bundle/ApiBundle/EventHandler/ResetPasswordRequestedHandler.php diff --git a/src/Sylius/Bundle/ApiBundle/CommandHandler/RequestResetPasswordTokenHandler.php b/src/Sylius/Bundle/ApiBundle/CommandHandler/RequestResetPasswordTokenHandler.php index 76a207ffbf9..f0ce8fb9ebe 100644 --- a/src/Sylius/Bundle/ApiBundle/CommandHandler/RequestResetPasswordTokenHandler.php +++ b/src/Sylius/Bundle/ApiBundle/CommandHandler/RequestResetPasswordTokenHandler.php @@ -14,6 +14,7 @@ namespace Sylius\Bundle\ApiBundle\CommandHandler; use Sylius\Bundle\ApiBundle\Command\RequestResetPasswordToken; +use Sylius\Bundle\ApiBundle\Command\SendResetPasswordEmail; use Sylius\Bundle\ApiBundle\Event\ResetPasswordRequested; use Sylius\Component\User\Repository\UserRepositoryInterface; use Sylius\Component\User\Security\Generator\GeneratorInterface; @@ -51,8 +52,11 @@ public function __invoke(RequestResetPasswordToken $command): void $user->setPasswordRequestedAt(new \DateTime()); $this->eventBus->dispatch( - new ResetPasswordRequested($command->getEmail(), $command->getChannelCode(), $command->getLocaleCode()), - [new DispatchAfterCurrentBusStamp()] + new SendResetPasswordEmail( + $command->getEmail(), + $command->getChannelCode(), + $command->getLocaleCode() + ) ); } } diff --git a/src/Sylius/Bundle/ApiBundle/Event/ResetPasswordRequested.php b/src/Sylius/Bundle/ApiBundle/Event/ResetPasswordRequested.php deleted file mode 100644 index 1cb8d9f990f..00000000000 --- a/src/Sylius/Bundle/ApiBundle/Event/ResetPasswordRequested.php +++ /dev/null @@ -1,51 +0,0 @@ -email = $email; - $this->channelCode = $channelCode; - $this->localeCode = $localeCode; - } - - public function email(): string - { - return $this->email; - } - - public function channelCode(): string - { - return $this->channelCode; - } - - public function localeCode(): string - { - return $this->localeCode; - } -} diff --git a/src/Sylius/Bundle/ApiBundle/EventHandler/ResetPasswordRequestedHandler.php b/src/Sylius/Bundle/ApiBundle/EventHandler/ResetPasswordRequestedHandler.php deleted file mode 100644 index 80fa3a23980..00000000000 --- a/src/Sylius/Bundle/ApiBundle/EventHandler/ResetPasswordRequestedHandler.php +++ /dev/null @@ -1,41 +0,0 @@ -commandBus = $commandBus; - } - - public function __invoke(ResetPasswordRequested $resetPasswordRequested): void - { - $this->commandBus->dispatch( - new SendResetPasswordEmail( - $resetPasswordRequested->email(), - $resetPasswordRequested->channelCode(), - $resetPasswordRequested->localeCode() - ) - ); - } -} 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 531d285161e..9cb4f30b297 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/services/command_handlers.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/services/command_handlers.xml @@ -104,7 +104,7 @@ - + diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/services/event_handlers.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/services/event_handlers.xml index 492ccf5c218..8ad82cce7ce 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/services/event_handlers.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/services/event_handlers.xml @@ -21,10 +21,5 @@
- - - - - From 47e33077f48b37dc385e6c55813519d76df3817f Mon Sep 17 00:00:00 2001 From: arti0090 Date: Wed, 24 Feb 2021 11:50:04 +0100 Subject: [PATCH 12/15] add test for send reset password email --- .../SendResetPasswordEmailHandlerTest.php | 141 +++++++++++++ .../Bundle/ApiBundle/Tests/TestKernel.php | 199 ++++++++++++++++++ src/Sylius/Bundle/ApiBundle/phpunit.xml.dist | 11 + .../views/Email/passwordReset.html.twig | 4 +- 4 files changed, 353 insertions(+), 2 deletions(-) create mode 100644 src/Sylius/Bundle/ApiBundle/Tests/CommandHandler/SendResetPasswordEmailHandlerTest.php create mode 100644 src/Sylius/Bundle/ApiBundle/Tests/TestKernel.php diff --git a/src/Sylius/Bundle/ApiBundle/Tests/CommandHandler/SendResetPasswordEmailHandlerTest.php b/src/Sylius/Bundle/ApiBundle/Tests/CommandHandler/SendResetPasswordEmailHandlerTest.php new file mode 100644 index 00000000000..39cea837ed0 --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/Tests/CommandHandler/SendResetPasswordEmailHandlerTest.php @@ -0,0 +1,141 @@ +getContainer()->get('filesystem'); + + /** @var TranslatorInterface $translator */ + $translator = static::$kernel->getContainer()->get('translator'); + + /** @var EmailChecker $emailChecker */ + $emailChecker = static::$kernel->getContainer()->get('sylius.behat.email_checker'); + + $filesystem->remove($emailChecker->getSpoolDirectory()); + + $emailSender = static::$kernel->getContainer()->get('sylius.email_sender'); + + /** @var ChannelRepositoryInterface|ObjectProphecy $channelRepository */ + $channelRepository = $this->prophesize(ChannelRepositoryInterface::class); + /** @var UserRepositoryInterface|ObjectProphecy $userRepository */ + $userRepository = $this->prophesize(UserRepositoryInterface::class); + /** @var ChannelInterface|ObjectProphecy $channel */ + $channel = $this->prophesize(ChannelInterface::class); + /** @var UserInterface|ObjectProphecy $user */ + $user = $this->prophesize(UserInterface::class); + + $user->getUsername()->willReturn('username'); + $user->getPasswordResetToken()->willReturn('token'); + + $channelRepository->findOneByCode('CHANNEL_CODE')->willReturn($channel->reveal()); + $userRepository->findOneByEmail('user@example.com')->willReturn($user->reveal()); + + $resetPasswordEmailHandler = new SendResetPasswordEmailHandler( + $emailSender, + $channelRepository->reveal(), + $userRepository->reveal() + ); + + $resetPasswordEmailHandler(new SendResetPasswordEmail( + 'user@example.com', + 'CHANNEL_CODE', + 'en_US' + )); + + + self::assertSame(1, $emailChecker->countMessagesTo('user@example.com')); + + self::assertTrue($emailChecker->hasMessageTo( + $translator->trans('sylius.email.password_reset.to_reset_your_password_token', [], null, 'en_US'), + 'user@example.com' + )); + } + + /** + * @test + */ + public function it_sends_password_reset_token_email_with_hostname(): void + { + static::bootKernel(); + + /** @var Filesystem $filesystem */ + $filesystem = static::$kernel->getContainer()->get('filesystem'); + + /** @var TranslatorInterface $translator */ + $translator = static::$kernel->getContainer()->get('translator'); + + /** @var EmailChecker $emailChecker */ + $emailChecker = static::$kernel->getContainer()->get('sylius.behat.email_checker'); + + $filesystem->remove($emailChecker->getSpoolDirectory()); + + $emailSender = static::$kernel->getContainer()->get('sylius.email_sender'); + + /** @var ChannelRepositoryInterface|ObjectProphecy $channelRepository */ + $channelRepository = $this->prophesize(ChannelRepositoryInterface::class); + /** @var UserRepositoryInterface|ObjectProphecy $userRepository */ + $userRepository = $this->prophesize(UserRepositoryInterface::class); + /** @var ChannelInterface|ObjectProphecy $channel */ + $channel = $this->prophesize(ChannelInterface::class); + /** @var UserInterface|ObjectProphecy $user */ + $user = $this->prophesize(UserInterface::class); + + $user->getUsername()->willReturn('username'); + $user->getPasswordResetToken()->willReturn('token'); + + $channelRepository->findOneByCode('CHANNEL_CODE')->willReturn($channel->reveal()); + $userRepository->findOneByEmail('user@example.com')->willReturn($user->reveal()); + + $resetPasswordEmailHandler = new SendResetPasswordEmailHandler( + $emailSender, + $channelRepository->reveal(), + $userRepository->reveal() + ); + + $resetPasswordEmailHandler(new SendResetPasswordEmail( + 'user@example.com', + 'CHANNEL_CODE', + 'en_US' + )); + + self::assertSame(1, $emailChecker->countMessagesTo('user@example.com')); + + self::assertTrue($emailChecker->hasMessageTo( + $translator->trans('sylius.email.password_reset.to_reset_your_password_token', [], null, 'en_US'), + 'user@example.com' + )); + } +} diff --git a/src/Sylius/Bundle/ApiBundle/Tests/TestKernel.php b/src/Sylius/Bundle/ApiBundle/Tests/TestKernel.php new file mode 100644 index 00000000000..6616a08ac96 --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/Tests/TestKernel.php @@ -0,0 +1,199 @@ +setParameter('locale', 'en_US'); + + $containerBuilder->loadFromExtension('framework', [ + 'test' => null, + 'secret' => 'S0ME_SECRET', + 'session' => [ + 'handler_id' => null, + ], + 'default_locale' => '%locale%', + 'translator' => [ + 'fallbacks' => [ + '%locale%', + 'en', + ], + ], + ]); + + $containerBuilder->loadFromExtension('security', [ + 'firewalls' => [ + 'main' => [ + 'anonymous' => true, + ], + ], + ]); + + $containerBuilder->loadFromExtension('doctrine', [ + 'dbal' => [ + 'driver' => 'pdo_mysql', + 'server_version' => '5.7', + 'charset' => 'UTF8', + 'url' => 'sqlite:///%kernel.project_dir%/var/data.db', + ], + ]); + + $containerBuilder->loadFromExtension('swiftmailer', [ + 'disable_delivery' => true, + 'logging' => true, + 'spool' => [ + 'type' => 'file', + 'path' => '%kernel.cache_dir%/spool', + ], + ]); + + $containerBuilder->loadFromExtension('stof_doctrine_extensions', [ + 'default_locale' => '%locale%', + ]); + + $containerBuilder->loadFromExtension('twig', [ + 'debug' => '%kernel.debug%', + 'strict_variables' => '%kernel.debug%', + ]); + + $containerBuilder->loadFromExtension('lexik_jwt_authentication', [ + 'secret_key' => 'var', + 'public_key' => 'var', + 'pass_phrase' => 'var', + ]); + + $loader->load('@SyliusCoreBundle/Resources/config/app/config.yml'); + $loader->load('@SyliusApiBundle/Resources/config/app/config.yaml'); + } + + protected function configureRoutes(RoutingConfigurator $routes): void + { + } + + public function getCacheDir(): string + { + return sys_get_temp_dir() . '/SyliusApiBundle/cache/' . $this->getEnvironment(); + } + + public function getLogDir(): string + { + return sys_get_temp_dir() . '/SyliusApiBundle/logs'; + } +} diff --git a/src/Sylius/Bundle/ApiBundle/phpunit.xml.dist b/src/Sylius/Bundle/ApiBundle/phpunit.xml.dist index 31c6db728e2..5d986d3f7f9 100644 --- a/src/Sylius/Bundle/ApiBundle/phpunit.xml.dist +++ b/src/Sylius/Bundle/ApiBundle/phpunit.xml.dist @@ -9,4 +9,15 @@ ./Tests/ + + + + + + + + + + + diff --git a/src/Sylius/Bundle/CoreBundle/Resources/views/Email/passwordReset.html.twig b/src/Sylius/Bundle/CoreBundle/Resources/views/Email/passwordReset.html.twig index f696ebd2806..559ec8c2d02 100644 --- a/src/Sylius/Bundle/CoreBundle/Resources/views/Email/passwordReset.html.twig +++ b/src/Sylius/Bundle/CoreBundle/Resources/views/Email/passwordReset.html.twig @@ -6,7 +6,7 @@ {% block content %} {% if sylius_bundle_loaded_checker('SyliusShopBundle') %} - {% set url = channel.hostname is not null ? 'http://' ~ channel.hostname ~ path('sylius_shop_password_reset', { 'token': user.passwordResetToken}) : url('sylius_shop_password_reset', { 'token': user.passwordResetToken}) %} + {% set url = channel.hostname is not null ? 'http://' ~ channel.hostname ~ path('sylius_shop_password_reset', { 'token': user.passwordResetToken}) : url('sylius_shop_password_reset', { 'token': user.passwordResetToken, '_locale': localeCode}) %} {% endif %}
@@ -15,7 +15,7 @@ {% if sylius_bundle_loaded_checker('SyliusShopBundle') %} {{ 'sylius.email.password_reset.to_reset_your_password'|trans({}, null, localeCode) }}: {% else %} - {{ 'sylius.email.password_reset.to_reset_your_password'|trans({}, null, localeCode) }}: + {{ 'sylius.email.password_reset.to_reset_your_password_token'|trans({}, null, localeCode) }}: {% endif %}
From e79526a4d5b254abbdde09560d4bbe59cfe16658 Mon Sep 17 00:00:00 2001 From: arti0090 Date: Wed, 24 Feb 2021 12:21:42 +0100 Subject: [PATCH 13/15] fixes --- src/Sylius/Behat/Context/Api/Shop/LoginContext.php | 2 +- .../ApiBundle/Command/LocaleCodeAwareInterface.php | 10 ++++++++++ .../ApiBundle/Command/SendResetPasswordEmail.php | 1 + .../RequestResetPasswordTokenHandler.php | 11 ++++++----- .../CommandHandler/SendResetPasswordEmailHandler.php | 1 + .../LocaleCodeAwareInputCommandDataTransformer.php | 9 +++++++++ .../Resources/config/api_resources/Customer.xml | 2 +- .../serialization/Commands/Account/ResetPassword.xml | 4 ++-- .../Resources/config/validation/ResetPassword.xml | 1 - .../SendResetPasswordEmailHandlerTest.php | 2 -- src/Sylius/Bundle/ApiBundle/composer.json | 3 ++- 11 files changed, 33 insertions(+), 13 deletions(-) diff --git a/src/Sylius/Behat/Context/Api/Shop/LoginContext.php b/src/Sylius/Behat/Context/Api/Shop/LoginContext.php index 7441d1ba3f9..fb3d2e4864b 100644 --- a/src/Sylius/Behat/Context/Api/Shop/LoginContext.php +++ b/src/Sylius/Behat/Context/Api/Shop/LoginContext.php @@ -31,7 +31,7 @@ final class LoginContext implements Context /** @var ResponseCheckerInterface */ private $responseChecker; - /** @var Request */ + /** @var Request|null */ private $request; public function __construct( diff --git a/src/Sylius/Bundle/ApiBundle/Command/LocaleCodeAwareInterface.php b/src/Sylius/Bundle/ApiBundle/Command/LocaleCodeAwareInterface.php index 2599be8a758..d0573a1da81 100644 --- a/src/Sylius/Bundle/ApiBundle/Command/LocaleCodeAwareInterface.php +++ b/src/Sylius/Bundle/ApiBundle/Command/LocaleCodeAwareInterface.php @@ -1,9 +1,19 @@ userRepository = $userRepository; - $this->eventBus = $eventBus; + $this->commandBus = $eventBus; $this->generator = $generator; } @@ -51,12 +51,13 @@ public function __invoke(RequestResetPasswordToken $command): void $user->setPasswordResetToken($this->generator->generate()); $user->setPasswordRequestedAt(new \DateTime()); - $this->eventBus->dispatch( + $this->commandBus->dispatch( new SendResetPasswordEmail( $command->getEmail(), $command->getChannelCode(), $command->getLocaleCode() - ) + ), + [new DispatchAfterCurrentBusStamp()] ); } } diff --git a/src/Sylius/Bundle/ApiBundle/CommandHandler/SendResetPasswordEmailHandler.php b/src/Sylius/Bundle/ApiBundle/CommandHandler/SendResetPasswordEmailHandler.php index 279ceaf480f..0b4eba47224 100644 --- a/src/Sylius/Bundle/ApiBundle/CommandHandler/SendResetPasswordEmailHandler.php +++ b/src/Sylius/Bundle/ApiBundle/CommandHandler/SendResetPasswordEmailHandler.php @@ -20,6 +20,7 @@ use Sylius\Component\User\Repository\UserRepositoryInterface; use Symfony\Component\Messenger\Handler\MessageHandlerInterface; +/** @experimental */ final class SendResetPasswordEmailHandler implements MessageHandlerInterface { /** @var SenderInterface */ diff --git a/src/Sylius/Bundle/ApiBundle/DataTransformer/LocaleCodeAwareInputCommandDataTransformer.php b/src/Sylius/Bundle/ApiBundle/DataTransformer/LocaleCodeAwareInputCommandDataTransformer.php index b0b02027a68..4049d0dbaa3 100644 --- a/src/Sylius/Bundle/ApiBundle/DataTransformer/LocaleCodeAwareInputCommandDataTransformer.php +++ b/src/Sylius/Bundle/ApiBundle/DataTransformer/LocaleCodeAwareInputCommandDataTransformer.php @@ -1,5 +1,14 @@ sylius_shop_password_reset - shop:password_reset:create + shop:reset_password:create Request password reset diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/serialization/Commands/Account/ResetPassword.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/serialization/Commands/Account/ResetPassword.xml index 194ac5cd5b9..26c1d0c2685 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/serialization/Commands/Account/ResetPassword.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/serialization/Commands/Account/ResetPassword.xml @@ -17,10 +17,10 @@ > - shop:password_reset:create + shop:reset_password:create - shop:password_reset:create + shop:reset_password:create diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/validation/ResetPassword.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/validation/ResetPassword.xml index e22a04d6c04..933f0360cff 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/validation/ResetPassword.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/validation/ResetPassword.xml @@ -24,6 +24,5 @@ - diff --git a/src/Sylius/Bundle/ApiBundle/Tests/CommandHandler/SendResetPasswordEmailHandlerTest.php b/src/Sylius/Bundle/ApiBundle/Tests/CommandHandler/SendResetPasswordEmailHandlerTest.php index 39cea837ed0..a69aceae048 100644 --- a/src/Sylius/Bundle/ApiBundle/Tests/CommandHandler/SendResetPasswordEmailHandlerTest.php +++ b/src/Sylius/Bundle/ApiBundle/Tests/CommandHandler/SendResetPasswordEmailHandlerTest.php @@ -27,7 +27,6 @@ final class SendResetPasswordEmailHandlerTest extends KernelTestCase { - /** * @test */ @@ -75,7 +74,6 @@ public function it_sends_password_reset_token_email_without_hostname(): void 'en_US' )); - self::assertSame(1, $emailChecker->countMessagesTo('user@example.com')); self::assertTrue($emailChecker->hasMessageTo( diff --git a/src/Sylius/Bundle/ApiBundle/composer.json b/src/Sylius/Bundle/ApiBundle/composer.json index d58b096da0c..dce65a573a5 100644 --- a/src/Sylius/Bundle/ApiBundle/composer.json +++ b/src/Sylius/Bundle/ApiBundle/composer.json @@ -26,7 +26,8 @@ "php": "^7.4", "api-platform/core": "^2.5", "sylius/core-bundle": "^1.7", - "symfony/messenger": "^4.4 || ^5.2" + "symfony/messenger": "^4.4 || ^5.2", + "lexik/jwt-authentication-bundle": "^2.6" }, "require-dev": { "matthiasnoback/symfony-config-test": "^4.2", From 53e2976eb679e0d8493c0ecdfb705bf026a461bc Mon Sep 17 00:00:00 2001 From: arti0090 Date: Thu, 25 Feb 2021 08:25:59 +0100 Subject: [PATCH 14/15] more fixes --- .../Behat/Context/Api/Shop/LoginContext.php | 30 +++++++++---------- .../Command/RequestResetPasswordToken.php | 1 + .../SendResetPasswordEmailHandlerTest.php | 24 +++++++-------- 3 files changed, 27 insertions(+), 28 deletions(-) diff --git a/src/Sylius/Behat/Context/Api/Shop/LoginContext.php b/src/Sylius/Behat/Context/Api/Shop/LoginContext.php index fb3d2e4864b..31f638b783d 100644 --- a/src/Sylius/Behat/Context/Api/Shop/LoginContext.php +++ b/src/Sylius/Behat/Context/Api/Shop/LoginContext.php @@ -23,7 +23,7 @@ final class LoginContext implements Context { /** @var ApiSecurityClientInterface */ - private $client; + private $apiSecurityClient; /** @var ApiClientInterface */ private $apiClient; @@ -35,11 +35,11 @@ final class LoginContext implements Context private $request; public function __construct( - ApiSecurityClientInterface $client, + ApiSecurityClientInterface $apiSecurityClient, ApiClientInterface $apiClient, ResponseCheckerInterface $responseChecker ) { - $this->client = $client; + $this->apiSecurityClient = $apiSecurityClient; $this->apiClient = $apiClient; $this->responseChecker = $responseChecker; } @@ -57,7 +57,7 @@ public function iAmAVisitor(): void */ public function iWantToLogIn(): void { - $this->client->prepareLoginRequest(); + $this->apiSecurityClient->prepareLoginRequest(); } /** @@ -93,7 +93,7 @@ public function iResetIt(): void */ public function iSpecifyTheUsername(string $username): void { - $this->client->setEmail($username); + $this->apiSecurityClient->setEmail($username); } /** @@ -110,7 +110,7 @@ public function iSpecifyTheEmail(string $email = ''): void */ public function iSpecifyThePasswordAs(string $password): void { - $this->client->setPassword($password); + $this->apiSecurityClient->setPassword($password); } /** @@ -119,7 +119,7 @@ public function iSpecifyThePasswordAs(string $password): void */ public function iLogIn(): void { - $this->client->call(); + $this->apiSecurityClient->call(); } /** @@ -127,10 +127,10 @@ public function iLogIn(): void */ public function iLogInAsWithPassword(string $email, string $password): void { - $this->client->prepareLoginRequest(); - $this->client->setEmail($email); - $this->client->setPassword($password); - $this->client->call(); + $this->apiSecurityClient->prepareLoginRequest(); + $this->apiSecurityClient->setEmail($email); + $this->apiSecurityClient->setPassword($password); + $this->apiSecurityClient->call(); } /** @@ -139,7 +139,7 @@ public function iLogInAsWithPassword(string $email, string $password): void */ public function iLogOut() { - $this->client->logOut(); + $this->apiSecurityClient->logOut(); } /** @@ -147,7 +147,7 @@ public function iLogOut() */ public function iShouldBeLoggedIn(): void { - Assert::true($this->client->isLoggedIn(), 'Shop user should be logged in, but they are not.'); + Assert::true($this->apiSecurityClient->isLoggedIn(), 'Shop user should be logged in, but they are not.'); } /** @@ -155,7 +155,7 @@ public function iShouldBeLoggedIn(): void */ public function iShouldNotBeLoggedIn(): void { - Assert::false($this->client->isLoggedIn(), 'Shop user should not be logged in, but they are.'); + Assert::false($this->apiSecurityClient->isLoggedIn(), 'Shop user should not be logged in, but they are.'); } /** @@ -163,7 +163,7 @@ public function iShouldNotBeLoggedIn(): void */ public function iShouldBeNotifiedAboutBadCredentials(): void { - Assert::same($this->client->getErrorMessage(), 'Invalid credentials.'); + Assert::same($this->apiSecurityClient->getErrorMessage(), 'Invalid credentials.'); } /** diff --git a/src/Sylius/Bundle/ApiBundle/Command/RequestResetPasswordToken.php b/src/Sylius/Bundle/ApiBundle/Command/RequestResetPasswordToken.php index 615078b54e0..786c3089b1a 100644 --- a/src/Sylius/Bundle/ApiBundle/Command/RequestResetPasswordToken.php +++ b/src/Sylius/Bundle/ApiBundle/Command/RequestResetPasswordToken.php @@ -13,6 +13,7 @@ namespace Sylius\Bundle\ApiBundle\Command; +/** @experimental */ class RequestResetPasswordToken implements ChannelCodeAwareInterface, LocaleCodeAwareInterface { /** @var string */ diff --git a/src/Sylius/Bundle/ApiBundle/Tests/CommandHandler/SendResetPasswordEmailHandlerTest.php b/src/Sylius/Bundle/ApiBundle/Tests/CommandHandler/SendResetPasswordEmailHandlerTest.php index a69aceae048..37a236e0d4d 100644 --- a/src/Sylius/Bundle/ApiBundle/Tests/CommandHandler/SendResetPasswordEmailHandlerTest.php +++ b/src/Sylius/Bundle/ApiBundle/Tests/CommandHandler/SendResetPasswordEmailHandlerTest.php @@ -32,20 +32,20 @@ final class SendResetPasswordEmailHandlerTest extends KernelTestCase */ public function it_sends_password_reset_token_email_without_hostname(): void { - static::bootKernel(); + $container = self::bootKernel()->getContainer(); /** @var Filesystem $filesystem */ - $filesystem = static::$kernel->getContainer()->get('filesystem'); + $filesystem = $container->get('filesystem'); /** @var TranslatorInterface $translator */ - $translator = static::$kernel->getContainer()->get('translator'); + $translator = $container->get('translator'); /** @var EmailChecker $emailChecker */ - $emailChecker = static::$kernel->getContainer()->get('sylius.behat.email_checker'); + $emailChecker = $container->get('sylius.behat.email_checker'); $filesystem->remove($emailChecker->getSpoolDirectory()); - $emailSender = static::$kernel->getContainer()->get('sylius.email_sender'); + $emailSender = $container->get('sylius.email_sender'); /** @var ChannelRepositoryInterface|ObjectProphecy $channelRepository */ $channelRepository = $this->prophesize(ChannelRepositoryInterface::class); @@ -75,9 +75,8 @@ public function it_sends_password_reset_token_email_without_hostname(): void )); self::assertSame(1, $emailChecker->countMessagesTo('user@example.com')); - self::assertTrue($emailChecker->hasMessageTo( - $translator->trans('sylius.email.password_reset.to_reset_your_password_token', [], null, 'en_US'), + $translator->trans('sylius.email.password_reset.to_reset_your_password_token', [], null, 'en_US'), 'user@example.com' )); } @@ -87,20 +86,20 @@ public function it_sends_password_reset_token_email_without_hostname(): void */ public function it_sends_password_reset_token_email_with_hostname(): void { - static::bootKernel(); + $container = self::bootKernel()->getContainer(); /** @var Filesystem $filesystem */ - $filesystem = static::$kernel->getContainer()->get('filesystem'); + $filesystem = $container->get('filesystem'); /** @var TranslatorInterface $translator */ - $translator = static::$kernel->getContainer()->get('translator'); + $translator = $container->get('translator'); /** @var EmailChecker $emailChecker */ - $emailChecker = static::$kernel->getContainer()->get('sylius.behat.email_checker'); + $emailChecker = $container->get('sylius.behat.email_checker'); $filesystem->remove($emailChecker->getSpoolDirectory()); - $emailSender = static::$kernel->getContainer()->get('sylius.email_sender'); + $emailSender = $container->get('sylius.email_sender'); /** @var ChannelRepositoryInterface|ObjectProphecy $channelRepository */ $channelRepository = $this->prophesize(ChannelRepositoryInterface::class); @@ -130,7 +129,6 @@ public function it_sends_password_reset_token_email_with_hostname(): void )); self::assertSame(1, $emailChecker->countMessagesTo('user@example.com')); - self::assertTrue($emailChecker->hasMessageTo( $translator->trans('sylius.email.password_reset.to_reset_your_password_token', [], null, 'en_US'), 'user@example.com' From 72aa4fc521f896c9de775dcce9cbc5601e32d111 Mon Sep 17 00:00:00 2001 From: arti0090 Date: Thu, 25 Feb 2021 12:40:31 +0100 Subject: [PATCH 15/15] change configuration for endpoint to custom resource --- .../config/api_resources/Customer.xml | 19 -------- .../config/api_resources/PasswordReset.xml | 46 +++++++++++++++++++ 2 files changed, 46 insertions(+), 19 deletions(-) create mode 100644 src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/PasswordReset.xml diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Customer.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Customer.xml index ed1625ecb22..a4279b8058b 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Customer.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Customer.xml @@ -33,25 +33,6 @@ Sylius\Bundle\ApiBundle\Command\RegisterShopUser false - - - POST - shop/request-reset-password - input - Sylius\Bundle\ApiBundle\Command\RequestResetPasswordToken - false - 202 - - sylius - sylius_shop_password_reset - - - shop:reset_password:create - - - Request password reset - - diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/PasswordReset.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/PasswordReset.xml new file mode 100644 index 00000000000..d1b5f792244 --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/PasswordReset.xml @@ -0,0 +1,46 @@ + + + + + + + + sylius + + + + POST + shop/request-reset-password + input + Sylius\Bundle\ApiBundle\Command\RequestResetPasswordToken + false + 202 + + sylius + sylius_shop_password_reset + + + shop:reset_password:create + + + Request password reset + + + + + + + +