From a1532367a5d7261f7f392377180713cddb0eed94 Mon Sep 17 00:00:00 2001 From: CSchulz Date: Sun, 22 Sep 2019 11:37:13 +0200 Subject: [PATCH 1/8] add validation to verify account action and update swagger.yml --- doc/swagger.yml | 17 ++++++ .../VerificationTokenExistsValidatorSpec.php | 61 +++++++++++++++++++ .../Customer/VerifyAccountAction.php | 1 + .../config/services/validators/customer.xml | 6 ++ ...rRequest.xml => UpdateCustomerRequest.xml} | 0 .../customer/VerifyAccountRequest.xml | 13 ++++ src/Resources/translations/validators.en.yml | 3 + .../Constraints/VerificationTokenExists.php | 25 ++++++++ .../VerificationTokenExistsValidator.php | 27 ++++++++ tests/Controller/Customer/VerifyApiTest.php | 32 ++++++++++ .../verify_account_required_data.json | 9 +++ .../verify_account_token_not_exists.json | 9 +++ 12 files changed, 203 insertions(+) create mode 100644 spec/Validator/Customer/VerificationTokenExistsValidatorSpec.php rename src/Resources/config/validation/customer/{CustomerRequest.xml => UpdateCustomerRequest.xml} (100%) create mode 100644 src/Resources/config/validation/customer/VerifyAccountRequest.xml create mode 100644 src/Validator/Constraints/VerificationTokenExists.php create mode 100644 src/Validator/Customer/VerificationTokenExistsValidator.php create mode 100644 tests/Responses/Expected/customer/verify_account_required_data.json create mode 100644 tests/Responses/Expected/customer/verify_account_token_not_exists.json diff --git a/doc/swagger.yml b/doc/swagger.yml index 4435bd477..2045d8cf3 100644 --- a/doc/swagger.yml +++ b/doc/swagger.yml @@ -785,6 +785,23 @@ paths: description: "User was logged in" schema: $ref: "#/definitions/LoginSuccess" + + /verify-account: + parameters: + - name: "token" + in: "query" + required: true + type: "string" + get: + tags: + - "users" + summary: "Verify an account by verification token" + description: "This route is needed to verify an user." + operationId: "verifyUser" + responses: + 204: + description: "User unlocked" + /orders: parameters: - $ref: "#/parameters/ChannelCode" diff --git a/spec/Validator/Customer/VerificationTokenExistsValidatorSpec.php b/spec/Validator/Customer/VerificationTokenExistsValidatorSpec.php new file mode 100644 index 000000000..49b6083b9 --- /dev/null +++ b/spec/Validator/Customer/VerificationTokenExistsValidatorSpec.php @@ -0,0 +1,61 @@ +beConstructedWith($userRepository); + + $this->initialize($executionContext); + } + + function it_is_initializable(): void + { + $this->shouldHaveType(VerificationTokenExistsValidator::class); + } + + function it_does_not_add_constraint_if_verification_token_is_empty( + UserRepositoryInterface $userRepository, + ExecutionContextInterface $executionContext + ): void { + $executionContext->addViolation(Argument::cetera())->shouldNotBeCalled(); + + $this->validate('', new VerificationTokenExists()); + $this->validate(null, new VerificationTokenExists()); + } + + function it_does_not_add_constraint_if_verification_token_exists( + ShopUserInterface $user, + UserRepositoryInterface $userRepository, + ExecutionContextInterface $executionContext + ): void { + $userRepository->findOneBy(['emailVerificationToken' => 'token'])->willReturn($user); + + $executionContext->addViolation(Argument::cetera())->shouldNotBeCalled(); + + $this->validate('token', new VerificationTokenExists()); + } + + function it_adds_constraint_if_verification_token_does_not_exist( + UserRepositoryInterface $userRepository, + ExecutionContextInterface $executionContext + ): void { + $userRepository->findOneBy(['emailVerificationToken' => 'token'])->willReturn(null); + + $executionContext->addViolation('sylius.shop_api.token.not_exists')->shouldBeCalled(); + + $this->validate('token', new VerificationTokenExists()); + } +} diff --git a/src/Controller/Customer/VerifyAccountAction.php b/src/Controller/Customer/VerifyAccountAction.php index 3ef65380b..dd69359d9 100644 --- a/src/Controller/Customer/VerifyAccountAction.php +++ b/src/Controller/Customer/VerifyAccountAction.php @@ -10,6 +10,7 @@ use Sylius\ShopApiPlugin\Factory\ValidationErrorViewFactoryInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\Messenger\MessageBusInterface; final class VerifyAccountAction diff --git a/src/Resources/config/services/validators/customer.xml b/src/Resources/config/services/validators/customer.xml index 10c01dc66..ea7793182 100644 --- a/src/Resources/config/services/validators/customer.xml +++ b/src/Resources/config/services/validators/customer.xml @@ -14,5 +14,11 @@ + + + + + diff --git a/src/Resources/config/validation/customer/CustomerRequest.xml b/src/Resources/config/validation/customer/UpdateCustomerRequest.xml similarity index 100% rename from src/Resources/config/validation/customer/CustomerRequest.xml rename to src/Resources/config/validation/customer/UpdateCustomerRequest.xml diff --git a/src/Resources/config/validation/customer/VerifyAccountRequest.xml b/src/Resources/config/validation/customer/VerifyAccountRequest.xml new file mode 100644 index 000000000..9150e009d --- /dev/null +++ b/src/Resources/config/validation/customer/VerifyAccountRequest.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/src/Resources/translations/validators.en.yml b/src/Resources/translations/validators.en.yml index e2bb688bb..bff982efc 100644 --- a/src/Resources/translations/validators.en.yml +++ b/src/Resources/translations/validators.en.yml @@ -18,3 +18,6 @@ sylius: not_exists: Address doesn't exist country: not_exists: The country does not exist + token: + not_blank: Please provide a token. + not_exists: The token does not exist. diff --git a/src/Validator/Constraints/VerificationTokenExists.php b/src/Validator/Constraints/VerificationTokenExists.php new file mode 100644 index 000000000..2cc99bf23 --- /dev/null +++ b/src/Validator/Constraints/VerificationTokenExists.php @@ -0,0 +1,25 @@ +userRepository = $userRepository; + } + + public function validate($token, Constraint $constraint) + { + if (null !== $token && strlen($token) > 0 && null === $this->userRepository->findOneBy(['emailVerificationToken' => $token])) { + $this->context->addViolation($constraint->message); + } + } +} diff --git a/tests/Controller/Customer/VerifyApiTest.php b/tests/Controller/Customer/VerifyApiTest.php index 4eeb26107..52fde278a 100644 --- a/tests/Controller/Customer/VerifyApiTest.php +++ b/tests/Controller/Customer/VerifyApiTest.php @@ -45,6 +45,38 @@ public function it_allows_to_verify_customer(): void $this->assertResponseCode($response, Response::HTTP_NO_CONTENT); } + /** + * @test + */ + public function it_does_not_allow_to_verify_account_without_required_data(): void + { + $response = $this->verifyAccount(null); + $this->assertResponse($response, 'customer/verify_account_required_data', Response::HTTP_BAD_REQUEST); + } + + /** + * @test + */ + public function it_allows_to_verify_customer_and_returns_properly_error_code(): void + { + $response = $this->verifyAccount('token'); + $this->assertResponse($response, 'customer/verify_account_token_not_exists', Response::HTTP_BAD_REQUEST); + } + + private function verifyAccount(?string $token): Response + { + $token = $token !== null ? '?token=' . $token : ''; + $this->client->request( + 'GET', + sprintf('/shop-api/verify-account%s', $token), + [], + [], + self::CONTENT_TYPE_HEADER + ); + + return $this->client->getResponse(); + } + protected function getContainer(): ContainerInterface { return static::$sharedKernel->getContainer(); diff --git a/tests/Responses/Expected/customer/verify_account_required_data.json b/tests/Responses/Expected/customer/verify_account_required_data.json new file mode 100644 index 000000000..f4c369de9 --- /dev/null +++ b/tests/Responses/Expected/customer/verify_account_required_data.json @@ -0,0 +1,9 @@ +{ + "code": 400, + "message": "Validation failed", + "errors": { + "token": [ + "Please provide a token." + ] + } +} diff --git a/tests/Responses/Expected/customer/verify_account_token_not_exists.json b/tests/Responses/Expected/customer/verify_account_token_not_exists.json new file mode 100644 index 000000000..c992e9abf --- /dev/null +++ b/tests/Responses/Expected/customer/verify_account_token_not_exists.json @@ -0,0 +1,9 @@ +{ + "code": 400, + "message": "Validation failed", + "errors": { + "token": [ + "The token does not exist." + ] + } +} From 6ce6b1dae2dd6948c0340bd1052f301dceadc830 Mon Sep 17 00:00:00 2001 From: CSchulz Date: Sun, 22 Sep 2019 13:25:53 +0200 Subject: [PATCH 2/8] review comments --- .../Customer/VerificationTokenExistsValidatorSpec.php | 10 ++++++++-- src/Controller/Customer/VerifyAccountAction.php | 1 - .../Customer/VerificationTokenExistsValidator.php | 5 ++++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/spec/Validator/Customer/VerificationTokenExistsValidatorSpec.php b/spec/Validator/Customer/VerificationTokenExistsValidatorSpec.php index 49b6083b9..416db280d 100644 --- a/spec/Validator/Customer/VerificationTokenExistsValidatorSpec.php +++ b/spec/Validator/Customer/VerificationTokenExistsValidatorSpec.php @@ -27,12 +27,18 @@ function it_is_initializable(): void } function it_does_not_add_constraint_if_verification_token_is_empty( - UserRepositoryInterface $userRepository, ExecutionContextInterface $executionContext ): void { - $executionContext->addViolation(Argument::cetera())->shouldNotBeCalled(); + $executionContext->addViolation(Argument::any())->shouldNotBeCalled(); $this->validate('', new VerificationTokenExists()); + } + + function it_does_not_add_constraint_if_verification_token_is_null( + ExecutionContextInterface $executionContext + ): void { + $executionContext->addViolation(Argument::any())->shouldNotBeCalled(); + $this->validate(null, new VerificationTokenExists()); } diff --git a/src/Controller/Customer/VerifyAccountAction.php b/src/Controller/Customer/VerifyAccountAction.php index dd69359d9..3ef65380b 100644 --- a/src/Controller/Customer/VerifyAccountAction.php +++ b/src/Controller/Customer/VerifyAccountAction.php @@ -10,7 +10,6 @@ use Sylius\ShopApiPlugin\Factory\ValidationErrorViewFactoryInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\Messenger\MessageBusInterface; final class VerifyAccountAction diff --git a/src/Validator/Customer/VerificationTokenExistsValidator.php b/src/Validator/Customer/VerificationTokenExistsValidator.php index c1424c62f..e1d9ced27 100644 --- a/src/Validator/Customer/VerificationTokenExistsValidator.php +++ b/src/Validator/Customer/VerificationTokenExistsValidator.php @@ -20,7 +20,10 @@ public function __construct(UserRepositoryInterface $userRepository) public function validate($token, Constraint $constraint) { - if (null !== $token && strlen($token) > 0 && null === $this->userRepository->findOneBy(['emailVerificationToken' => $token])) { + if (null === $token || 0 === strlen($token)) { + return; + } + if (null === $this->userRepository->findOneBy(['emailVerificationToken' => $token])) { $this->context->addViolation($constraint->message); } } From 1e5a688d7f9fd1c8d181a6e07ab1a7685ad6a5fe Mon Sep 17 00:00:00 2001 From: CSchulz Date: Sun, 22 Sep 2019 13:44:32 +0200 Subject: [PATCH 3/8] rename token --- .../config/validation/customer/VerifyAccountRequest.xml | 2 +- src/Resources/translations/validators.en.yml | 4 ++-- src/Validator/Constraints/VerificationTokenExists.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Resources/config/validation/customer/VerifyAccountRequest.xml b/src/Resources/config/validation/customer/VerifyAccountRequest.xml index 9150e009d..3dac0703f 100644 --- a/src/Resources/config/validation/customer/VerifyAccountRequest.xml +++ b/src/Resources/config/validation/customer/VerifyAccountRequest.xml @@ -5,7 +5,7 @@ - + diff --git a/src/Resources/translations/validators.en.yml b/src/Resources/translations/validators.en.yml index ba19b4435..761b97330 100644 --- a/src/Resources/translations/validators.en.yml +++ b/src/Resources/translations/validators.en.yml @@ -28,9 +28,9 @@ sylius: product: not_configurable: The product is not configurable. not_found: The product does not exists. - not_simple: The product is not a simple product + not_simple: The product is not a simple product. product_variant: not_exists: The product variant does not exist. - token: + verification_token: not_blank: Please provide a token. not_exists: The token does not exist. diff --git a/src/Validator/Constraints/VerificationTokenExists.php b/src/Validator/Constraints/VerificationTokenExists.php index 2cc99bf23..88c175642 100644 --- a/src/Validator/Constraints/VerificationTokenExists.php +++ b/src/Validator/Constraints/VerificationTokenExists.php @@ -9,7 +9,7 @@ final class VerificationTokenExists extends Constraint { /** @var string */ - public $message = 'sylius.shop_api.token.not_exists'; + public $message = 'sylius.shop_api.verification_token.not_exists'; /** {@inheritdoc} */ public function getTargets(): string From adeb78d0c18facf9aa80c10f2ea8bea37401d1c2 Mon Sep 17 00:00:00 2001 From: CSchulz Date: Sun, 22 Sep 2019 07:41:56 -0400 Subject: [PATCH 4/8] try to use request parameters --- tests/Controller/Customer/VerifyApiTest.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/Controller/Customer/VerifyApiTest.php b/tests/Controller/Customer/VerifyApiTest.php index 52fde278a..7ee363fa2 100644 --- a/tests/Controller/Customer/VerifyApiTest.php +++ b/tests/Controller/Customer/VerifyApiTest.php @@ -65,11 +65,10 @@ public function it_allows_to_verify_customer_and_returns_properly_error_code(): private function verifyAccount(?string $token): Response { - $token = $token !== null ? '?token=' . $token : ''; $this->client->request( 'GET', - sprintf('/shop-api/verify-account%s', $token), - [], + '/shop-api/verify-account', + [$token !== null ? '?token=' . $token : ''], [], self::CONTENT_TYPE_HEADER ); From 44c052362a1378970157c541ec1612d0db938e06 Mon Sep 17 00:00:00 2001 From: CSchulz Date: Sun, 22 Sep 2019 07:48:34 -0400 Subject: [PATCH 5/8] fix forgotten key --- .../Validator/Customer/VerificationTokenExistsValidatorSpec.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/Validator/Customer/VerificationTokenExistsValidatorSpec.php b/spec/Validator/Customer/VerificationTokenExistsValidatorSpec.php index 416db280d..369c948aa 100644 --- a/spec/Validator/Customer/VerificationTokenExistsValidatorSpec.php +++ b/spec/Validator/Customer/VerificationTokenExistsValidatorSpec.php @@ -60,7 +60,7 @@ function it_adds_constraint_if_verification_token_does_not_exist( ): void { $userRepository->findOneBy(['emailVerificationToken' => 'token'])->willReturn(null); - $executionContext->addViolation('sylius.shop_api.token.not_exists')->shouldBeCalled(); + $executionContext->addViolation('sylius.shop_api.verification_token.not_exists')->shouldBeCalled(); $this->validate('token', new VerificationTokenExists()); } From 91936dff9d207e3621a9b931bd28b13c925818b9 Mon Sep 17 00:00:00 2001 From: CSchulz Date: Sun, 22 Sep 2019 13:55:59 +0200 Subject: [PATCH 6/8] Update tests/Controller/Customer/VerifyApiTest.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Łukasz Chruściel --- tests/Controller/Customer/VerifyApiTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Controller/Customer/VerifyApiTest.php b/tests/Controller/Customer/VerifyApiTest.php index 7ee363fa2..7e7bf96eb 100644 --- a/tests/Controller/Customer/VerifyApiTest.php +++ b/tests/Controller/Customer/VerifyApiTest.php @@ -68,7 +68,7 @@ private function verifyAccount(?string $token): Response $this->client->request( 'GET', '/shop-api/verify-account', - [$token !== null ? '?token=' . $token : ''], + $token !== null : ['token' => $token] ? [], [], self::CONTENT_TYPE_HEADER ); From a6aecd793b086efe6b290a74c641c24d2f18a628 Mon Sep 17 00:00:00 2001 From: CSchulz Date: Sun, 22 Sep 2019 14:03:22 +0200 Subject: [PATCH 7/8] Update VerifyApiTest.php --- tests/Controller/Customer/VerifyApiTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Controller/Customer/VerifyApiTest.php b/tests/Controller/Customer/VerifyApiTest.php index 7e7bf96eb..a246912f4 100644 --- a/tests/Controller/Customer/VerifyApiTest.php +++ b/tests/Controller/Customer/VerifyApiTest.php @@ -68,7 +68,7 @@ private function verifyAccount(?string $token): Response $this->client->request( 'GET', '/shop-api/verify-account', - $token !== null : ['token' => $token] ? [], + $token !== null ? ['token' => $token] : [], [], self::CONTENT_TYPE_HEADER ); From 1f3d470abd8fee8128d5815b2ab6a87db3008c66 Mon Sep 17 00:00:00 2001 From: CSchulz Date: Sun, 22 Sep 2019 14:15:17 +0200 Subject: [PATCH 8/8] unify validation message --- .../Expected/cart/validation_product_not_simple_response.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Responses/Expected/cart/validation_product_not_simple_response.json b/tests/Responses/Expected/cart/validation_product_not_simple_response.json index b928cd5d2..8c92aa5d9 100644 --- a/tests/Responses/Expected/cart/validation_product_not_simple_response.json +++ b/tests/Responses/Expected/cart/validation_product_not_simple_response.json @@ -3,7 +3,7 @@ "message": "Validation failed", "errors": { "productCode": [ - "The product is not a simple product" + "The product is not a simple product." ] } }