Passed
Push — master ( 153cf2...1d1f3f )
by Daniel
12:32 queued 07:14
created

AbstractUser::getRoles()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
/*
4
 * This file is part of the Silverback API Component 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\ApiComponentBundle\Entity\User;
15
16
use ApiPlatform\Core\Annotation\ApiProperty;
17
use DateTime;
18
use Doctrine\ORM\Mapping as ORM;
19
use Lexik\Bundle\JWTAuthenticationBundle\Security\User\JWTUserInterface;
20
use Silverback\ApiComponentBundle\Entity\Utility\IdTrait;
21
use Silverback\ApiComponentBundle\Entity\Utility\TimestampedInterface;
22
use Silverback\ApiComponentBundle\Entity\Utility\TimestampedTrait;
23
use Silverback\ApiComponentBundle\Validator\Constraints as APIAssert;
24
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
25
use Symfony\Component\Security\Core\User\UserInterface as SymfonyUserInterface;
26
use Symfony\Component\Security\Core\Validator\Constraints\UserPassword;
27
use Symfony\Component\Serializer\Annotation\Groups;
28
use Symfony\Component\Validator\Constraints as Assert;
29
30
/**
31
 * @author Daniel West <[email protected]>
32
 * @ORM\MappedSuperclass(repositoryClass="Silverback\ApiComponentBundle\Repository\User\UserRepository")
33
 * @UniqueEntity(fields={"username"}, errorPath="username", message="Sorry, that user already exists in the database.")
34
 * @APIAssert\NewEmailAddress(groups={"new_email_address", "Default"})
35
 */
