Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add validation to verify account action and update swagger.yml #555

Merged
merged 9 commits into from
Sep 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions doc/swagger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
67 changes: 67 additions & 0 deletions spec/Validator/Customer/VerificationTokenExistsValidatorSpec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

declare(strict_types=1);

namespace spec\Sylius\ShopApiPlugin\Validator\Customer;

use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Sylius\Component\Core\Model\ShopUserInterface;
use Sylius\Component\User\Repository\UserRepositoryInterface;
use Sylius\ShopApiPlugin\Validator\Constraints\VerificationTokenExists;
use Sylius\ShopApiPlugin\Validator\Customer\VerificationTokenExistsValidator;
use Symfony\Component\Validator\Context\ExecutionContextInterface;

final class VerificationTokenExistsValidatorSpec extends ObjectBehavior
{
function let(ExecutionContextInterface $executionContext, UserRepositoryInterface $userRepository): void
{
$this->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(
ExecutionContextInterface $executionContext
): void {
$executionContext->addViolation(Argument::any())->shouldNotBeCalled();

$this->validate('', new VerificationTokenExists());
CSchulz marked this conversation as resolved.
Show resolved Hide resolved
}

function it_does_not_add_constraint_if_verification_token_is_null(
ExecutionContextInterface $executionContext
): void {
$executionContext->addViolation(Argument::any())->shouldNotBeCalled();

$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.verification_token.not_exists')->shouldBeCalled();

$this->validate('token', new VerificationTokenExists());
}
}
6 changes: 6 additions & 0 deletions src/Resources/config/services/validators/customer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,11 @@
<argument type="service" id="sylius.repository.shop_user"/>
<tag name="validator.constraint_validator" alias="sylius_shop_api_shop_user_does_not_exist_validator"/>
</service>

<service id="sylius.shop_api_plugin.validator.verification_token_exists_validator"
class="Sylius\ShopApiPlugin\Validator\Customer\VerificationTokenExistsValidator">
<argument type="service" id="sylius.repository.shop_user"/>
<tag name="validator.constraint_validator" alias="sylius_shop_api_verification_token_exists_validator"/>
</service>
</services>
</container>
13 changes: 13 additions & 0 deletions src/Resources/config/validation/customer/VerifyAccountRequest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
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">
<class name="Sylius\ShopApiPlugin\Request\Customer\VerifyAccountRequest">
<property name="token">
<constraint name="NotBlank">
<option name="message">sylius.shop_api.verification_token.not_blank</option>
</constraint>
<constraint name="Sylius\ShopApiPlugin\Validator\Constraints\VerificationTokenExists" />
</property>
</class>
</constraint-mapping>
5 changes: 4 additions & 1 deletion src/Resources/translations/validators.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +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.
verification_token:
not_blank: Please provide a token.
not_exists: The token does not exist.
25 changes: 25 additions & 0 deletions src/Validator/Constraints/VerificationTokenExists.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace Sylius\ShopApiPlugin\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

final class VerificationTokenExists extends Constraint
{
/** @var string */
public $message = 'sylius.shop_api.verification_token.not_exists';

/** {@inheritdoc} */
public function getTargets(): string
{
return self::PROPERTY_CONSTRAINT;
}

/** {@inheritdoc} */
public function validatedBy(): string
{
return 'sylius_shop_api_verification_token_exists_validator';
}
}
30 changes: 30 additions & 0 deletions src/Validator/Customer/VerificationTokenExistsValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace Sylius\ShopApiPlugin\Validator\Customer;

use Sylius\Component\User\Repository\UserRepositoryInterface;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use the interface from the core.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is only this interface. Do you mean the class?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use a core interface

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know which one you mean. The UserRepositoryInterface from the user component is the only one, I have found.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, my bad.

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

final class VerificationTokenExistsValidator extends ConstraintValidator
{
/** @var UserRepositoryInterface */
private $userRepository;

public function __construct(UserRepositoryInterface $userRepository)
{
$this->userRepository = $userRepository;
}

public function validate($token, Constraint $constraint)
{
if (null === $token || 0 === strlen($token)) {
return;
}
if (null === $this->userRepository->findOneBy(['emailVerificationToken' => $token])) {
$this->context->addViolation($constraint->message);
}
}
}
31 changes: 31 additions & 0 deletions tests/Controller/Customer/VerifyApiTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,37 @@ 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
{
$this->client->request(
'GET',
'/shop-api/verify-account',
$token !== null ? ['token' => $token] : [],
[],
self::CONTENT_TYPE_HEADER
);

return $this->client->getResponse();
}

protected function getContainer(): ContainerInterface
{
return static::$sharedKernel->getContainer();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"message": "Validation failed",
"errors": {
"productCode": [
"The product is not a simple product"
"The product is not a simple product."
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"code": 400,
"message": "Validation failed",
"errors": {
"token": [
"Please provide a token."
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"code": 400,
"message": "Validation failed",
"errors": {
"token": [
"The token does not exist."
]
}
}