From e912206db5dd0e99a19a43a3b081606e63fc5fa4 Mon Sep 17 00:00:00 2001 From: kloz Date: Mon, 12 Jun 2023 12:01:18 +0200 Subject: [PATCH 01/11] [VSF2] Missing migrations added: refresh_token (create), product_attribute_value (index) --- migrations/Version20230612094617.php | 26 +++++++++++++++++++ migrations/Version20230612095046.php | 26 +++++++++++++++++++ .../config/packages/doctrine_migrations.yaml | 3 +++ 3 files changed, 55 insertions(+) create mode 100644 migrations/Version20230612094617.php create mode 100644 migrations/Version20230612095046.php diff --git a/migrations/Version20230612094617.php b/migrations/Version20230612094617.php new file mode 100644 index 00000000..be3c2fae --- /dev/null +++ b/migrations/Version20230612094617.php @@ -0,0 +1,26 @@ +addSql('CREATE TABLE bitbag_refresh_token (id INT AUTO_INCREMENT NOT NULL, refresh_token VARCHAR(128) NOT NULL, username VARCHAR(255) NOT NULL, valid DATETIME NOT NULL, remember_me TINYINT(1) NOT NULL, UNIQUE INDEX UNIQ_CD7BD0E9C74F2195 (refresh_token), PRIMARY KEY(id)) DEFAULT CHARACTER SET UTF8 COLLATE `UTF8_unicode_ci` ENGINE = InnoDB'); + } + + public function down(Schema $schema): void + { + $this->addSql('DROP TABLE bitbag_refresh_token'); + } +} diff --git a/migrations/Version20230612095046.php b/migrations/Version20230612095046.php new file mode 100644 index 00000000..d584e341 --- /dev/null +++ b/migrations/Version20230612095046.php @@ -0,0 +1,26 @@ +addSql('CREATE INDEX locale_code ON sylius_product_attribute_value (locale_code)'); + } + + public function down(Schema $schema): void + { + $this->addSql('DROP INDEX locale_code ON sylius_product_attribute_value'); + } +} diff --git a/tests/Application/config/packages/doctrine_migrations.yaml b/tests/Application/config/packages/doctrine_migrations.yaml index cdbc01ae..7ffde0f7 100644 --- a/tests/Application/config/packages/doctrine_migrations.yaml +++ b/tests/Application/config/packages/doctrine_migrations.yaml @@ -2,3 +2,6 @@ doctrine_migrations: storage: table_storage: table_name: sylius_migrations + + migrations_paths: + 'migrations': '%kernel.project_dir%/../../migrations' From 9f61231bf9bee71e21897cf26a951f9d816f392a Mon Sep 17 00:00:00 2001 From: kloz Date: Mon, 12 Jun 2023 12:23:06 +0200 Subject: [PATCH 02/11] [VSF2] IF NOT EXISTS on bitbag_refresh_token creation --- migrations/Version20230612094617.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migrations/Version20230612094617.php b/migrations/Version20230612094617.php index be3c2fae..fd84b5d3 100644 --- a/migrations/Version20230612094617.php +++ b/migrations/Version20230612094617.php @@ -16,7 +16,7 @@ public function getDescription(): string public function up(Schema $schema): void { - $this->addSql('CREATE TABLE bitbag_refresh_token (id INT AUTO_INCREMENT NOT NULL, refresh_token VARCHAR(128) NOT NULL, username VARCHAR(255) NOT NULL, valid DATETIME NOT NULL, remember_me TINYINT(1) NOT NULL, UNIQUE INDEX UNIQ_CD7BD0E9C74F2195 (refresh_token), PRIMARY KEY(id)) DEFAULT CHARACTER SET UTF8 COLLATE `UTF8_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE IF NOT EXISTS bitbag_refresh_token (id INT AUTO_INCREMENT NOT NULL, refresh_token VARCHAR(128) NOT NULL, username VARCHAR(255) NOT NULL, valid DATETIME NOT NULL, remember_me TINYINT(1) NOT NULL, UNIQUE INDEX UNIQ_CD7BD0E9C74F2195 (refresh_token), PRIMARY KEY(id)) DEFAULT CHARACTER SET UTF8 COLLATE `UTF8_unicode_ci` ENGINE = InnoDB'); } public function down(Schema $schema): void From 87baf173ecccc082a7a47e215d89965f2c51f590 Mon Sep 17 00:00:00 2001 From: Maciej Date: Tue, 13 Jun 2023 14:36:26 +0200 Subject: [PATCH 03/11] VSF2-54 - adds sylius mailer for test app, nulls password token after password change --- composer.json | 2 ++ src/CommandHandler/Account/ResetPasswordHandler.php | 1 + tests/Application/.env | 7 +++++++ tests/Application/config/packages/_sylius.yaml | 3 +++ tests/Application/config/packages/framework.yaml | 2 ++ 5 files changed, 15 insertions(+) diff --git a/composer.json b/composer.json index de9ba0cf..6a81121a 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,9 @@ "ext-openssl": "*", "bitbag/wishlist-plugin": "^3.0", "gesdinet/jwt-refresh-token-bundle": "^0.12.0", + "php-http/message-factory": "^1.1", "sylius/sylius": "~1.11.0", + "symfony/mailer": "^6.0", "webonyx/graphql-php": "^14.9" }, "require-dev": { diff --git a/src/CommandHandler/Account/ResetPasswordHandler.php b/src/CommandHandler/Account/ResetPasswordHandler.php index 849f34de..62e66f03 100644 --- a/src/CommandHandler/Account/ResetPasswordHandler.php +++ b/src/CommandHandler/Account/ResetPasswordHandler.php @@ -65,6 +65,7 @@ public function __invoke(ResetPassword $command): CustomerInterface $user->setPlainPassword($command->newPassword); $this->passwordUpdater->updatePassword($user); + $user->setPasswordResetToken(null); $customer = $user->getCustomer(); Assert::notNull($customer); diff --git a/tests/Application/.env b/tests/Application/.env index 4040c0ac..24b7e335 100644 --- a/tests/Application/.env +++ b/tests/Application/.env @@ -31,6 +31,13 @@ JWT_PASSPHRASE=acme_plugin_development MAILER_URL=smtp://localhost ###< symfony/swiftmailer-bundle ### +###> symfony/mailer ### +# For Gmail as a transport, use: "gmail://username:password@localhost" +# For a generic SMTP server, use: "smtp://localhost:25?encryption=&auth_mode=" +# Delivery is disabled by default via "null://null" +MAILER_DSN=null://null +###< symfony/mailer ### + ###> symfony/messenger ### # Choose one of the transports below # MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages diff --git a/tests/Application/config/packages/_sylius.yaml b/tests/Application/config/packages/_sylius.yaml index d4bdff13..a72da91d 100644 --- a/tests/Application/config/packages/_sylius.yaml +++ b/tests/Application/config/packages/_sylius.yaml @@ -20,3 +20,6 @@ sylius_attribute: sylius_api: enabled: true + +sylius_mailer: + sender_adapter: sylius.email_sender.adapter.symfony_mailer diff --git a/tests/Application/config/packages/framework.yaml b/tests/Application/config/packages/framework.yaml index ea257191..a29afc11 100644 --- a/tests/Application/config/packages/framework.yaml +++ b/tests/Application/config/packages/framework.yaml @@ -9,3 +9,5 @@ framework: mapping: paths: - '%kernel.project_dir%/../../src/Resources/serialization' + mailer: + dsn: '%env(MAILER_DSN)%' From 20d1813de1c0e4020da9c93cef13d2da2d4c089a Mon Sep 17 00:00:00 2001 From: Maciej Date: Thu, 15 Jun 2023 09:11:03 +0200 Subject: [PATCH 04/11] VSF2-54 - adds graphql api configuration for password reset --- .../Query/PasswordResetTokenResolver.php | 38 +++++++++++++++++++ src/Resources/api_resources/ShopUser.xml | 12 ++++++ src/Resources/serialization/ShopUser.xml | 3 ++ src/Resources/services/resolvers.xml | 6 +++ 4 files changed, 59 insertions(+) create mode 100644 src/Resolver/Query/PasswordResetTokenResolver.php diff --git a/src/Resolver/Query/PasswordResetTokenResolver.php b/src/Resolver/Query/PasswordResetTokenResolver.php new file mode 100644 index 00000000..6c204c47 --- /dev/null +++ b/src/Resolver/Query/PasswordResetTokenResolver.php @@ -0,0 +1,38 @@ +userRepository = $userRepository; + } + + + public function __invoke($item, array $context) + { + $token = $context['args']['passwordResetToken']; + $user = $this->userRepository->findOneBy(['passwordResetToken' => $token]); + + if (null !== $user){ + return $user; + } + + throw new \Exception('Invalid token'); + } +} diff --git a/src/Resources/api_resources/ShopUser.xml b/src/Resources/api_resources/ShopUser.xml index d99ef0f9..c0056dac 100644 --- a/src/Resources/api_resources/ShopUser.xml +++ b/src/Resources/api_resources/ShopUser.xml @@ -13,6 +13,18 @@ We are hiring developers from all over the world. Join us and start your new, ex + + + shop:password_reset_token:read + + bitbag.sylius_vue_storefront2plugin.resolver.query.password_reset_token_resolver + + + String! + + + + input \Sylius\Bundle\ApiBundle\Command\Account\RegisterShopUser diff --git a/src/Resources/serialization/ShopUser.xml b/src/Resources/serialization/ShopUser.xml index cdad00cc..c82bce8f 100644 --- a/src/Resources/serialization/ShopUser.xml +++ b/src/Resources/serialization/ShopUser.xml @@ -15,5 +15,8 @@ We are hiring developers from all over the world. Join us and start your new, ex shop:customer:read shop:user_login:read + + shop:password_reset_token:read + diff --git a/src/Resources/services/resolvers.xml b/src/Resources/services/resolvers.xml index 9f480639..be3b049d 100644 --- a/src/Resources/services/resolvers.xml +++ b/src/Resources/services/resolvers.xml @@ -48,6 +48,12 @@ We are hiring developers from all over the world. Join us and start your new, ex + + + + + From 64ffd156e9622b63fbf31ae05f782fabc1344c82 Mon Sep 17 00:00:00 2001 From: Maciej Date: Thu, 15 Jun 2023 11:38:53 +0200 Subject: [PATCH 05/11] VSF2-54 - changes error throw with null being returned, adds specs --- .../Account/ResetPasswordHandlerSpec.php | 1 + .../Query/PasswordResetTokenResolverSpec.php | 67 +++++++++++++++++++ .../Query/PasswordResetTokenResolver.php | 10 +-- 3 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 spec/Resolver/Query/PasswordResetTokenResolverSpec.php diff --git a/spec/CommandHandler/Account/ResetPasswordHandlerSpec.php b/spec/CommandHandler/Account/ResetPasswordHandlerSpec.php index 7ae6a8ca..9a41e7c2 100644 --- a/spec/CommandHandler/Account/ResetPasswordHandlerSpec.php +++ b/spec/CommandHandler/Account/ResetPasswordHandlerSpec.php @@ -72,6 +72,7 @@ public function it_is_invokable( $user->setPlainPassword($command->newPassword)->shouldBeCalled(); $passwordUpdater->updatePassword($user->getWrappedObject())->shouldBeCalled(); + $user->setPasswordResetToken(null)->shouldBeCalled(); $user->getCustomer()->willReturn($customer); diff --git a/spec/Resolver/Query/PasswordResetTokenResolverSpec.php b/spec/Resolver/Query/PasswordResetTokenResolverSpec.php new file mode 100644 index 00000000..1f4e1d32 --- /dev/null +++ b/spec/Resolver/Query/PasswordResetTokenResolverSpec.php @@ -0,0 +1,67 @@ +beConstructedWith( + $userRepository + ); + } + + public function it_is_initializable(): void + { + $this->shouldHaveType(PasswordResetTokenResolver::class); + } + + public function it_returns_user_on_valid_token( + UserRepositoryInterface $userRepository, + ShopUserInterface $user + ): void { + $context = [ + 'args' => [ + 'passwordResetToken' => "TOKEN", + ], + ]; + + $token = $context['args']['passwordResetToken']; + + $userRepository->findOneBy(['passwordResetToken' => $token])->willReturn($user); + + $this->__invoke(null, $context)->shouldReturn($user); + } + + public function it_should_return_null_on_invalid_token( + UserRepositoryInterface $userRepository, + ): void { + $context = [ + 'args' => [ + 'passwordResetToken' => "TOKEN", + ], + ]; + + $token = $context['args']['passwordResetToken']; + + $userRepository->findOneBy(['passwordResetToken' => $token])->willReturn(null); + + $this->__invoke(null, $context)->shouldReturn(null); + } +} diff --git a/src/Resolver/Query/PasswordResetTokenResolver.php b/src/Resolver/Query/PasswordResetTokenResolver.php index 6c204c47..89c986b5 100644 --- a/src/Resolver/Query/PasswordResetTokenResolver.php +++ b/src/Resolver/Query/PasswordResetTokenResolver.php @@ -13,26 +13,28 @@ namespace BitBag\SyliusVueStorefront2Plugin\Resolver\Query; use ApiPlatform\GraphQl\Resolver\QueryItemResolverInterface; +use Sylius\Component\Core\Model\ShopUserInterface; use Sylius\Component\User\Repository\UserRepositoryInterface; class PasswordResetTokenResolver implements QueryItemResolverInterface { - private UserRepositoryInterface $userRepository; + private UserRepositoryInterface $userRepository; + public function __construct(UserRepositoryInterface $userRepository) { $this->userRepository = $userRepository; } - public function __invoke($item, array $context) + public function __invoke($item, array $context): ?ShopUserInterface { $token = $context['args']['passwordResetToken']; $user = $this->userRepository->findOneBy(['passwordResetToken' => $token]); - if (null !== $user){ + if (null !== $user) { return $user; } - throw new \Exception('Invalid token'); + return null; } } From d64d049863cd89e87e2cf5b0f4de7f337e83eabf Mon Sep 17 00:00:00 2001 From: Maciej Date: Thu, 15 Jun 2023 14:20:32 +0200 Subject: [PATCH 06/11] VSF2-54 - adds tests for password reminder functionality --- .../shop/account/resetting_password.feature | 37 ++++++++++ src/Resources/services/behat/contexts.xml | 1 + .../Context/GraphqlApiPlatformContext.php | 9 +++ tests/Behat/Context/Shop/CustomerContext.php | 73 +++++++++++++++++++ tests/Behat/Resources/suites.yml | 1 + .../suites/account/resetting_password.yaml | 11 +++ 6 files changed, 132 insertions(+) create mode 100644 features/shop/account/resetting_password.feature create mode 100755 tests/Behat/Resources/suites/account/resetting_password.yaml diff --git a/features/shop/account/resetting_password.feature b/features/shop/account/resetting_password.feature new file mode 100644 index 00000000..63f79e9e --- /dev/null +++ b/features/shop/account/resetting_password.feature @@ -0,0 +1,37 @@ +@resetting_password +Feature: Resetting one customer password + In order to reset my password + As a Customer + I need to be able to reset it by reset query + + + Background: + Given the store operates on a single channel in "United States" + And the store has locale "en_US" + And there is a customer account "shop@example.com" + + @graphql + Scenario: Setting token for password reset + Given I prepare password reset request operation for user "shop@example.com" + And I send that GraphQL request + Then I should receive a JSON response + And This response should contain pattern '/^\{"data":\{"shop_send_reset_password_emailCustomer":\{"customer":\{"id":"\/api\/v2\/shop\/customers\/(\d+)"\}\}\}\}$/' + And user "shop@example.com" should have reset password token set + + @graphql + Scenario: Checking for valid reset password token availability + Given I prepare password reset request operation for user "shop@example.com" + And I send that GraphQL request + And I prepare check reset password token operation for user's "shop@example.com" token + And I send that GraphQL request + Then I should receive a JSON response + And This response should contain pattern '/^\{"data":\{"password_reset_tokenUser":\{"username":"([^"]+)"\}\}\}$/' + + @graphql + Scenario: Checking for invalid reset password token availability + Given I prepare password reset request operation for user "shop@example.com" + And I send that GraphQL request + And I prepare check reset password token operation for invalid token + And I send that GraphQL request + Then I should receive a JSON response + And This response should contain pattern '/^\{"data":\{"password_reset_tokenUser":null\}\}$/' diff --git a/src/Resources/services/behat/contexts.xml b/src/Resources/services/behat/contexts.xml index 2494fa85..efb62fa4 100755 --- a/src/Resources/services/behat/contexts.xml +++ b/src/Resources/services/behat/contexts.xml @@ -19,6 +19,7 @@ + castToType($value, $type); $operation->addFilter($filterName, $value); } + + /** + * @Then This response should contain pattern :pattern + */ + public function responseShouldContainPattern(string $pattern): void{ + $response = $this->client->getLastResponse(); + $data = stripslashes($response->getContent()); + Assert::true((bool)preg_match($pattern, $data)); + } } diff --git a/tests/Behat/Context/Shop/CustomerContext.php b/tests/Behat/Context/Shop/CustomerContext.php index ced5fe3b..8b5d3d3e 100644 --- a/tests/Behat/Context/Shop/CustomerContext.php +++ b/tests/Behat/Context/Shop/CustomerContext.php @@ -13,8 +13,11 @@ use ApiPlatform\Core\Api\IriConverterInterface; use Behat\Behat\Context\Context; use BitBag\SyliusVueStorefront2Plugin\Factory\ShopUserTokenFactoryInterface; +use Doctrine\Common\DataFixtures\Purger\ORMPurger; +use Doctrine\ORM\EntityManagerInterface; use Sylius\Behat\Service\SharedStorageInterface; use Sylius\Component\Core\Model\ShopUserInterface; +use Sylius\Component\Locale\Model\LocaleInterface; use Sylius\Component\User\Repository\UserRepositoryInterface; use Tests\BitBag\SyliusVueStorefront2Plugin\Behat\Client\GraphqlClient; use Tests\BitBag\SyliusVueStorefront2Plugin\Behat\Client\GraphqlClientInterface; @@ -32,18 +35,33 @@ final class CustomerContext implements Context private IriConverterInterface $iriConverter; + private EntityManagerInterface $entityManager; + public function __construct( GraphqlClientInterface $client, SharedStorageInterface $sharedStorage, UserRepositoryInterface $userRepository, ShopUserTokenFactoryInterface $tokenFactory, IriConverterInterface $iriConverter, + EntityManagerInterface $entityManager, ) { $this->client = $client; $this->sharedStorage = $sharedStorage; $this->userRepository = $userRepository; $this->tokenFactory = $tokenFactory; $this->iriConverter = $iriConverter; + $this->entityManager = $entityManager; + } + + /** + * @BeforeScenario + */ + public function purgeDatabase() + { + $this->entityManager->getConnection()->getConfiguration()->setSQLLogger(null); + $purger = new ORMPurger($this->entityManager); + $purger->purge(); + $this->entityManager->clear(); } /** @@ -158,4 +176,59 @@ public function iPrepareRefreshJwtTokenOperation(): void $operation->addVariable('refreshToken', $refreshToken); $this->sharedStorage->set(GraphqlClient::GRAPHQL_OPERATION, $operation); } + + /** + * @Given I prepare password reset request operation for user :email + */ + public function iPreparePasswordResetRequestOperation(string $email): void + { + $mutationBody = ' + customer { + id + }'; + + /** @var LocaleInterface $locale */ + $locale = $this->sharedStorage->get('locale'); + + $operation = $this->client->prepareOperation('shop_send_reset_password_emailCustomer', $mutationBody); + $operation->addVariable('email', $email); + $operation->addVariable('localeCode', $locale->getCode()); + $this->sharedStorage->set(GraphqlClient::GRAPHQL_OPERATION, $operation); + } + + /** + * @Given /^user "([^"]*)" should have reset password token set$/ + */ + public function userShouldHaveResetPasswordTokenSet(string $email) + { + $user = $this->userRepository->findOneByEmail($email); + Assert::notNull($user->getPasswordResetToken()); + } + + /** + * @Given /^I prepare check reset password token operation for user's "([^"]*)" token$/ + */ + public function iPrepareCheckResetPasswordTokenOperationForUserSToken(string $email) + { + $user = $this->userRepository->findOneByEmail($email); + $token = "\"" . $user->getPasswordResetToken() . "\""; + $queryBody = 'username'; + $operation = $this->client->prepareQuery('password_reset_tokenUser', $queryBody); + + $operation->addFilter('passwordResetToken', $token); + $this->sharedStorage->set(GraphqlClient::GRAPHQL_OPERATION, $operation); + } + + /** + * @Given /^I prepare check reset password token operation for invalid token$/ + */ + public function iPrepareCheckResetPasswordTokenOperationForUserSInvalidToken() + { + $token = "\"invalid-token\""; + $queryBody = 'username'; + $operation = $this->client->prepareQuery('password_reset_tokenUser', $queryBody); + + $operation->addFilter('passwordResetToken', $token); + $this->sharedStorage->set(GraphqlClient::GRAPHQL_OPERATION, $operation); + } } diff --git a/tests/Behat/Resources/suites.yml b/tests/Behat/Resources/suites.yml index afd822e2..cde8719d 100644 --- a/tests/Behat/Resources/suites.yml +++ b/tests/Behat/Resources/suites.yml @@ -6,6 +6,7 @@ imports: - suites/account/creating_account.yaml - suites/account/editing_account.yaml - suites/account/changing_password.yaml + - suites/account/resetting_password.yaml - suites/account/managing_addresses.yaml - suites/wishlist/wishlist_as_guest.yaml - suites/wishlist/wishlist_as_customer.yaml diff --git a/tests/Behat/Resources/suites/account/resetting_password.yaml b/tests/Behat/Resources/suites/account/resetting_password.yaml new file mode 100755 index 00000000..1627f039 --- /dev/null +++ b/tests/Behat/Resources/suites/account/resetting_password.yaml @@ -0,0 +1,11 @@ +default: + suites: + graphql_resetting_password: + contexts: + - sylius.behat.context.setup.locale + - sylius.behat.context.setup.customer + - bitbag.sylius_vue_storefront2_plugin.context.graphql + - bitbag.sylius_vue_storefront2_plugin.context.customer + - sylius.behat.context.setup.channel + filters: + tags: "@resetting_password&&@graphql" From 903307832ef4ef901354251c1b4df1a82ff6803a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Kukli=C5=84ski?= Date: Thu, 15 Jun 2023 21:19:22 +0200 Subject: [PATCH 07/11] Update migrations/Version20230612094617.php --- migrations/Version20230612094617.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/migrations/Version20230612094617.php b/migrations/Version20230612094617.php index fd84b5d3..e726f2d1 100644 --- a/migrations/Version20230612094617.php +++ b/migrations/Version20230612094617.php @@ -1,5 +1,12 @@ Date: Thu, 15 Jun 2023 21:19:50 +0200 Subject: [PATCH 08/11] Update migrations/Version20230612095046.php --- migrations/Version20230612095046.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/migrations/Version20230612095046.php b/migrations/Version20230612095046.php index d584e341..4c085fb5 100644 --- a/migrations/Version20230612095046.php +++ b/migrations/Version20230612095046.php @@ -1,5 +1,12 @@ Date: Fri, 16 Jun 2023 07:21:15 +0200 Subject: [PATCH 09/11] VSF2-54 - adds doc block for user variable --- src/Resolver/Query/PasswordResetTokenResolver.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Resolver/Query/PasswordResetTokenResolver.php b/src/Resolver/Query/PasswordResetTokenResolver.php index 89c986b5..d4f48be0 100644 --- a/src/Resolver/Query/PasswordResetTokenResolver.php +++ b/src/Resolver/Query/PasswordResetTokenResolver.php @@ -9,7 +9,6 @@ declare(strict_types=1); - namespace BitBag\SyliusVueStorefront2Plugin\Resolver\Query; use ApiPlatform\GraphQl\Resolver\QueryItemResolverInterface; @@ -25,10 +24,10 @@ public function __construct(UserRepositoryInterface $userRepository) $this->userRepository = $userRepository; } - public function __invoke($item, array $context): ?ShopUserInterface { $token = $context['args']['passwordResetToken']; + /** @var ?ShopUserInterface $user */ $user = $this->userRepository->findOneBy(['passwordResetToken' => $token]); if (null !== $user) { From 7ce67f76549e8e2c47aa0f06c23a3adbdecb7a3e Mon Sep 17 00:00:00 2001 From: Maciej Date: Fri, 16 Jun 2023 07:42:26 +0200 Subject: [PATCH 10/11] VSF2-54 - throws error on no token found, adjusts tests --- features/shop/account/resetting_password.feature | 2 +- spec/Resolver/Query/PasswordResetTokenResolverSpec.php | 3 ++- src/Resolver/Query/PasswordResetTokenResolver.php | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/features/shop/account/resetting_password.feature b/features/shop/account/resetting_password.feature index 63f79e9e..efb12951 100644 --- a/features/shop/account/resetting_password.feature +++ b/features/shop/account/resetting_password.feature @@ -34,4 +34,4 @@ Feature: Resetting one customer password And I prepare check reset password token operation for invalid token And I send that GraphQL request Then I should receive a JSON response - And This response should contain pattern '/^\{"data":\{"password_reset_tokenUser":null\}\}$/' + And This response should contain pattern '/"data":\{"password_reset_tokenUser":null\}/' diff --git a/spec/Resolver/Query/PasswordResetTokenResolverSpec.php b/spec/Resolver/Query/PasswordResetTokenResolverSpec.php index 1f4e1d32..23c06811 100644 --- a/spec/Resolver/Query/PasswordResetTokenResolverSpec.php +++ b/spec/Resolver/Query/PasswordResetTokenResolverSpec.php @@ -62,6 +62,7 @@ public function it_should_return_null_on_invalid_token( $userRepository->findOneBy(['passwordResetToken' => $token])->willReturn(null); - $this->__invoke(null, $context)->shouldReturn(null); + $this->shouldThrow(\RuntimeException::class) + ->during('__invoke', [null, $context]); } } diff --git a/src/Resolver/Query/PasswordResetTokenResolver.php b/src/Resolver/Query/PasswordResetTokenResolver.php index d4f48be0..e26a9e49 100644 --- a/src/Resolver/Query/PasswordResetTokenResolver.php +++ b/src/Resolver/Query/PasswordResetTokenResolver.php @@ -24,7 +24,7 @@ public function __construct(UserRepositoryInterface $userRepository) $this->userRepository = $userRepository; } - public function __invoke($item, array $context): ?ShopUserInterface + public function __invoke($item, array $context): ShopUserInterface { $token = $context['args']['passwordResetToken']; /** @var ?ShopUserInterface $user */ @@ -34,6 +34,6 @@ public function __invoke($item, array $context): ?ShopUserInterface return $user; } - return null; + throw new \RuntimeException('Token not found'); } } From 4375538885020e1254066a443bcd3122b57c6515 Mon Sep 17 00:00:00 2001 From: Maciej Date: Fri, 16 Jun 2023 08:50:39 +0200 Subject: [PATCH 11/11] VSF2-54 - swaps config --- src/Resources/api_resources/ShopUser.xml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Resources/api_resources/ShopUser.xml b/src/Resources/api_resources/ShopUser.xml index c0056dac..4fb8c892 100644 --- a/src/Resources/api_resources/ShopUser.xml +++ b/src/Resources/api_resources/ShopUser.xml @@ -13,18 +13,6 @@ We are hiring developers from all over the world. Join us and start your new, ex - - - shop:password_reset_token:read - - bitbag.sylius_vue_storefront2plugin.resolver.query.password_reset_token_resolver - - - String! - - - - input \Sylius\Bundle\ApiBundle\Command\Account\RegisterShopUser @@ -51,6 +39,18 @@ We are hiring developers from all over the world. Join us and start your new, ex + + + + shop:password_reset_token:read + + bitbag.sylius_vue_storefront2plugin.resolver.query.password_reset_token_resolver + + + String! + + +