36
abstract class AbstractUser implements SymfonyUserInterface, TimestampedInterface, JWTUserInterface
37
{
38
    use IdTrait;
39
    use TimestampedTrait;
40
41
    /**
42
     * @ORM\Column(type="string", length=255, unique=true)
43
     * @Assert\NotBlank(groups={"Default"})
44
     * @Groups({"User:super_admin", "User:output"})
45
     */
46
    protected ?string $username;
47
48
    /**
49
     * @ORM\Column(type="string", length=255, unique=true)
50
     * @Assert\NotBlank(groups={"Default"})
51
     * @Assert\Email()
52
     * @Groups({"User:super_admin", "User:output"})
53
     */
54
    protected ?string $emailAddress;
55
56
    /**
57
     * @ORM\Column(type="array")
58
     * @Groups({"User:super_admin"})
59
     */
60
    protected array $roles;
61
62
    /**
63
     * @ORM\Column(type="boolean")
64
     * @Groups({"User:super_admin"})
65
     */
66
    protected bool $enabled;
67
68
    /**
69
     * @ORM\Column(type="string", length=255)
70
     * @ApiProperty(readable=false, writable=false)
71
     */
72
    protected string $password;
73
74
    /**
75
     * @ApiProperty(readable=false)
76
     * @Assert\NotBlank(message="Please enter your desired password", groups={"password_reset", "change_password"})
77
     * @Assert\Length(max="4096", min="6", maxMessage="Your password cannot be over 4096 characters", minMessage="Your password must be more than 6 characters long", groups={"Default", "password_reset", "change_password"})
78
     * @Groups({"User:input"})
79
     */
80
    protected ?string $plainPassword = null;
81
82
    /**
83
     * Random string sent to the user email address in order to verify it.
84
     *
85
     * @ORM\Column(nullable=true)
86
     * @ApiProperty(readable=false, writable=false)
87
     */
88
    protected ?string $newPasswordConfirmationToken = null;
89
90
    /**
91
     * @ORM\Column(type="datetime", nullable=true)
92
     * @ApiProperty(readable=false, writable=false)
93
     */
94
    protected ?DateTime $passwordRequestedAt = null;
95
96
    /**
97
     * @ApiProperty(readable=false)
98
     * @UserPassword(message="You have not entered your current password correctly. Please try again.", groups={"change_password"})
99
     * @Groups({"User:input"})
100
     */
101
    protected ?string $oldPassword = null;
102
103
    /**
104
     * @ApiProperty(readable=false, writable=false)
105
     * @ORM\Column(type="datetime", nullable=true)
106
     */
107
    protected ?DateTime $passwordLastUpdated = null;
108
109
    /**
110
     * @ORM\Column(type="string", length=255, nullable=true)
111
     * @Assert\NotBlank(groups={"new_email_address"})
112
     * @Groups({"User:input", "User:output", "new_email_address"})
113
     */
114
    protected ?string $newEmailAddress = null;
115
116
    /**
117
     * Random string sent to the user's new email address in order to verify it.
118
     *
119
     * @ORM\Column(nullable=true)
120
     * @ApiProperty(readable=false, writable=false)
121
     */
122
    protected ?string $newEmailVerificationToken = null;
123
124
    /**
125
     * @ORM\Column(type="boolean", nullable=false)
126
     * @ApiProperty(readable=false, writable=false)
127
     */
128
    protected bool $emailAddressVerified = false;
129
130 56
    public function __construct(
131
        string $username = '',
132
        string $emailAddress = '',
133
        bool $emailAddressVerified = false,
134
        array $roles = ['ROLE_USER'],
135
        string $password = '',
136
        bool $enabled = true
137
    ) {
138 56
        $this->username = $username;
139 56
        $this->emailAddress = $emailAddress;
140 56
        $this->emailAddressVerified = $emailAddressVerified;
141 56
        $this->roles = $roles;
142 56
        $this->password = $password;
143 56
        $this->enabled = $enabled;
144 56
        $this->setId();
145 56
    }
146
147 28
    public function getUsername(): ?string
148
    {
149 28
        return $this->username;
150
    }
151
152 21
    public function setUsername(?string $username): self
153
    {
154 21
        $this->username = $username;
155
156 21
        return $this;
157
    }
158
159 25
    public function getEmailAddress(): ?string
160
    {
161 25
        return $this->emailAddress;
162
    }
163
164 23
    public function setEmailAddress(?string $emailAddress): self
165
    {
166 23
        $this->emailAddress = $emailAddress;
167
168 23
        return $this;
169
    }
170
171 4
    public function getRoles(): array
172
    {
173 4
        return $this->roles;
174
    }
175
176 1
    public function setRoles(?array $roles): self
177
    {
178 1
        $this->roles = $roles;
179
180 1
        return $this;
181
    }
182
183 6
    public function isEnabled(): bool
184
    {
185 6
        return $this->enabled;
186
    }
187
188 4
    public function setEnabled(bool $enabled): self
189
    {
190 4
        $this->enabled = $enabled;
191
192 4
        return $this;
193
    }
194
195 3
    public function getPassword(): ?string
196
    {
197 3
        return $this->password;
198
    }
199
200 2
    public function setPassword(string $password): self
201
    {
202 2
        $this->password = $password;
203
204 2
        return $this;
205
    }
206
207 6
    public function getPlainPassword(): ?string
208
    {
209 6
        return $this->plainPassword;
210
    }
211
212 1
    public function setPlainPassword(?string $plainPassword): self
213
    {
214 1
        $this->plainPassword = $plainPassword;
215 1
        if ($plainPassword) {
216
            // Needs to update mapped field to trigger update event which will encode the plain password
217 1
            $this->passwordLastUpdated = new \DateTime();
218
        }
219
220 1
        return $this;
221
    }
222
223 3
    public function getNewPasswordConfirmationToken(): ?string
224
    {
225 3
        return $this->newPasswordConfirmationToken;
226
    }
227
228 4
    public function setNewPasswordConfirmationToken(?string $newPasswordConfirmationToken): self
229
    {
230 4
        $this->newPasswordConfirmationToken = $newPasswordConfirmationToken;
231
232 4
        return $this;
233
    }
234
235 2
    public function getPasswordRequestedAt(): ?DateTime
236
    {
237 2
        return $this->passwordRequestedAt;
238
    }
239
240 4
    public function setPasswordRequestedAt(?DateTime $passwordRequestedAt): self
241
    {
242 4
        $this->passwordRequestedAt = $passwordRequestedAt;
243
244 4
        return $this;
245
    }
246
247 1
    public function getOldPassword(): ?string
248
    {
249 1
        return $this->oldPassword;
250
    }
251
252 1
    public function setOldPassword(?string $oldPassword): self
253
    {
254 1
        $this->oldPassword = $oldPassword;
255
256 1
        return $this;
257
    }
258
259 5
    public function getNewEmailAddress(): ?string
260
    {
261 5
        return $this->newEmailAddress;
262
    }
263
264 9
    public function setNewEmailAddress(?string $newEmailAddress): self
265
    {
266 9
        $this->newEmailAddress = $newEmailAddress;
267
268 9
        return $this;
269
    }
270
271 10
    public function getNewEmailVerificationToken(): ?string
272
    {
273 10
        return $this->newEmailVerificationToken;
274
    }
275
276 4
    public function setNewEmailVerificationToken(?string $newEmailVerificationToken): self
277
    {
278 4
        $this->newEmailVerificationToken = $newEmailVerificationToken;
279
280 4
        return $this;
281
    }
282
283 3
    public function isEmailAddressVerified(): bool
284
    {
285 3
        return $this->emailAddressVerified;
286
    }
287
288 9
    public function setEmailAddressVerified(bool $emailAddressVerified): self
289
    {
290 9
        $this->emailAddressVerified = $emailAddressVerified;
291
292 9
        return $this;
293
    }
294
295 1
    public function isPasswordRequestLimitReached($ttl): bool
296
    {
297 1
        $lastRequest = $this->getPasswordRequestedAt();
298
299 1
        return $lastRequest instanceof DateTime &&
300 1
            $lastRequest->getTimestamp() + $ttl > time();
301
    }
302
303
    /** @see \Serializable::serialize() */
304 1
    public function serialize(): string
305
    {
306 1
        return serialize([
307 1
            $this->id,
308 1
            $this->username,
309 1
            $this->emailAddress,
310 1
            $this->password,
311 1
            $this->enabled,
312 1
            $this->roles,
313
        ]);
314
    }
315
316
    /**
317
     * @see \Serializable::unserialize()
318
     */
319 2
    public function unserialize(string $serialized): self
320
    {
321
        [
322 2
            $this->id,
323 2
            $this->username,
324 2
            $this->emailAddress,
325 2
            $this->password,
326 2
            $this->enabled,
327 2
            $this->roles,
328 2
        ] = unserialize($serialized, ['allowed_classes' => false]);
329
330 2
        return $this;
331
    }
332
333
    /**
334
     * Not needed - we use bcrypt.
335
     *
336
     * @ApiProperty(readable=false, writable=false)
337
     */
338
    public function getSalt()
339
    {
340
    }
341
342
    /**
343
     * Remove sensitive data - e.g. plain passwords etc.
344
     */
345 1
    public function eraseCredentials(): void
346
    {
347 1
        $this->plainPassword = null;
348 1
    }
349
350 1
    public function __toString()
351
    {
352 1
        return $this->id;
353
    }
354
355
    public static function createFromPayload($username, array $payload)
356
    {
357
        return new static(
358
            $username,
359
            $payload['roles']
360
        );
361
    }
362
}
363