EmailAddressManager   A
last analyzed

Complexity

Total Complexity 9

Size/Duplication

Total Lines 77
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
eloc 44
dl 0
loc 77
ccs 0
cts 44
cp 0
rs 10
c 0
b 0
f 0
wmc 9

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 12 1
A verifyEmailAddress() 0 18 3
A confirmNewEmailAddress() 0 35 5
1
<?php
2
3
/*
4
 * This file is part of the Silverback API Components Bundle Project
5
 *
6
 * (c) Daniel West <[email protected]>
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 Silverback\ApiComponentsBundle\Helper\User;
15
16
use Doctrine\ORM\EntityManagerInterface;
17
use Silverback\ApiComponentsBundle\EventListener\Api\UserEventListener;
18
use Silverback\ApiComponentsBundle\Exception\InvalidArgumentException;
19
use Silverback\ApiComponentsBundle\Exception\UnexpectedValueException;
20
use Silverback\ApiComponentsBundle\Repository\User\UserRepositoryInterface;
21
use Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface;
22
23
/**
24
 * @author Daniel West <[email protected]>
25
 */
26
class EmailAddressManager
27
{
28
    private EntityManagerInterface $entityManager;
29
    private UserRepositoryInterface $userRepository;
30
    private PasswordHasherFactoryInterface $passwordHasherFactory;
31
    private UserDataProcessor $userDataProcessor;
32
    private UserEventListener $userEventListener;
33
34
    public function __construct(
35
        EntityManagerInterface $entityManager,
36
        UserRepositoryInterface $userRepository,
37
        PasswordHasherFactoryInterface $passwordHasherFactory,
38
        UserDataProcessor $userDataProcessor,
39
        UserEventListener $userEventListener
40
    ) {
41
        $this->entityManager = $entityManager;
42
        $this->userRepository = $userRepository;
43
        $this->passwordHasherFactory = $passwordHasherFactory;
44
        $this->userDataProcessor = $userDataProcessor;
45
        $this->userEventListener = $userEventListener;
46
    }
47
48
    public function confirmNewEmailAddress(string $username, string $email, string $token): void
49
    {
50
        if ('' === $email) {
51
            throw new InvalidArgumentException('User not found');
52
        }
53
        $user = $this->userRepository->findOneByUsernameAndNewEmailAddress($username, $email);
54
        if (!$user) {
55
            throw new InvalidArgumentException('User not found');
56
        }
57
        $previousUser = clone $user;
58
        $hasher = $this->passwordHasherFactory->getPasswordHasher($user);
59
        if (!$hasher->verify($user->getNewEmailConfirmationToken(), $token)) {
0 ignored issues
show
Bug introduced by
It seems like $user->getNewEmailConfirmationToken() can also be of type null; however, parameter $hashedPassword of Symfony\Component\Passwo...sherInterface::verify() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

59
        if (!$hasher->verify(/** @scrutinizer ignore-type */ $user->getNewEmailConfirmationToken(), $token)) {
Loading history...
60
            throw new InvalidArgumentException('Invalid token');
61
        }
62
63
        // Check if another user now exists with this new email address before persisting!
64
        $existingUser = $this->userRepository->findExistingUserByNewEmail($user);
65
        if ($existingUser) {
66
            $user
67
                ->setNewEmailAddress(null)
68
                ->setNewEmailConfirmationToken(null);
69
70
            $this->entityManager->flush();
71
            throw new UnexpectedValueException('Another user now exists with that email. Verification aborted.');
72
        }
73
74
        $user
75
            ->setEmailAddress($user->getNewEmailAddress())
76
            ->setNewEmailAddress(null)
77
            ->setEmailAddressVerified(false)
78
            ->setNewEmailConfirmationToken(null);
79
80
        $this->userDataProcessor->processChanges($user, $previousUser);
81
        $this->entityManager->flush();
82
        $this->userEventListener->postWrite($user, $previousUser);
83
    }
84
85
    public function verifyEmailAddress(string $username, string $token): void
86
    {
87
        $user = $this->userRepository->findOneBy(
0 ignored issues
show
Bug introduced by
The method findOneBy() does not exist on Silverback\ApiComponents...UserRepositoryInterface. Did you maybe mean findOneByEmail()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

87
        /** @scrutinizer ignore-call */ 
88
        $user = $this->userRepository->findOneBy(

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
88
            [
89
                'username' => $username,
90
            ]
91
        );
92
        if (!$user) {
93
            throw new InvalidArgumentException('User not found');
94
        }
95
96
        $hasher = $this->passwordHasherFactory->getPasswordHasher($user);
97
        if (!$hasher->verify($user->getEmailAddressVerifyToken(), $token)) {
98
            throw new InvalidArgumentException('Invalid token');
99
        }
100
101
        $user->setEmailAddressVerified(true);
102
        $this->entityManager->flush();
103
    }
104
}
105