Completed
Push — master ( a3cce1...d6fbcc )
by Marcel
09:39
created

User   F

Complexity

Total Complexity 68

Size/Duplication

Total Lines 671
Duplicated Lines 0 %

Test Coverage

Coverage 56.79%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 125
c 4
b 0
f 0
dl 0
loc 671
ccs 96
cts 169
cp 0.5679
rs 2.96
wmc 68

64 Methods

Rating   Name   Duplication   Size   Complexity  
A isEmailConfirmationPending() 0 2 1
A getType() 0 2 1
A setBackupCodes() 0 3 1
A getPassword() 0 2 1
A getExternalId() 0 2 1
A invalidateBackupCode() 0 4 2
A isMustChangePassword() 0 2 1
A setExternalId() 0 3 1
A getFirstname() 0 2 1
A getEnabledFrom() 0 2 1
A eraseCredentials() 0 2 1
A setEnabledFrom() 0 3 1
A isBackupCode() 0 2 1
A setIsEmailConfirmationPending() 0 3 1
A canChangePassword() 0 2 1
A getPreferredTwoFactorProvider() 0 8 3
A __construct() 0 7 1
A addU2FKey() 0 2 1
A getUsername() 0 2 1
A setFirstname() 0 3 1
A getTrustedTokenVersion() 0 2 1
A removeUserRole() 0 2 1
A setType() 0 3 1
A getUserRoles() 0 2 1
A getSalt() 0 2 1
A setUsername() 0 3 1
A getCreatedAt() 0 2 1
A setPassword() 0 3 1
A getTypeString() 0 2 1
A getRoles() 0 2 1
A getData() 0 2 1
A removeEnabledService() 0 2 1
A isU2FAuthEnabled() 0 2 1
A getEmail() 0 2 1
A setData() 0 2 1
A setMustChangePassword() 0 3 1
A addUserRole() 0 2 1
A setPrivacyPolicyConfirmedAt() 0 3 1
A setIsActive() 0 3 1
A getAttributes() 0 2 1
A getBackupCodes() 0 2 1
A getEnabledServices() 0 2 1
A setGrade() 0 3 1
A setIsProvisioned() 0 3 1
A setCanChangePassword() 0 3 1
A addEnabledService() 0 2 1
A getEnabledUntil() 0 2 1
A isProvisioned() 0 2 1
A getGrade() 0 2 1
A getU2FKeys() 0 2 1
A emptyBackupCodes() 0 2 1
A removeU2FKey() 0 2 1
A setEmail() 0 3 1
A setEnabledUntil() 0 3 1
A getPrivacyPolicyConfirmedAt() 0 2 1
A getLastname() 0 2 1
A setRoles() 0 3 1
A isGoogleAuthenticatorEnabled() 0 2 1
A setGoogleAuthenticatorSecret() 0 2 1
A getGoogleAuthenticatorUsername() 0 2 1
A getUpdatedAt() 0 2 1
A getGoogleAuthenticatorSecret() 0 6 2
A isActive() 0 2 1
A setLastname() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like User often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use User, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace App\Entity;
4
5
use DateTime;
6
use Doctrine\Common\Collections\ArrayCollection;
7
use Doctrine\Common\Collections\Collection;
8
use Doctrine\ORM\Mapping as ORM;
9
use Gedmo\Mapping\Annotation as Gedmo;
10
use Gedmo\SoftDeleteable\Traits\SoftDeleteableEntity;
11
use JMS\Serializer\Annotation as Serializer;
12
use R\U2FTwoFactorBundle\Model\U2F\TwoFactorInterface as U2FTwoFactorInterface;
13
use Ramsey\Uuid\Uuid;
14
use Scheb\TwoFactorBundle\Model\BackupCodeInterface;
15
use Scheb\TwoFactorBundle\Model\Google\TwoFactorInterface as GoogleTwoFactorInterface;
16
use Scheb\TwoFactorBundle\Model\PreferredProviderInterface;
17
use Scheb\TwoFactorBundle\Model\TrustedDeviceInterface;
18
use Swagger\Annotations as SWG;
19
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
20
use Symfony\Component\Security\Core\User\UserInterface;
21
use Symfony\Component\Validator\Constraints as Assert;
22
23
/**
24
 * @ORM\Entity()
25
 * @ORM\InheritanceType("SINGLE_TABLE")
26
 * @ORM\DiscriminatorColumn(name="class", type="string")
27
 * @ORM\DiscriminatorMap({"user" = "User", "ad" = "ActiveDirectoryUser"})
28
 * @UniqueEntity(fields={"username"})
29
 * @Serializer\Discriminator(disabled=true)
30
 * @Gedmo\SoftDeleteable(fieldName="deletedAt", timeAware=false, hardDelete=true)
31
 */
