Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ab9bda4

Browse files
committed
[API] Resend Verification email
1 parent fa4c1d3 commit ab9bda4

18 files changed

Lines changed: 774 additions & 8 deletions

File tree

features/account/verification/verifying_email_address.feature

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@ Feature: Verifying account's email address
2222
When I try to verify using "twinklelittlestar" token
2323
Then I should be notified that the verification token is invalid
2424

25-
@ui @email
25+
@ui @email @api
2626
Scenario: Resending the verification email as a logged in user
2727
Given I am logged in as "[email protected]"
2828
When I resend the verification email
2929
Then I should be notified that the verification email has been sent
3030
And it should be sent to "[email protected]"
3131

32-
@ui
32+
@ui @api
3333
Scenario: Being unable to verify using old verification links
3434
Given I am logged in as "[email protected]"
3535
And I have already received a verification email
@@ -39,7 +39,7 @@ Feature: Verifying account's email address
3939
Then I should be notified that the verification token is invalid
4040
And my account should not be verified
4141

42-
@ui
42+
@ui @api
4343
Scenario: Being unable to resend verification token when verified
4444
Given I am logged in as "[email protected]"
4545
And I have already verified my account

src/Sylius/Behat/Context/Api/EmailContext.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,15 @@ public function numberOfEmailsShouldBeSentTo(int $count, string $recipient): voi
5252
Assert::same($this->emailChecker->countMessagesTo($recipient), $count);
5353
}
5454

55+
/**
56+
* @Then it should be sent to :recipient
57+
* @Then the email with contact request should be sent to :recipient
58+
*/
59+
public function anEmailShouldBeSentTo(string $recipient): void
60+
{
61+
Assert::true($this->emailChecker->hasRecipient($recipient));
62+
}
63+
5564
private function assertEmailContainsMessageTo(string $message, string $recipient): void
5665
{
5766
Assert::true($this->emailChecker->hasMessageTo($message, $recipient));

src/Sylius/Behat/Context/Api/Shop/CustomerContext.php

Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,27 @@ public function iTryToVerifyUsing(string $token): void
200200
$this->verifyAccount($token);
201201
}
202202

203+
/**
204+
* @When I resend the verification email
205+
*/
206+
public function iResendVerificationEmail(): void
207+
{
208+
/** @var ShopUserInterface $user */
209+
$user = $this->sharedStorage->get('user');
210+
211+
$this->resendVerificationEmail($user->getEmail());
212+
}
213+
214+
/**
215+
* @When I use the verification link from the first email to verify
216+
*/
217+
public function iUseVerificationLinkFromFirstEmailToVerify(): void
218+
{
219+
$token = $this->sharedStorage->get('verification_token');
220+
221+
$this->verifyAccount($token);
222+
}
223+
203224
/**
204225
* @When I register with email :email and password :password
205226
*/
@@ -217,6 +238,14 @@ public function iShouldBeNotifiedThatItHasBeenSuccessfullyEdited(): void
217238
Assert::true($this->responseChecker->isUpdateSuccessful($this->customerClient->getLastResponse()));
218239
}
219240

241+
/**
242+
* @Then I should be notified that the verification email has been sent
243+
*/
244+
public function iShouldBeNotifiedThatTheVerificationEmailHasBeenSent(): void
245+
{
246+
Assert::same($this->customerClient->getLastResponse()->getStatusCode(), 202);
247+
}
248+
220249
/**
221250
* @Then my email should be :email
222251
* @Then my email should still be :email
@@ -419,14 +448,36 @@ public function iShouldBeNotifiedThatTheElementShouldBe(string $elementName, str
419448
* @Then my account should be verified
420449
*/
421450
public function myAccountShouldBeVerified(): void
451+
{
452+
$response = $this->getResponseWithAccountData();
453+
454+
Assert::true($this->responseChecker->getResponseContent($response)['user']['verified']);
455+
}
456+
457+
/**
458+
* @Then /^(?:my|his|her) account should not be verified$/
459+
*/
460+
public function myAccountShouldNotBeVerified(): void
461+
{
462+
$response = $this->getResponseWithAccountData();
463+
464+
Assert::false($this->responseChecker->getResponseContent($response)['user']['verified']);
465+
}
466+
467+
/**
468+
* @Then I should not be able to resend the verification email
469+
*/
470+
public function iShouldBeUnableToResendVerificationEmail(): void
422471
{
423472
/** @var ShopUserInterface $user */
424473
$user = $this->sharedStorage->get('user');
425-
$this->loginContext->iLogInAsWithPassword($user->getEmail(), 'sylius');
426474

427-
$response = $this->customerClient->show((string) $user->getCustomer()->getId());
475+
$this->resendVerificationEmail($user->getEmail());
428476

429-
Assert::true($this->responseChecker->getResponseContent($response)['user']['verified']);
477+
Assert::same($this->responseChecker->getError($this->customerClient->getLastResponse()),
478+
\sprintf('Account with email %s is currently verified.', $user->getEmail()),
479+
'Validation message is different then expected.'
480+
);
430481
}
431482

