Passed
Push — master ( d48eaa...ef7f73 )
by Daniel
07:23 queued 33s
created

UserDataProcessor::processChanges()   B

Complexity

Conditions 7
Paths 9

Size

Total Lines 18
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 12
c 1
b 0
f 0
nc 9
nop 2
dl 0
loc 18
ccs 0
cts 12
cp 0
crap 56
rs 8.8333
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 Silverback\ApiComponentsBundle\Entity\User\AbstractUser;
17
use Silverback\ApiComponentsBundle\Exception\InvalidArgumentException;
18
use Silverback\ApiComponentsBundle\Exception\UnexpectedValueException;
19
use Silverback\ApiComponentsBundle\Repository\User\UserRepository;
20
use Silverback\ApiComponentsBundle\Security\TokenGenerator;
21
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
22
23
/**
24
 * @author Daniel West <[email protected]>
25
 */
26
class UserDataProcessor
27
{
28
    private UserPasswordEncoderInterface $passwordEncoder;
29
    private UserRepository $userRepository;
30
    private bool $initialEmailVerifiedState;
31
    private bool $verifyEmailOnRegister;
32
    private bool $verifyEmailOnChange;
33
    private int $tokenTtl;
34
35
    public function __construct(
36
        UserPasswordEncoderInterface $passwordEncoder,
37
        UserRepository $userRepository,
38
        bool $initialEmailVerifiedState,
39
        bool $verifyEmailOnRegister,
40
        bool $verifyEmailOnChange,
41
        int $tokenTtl = 8600
42
    ) {
43
        $this->passwordEncoder = $passwordEncoder;
44
        $this->userRepository = $userRepository;
45
        $this->initialEmailVerifiedState = $initialEmailVerifiedState;
46
        $this->verifyEmailOnRegister = $verifyEmailOnRegister;
47
        $this->verifyEmailOnChange = $verifyEmailOnChange;
48
        $this->tokenTtl = $tokenTtl;
49
    }
50
51
    public function updatePasswordConfirmationToken(string $usernameQuery): ?AbstractUser
52
    {
53
        $user = $this->userRepository->findOneBy(['username' => $usernameQuery]);
54
        if (!$user) {
55
            throw new InvalidArgumentException('Username not found');
56
        }
57
58
        if ($user->isPasswordRequestLimitReached($this->tokenTtl)) {
59
            return null;
60
        }
61
62
        $username = $user->getUsername();
63
        if (!$username) {
64
            throw new UnexpectedValueException(sprintf('The entity %s should have a username set to send a password reset email.', AbstractUser::class));
65
        }
66
        $user->setNewPasswordConfirmationToken(TokenGenerator::generateToken());
67
        $user->setPasswordRequestedAt(new \DateTime());
68
69
        return $user;
70
    }
71
72
    public function passwordReset(string $username, string $token, string $newPassword): ?AbstractUser
73
    {
74
        $user = $this->userRepository->findOneByPasswordResetToken($username, $token);
75
        if (!$user) {
76
            return null;
77
        }
78
79
        $user->setPlainPassword($newPassword);
80
        $user->setNewPasswordConfirmationToken(null);
81
        $user->setPasswordRequestedAt(null);
82
        $this->encodePassword($user);
83
84
        return $user;
85
    }
86
87
    public function processChanges(AbstractUser $user, ?AbstractUser $previousUser): void
88
    {
89
        $this->encodePassword($user);
90
        $user->setEmailAddressVerified($this->initialEmailVerifiedState);
91
92
        if (!$previousUser && !$this->initialEmailVerifiedState) {
93
            $user->setNewEmailAddress($user->getEmailAddress());
94
            if ($this->verifyEmailOnRegister) {
95
                $user->setNewEmailVerificationToken(TokenGenerator::generateToken());
96
            }
97
        }
98
99
        if ($previousUser && $previousUser->getNewEmailAddress() !== ($newEmail = $user->getNewEmailAddress())) {
100
            if ($this->verifyEmailOnChange) {
101
                $user->setNewEmailVerificationToken(TokenGenerator::generateToken());
102
            } else {
103
                $user->setEmailAddress($newEmail);
104
                $user->setNewEmailAddress(null);
105
            }
106
        }
107
    }
108
109
    private function encodePassword(AbstractUser $entity): bool
110
    {
111
        if (!$entity->getPlainPassword()) {
112
            return false;
113
        }
114
        $encoded = $this->passwordEncoder->encodePassword($entity, $entity->getPlainPassword());
115
        $entity->setPassword($encoded);
116
        $entity->eraseCredentials();
117
118
        return true;
119
    }
120
}
121