32
class User implements UserInterface, GoogleTwoFactorInterface, TrustedDeviceInterface, BackupCodeInterface, U2FTwoFactorInterface, PreferredProviderInterface {
33
34
    use IdTrait;
35
    use UuidTrait;
36
    use SoftDeleteableEntity;
37
38
    /**
39
     * @ORM\Column(type="string", unique=true)
40
     * @Assert\NotBlank()
41
     * @Assert\Email(mode="html5")
42
     * @ORM\OrderBy()
43
     * @Assert\Length(max="128", min="4")
44
     */
45
    private $username;
46
47
    /**
48
     * @ORM\Column(type="string", nullable=true)
49
     * @Assert\NotBlank(allowNull=true)
50
     * @var string|null
51
     */
52
    private $firstname;
53
54
    /**
55
     * @ORM\Column(type="string", nullable=true)
56
     * @Assert\NotBlank(allowNull=true)
57
     * @var string|null
58
     */
59
    private $lastname;
60
61
    /**
62
     * @ORM\Column(type="string", length=62, nullable=true)
63
     * @Serializer\Exclude()
64
     */
65
    private $password;
66
67
    /**
68
     * @ORM\Column(type="string", nullable=true)
69
     * @Assert\NotBlank(allowNull=true)
70
     * @Assert\Length(max="191")
71
     * @Assert\Email()
72
     * @var string|null
73
     */
74
    private $email;
75
76
    /**
77
     * @ORM\Column(type="string", nullable=true)
78
     * @var string|null
79
     */
80
    private $grade;
81
82
    /**
83
     * @ORM\ManyToOne(targetEntity="UserType", inversedBy="users")
84
     * @ORM\JoinColumn(onDelete="SET NULL")
85
     * @Serializer\ReadOnly()
86
     * @Serializer\Accessor(getter="getTypeString")
87
     * @Serializer\Type("string")
88
     * @SWG\Property(description="UUID of the usertype")
89
     * @Assert\NotNull()
90
     * @var UserType|null
91
     */
92
    private $type;
93
94
    /**
95
     * @ORM\Column(type="json")
96
     * @Serializer\Exclude()
97
     */
98
    private $roles = [ 'ROLE_USER' ];
99
100
    /**
101
     * @ORM\Column(type="string", nullable=true)
102
     */
103
    private $externalId;
104
105
    /**
106
     * @ORM\Column(type="boolean")
107
     */
108
    private $isActive = true;
109
110
    /**
111
     * @ORM\Column(type="boolean")
112
     * @Serializer\Exclude()
113
     * @var bool
114
     */
115
    private $isEmailConfirmationPending = false;
116
117
    /**
118
     * @ORM\ManyToMany(targetEntity="ServiceProvider")
119
     * @ORM\JoinTable(
120
     *  joinColumns={@ORM\JoinColumn(onDelete="CASCADE")},
121
     *  inverseJoinColumns={@ORM\JoinColumn(onDelete="CASCADE")}
122
     * )
123
     * @Serializer\Exclude()
124
     */
125
    private $enabledServices;
126
127
    /**
128
     * @ORM\OneToMany(targetEntity="ServiceAttributeValue", mappedBy="user")
129
     * @Serializer\Exclude()
130
     */
131
    private $attributes;
132
133
    /**
134
     * @ORM\ManyToMany(targetEntity="UserRole", inversedBy="users")
135
     * @Serializer\Exclude()
136
     */
137
    private $userRoles;
138
139
    /**
140
     * @ORM\Column(type="string", nullable=true)
141
     * @Serializer\Exclude()
142
     */
143
    private $googleAuthenticatorSecret;
144
145
    /**
146
     * @ORM\Column(type="json")
147
     * @Serializer\Exclude()
148
     */
149
    private $backupCodes = [ ];
150
151
    /**
152
     * @ORM\Column(type="integer", name="trusted_version")
153
     * @Serializer\Exclude()
154
     */
155
    private $trustedVersion = 0;
156
157
    /**
158
     * @ORM\Column(type="datetime")
159
     * @Gedmo\Timestampable(on="create")
160
     * @Serializer\Exclude()
161
     */
162
    private $createdAt;
163
164
    /**
165
     * @ORM\Column(type="datetime", nullable=true)
166
     * @Gedmo\Timestampable(on="update", field={"firstname", "lastname", "email", "type", "userRoles"})
167
     * @Serializer\Exclude()
168
     */
169
    private $updatedAt;
170
171
    /**
172
     * @ORM\OneToMany(targetEntity="U2fKey", mappedBy="user")
173
     * @Serializer\Exclude()
174
     */
175
    private $u2fKeys;
176
177
    /**
178
     * @ORM\Column(type="datetime", nullable=true)
179
     */
180
    private $enabledFrom;
181
182
    /**
183
     * @ORM\Column(type="datetime", nullable=true)
184
     */
185
    private $enabledUntil;
186
187
    /**
188
     * @ORM\Column(type="json")
189
     * @Serializer\Exclude()
190
     * @var array
191
     */
192
    private $data = [ ];
193
194
    /**
195
     * @ORM\Column(type="datetime", nullable=true)
196
     * @var DateTime|null
197
     */
198
    private $privacyPolicyConfirmedAt = null;
199
200
    /**
201
     * @ORM\Column(type="boolean")
202
     * @var bool
203
     */
204
    private $isProvisioned = true;
205
206
    /**
207
     * @ORM\Column(type="boolean")
208
     * @var bool
209
     */
210
    private $mustChangePassword = false;
211
212
    /**
213
     * @ORM\Column(type="boolean", options={"default": 1 })
214
     * @var bool
215
     */
216
    private $canChangePassword = true;
217
218 21
    public function __construct() {
219 21
        $this->uuid = Uuid::uuid4();
220
221 21
        $this->enabledServices = new ArrayCollection();
222 21
        $this->attributes = new ArrayCollection();
223 21
        $this->userRoles = new ArrayCollection();
224 21
        $this->u2fKeys = new ArrayCollection();
225 21
    }
226
227
    /**
228
     * @return string
229
     */
230 8
    public function getUsername() {
231 8
        return $this->username;
232
    }
233
234
    /**
235
     * @param string $username
236
     * @return User
237
     */
238 12
    public function setUsername($username) {
239 12
        $this->username = mb_strtolower($username);
240 12
        return $this;
241
    }
242
243
    /**
244
     * @return string|null
245
     */
246 5
    public function getFirstname() {
247 5
        return $this->firstname;
248
    }
249
250
    /**
251
     * @param string|null $firstname
252
     * @return User
253
     */
254 7
    public function setFirstname($firstname) {
255 7
        $this->firstname = $firstname;
256 7
        return $this;
257
    }
258
259
    /**
260
     * @return string|null
261
     */
262 5
    public function getLastname() {
263 5
        return $this->lastname;
264
    }
265
266
    /**
267
     * @param string|null $lastname
268
     * @return User
269
     */
270 7
    public function setLastname($lastname) {
271 7
        $this->lastname = $lastname;
272 7
        return $this;
273
    }
274
275
    /**
276
     * @param string $password
277
     * @return User
278
     */
279 11
    public function setPassword($password) {
280 11
        $this->password = $password;
281 11
        return $this;
282
    }
283
284
    /**
285
     * @param string|null $email
286
     * @return User
287
     */
288 7
    public function setEmail($email) {
289 7
        $this->email = $email;
290 7
        return $this;
291
    }
292
293
    /**
294
     * @return string|null
295
     */
296 1
    public function getEmail() {
297 1
        return $this->email;
298
    }
299
300
    /**
301
     * @return string|null
302
     */
303
    public function getGrade() {
304
        return $this->grade;
305
    }
306
307
    /**
308
     * @param string $grade
309
     * @return User
310
     */
311
    public function setGrade($grade) {
312
        $this->grade = $grade;
313
        return $this;
314
    }
315
316
    /**
317
     * @return UserType
318
     */
319 7
    public function getType() {
320 7
        return $this->type;
321
    }
322
323
    /**
324
     * @param UserType $userType
325
     * @return User
326
     */
327 11
    public function setType(UserType $userType) {
328 11
        $this->type = $userType;
329 11
        return $this;
330
    }
331
332
    /**
333
     * @return string|int
334
     */
335 7
    public function getExternalId() {
336 7
        return $this->externalId;
337
    }
338
339
    /**
340
     * @param string|int $externalId
341
     * @return User
342
     */
343 2
    public function setExternalId($externalId) {
344 2
        $this->externalId = $externalId;
345 2
        return $this;
346
    }
347
348
    /**
349
     * @return bool
350
     */
351 12
    public function isActive() {
352 12
        return $this->isActive;
353
    }
354
355
    /**
356
     * @param bool $active
357
     * @return User
358
     */
359 12
    public function setIsActive($active) {
360 12
        $this->isActive = $active;
361 12
        return $this;
362
    }
363
364
    /**
365
     * @return bool
366
     */
367 11
    public function isEmailConfirmationPending(): bool {
368 11
        return $this->isEmailConfirmationPending;
369
    }
370
371
    /**
372
     * @param bool $isEmailConfirmationPending
373
     * @return User
374
     */
375
    public function setIsEmailConfirmationPending(bool $isEmailConfirmationPending): User {
376
        $this->isEmailConfirmationPending = $isEmailConfirmationPending;
377
        return $this;
378
    }
379
380
    /**
381
     * @param ServiceProvider $serviceProvider
382
     */
383
    public function addEnabledService(ServiceProvider $serviceProvider) {
384
        $this->enabledServices->add($serviceProvider);
385
    }
386
387
    /**
388
     * @param ServiceProvider $serviceProvider
389
     */
390
    public function removeEnabledService(ServiceProvider $serviceProvider) {
391
        $this->enabledServices->removeElement($serviceProvider);
392
    }
393
394
    /**
395
     * @return Collection
396
     */
397 5
    public function getEnabledServices(): Collection {
398 5
        return $this->enabledServices;
399
    }
400
401
    /**
402
     * @return Collection
403
     */
404
    public function getAttributes(): Collection {
405
        return $this->attributes;
406
    }
407
408
    /**
409
     * @return Collection
410
     */
411 5
    public function getUserRoles(): Collection {
412 5
        return $this->userRoles;
413
    }
414
415
    /**
416
     * @param UserRole $role
417
     */
418
    public function addUserRole(UserRole $role) {
419
        $this->userRoles->add($role);
420
    }
421
422
    /**
423
     * @param UserRole $role
424
     */
425
    public function removeUserRole(UserRole $role) {
426
        $this->userRoles->removeElement($role);
427
    }
428
429
    /**
430
     * @return string[]
431
     */
432 7
    public function getRoles() {
433 7
        return $this->roles;
434
    }
435
436
    /**
437
     * @param string[] $roles
438
     * @return User
439
     */
440
    public function setRoles(array $roles) {
441
        $this->roles = $roles;
442
        return $this;
443
    }
444
445
    /**
446
     * @return string
447
     */
448 9
    public function getPassword() {
449 9
        return $this->password;
450
    }
451
452
    /**
453
     * @return null
454
     */
455 8
    public function getSalt() {
456 8
        return null;
457
    }
458
459
    /**
460
     * @return null
461
     */
462 6
    public function eraseCredentials() {
463 6
        return null;
464
    }
465
466
    /**
467
     * @inheritDoc
468
     */
469 2
    public function getGoogleAuthenticatorSecret(): string {
470 2
        if($this->googleAuthenticatorSecret === null) {
471
            return ''; // dirty hack
472
        }
473
474 2
        return $this->googleAuthenticatorSecret;
475
    }
476
477
    /**
478
     * @inheritDoc
479
     */
480 3
    public function setGoogleAuthenticatorSecret(?string $googleAuthenticatorSecret): void {
481 3
        $this->googleAuthenticatorSecret = $googleAuthenticatorSecret;
482 3
    }
483
484
    /**
485
     * @return string[]
486
     */
487
    public function getBackupCodes() {
488
        return $this->backupCodes;
489
    }
490
491
    public function emptyBackupCodes() {
492
        $this->backupCodes = [ ];
493
    }
494
495
    /**
496
     * @param string[] $backupCodes
497
     * @return User
498
     */
499
    public function setBackupCodes(array $backupCodes) {
500
        $this->backupCodes = $backupCodes;
501
        return $this;
502
    }
503
504
    /**
505
     * @inheritDoc
506
     */
507
    public function isBackupCode(string $code): bool {
508
        return in_array($code, $this->backupCodes);
509
    }
510
511
    /**
512
     * @inheritDoc
513
     */
514
    public function invalidateBackupCode(string $code): void {
515
        $key = array_search($code, $this->backupCodes);
516
        if ($key !== false){
517
            unset($this->backupCodes[$key]);
518
        }
519
    }
520
521
    /**
522
     * @return bool
523
     */
524 7
    public function isGoogleAuthenticatorEnabled(): bool {
525 7
        return $this->googleAuthenticatorSecret !== null;
526
    }
527
528
    /**
529
     * @return string
530
     */
531
    public function getGoogleAuthenticatorUsername(): string {
532
        return $this->getUsername();
533
    }
534
535
    /**
536
     * @return int
537
     */
538 7
    public function getTrustedTokenVersion(): int {
539 7
        return $this->trustedVersion;
540
    }
541
542
    /**
543
     * @return \DateTime
544
     */
545
    public function getCreatedAt(): \DateTime {
546
        return $this->createdAt;
547
    }
548
549
    /**
550
     * @return \DateTime|null
551
     */
552
    public function getUpdatedAt(): ?\DateTime {
553
        return $this->updatedAt;
554
    }
555
556
    /**
557
     * @inheritDoc
558
     */
559 7
    public function isU2FAuthEnabled(): bool {
560 7
        return count($this->u2fKeys) > 0;
561
    }
562
563
    /**
564
     * @return Collection
565
     */
566
    public function getU2FKeys(): Collection {
567
        return $this->u2fKeys;
568
    }
569
570
    /**
571
     * @inheritDoc
572
     */
573
    public function addU2FKey($key): void {
574
        $this->u2fKeys->add($key);
575
    }
576
577
    /**
578
     * @inheritDoc
579
     */
580
    public function removeU2FKey($key): void {
581
        $this->u2fKeys->removeElement($key);
582
    }
583
584
    /**
585
     * @inheritDoc
586
     */
587 2
    public function getPreferredTwoFactorProvider(): ?string {
588 2
        if($this->isU2FAuthEnabled()) {
589
            return 'u2f_two_factor';
590 2
        } else if($this->isGoogleAuthenticatorEnabled()) {
591 2
            return 'google';
592
        }
593
594
        return null;
595
    }
596
597
    /**
598
     * @return \DateTime|null
599
     */
600 11
    public function getEnabledFrom(): ?\DateTime {
601 11
        return $this->enabledFrom;
602
    }
603
604
    /**
605
     * @param \DateTime|null $enabledFrom
606
     * @return User
607
     */
608 5
    public function setEnabledFrom(?\DateTime $enabledFrom): User {
609 5
        $this->enabledFrom = $enabledFrom;
610 5
        return $this;
611
    }
612
613
    /**
614
     * @return \DateTime|null
615
     */
616 10
    public function getEnabledUntil(): ?\DateTime {
617 10
        return $this->enabledUntil;
618
    }
619
620
    /**
621
     * @param \DateTime|null $enabledUntil
622
     * @return User
623
     */
624 5
    public function setEnabledUntil(?\DateTime$enabledUntil): User {
625 5
        $this->enabledUntil = $enabledUntil;
626 5
        return $this;
627
    }
628
629 5
    public function getData(string $key, $default = null) {
630 5
        return $this->data[$key] ?? $default;
631
    }
632
633
    public function setData(string $key, $value): void {
634
        $this->data[$key] = $value;
635
    }
636
637
    /**
638
     * @return DateTime|null
639
     */
640
    public function getPrivacyPolicyConfirmedAt(): ?DateTime {
641
        return $this->privacyPolicyConfirmedAt;
642
    }
643
644
    /**
645
     * @param DateTime|null $privacyPolicyConfirmedAt
646
     * @return User
647
     */
648
    public function setPrivacyPolicyConfirmedAt(?DateTime $privacyPolicyConfirmedAt): User {
649
        $this->privacyPolicyConfirmedAt = $privacyPolicyConfirmedAt;
650
        return $this;
651
    }
652
653
    /**
654
     * @return bool
655
     */
656 6
    public function isProvisioned(): bool {
657 6
        return $this->isProvisioned;
658
    }
659
660
    /**
661
     * @param bool $isProvisioned
662
     * @return User
663
     */
664
    public function setIsProvisioned(bool $isProvisioned): User {
665
        $this->isProvisioned = $isProvisioned;
666
        return $this;
667
    }
668
669
    /**
670
     * @return bool
671
     */
672 7
    public function isMustChangePassword(): bool {
673 7
        return $this->mustChangePassword;
674
    }
675
676
    /**
677
     * @param bool $mustChangePassword
678
     * @return User
679
     */
680 2
    public function setMustChangePassword(bool $mustChangePassword): User {
681 2
        $this->mustChangePassword = $mustChangePassword;
682 2
        return $this;
683
    }
684
685
    /**
686
     * @return bool
687
     */
688 5
    public function canChangePassword(): bool {
689 5
        return $this->canChangePassword;
690
    }
691
692
    /**
693
     * @param bool $canChangePassword
694
     * @return User
695
     */
696
    public function setCanChangePassword(bool $canChangePassword): User {
697
        $this->canChangePassword = $canChangePassword;
698
        return $this;
699
    }
700
701
    public function getTypeString(): string {
702
        return (string)$this->getType()->getUuid();
703
    }
704
}