432483
private function isViolationWithMessageInResponse(Response $response, string $message): bool
@@ -464,4 +515,22 @@ private function registerAccount(?string $email = '[email protected]', ?string
464515

465516
$this->customerClient->executeCustomRequest($request);
466517
}
518+
519+
private function resendVerificationEmail(string $email): void
520+
{
521+
$request = Request::create('shop', 'account-verification-requests', 'Bearer');
522+
523+
$request->setContent(['email' => $email]);
524+
525+
$this->customerClient->executeCustomRequest($request);
526+
}
527+
528+
private function getResponseWithAccountData(): Response
529+
{
530+
/** @var ShopUserInterface $user */
531+
$user = $this->sharedStorage->get('user');
532+
$this->loginContext->iLogInAsWithPassword($user->getEmail(), 'sylius');
533+
534+
return $this->customerClient->show((string) $user->getCustomer()->getId());
535+
}
467536
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Sylius package.
5+
*
6+
* (c) Paweł Jędrzejewski
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace Sylius\Bundle\ApiBundle\Command;
15+
16+
/** @experimental */
17+
class ResendVerificationEmail implements ChannelCodeAwareInterface, LocaleCodeAwareInterface
18+
{
19+
/** @var string */
20+
public $email;
21+
22+
/**
23+
* @var string
24+
* @psalm-immutable
25+
*/
26+
public $channelCode;
27+
28+
/**
29+
* @var string|null
30+
* @psalm-immutable
31+
*/
32+
public $localeCode;
33+
34+
public function __construct(string $email)
35+
{
36+
$this->email = $email;
37+
}
38+
39+
public function getChannelCode(): string
40+
{
41+
return $this->channelCode;
42+
}
43+
44+
public function setChannelCode(?string $channelCode): void
45+
{
46+
$this->channelCode = $channelCode;
47+
}
48+
49+
public function getLocaleCode(): ?string
50+
{
51+
return $this->localeCode;
52+
}
53+
54+
public function setLocaleCode(?string $localeCode): void
55+
{
56+
$this->localeCode = $localeCode;
57+
}
58+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Sylius package.
5+
*
6+
* (c) Paweł Jędrzejewski
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace Sylius\Bundle\ApiBundle\CommandHandler;
15+
16+
use Sylius\Component\User\Repository\UserRepositoryInterface;
17+
use Webmozart\Assert\Assert;
18+
use Sylius\Bundle\ApiBundle\Command\ResendVerificationEmail;
19+
use Sylius\Bundle\ApiBundle\Command\SendAccountVerificationEmail;
20+
use Sylius\Component\Channel\Repository\ChannelRepositoryInterface;
21+
use Sylius\Component\Core\Model\ChannelInterface;
22+
use Sylius\Component\User\Model\UserInterface;
23+
use Sylius\Component\User\Security\Generator\GeneratorInterface;
24+
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;
25+
use Symfony\Component\Messenger\MessageBusInterface;
26+
use Symfony\Component\Messenger\Stamp\DispatchAfterCurrentBusStamp;
27+
28+
/** @experimental */
29+
final class ResendVerificationEmailHandler implements MessageHandlerInterface
30+
{
31+
/** @var UserRepositoryInterface */
32+
private $shopUserRepository;
33+
34+
/** @var GeneratorInterface */
35+
private $tokenGenerator;
36+
37+
/** @var ChannelRepositoryInterface */
38+
private $channelRepository;
39+
40+
/** @var MessageBusInterface */
41+
private $commandBus;
42+
43+
public function __construct(
44+
UserRepositoryInterface $shopUserRepository,
45+
GeneratorInterface $tokenGenerator,
46+
ChannelRepositoryInterface $channelRepository,
47+
MessageBusInterface $commandBus
48+
) {
49+
$this->shopUserRepository = $shopUserRepository;
50+
$this->tokenGenerator = $tokenGenerator;
51+
$this->channelRepository = $channelRepository;
52+
$this->commandBus = $commandBus;
53+
}
54+
55+
public function __invoke(ResendVerificationEmail $command): void
56+
{
57+
/** @var UserInterface|null $user */
58+
Assert::notNull($user = $this->shopUserRepository->findOneByEmail($command->email));
59+
60+
/** @var ChannelInterface $channel */
61+
$channel = $this->channelRepository->findOneByCode($command->channelCode);
62+
63+
if (!$channel->isAccountVerificationRequired()) {
64+
$user->setEnabled(true);
65+
66+
return;
67+
}
68+
69+
$token = $this->tokenGenerator->generate();
70+
$user->setEmailVerificationToken($token);
71+
72+
$this->commandBus->dispatch(new SendAccountVerificationEmail(
73+
$command->email,
74+
$command->localeCode,
75+
$command->channelCode
76+
), [new DispatchAfterCurrentBusStamp()]);
77+
}
78+
}

src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/VerifyCustomerAccount.xml

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,28 @@
1919
<attribute name="route_prefix">shop</attribute>
2020
<attribute name="messenger">input</attribute>
2121
<attribute name="validation_groups">sylius</attribute>
22+
<attribute name="output">false</attribute>
2223

23-
<collectionOperations />
24+
<collectionOperations>
25+
<collectionOperation name="shop_resend_verification_email">
26+
<attribute name="method">POST</attribute>
27+
<attribute name="path">/account-verification-requests</attribute>
28+
<attribute name="input">Sylius\Bundle\ApiBundle\Command\ResendVerificationEmail</attribute>
29+
<attribute name="status">202</attribute>
30+
<attribute name="denormalization_context">
31+
<attribute name="groups">shop:resend_verification_email:create</attribute>
32+
</attribute>
33+
<attribute name="openapi_context">
34+
<attribute name="summary">Resends verification email</attribute>
35+
</attribute>
36+
</collectionOperation>
37+
</collectionOperations>
2438

2539
<itemOperations>
2640
<itemOperation name="shop_verify_customer_account">
2741
<attribute name="method">PATCH</attribute>
2842
<attribute name="path">/account-verification-requests/{id}</attribute>
2943
<attribute name="input">Sylius\Bundle\ApiBundle\Command\VerifyCustomerAccount</attribute>
30-
<attribute name="output">false</attribute>
3144
<attribute name="status">202</attribute>
3245
<attribute name="denormalization_context">
3346
<attribute name="groups">shop:account_verification:update</attribute>
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?xml version="1.0" ?>
2+
3+
<!--
4+
5+
This file is part of the Sylius package.
6+
7+
(c) Paweł Jędrzejewski
8+
9+
For the full copyright and license information, please view the LICENSE
10+
file that was distributed with this source code.
11+
12+
-->
13+
14+
<serializer xmlns="http://symfony.com/schema/dic/serializer-mapping"
15+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
16+
xsi:schemaLocation="http://symfony.com/schema/dic/serializer-mapping https://symfony.com/schema/dic/serializer-mapping/serializer-mapping-1.0.xsd"
17+
>
18+
<class name="Sylius\Bundle\ApiBundle\Command\ResendVerificationEmail">
19+
<attribute name="email">
20+
<group>shop:resend_verification_email:create</group>
21+
</attribute>
22+
<attribute name="localeCode">
23+
<group>shop:resend_verification_email:create</group>
24+
</attribute>
25+
</class>
26+
</serializer>

src/Sylius/Bundle/ApiBundle/Resources/config/services/command_handlers.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,14 @@
111111
<tag name="messenger.message_handler" bus="sylius_default.bus"/>
112112
</service>
113113

114+
<service id="Sylius\Bundle\ApiBundle\CommandHandler\ResendVerificationEmailHandler">
115+
<argument type="service" id="sylius.repository.shop_user" />
116+
<argument type="service" id="sylius.shop_user.token_generator.email_verification" />
117+
<argument type="service" id="sylius.repository.channel" />
118+
<argument type="service" id="sylius_default.bus" />
119+
<tag name="messenger.message_handler" bus="sylius_default.bus"/>
120+
</service>
121+
114122
<service id="Sylius\Bundle\ApiBundle\CommandHandler\ResetPasswordHandler">
115123
<argument type="service" id="sylius.repository.shop_user" />
116124
<argument type="service">

src/Sylius/Bundle/ApiBundle/Resources/config/services/validator.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,16 @@
5959
<tag name="validator.constraint_validator" alias="sylius_api_promotion_coupon_eligibility" />
6060
</service>
6161

62+
<service id="sylius.api.validator.shop_user_exists" class="Sylius\Bundle\ApiBundle\Validator\Constraints\ShopUserExistsValidator">
63+
<argument type="service" id="sylius.repository.shop_user" />
64+
<tag name="validator.constraint_validator" alias="sylius_api_shop_user_exists" />
65+
</service>
66+
67+
<service id="sylius.api.validator.shop_user_verification_state" class="Sylius\Bundle\ApiBundle\Validator\Constraints\ShopUserVerificationStateValidator">
68+
<argument type="service" id="sylius.repository.shop_user" />
69+
<tag name="validator.constraint_validator" alias="sylius_api_shop_user_verification_state" />
70+
</service>
71+
6272
<service id="sylius.api.validator.account_verification_token_eligibility" class="Sylius\Bundle\ApiBundle\Validator\Constraints\AccountVerificationTokenEligibilityValidator">
6373
<argument type="service" id="sylius.repository.shop_user" />
6474
<tag name="validator.constraint_validator" alias="sylius_api_validator_account_verification_token_eligibility" />

0 commit comments

Comments
 (0)