From 88c486392ebdc032a03698ac22d6bdaf8dfecd44 Mon Sep 17 00:00:00 2001 From: Wojdylak Date: Fri, 5 Jan 2024 15:08:47 +0100 Subject: [PATCH 01/11] [ApiBundle][Admin] Fix password update issue when on other user details are changed --- .../changing_shop_user_password.feature | 2 +- .../Api/Admin/ManagingCustomersContext.php | 10 +++ src/Sylius/Behat/Resources/config/suites.yml | 1 + .../config/suites/api/user/managing_users.yml | 23 +++++ .../DataPersister/CustomerDataPersister.php | 54 +++++++++++ .../config/services/data_persisters.xml | 6 ++ .../CustomerDataPersisterSpec.php | 90 +++++++++++++++++++ 7 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 src/Sylius/Behat/Resources/config/suites/api/user/managing_users.yml create mode 100644 src/Sylius/Bundle/ApiBundle/DataPersister/CustomerDataPersister.php create mode 100644 src/Sylius/Bundle/ApiBundle/spec/DataPersister/CustomerDataPersisterSpec.php diff --git a/features/user/managing_users/changing_shop_user_password.feature b/features/user/managing_users/changing_shop_user_password.feature index 4b1aaffcef1..b05422d1499 100644 --- a/features/user/managing_users/changing_shop_user_password.feature +++ b/features/user/managing_users/changing_shop_user_password.feature @@ -9,7 +9,7 @@ Feature: Changing shop user's password And there is a user "kibsoon@example.com" identified by "goodGuy" And I am logged in as an administrator - @ui + @api @ui Scenario: Changing a password of a shop user When I change the password of user "kibsoon@example.com" to "veryGoodGuy" Then I should be notified that it has been successfully edited diff --git a/src/Sylius/Behat/Context/Api/Admin/ManagingCustomersContext.php b/src/Sylius/Behat/Context/Api/Admin/ManagingCustomersContext.php index ef73478650d..066a0f003a9 100644 --- a/src/Sylius/Behat/Context/Api/Admin/ManagingCustomersContext.php +++ b/src/Sylius/Behat/Context/Api/Admin/ManagingCustomersContext.php @@ -210,6 +210,16 @@ public function iSortThemBy(string $sortType = 'ascending'): void ]); } + /** + * @When I change the password of user :customer to :newPassword + */ + public function iChangeThePasswordOfUserTo(CustomerInterface $customer, string $newPassword): void + { + $this->iWantToEditThisCustomer($customer); + $this->iSpecifyItsPasswordAs($newPassword); + $this->client->update(); + } + /** * @When I do not specify any information * @When I do not choose create account option diff --git a/src/Sylius/Behat/Resources/config/suites.yml b/src/Sylius/Behat/Resources/config/suites.yml index 2173fa4722a..88c90f818bc 100644 --- a/src/Sylius/Behat/Resources/config/suites.yml +++ b/src/Sylius/Behat/Resources/config/suites.yml @@ -68,6 +68,7 @@ imports: - suites/api/user/managing_administrators.yml - suites/api/user/managing_customer_groups.yml - suites/api/user/managing_customers.yml + - suites/api/user/managing_users.yml - suites/cli/canceling_unpaid_orders.yml - suites/cli/installer.yml diff --git a/src/Sylius/Behat/Resources/config/suites/api/user/managing_users.yml b/src/Sylius/Behat/Resources/config/suites/api/user/managing_users.yml new file mode 100644 index 00000000000..da596276814 --- /dev/null +++ b/src/Sylius/Behat/Resources/config/suites/api/user/managing_users.yml @@ -0,0 +1,23 @@ +# This file is part of the Sylius package. +# (c) Sylius Sp. z o.o. + +default: + suites: + api_managing_users: + contexts: + - sylius.behat.context.hook.doctrine_orm + + - sylius.behat.context.transform.customer + - sylius.behat.context.transform.shared_storage + + - sylius.behat.context.setup.admin_api_security + - sylius.behat.context.setup.channel + - sylius.behat.context.setup.user + + - sylius.behat.context.api.admin.managing_customers + - sylius.behat.context.api.admin.response + + - sylius.behat.context.api.shop.login + + filters: + tags: "@managing_users&&@api" diff --git a/src/Sylius/Bundle/ApiBundle/DataPersister/CustomerDataPersister.php b/src/Sylius/Bundle/ApiBundle/DataPersister/CustomerDataPersister.php new file mode 100644 index 00000000000..613791d283e --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/DataPersister/CustomerDataPersister.php @@ -0,0 +1,54 @@ + $context */ + public function supports($data, array $context = []): bool + { + return $data instanceof CustomerInterface; + } + + /** + * @param CustomerInterface $data + * @param array $context + */ + public function persist($data, array $context = []): void + { + $user = $data->getUser(); + if (null !== $user && null !== $user->getPlainPassword()) { + $this->passwordUpdater->updatePassword($user); + } + + $this->decoratedDataPersister->persist($data, $context); + } + + /** @param array $context */ + public function remove($data, array $context = []): void + { + $this->decoratedDataPersister->remove($data, $context); + } +} diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/services/data_persisters.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/services/data_persisters.xml index bc5248e1185..2cff1c5bd40 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/services/data_persisters.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/services/data_persisters.xml @@ -105,5 +105,11 @@ + + + + + + diff --git a/src/Sylius/Bundle/ApiBundle/spec/DataPersister/CustomerDataPersisterSpec.php b/src/Sylius/Bundle/ApiBundle/spec/DataPersister/CustomerDataPersisterSpec.php new file mode 100644 index 00000000000..e15815950f9 --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/spec/DataPersister/CustomerDataPersisterSpec.php @@ -0,0 +1,90 @@ +beConstructedWith($decoratedDataPersister, $passwordUpdater); + } + + function it_supports_only_customer_entity(CustomerInterface $customer, ProductInterface $product): void + { + $this->supports($customer)->shouldReturn(true); + $this->supports($product)->shouldReturn(false); + } + + function it_does_not_update_password_when_user_is_null( + ContextAwareDataPersisterInterface $decoratedDataPersister, + PasswordUpdaterInterface $passwordUpdater, + CustomerInterface $customer, + ): void { + $customer->getUser()->willReturn(null); + $passwordUpdater->updatePassword(Argument::any())->shouldNotBeCalled(); + + $decoratedDataPersister->persist($customer, [])->shouldBeCalled(); + + $this->persist($customer, []); + } + + function it_does_not_update_password_when_plain_password_is_null( + ContextAwareDataPersisterInterface $decoratedDataPersister, + PasswordUpdaterInterface $passwordUpdater, + CustomerInterface $customer, + ShopUserInterface $user, + ): void { + $user->getPlainPassword()->willReturn(null); + $customer->getUser()->willReturn($user); + $passwordUpdater->updatePassword($user)->shouldNotBeCalled(); + + $decoratedDataPersister->persist($customer, [])->shouldBeCalled(); + + $this->persist($customer, []); + } + + function it_updates_password_when_plain_password_is_set( + ContextAwareDataPersisterInterface $decoratedDataPersister, + PasswordUpdaterInterface $passwordUpdater, + CustomerInterface $customer, + ShopUserInterface $user, + ): void { + $user->getPlainPassword()->willReturn('password'); + $customer->getUser()->willReturn($user); + $passwordUpdater->updatePassword($user)->shouldBeCalled(); + + $decoratedDataPersister->persist($customer, [])->shouldBeCalled(); + + $this->persist($customer, []); + } + + function it_uses_decorated_data_persister_to_remove_customer( + ContextAwareDataPersisterInterface $decoratedDataPersister, + CustomerInterface $customer, + ): void { + $decoratedDataPersister->remove($customer, [])->shouldBeCalled(); + + $this->remove($customer, []); + } +} From 55c7a461904206219e75f47ae2013813c393fd2d Mon Sep 17 00:00:00 2001 From: Wojdylak Date: Fri, 5 Jan 2024 16:40:45 +0100 Subject: [PATCH 02/11] [ApiBundle][Admin] Add feature to remove shop user --- .../managing_users/deleting_account.feature | 2 +- .../Api/Admin/ManagingCustomersContext.php | 9 ++++ .../Context/Transform/ShopUserContext.php | 38 ++++++++++++++ .../config/services/contexts/transform.xml | 4 ++ .../config/suites/api/user/managing_users.yml | 2 + .../Command/Customer/RemoveShopUser.php | 33 +++++++++++++ .../Customer/RemoveShopUserHandler.php | 39 +++++++++++++++ .../RemoveCustomerShopUserAction.php | 49 +++++++++++++++++++ .../Exception/UserNotFoundException.php | 30 ++++++++++++ .../config/api_resources/Customer.xml | 6 +++ .../config/services/command_handlers.xml | 6 +++ .../Resources/config/services/controllers.xml | 6 +++ 12 files changed, 223 insertions(+), 1 deletion(-) create mode 100644 src/Sylius/Behat/Context/Transform/ShopUserContext.php create mode 100644 src/Sylius/Bundle/ApiBundle/Command/Customer/RemoveShopUser.php create mode 100644 src/Sylius/Bundle/ApiBundle/CommandHandler/Customer/RemoveShopUserHandler.php create mode 100644 src/Sylius/Bundle/ApiBundle/Controller/RemoveCustomerShopUserAction.php create mode 100644 src/Sylius/Bundle/ApiBundle/Exception/UserNotFoundException.php diff --git a/features/user/managing_users/deleting_account.feature b/features/user/managing_users/deleting_account.feature index 1c075b00ba9..c87d920f4c5 100644 --- a/features/user/managing_users/deleting_account.feature +++ b/features/user/managing_users/deleting_account.feature @@ -9,7 +9,7 @@ Feature: Deleting the customer account And there is a user "theodore@example.com" identified by "pswd" And I am logged in as an administrator - @ui + @api @ui Scenario: Deleting account should not delete customer details When I delete the account of "theodore@example.com" user Then the user account should be deleted diff --git a/src/Sylius/Behat/Context/Api/Admin/ManagingCustomersContext.php b/src/Sylius/Behat/Context/Api/Admin/ManagingCustomersContext.php index 066a0f003a9..b380fb982ec 100644 --- a/src/Sylius/Behat/Context/Api/Admin/ManagingCustomersContext.php +++ b/src/Sylius/Behat/Context/Api/Admin/ManagingCustomersContext.php @@ -20,6 +20,7 @@ use Sylius\Behat\Context\Api\Resources; use Sylius\Component\Addressing\Model\CountryInterface; use Sylius\Component\Core\Model\CustomerInterface; +use Sylius\Component\Core\Model\ShopUserInterface; use Sylius\Component\Customer\Model\CustomerGroupInterface; use Webmozart\Assert\Assert; @@ -220,6 +221,14 @@ public function iChangeThePasswordOfUserTo(CustomerInterface $customer, string $ $this->client->update(); } + /** + * @When I delete the account of :shopUser user + */ + public function iDeleteAccount(ShopUserInterface $shopUser): void + { + $this->client->delete(sprintf('customer/%s', $shopUser->getCustomer()->getId()), 'user'); + } + /** * @When I do not specify any information * @When I do not choose create account option diff --git a/src/Sylius/Behat/Context/Transform/ShopUserContext.php b/src/Sylius/Behat/Context/Transform/ShopUserContext.php new file mode 100644 index 00000000000..678c8bcc77b --- /dev/null +++ b/src/Sylius/Behat/Context/Transform/ShopUserContext.php @@ -0,0 +1,38 @@ +shopUserRepository->findOneByEmail($email); + + Assert::notNull($shopUser, sprintf('User with email "%s" does not exist', $email)); + + return $shopUser; + } +} diff --git a/src/Sylius/Behat/Resources/config/services/contexts/transform.xml b/src/Sylius/Behat/Resources/config/services/contexts/transform.xml index 9991189eb17..1fb1c7d1939 100644 --- a/src/Sylius/Behat/Resources/config/services/contexts/transform.xml +++ b/src/Sylius/Behat/Resources/config/services/contexts/transform.xml @@ -179,5 +179,9 @@ + + + + diff --git a/src/Sylius/Behat/Resources/config/suites/api/user/managing_users.yml b/src/Sylius/Behat/Resources/config/suites/api/user/managing_users.yml index da596276814..913ff7c923e 100644 --- a/src/Sylius/Behat/Resources/config/suites/api/user/managing_users.yml +++ b/src/Sylius/Behat/Resources/config/suites/api/user/managing_users.yml @@ -9,9 +9,11 @@ default: - sylius.behat.context.transform.customer - sylius.behat.context.transform.shared_storage + - sylius.behat.context.transform.shop_user - sylius.behat.context.setup.admin_api_security - sylius.behat.context.setup.channel + - sylius.behat.context.setup.customer - sylius.behat.context.setup.user - sylius.behat.context.api.admin.managing_customers diff --git a/src/Sylius/Bundle/ApiBundle/Command/Customer/RemoveShopUser.php b/src/Sylius/Bundle/ApiBundle/Command/Customer/RemoveShopUser.php new file mode 100644 index 00000000000..dbbbc00f947 --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/Command/Customer/RemoveShopUser.php @@ -0,0 +1,33 @@ +shopUserId; + } + + public function setShopUserId($shopUserId): void + { + $this->shopUserId = $shopUserId; + } +} diff --git a/src/Sylius/Bundle/ApiBundle/CommandHandler/Customer/RemoveShopUserHandler.php b/src/Sylius/Bundle/ApiBundle/CommandHandler/Customer/RemoveShopUserHandler.php new file mode 100644 index 00000000000..1bc0dba9faa --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/CommandHandler/Customer/RemoveShopUserHandler.php @@ -0,0 +1,39 @@ +shopUserRepository->find($removeShopUser->getShopUserId()); + + if (null === $shopUser) { + return; + } + + $shopUser->setCustomer(null); + $this->shopUserRepository->remove($shopUser); + } +} diff --git a/src/Sylius/Bundle/ApiBundle/Controller/RemoveCustomerShopUserAction.php b/src/Sylius/Bundle/ApiBundle/Controller/RemoveCustomerShopUserAction.php new file mode 100644 index 00000000000..f3457993efb --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/Controller/RemoveCustomerShopUserAction.php @@ -0,0 +1,49 @@ +attributes->get('id', ''); + + $user = $this->shopUserRepository->findOneBy(['customer' => $customerId]); + if (null === $user) { + throw new UserNotFoundException(); + } + + $this->commandBus->dispatch(new RemoveShopUser($user->getId())); + + return new JsonResponse(status: Response::HTTP_NO_CONTENT); + } +} diff --git a/src/Sylius/Bundle/ApiBundle/Exception/UserNotFoundException.php b/src/Sylius/Bundle/ApiBundle/Exception/UserNotFoundException.php new file mode 100644 index 00000000000..70c30904985 --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/Exception/UserNotFoundException.php @@ -0,0 +1,30 @@ + $headers */ + public function __construct( + string $message = 'User not found.', + \Throwable $previous = null, + int $code = 0, + array $headers = [], + ) { + parent::__construct($message, $previous, $code, $headers); + } +} 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 2b41ac3d254..7fd1cfa25cc 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Customer.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Customer.xml @@ -95,6 +95,12 @@ + + DELETE + /admin/customer/{id}/user + Sylius\Bundle\ApiBundle\Controller\RemoveCustomerShopUserAction + + GET /shop/customers/{id} 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 0c922f02120..7590e7a7ac7 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/services/command_handlers.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/services/command_handlers.xml @@ -231,5 +231,11 @@ + + + + + + diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/services/controllers.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/services/controllers.xml index e5499f53f2f..7f1a46eb6ea 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/services/controllers.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/services/controllers.xml @@ -60,5 +60,11 @@ + + + + + + From c6784336be6a545309f4ace56aaa76698cefafde Mon Sep 17 00:00:00 2001 From: Jacob Tobiasz Date: Mon, 8 Jan 2024 11:35:45 +0100 Subject: [PATCH 03/11] Revive CI --- .../Bundle/ApiBundle/Command/Customer/RemoveShopUser.php | 6 +++--- .../CommandHandler/Customer/RemoveShopUserHandler.php | 5 ++++- .../ApiBundle/Controller/RemoveCustomerShopUserAction.php | 6 ++++-- .../ApiBundle/Resources/config/services/controllers.xml | 1 - 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/Sylius/Bundle/ApiBundle/Command/Customer/RemoveShopUser.php b/src/Sylius/Bundle/ApiBundle/Command/Customer/RemoveShopUser.php index dbbbc00f947..d3f562812fd 100644 --- a/src/Sylius/Bundle/ApiBundle/Command/Customer/RemoveShopUser.php +++ b/src/Sylius/Bundle/ApiBundle/Command/Customer/RemoveShopUser.php @@ -18,15 +18,15 @@ /** @experimental */ class RemoveShopUser implements ShopUserIdAwareInterface { - public function __construct(private $shopUserId) + public function __construct(private mixed $shopUserId) { } - public function getShopUserId() + public function getShopUserId(): mixed { return $this->shopUserId; } - public function setShopUserId($shopUserId): void + public function setShopUserId(mixed $shopUserId): void { $this->shopUserId = $shopUserId; } diff --git a/src/Sylius/Bundle/ApiBundle/CommandHandler/Customer/RemoveShopUserHandler.php b/src/Sylius/Bundle/ApiBundle/CommandHandler/Customer/RemoveShopUserHandler.php index 1bc0dba9faa..f99859ab1d7 100644 --- a/src/Sylius/Bundle/ApiBundle/CommandHandler/Customer/RemoveShopUserHandler.php +++ b/src/Sylius/Bundle/ApiBundle/CommandHandler/Customer/RemoveShopUserHandler.php @@ -13,13 +13,16 @@ namespace Sylius\Bundle\ApiBundle\CommandHandler\Customer; -use Doctrine\ORM\EntityManagerInterface; use Sylius\Bundle\ApiBundle\Command\Customer\RemoveShopUser; +use Sylius\Component\Core\Model\ShopUserInterface; use Sylius\Component\User\Repository\UserRepositoryInterface; /** @experimental */ final class RemoveShopUserHandler { + /** + * @param UserRepositoryInterface $shopUserRepository + */ public function __construct( private UserRepositoryInterface $shopUserRepository, ){ diff --git a/src/Sylius/Bundle/ApiBundle/Controller/RemoveCustomerShopUserAction.php b/src/Sylius/Bundle/ApiBundle/Controller/RemoveCustomerShopUserAction.php index f3457993efb..1a7cd38c728 100644 --- a/src/Sylius/Bundle/ApiBundle/Controller/RemoveCustomerShopUserAction.php +++ b/src/Sylius/Bundle/ApiBundle/Controller/RemoveCustomerShopUserAction.php @@ -16,7 +16,7 @@ use Sylius\Bundle\ApiBundle\Command\Customer\RemoveShopUser; use Sylius\Bundle\ApiBundle\Exception\CustomerNotFoundException; use Sylius\Bundle\ApiBundle\Exception\UserNotFoundException; -use Sylius\Component\Core\Repository\CustomerRepositoryInterface; +use Sylius\Component\Core\Model\ShopUserInterface; use Sylius\Component\User\Repository\UserRepositoryInterface; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; @@ -26,9 +26,11 @@ /** @experimental */ final class RemoveCustomerShopUserAction { + /** + * @param UserRepositoryInterface $shopUserRepository + */ public function __construct( private MessageBusInterface $commandBus, - private CustomerRepositoryInterface $customerRepository, private UserRepositoryInterface $shopUserRepository, ) { } diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/services/controllers.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/services/controllers.xml index 7f1a46eb6ea..ed839beaa4f 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/services/controllers.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/services/controllers.xml @@ -62,7 +62,6 @@ - From 916d1540b7416fdebedb99c015681fb1e0e99748 Mon Sep 17 00:00:00 2001 From: Jacob Tobiasz Date: Tue, 9 Jan 2024 14:00:21 +0100 Subject: [PATCH 04/11] Implement missing behat steps checking deleting customer's account --- .../Api/Admin/ManagingCustomersContext.php | 19 ++++++++ src/Sylius/Behat/Context/Api/UserContext.php | 46 +++++++++++++++++++ .../config/services/contexts/api.xml | 8 ++++ .../config/services/contexts/api/admin.xml | 1 + .../config/suites/api/user/managing_users.yml | 2 + 5 files changed, 76 insertions(+) create mode 100644 src/Sylius/Behat/Context/Api/UserContext.php diff --git a/src/Sylius/Behat/Context/Api/Admin/ManagingCustomersContext.php b/src/Sylius/Behat/Context/Api/Admin/ManagingCustomersContext.php index b380fb982ec..699381562bf 100644 --- a/src/Sylius/Behat/Context/Api/Admin/ManagingCustomersContext.php +++ b/src/Sylius/Behat/Context/Api/Admin/ManagingCustomersContext.php @@ -18,6 +18,7 @@ use Sylius\Behat\Client\ApiClientInterface; use Sylius\Behat\Client\ResponseCheckerInterface; use Sylius\Behat\Context\Api\Resources; +use Sylius\Behat\Service\SharedStorageInterface; use Sylius\Component\Addressing\Model\CountryInterface; use Sylius\Component\Core\Model\CustomerInterface; use Sylius\Component\Core\Model\ShopUserInterface; @@ -32,6 +33,7 @@ public function __construct( private ApiClientInterface $client, private ResponseCheckerInterface $responseChecker, private IriConverterInterface $iriConverter, + private SharedStorageInterface $sharedStorage, ) { } @@ -226,7 +228,9 @@ public function iChangeThePasswordOfUserTo(CustomerInterface $customer, string $ */ public function iDeleteAccount(ShopUserInterface $shopUser): void { + $deletedShopUser = clone $shopUser; $this->client->delete(sprintf('customer/%s', $shopUser->getCustomer()->getId()), 'user'); + $this->sharedStorage->set('deleted_user', $deletedShopUser); } /** @@ -580,6 +584,21 @@ public function thisCustomerShouldHaveAsTheirGroup(CustomerGroupInterface $custo ); } + /** + * @Then the customer with this email should still exist + */ + public function customerShouldStillExist(): void + { + $deletedUser = $this->sharedStorage->get('deleted_user'); + + $this->client->show(Resources::CUSTOMERS, (string) $deletedUser->getCustomer()->getId()); + + Assert::same( + $this->responseChecker->getValue($this->client->getLastResponse(), 'email'), + $deletedUser->getCustomer()->getEmail(), + ); + } + /** * @Then I should not see create account option * @Then I should still be on the customer creation page diff --git a/src/Sylius/Behat/Context/Api/UserContext.php b/src/Sylius/Behat/Context/Api/UserContext.php new file mode 100644 index 00000000000..141d8c941d2 --- /dev/null +++ b/src/Sylius/Behat/Context/Api/UserContext.php @@ -0,0 +1,46 @@ +sharedStorage->get('deleted_user'); + + $response = $this->adminApiClient->show(Resources::CUSTOMERS, (string) $deletedUser->getCustomer()->getId()); + + Assert::null( + $this->responseChecker->getValue($response, 'user'), + ); + } +} diff --git a/src/Sylius/Behat/Resources/config/services/contexts/api.xml b/src/Sylius/Behat/Resources/config/services/contexts/api.xml index 632ea9a28df..fa4bd5a6d6b 100644 --- a/src/Sylius/Behat/Resources/config/services/contexts/api.xml +++ b/src/Sylius/Behat/Resources/config/services/contexts/api.xml @@ -18,4 +18,12 @@ + + + + + + + + diff --git a/src/Sylius/Behat/Resources/config/services/contexts/api/admin.xml b/src/Sylius/Behat/Resources/config/services/contexts/api/admin.xml index bc702557425..6726722186f 100644 --- a/src/Sylius/Behat/Resources/config/services/contexts/api/admin.xml +++ b/src/Sylius/Behat/Resources/config/services/contexts/api/admin.xml @@ -303,6 +303,7 @@ + diff --git a/src/Sylius/Behat/Resources/config/suites/api/user/managing_users.yml b/src/Sylius/Behat/Resources/config/suites/api/user/managing_users.yml index 913ff7c923e..c97405a64c9 100644 --- a/src/Sylius/Behat/Resources/config/suites/api/user/managing_users.yml +++ b/src/Sylius/Behat/Resources/config/suites/api/user/managing_users.yml @@ -21,5 +21,7 @@ default: - sylius.behat.context.api.shop.login + - sylius.behat.context.api.user + filters: tags: "@managing_users&&@api" From 9cdd902cc900023d931b59e8627d0313664f8a5b Mon Sep 17 00:00:00 2001 From: Jacob Tobiasz Date: Thu, 11 Jan 2024 17:09:52 +0100 Subject: [PATCH 05/11] Remove unnecessary UserContext inside the api directory --- .../Api/Admin/ManagingCustomersContext.php | 17 ++++++- src/Sylius/Behat/Context/Api/UserContext.php | 46 ------------------- .../Context/Transform/ShopUserContext.php | 2 +- .../config/services/contexts/api.xml | 8 ---- .../config/suites/api/user/managing_users.yml | 2 - 5 files changed, 16 insertions(+), 59 deletions(-) delete mode 100644 src/Sylius/Behat/Context/Api/UserContext.php diff --git a/src/Sylius/Behat/Context/Api/Admin/ManagingCustomersContext.php b/src/Sylius/Behat/Context/Api/Admin/ManagingCustomersContext.php index 699381562bf..09e523e0d0b 100644 --- a/src/Sylius/Behat/Context/Api/Admin/ManagingCustomersContext.php +++ b/src/Sylius/Behat/Context/Api/Admin/ManagingCustomersContext.php @@ -228,9 +228,9 @@ public function iChangeThePasswordOfUserTo(CustomerInterface $customer, string $ */ public function iDeleteAccount(ShopUserInterface $shopUser): void { - $deletedShopUser = clone $shopUser; $this->client->delete(sprintf('customer/%s', $shopUser->getCustomer()->getId()), 'user'); - $this->sharedStorage->set('deleted_user', $deletedShopUser); + + $this->sharedStorage->set('deleted_user', $shopUser); } /** @@ -610,4 +610,17 @@ public function customerShouldStillExist(): void public function intentionallyLeftBlank(): void { } + + /** + * @Then the user account should be deleted + */ + public function accountShouldBeDeleted(): void + { + /** @var ShopUserInterface $deletedUser */ + $deletedUser = $this->sharedStorage->get('deleted_user'); + + $response = $this->client->show(Resources::CUSTOMERS, (string) $deletedUser->getCustomer()->getId()); + + Assert::null($this->responseChecker->getValue($response, 'user')); + } } diff --git a/src/Sylius/Behat/Context/Api/UserContext.php b/src/Sylius/Behat/Context/Api/UserContext.php deleted file mode 100644 index 141d8c941d2..00000000000 --- a/src/Sylius/Behat/Context/Api/UserContext.php +++ /dev/null @@ -1,46 +0,0 @@ -sharedStorage->get('deleted_user'); - - $response = $this->adminApiClient->show(Resources::CUSTOMERS, (string) $deletedUser->getCustomer()->getId()); - - Assert::null( - $this->responseChecker->getValue($response, 'user'), - ); - } -} diff --git a/src/Sylius/Behat/Context/Transform/ShopUserContext.php b/src/Sylius/Behat/Context/Transform/ShopUserContext.php index 678c8bcc77b..57e8f98b1a8 100644 --- a/src/Sylius/Behat/Context/Transform/ShopUserContext.php +++ b/src/Sylius/Behat/Context/Transform/ShopUserContext.php @@ -31,7 +31,7 @@ public function getShopUserByEmail(string $email): ShopUserInterface { $shopUser = $this->shopUserRepository->findOneByEmail($email); - Assert::notNull($shopUser, sprintf('User with email "%s" does not exist', $email)); + Assert::notNull($shopUser, sprintf('Shop User with email "%s" does not exist', $email)); return $shopUser; } diff --git a/src/Sylius/Behat/Resources/config/services/contexts/api.xml b/src/Sylius/Behat/Resources/config/services/contexts/api.xml index fa4bd5a6d6b..632ea9a28df 100644 --- a/src/Sylius/Behat/Resources/config/services/contexts/api.xml +++ b/src/Sylius/Behat/Resources/config/services/contexts/api.xml @@ -18,12 +18,4 @@ - - - - - - - - diff --git a/src/Sylius/Behat/Resources/config/suites/api/user/managing_users.yml b/src/Sylius/Behat/Resources/config/suites/api/user/managing_users.yml index c97405a64c9..913ff7c923e 100644 --- a/src/Sylius/Behat/Resources/config/suites/api/user/managing_users.yml +++ b/src/Sylius/Behat/Resources/config/suites/api/user/managing_users.yml @@ -21,7 +21,5 @@ default: - sylius.behat.context.api.shop.login - - sylius.behat.context.api.user - filters: tags: "@managing_users&&@api" From 751186c1d46323e522558a6e00590c3637067e37 Mon Sep 17 00:00:00 2001 From: Jacob Tobiasz Date: Thu, 11 Jan 2024 17:21:57 +0100 Subject: [PATCH 06/11] Mark scenario as @no-api --- features/user/managing_users/deleting_account.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/user/managing_users/deleting_account.feature b/features/user/managing_users/deleting_account.feature index c87d920f4c5..44db9c8350c 100644 --- a/features/user/managing_users/deleting_account.feature +++ b/features/user/managing_users/deleting_account.feature @@ -15,7 +15,7 @@ Feature: Deleting the customer account Then the user account should be deleted But the customer with this email should still exist - @ui + @ui @no-api Scenario: A customer with no user cannot be deleted Given the account of "theodore@example.com" was deleted Then I should not be able to delete it again From d0271f1aae23db9c14fa42f58a6fa71cd3cafe38 Mon Sep 17 00:00:00 2001 From: Jacob Tobiasz Date: Thu, 11 Jan 2024 17:22:39 +0100 Subject: [PATCH 07/11] Add spec for RemoveShopUserHandler and add throwing an exception when a shop user is not found --- .../Command/Customer/RemoveShopUser.php | 1 + .../Customer/RemoveShopUserHandler.php | 3 +- .../Customer/RemoveShopUserHandlerSpec.php | 45 +++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 src/Sylius/Bundle/ApiBundle/spec/CommandHandler/Customer/RemoveShopUserHandlerSpec.php diff --git a/src/Sylius/Bundle/ApiBundle/Command/Customer/RemoveShopUser.php b/src/Sylius/Bundle/ApiBundle/Command/Customer/RemoveShopUser.php index d3f562812fd..ee292b31abb 100644 --- a/src/Sylius/Bundle/ApiBundle/Command/Customer/RemoveShopUser.php +++ b/src/Sylius/Bundle/ApiBundle/Command/Customer/RemoveShopUser.php @@ -21,6 +21,7 @@ class RemoveShopUser implements ShopUserIdAwareInterface public function __construct(private mixed $shopUserId) { } + public function getShopUserId(): mixed { return $this->shopUserId; diff --git a/src/Sylius/Bundle/ApiBundle/CommandHandler/Customer/RemoveShopUserHandler.php b/src/Sylius/Bundle/ApiBundle/CommandHandler/Customer/RemoveShopUserHandler.php index f99859ab1d7..cb7b580b649 100644 --- a/src/Sylius/Bundle/ApiBundle/CommandHandler/Customer/RemoveShopUserHandler.php +++ b/src/Sylius/Bundle/ApiBundle/CommandHandler/Customer/RemoveShopUserHandler.php @@ -14,6 +14,7 @@ namespace Sylius\Bundle\ApiBundle\CommandHandler\Customer; use Sylius\Bundle\ApiBundle\Command\Customer\RemoveShopUser; +use Sylius\Bundle\ApiBundle\Exception\UserNotFoundException; use Sylius\Component\Core\Model\ShopUserInterface; use Sylius\Component\User\Repository\UserRepositoryInterface; @@ -33,7 +34,7 @@ public function __invoke(RemoveShopUser $removeShopUser): void $shopUser = $this->shopUserRepository->find($removeShopUser->getShopUserId()); if (null === $shopUser) { - return; + throw new UserNotFoundException(); } $shopUser->setCustomer(null); diff --git a/src/Sylius/Bundle/ApiBundle/spec/CommandHandler/Customer/RemoveShopUserHandlerSpec.php b/src/Sylius/Bundle/ApiBundle/spec/CommandHandler/Customer/RemoveShopUserHandlerSpec.php new file mode 100644 index 00000000000..2e5097df322 --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/spec/CommandHandler/Customer/RemoveShopUserHandlerSpec.php @@ -0,0 +1,45 @@ +beConstructedWith($userRepository); + } + + public function it_throws_an_exception_if_user_has_not_been_found(UserRepositoryInterface $userRepository): void + { + $userRepository->find(42)->willReturn(null); + + $this->shouldThrow(UserNotFoundException::class)->during('__invoke', [new RemoveShopUser(42)]); + } + + public function it_should_remove_shop_user(UserRepositoryInterface $userRepository, ShopUserInterface $shopUser): void + { + $userRepository->find(42)->willReturn($shopUser); + $shopUser->setCustomer(null)->shouldBeCalled(); + $userRepository->remove($shopUser)->shouldBeCalled(); + + $this->__invoke(new RemoveShopUser(42)); + } +} From 5c1d41186401ab1a2c6a44cb78e6e13898f9f99f Mon Sep 17 00:00:00 2001 From: Jacob Tobiasz Date: Thu, 11 Jan 2024 17:22:54 +0100 Subject: [PATCH 08/11] Update the operation's name for deleting a shop user --- .../ApiBundle/Resources/config/api_resources/Customer.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 7fd1cfa25cc..13050ef69b0 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Customer.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Customer.xml @@ -95,7 +95,7 @@ - + DELETE /admin/customer/{id}/user Sylius\Bundle\ApiBundle\Controller\RemoveCustomerShopUserAction From f385423f7e4c825f1938facb6e8b8699b9999825 Mon Sep 17 00:00:00 2001 From: Jacob Tobiasz Date: Thu, 11 Jan 2024 17:46:18 +0100 Subject: [PATCH 09/11] Revert cloning a shop user before setting it as a deleted_user inside the shared storage --- .../Behat/Context/Api/Admin/ManagingCustomersContext.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Sylius/Behat/Context/Api/Admin/ManagingCustomersContext.php b/src/Sylius/Behat/Context/Api/Admin/ManagingCustomersContext.php index 09e523e0d0b..21a48ecf4e6 100644 --- a/src/Sylius/Behat/Context/Api/Admin/ManagingCustomersContext.php +++ b/src/Sylius/Behat/Context/Api/Admin/ManagingCustomersContext.php @@ -228,9 +228,8 @@ public function iChangeThePasswordOfUserTo(CustomerInterface $customer, string $ */ public function iDeleteAccount(ShopUserInterface $shopUser): void { + $this->sharedStorage->set('customer', $shopUser->getCustomer()); $this->client->delete(sprintf('customer/%s', $shopUser->getCustomer()->getId()), 'user'); - - $this->sharedStorage->set('deleted_user', $shopUser); } /** @@ -616,10 +615,10 @@ public function intentionallyLeftBlank(): void */ public function accountShouldBeDeleted(): void { - /** @var ShopUserInterface $deletedUser */ - $deletedUser = $this->sharedStorage->get('deleted_user'); + /** @var CustomerInterface $customer */ + $customer = $this->sharedStorage->get('customer'); - $response = $this->client->show(Resources::CUSTOMERS, (string) $deletedUser->getCustomer()->getId()); + $response = $this->client->show(Resources::CUSTOMERS, (string) $customer->getId()); Assert::null($this->responseChecker->getValue($response, 'user')); } From 5c728d2d27c0f590e789269289796b2a5ba17332 Mon Sep 17 00:00:00 2001 From: Jacob Tobiasz Date: Fri, 12 Jan 2024 09:31:11 +0100 Subject: [PATCH 10/11] Implement scenario checking redeleting shop user account --- features/user/managing_users/deleting_account.feature | 2 +- .../Context/Api/Admin/ManagingCustomersContext.php | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/features/user/managing_users/deleting_account.feature b/features/user/managing_users/deleting_account.feature index 44db9c8350c..064205fb661 100644 --- a/features/user/managing_users/deleting_account.feature +++ b/features/user/managing_users/deleting_account.feature @@ -15,7 +15,7 @@ Feature: Deleting the customer account Then the user account should be deleted But the customer with this email should still exist - @ui @no-api + @ui @api Scenario: A customer with no user cannot be deleted Given the account of "theodore@example.com" was deleted Then I should not be able to delete it again diff --git a/src/Sylius/Behat/Context/Api/Admin/ManagingCustomersContext.php b/src/Sylius/Behat/Context/Api/Admin/ManagingCustomersContext.php index 21a48ecf4e6..327ed77e209 100644 --- a/src/Sylius/Behat/Context/Api/Admin/ManagingCustomersContext.php +++ b/src/Sylius/Behat/Context/Api/Admin/ManagingCustomersContext.php @@ -622,4 +622,15 @@ public function accountShouldBeDeleted(): void Assert::null($this->responseChecker->getValue($response, 'user')); } + + /** + * @Then I should not be able to delete it again + */ + public function iShouldNotBeAbleToDeleteCustomerAgain(): void + { + $customer = $this->sharedStorage->get('customer'); + $this->client->delete(sprintf('customer/%s', $customer->getId()), 'user'); + + Assert::same($this->client->getLastResponse()->getStatusCode(), 404); + } } From d691033530dba88d0ecc2ed74981ed9799192148 Mon Sep 17 00:00:00 2001 From: Jacob Tobiasz Date: Fri, 12 Jan 2024 09:37:58 +0100 Subject: [PATCH 11/11] Fix failing scenario --- features/user/managing_users/deleting_account.feature | 2 +- .../Context/Api/Admin/ManagingCustomersContext.php | 11 +++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/features/user/managing_users/deleting_account.feature b/features/user/managing_users/deleting_account.feature index 064205fb661..d2fda525ff6 100644 --- a/features/user/managing_users/deleting_account.feature +++ b/features/user/managing_users/deleting_account.feature @@ -15,7 +15,7 @@ Feature: Deleting the customer account Then the user account should be deleted But the customer with this email should still exist - @ui @api + @api @ui Scenario: A customer with no user cannot be deleted Given the account of "theodore@example.com" was deleted Then I should not be able to delete it again diff --git a/src/Sylius/Behat/Context/Api/Admin/ManagingCustomersContext.php b/src/Sylius/Behat/Context/Api/Admin/ManagingCustomersContext.php index 327ed77e209..7db28f995e9 100644 --- a/src/Sylius/Behat/Context/Api/Admin/ManagingCustomersContext.php +++ b/src/Sylius/Behat/Context/Api/Admin/ManagingCustomersContext.php @@ -588,14 +588,13 @@ public function thisCustomerShouldHaveAsTheirGroup(CustomerGroupInterface $custo */ public function customerShouldStillExist(): void { - $deletedUser = $this->sharedStorage->get('deleted_user'); + /** @var CustomerInterface $customer */ + $customer = $this->sharedStorage->get('customer'); - $this->client->show(Resources::CUSTOMERS, (string) $deletedUser->getCustomer()->getId()); + $this->client->show(Resources::CUSTOMERS, (string) $customer->getId()); - Assert::same( - $this->responseChecker->getValue($this->client->getLastResponse(), 'email'), - $deletedUser->getCustomer()->getEmail(), - ); + Assert::same($this->client->getLastResponse()->getStatusCode(), 200); + Assert::same($this->responseChecker->getValue($this->client->getLastResponse(), 'email'), $customer->getEmail()); } /**