Completed
Pull Request — master (#2737)
by Jeroen
17:30 queued 02:36
created

UserManager::updatePassword()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
rs 9.584
c 0
b 0
f 0
cc 3
nc 3
nop 1
1
<?php
2
3
namespace Kunstmaan\AdminBundle\Service;
4
5
use Doctrine\ORM\EntityManagerInterface;
6
use Doctrine\ORM\EntityRepository;
7
use Kunstmaan\AdminBundle\Entity\UserInterface;
8
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
9
use Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder;
10
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
11
12
class UserManager
13
{
14
    /** @var EntityManagerInterface */
15
    private $em;
16
17
    /** @var string */
18
    private $class;
19
20
    /** @var string */
21
    private $encoderFactory;
22
23
    public function __construct(EncoderFactoryInterface $encoderFactory, EntityManagerInterface $em, string $class)
24
    {
25
        $this->em = $em;
26
        $this->class = $class;
27
        $this->encoderFactory = $encoderFactory;
0 ignored issues
show
Documentation Bug introduced by
It seems like $encoderFactory of type object<Symfony\Component...ncoderFactoryInterface> is incompatible with the declared type string of property $encoderFactory.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
28
    }
29
30
    public function deleteUser(UserInterface $user)
31
    {
32
        $this->em->remove($user);
33
        $this->em->flush();
34
    }
35
36
    public function findUsers()
37
    {
38
        return $this->getRepository()->findAll();
39
    }
40
41
    protected function getRepository(): EntityRepository
42
    {
43
        return $this->em->getRepository($this->getClass());
44
    }
45
46
    public function getClass()
47
    {
48
        if (false !== strpos($this->class, ':')) {
49
            $metadata = $this->em->getClassMetadata($this->class);
50
            $this->class = $metadata->getName();
51
        }
52
53
        return $this->class;
54
    }
55
56
    public function reloadUser(UserInterface $user)
57
    {
58
        $this->em->refresh($user);
59
    }
60
61
    public function updateUser(UserInterface $user, $andFlush = true)
62
    {
63
        $this->updatePassword($user);
64
65
        $this->em->persist($user);
66
        if ($andFlush) {
67
            $this->em->flush();
68
        }
69
    }
70
71
    public function updatePassword(UserInterface $user)
72
    {
73
        $plainPassword = $user->getPlainPassword();
74
75
        if (0 === strlen($plainPassword)) {
76
            return;
77
        }
78
79
        $encoder = $this->encoderFactory->getEncoder($user);
0 ignored issues
show
Bug introduced by
The method getEncoder cannot be called on $this->encoderFactory (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
80
81
        if ($encoder instanceof BCryptPasswordEncoder) {
82
            $user->setSalt(null);
83
        } else {
84
            $salt = rtrim(str_replace('+', '.', base64_encode(random_bytes(32))), '=');
85
            $user->setSalt($salt);
86
        }
87
88
        $hashedPassword = $encoder->encodePassword($plainPassword, $user->getSalt());
89
        $user->setPassword($hashedPassword);
90
        $user->eraseCredentials();
91
    }
92
93
    public function createUser()
94
    {
95
        $class = $this->getClass();
96
        $user = new $class();
97
98
        return $user;
99
    }
100
101
    public function findUserByUsernameOrEmail($usernameOrEmail)
102
    {
103
        if (preg_match('/^.+\@\S+\.\S+$/', $usernameOrEmail)) {
104
            $user = $this->findUserByEmail($usernameOrEmail);
105
            if (null !== $user) {
106
                return $user;
107
            }
108
        }
109
110
        return $this->findUserByUsername($usernameOrEmail);
111
    }
112
113
    public function findUserByEmail($email)
114
    {
115
        return $this->findUserBy(['email' => $email]);
116
    }
117
118
    public function findUserBy(array $criteria)
119
    {
120
        return $this->getRepository()->findOneBy($criteria);
121
    }
122
123
    public function findUserByUsername($username)
124
    {
125
        return $this->findUserBy(['username' => $username]);
126
    }
127
128
    public function findUserByConfirmationToken($token)
129
    {
130
        return $this->findUserBy(['confirmationToken' => $token]);
131
    }
132
133
    /**
134
     * Change the user password and update the security token
135
     */
136
    public function changePassword(UserInterface $user, string $newPassword)
137
    {
138
        $encoder = $this->encoderFactory->getEncoder($user);
0 ignored issues
show
Bug introduced by
The method getEncoder cannot be called on $this->encoderFactory (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
139
        $password = $encoder->encodePassword($user, $newPassword);
140
141
        $user->setPassword($password);
142
        $user->setConfirmationToken(null);
143
        $this->em->flush();
144
145
        $token = new UsernamePasswordToken($user, $password, 'main');
146
        $this->tokenStorage->setToken($token);
0 ignored issues
show
Bug introduced by
The property tokenStorage does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
147
        $this->session->set('_security_main', serialize($token));
0 ignored issues
show
Bug introduced by
The property session does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
148
    }
149
150
    public function setResetToken(UserInterface $user)
151
    {
152
        $token = bin2hex(random_bytes(32));
153
        $user->setConfirmationToken($token);
154
155
        $this->em->flush();
156
    }
157
}
158