Passed
Push — master ( d4c8c4...390086 )
by Adrien
06:52
created

User::activate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Application\Model;
6
7
use Application\Acl\Acl;
8
use Application\Api\Exception;
9
use Application\DBAL\Types\BillingTypeType;
10
use Application\DBAL\Types\RelationshipType;
11
use Application\ORM\Query\Filter\AclFilter;
12
use Application\Traits\HasAddress;
13
use Application\Traits\HasDoorAccess;
14
use Application\Traits\HasRemarks;
15
use Application\Utility;
16
use Cake\Chronos\Chronos;
17
use Cake\Chronos\Date;
18
use Doctrine\Common\Collections\ArrayCollection;
19
use Doctrine\Common\Collections\Collection;
20
use Doctrine\ORM\Mapping as ORM;
21
use GraphQL\Doctrine\Annotation as API;
22
23
/**
24
 * User
25
 *
26
 * @ORM\Entity(repositoryClass="Application\Repository\UserRepository")
27
 * @ORM\AssociationOverrides({
28
 *     @ORM\AssociationOverride(name="owner", inversedBy="users")
29
 * })
30
 */
31
class User extends AbstractModel
32
{
33
    const ROLE_ANONYMOUS = 'anonymous';
34
    const ROLE_BOOKING_ONLY = 'booking_only';
35
    const ROLE_INDIVIDUAL = 'individual';
36
    const ROLE_MEMBER = 'member';
37
    const ROLE_RESPONSIBLE = 'responsible';
38
    const ROLE_ADMINISTRATOR = 'administrator';
39
40
    const STATUS_INACTIVE = 'inactive';
41
    const STATUS_NEW = 'new';
42
    const STATUS_ACTIVE = 'active';
43
    const STATUS_ARCHIVED = 'archived';
44
45
    use HasDoorAccess;
46
    use HasRemarks;
47
    use HasAddress;
48
49
    /**
50
     * @var User
51
     */
52
    private static $currentUser;
53
54
    /**
55
     * Set currently logged in user
56
     * WARNING: this method should only be called from \Application\Authentication\AuthenticationListener
57
     *
58
     * @param \Application\Model\User $user
59
     */
60 57
    public static function setCurrent(?self $user): void
61
    {
62 57
        self::$currentUser = $user;
63
64
        // Initalize ACL filter with current user if a logged in one exists
65 57
        _em()->getFilters()->getFilter(AclFilter::class)->setUser($user);
66 57
    }
67
68
    /**
69
     * Returns currently logged user or null
70
     *
71
     * @return null|self
72
     */
73 45
    public static function getCurrent(): ?self
74
    {
75 45
        return self::$currentUser;
76
    }
77
78
    /**
79
     * @var null|string
80
     *
81
     * @ORM\Column(type="string", length=50, nullable=true, unique=true)
82
     */
83
    private $login;
84
85
    /**
86
     * @var string
87
     * @ORM\Column(type="string", length=191)
88
     */
89
    private $firstName = '';
90
91
    /**
92
     * @var string
93
     * @ORM\Column(type="string", length=191)
94
     */
95
    private $lastName = '';
96
97
    /**
98
     * @var string
99
     *
100
     * @ORM\Column(type="string", length=255)
101
     */
102
    private $password = '';
103
104
    /**
105
     * @var null|string
106
     * @ORM\Column(type="string", length=191, nullable=true, unique=true)
107
     */
108
    private $email;
109
110
    /**
111
     * @var string
112
     * @ORM\Column(type="UserRole", options={"default" = User::ROLE_INDIVIDUAL})
113
     */
114
    private $role = self::ROLE_INDIVIDUAL;
115
116
    /**
117
     * @var string
118
     * @ORM\Column(type="UserStatus", options={"default" = User::STATUS_NEW})
119
     */
120
    private $status = self::STATUS_NEW;
121
122
    /**
123
     * @var null|Chronos
124
     * @ORM\Column(type="datetime", nullable=true)
125
     */
126
    private $lastLogin;
127
128
    /**
129
     * @var null|Chronos
130
     * @ORM\Column(type="datetime", nullable=true)
131
     */
132
    private $welcomeSessionDate;
133
134
    /**
135
     * @var int sex according to ISO/IEC 5218
136
     * @ORM\Column(type="smallint", options={"default" = 0}))
137
     */
138
    private $sex = 0;
139
140
    /**
141
     * @var string
142
     * @ORM\Column(type="string", length=25, options={"default" = ""})
143
     */
144
    private $phone = '';
145
146
    /**
147
     * @var string
148
     * @ORM\Column(type="string", length=25, options={"default" = ""})
149
     */
150
    private $mobilePhone = '';
151
152
    /**
153
     * @var string
154
     * @ORM\Column(type="string", length=25, options={"default" = ""})
155
     */
156
    private $ichtusSwissSailing = '';
157
158
    /**
159
     * @var null|Date
160
     * @ORM\Column(type="date", nullable=true)
161
     */
162
    private $birthday;
163
164
    /**
165
     * @var bool
166
     * @ORM\Column(type="boolean", options={"default" = 0})
167
     */
168
    private $termsAgreement = false;
169
170
    /**
171
     * @var bool
172
     * @ORM\Column(type="boolean", options={"default" = 0})
173
     */
174
    private $hasInsurance = false;
175
176
    /**
177
     * @var bool
178
     * @ORM\Column(type="boolean", options={"default" = 0})
179
     */
180
    private $receivesNewsletter = false;
181
182
    /**
183
     * @var string
184
     * @ORM\Column(type="Relationship", options={"default" = RelationshipType::HOUSEHOLDER})
185
     */
186
    private $familyRelationship = RelationshipType::HOUSEHOLDER;
187
188
    /**
189
     * @var string
190
     * @ORM\Column(type="BillingType", options={"default" = BillingTypeType::ALL_ELECTRONIC})
191
     */
192
    private $billingType = BillingTypeType::ALL_ELECTRONIC;
193
194
    /**
195
     * @var null|string
196
     * @ORM\Column(type="string", length=32, nullable=true, unique=true)
197
     */
198
    private $token;
199
200
    /**
201
     * @var null|Chronos
202
     *
203
     * @ORM\Column(type="datetime", nullable=true)
204
     */
205
    private $tokenCreationDate;
206
207
    /**
208
     * @var Collection
209
     * @ORM\OneToMany(targetEntity="Booking", mappedBy="owner")
210
     */
211
    private $bookings;
212
213
    /**
214
     * @var Collection
215
     * @ORM\ManyToMany(targetEntity="License", mappedBy="users")
216
     */
217
    private $licenses;
218
219
    /**
220
     * @var Collection
221
     * @ORM\ManyToMany(targetEntity="UserTag", mappedBy="users")
222
     */
223
    private $userTags;
224
225
    /**
226
     * @var Collection
227
     * @ORM\OneToMany(targetEntity="Message", mappedBy="recipient")
228
     */
229
    private $messages;
230
231
    /**
232
     * There is actually 0 to 1 account, never more. And this is
233
     * enforced by DB unique constraints
234
     *
235
     * @var Collection
236
     * @ORM\OneToMany(targetEntity="Account", mappedBy="owner")
237
     */
238
    private $accounts;
239
240
    /**
241
     * @var Collection
242
     * @ORM\OneToMany(targetEntity="User", mappedBy="owner")
243
     */
244
    private $users;
245
246
    /**
247
     * Constructor
248
     *
249
     * @param string $role role for new user
250
     */
251 28
    public function __construct(string $role = self::ROLE_INDIVIDUAL)
252
    {
253 28
        $this->role = $role;
254 28
        $this->bookings = new ArrayCollection();
255 28
        $this->accounts = new ArrayCollection();
256 28
        $this->licenses = new ArrayCollection();
257 28
        $this->userTags = new ArrayCollection();
258 28
        $this->messages = new ArrayCollection();
259 28
        $this->users = new ArrayCollection();
260 28
    }
261
262
    /**
263
     * Set login (eg: johndoe)
264
     *
265
     * @API\Input(type="Login")
266
     *
267
     * @param string $login
268
     */
269 2
    public function setLogin(string $login): void
270
    {
271 2
        $this->login = $login;
272 2
    }
273
274
    /**
275
     * Get login (eg: johndoe)
276
     *
277
     * @API\Field(type="?Login")
278
     *
279
     * @return null|string
280
     */
281 12
    public function getLogin(): ?string
282
    {
283 12
        return $this->login;
284
    }
285
286
    /**
287
     * Hash and change the user password
288
     *
289
     * @param string $password
290
     */
291 6
    public function setPassword(string $password): void
292
    {
293
        // Ignore empty password that could be sent "by mistake" by the client
294
        // when agreeing to terms
295 6
        if ($password === '') {
296 1
            return;
297
        }
298
299 6
        $this->revokeToken();
300
301 6
        $this->password = password_hash($password, PASSWORD_DEFAULT);
302 6
    }
303
304
    /**
305
     * Returns the hashed password
306
     *
307
     * @API\Exclude
308
     *
309
     * @return string
310
     */
311 3
    public function getPassword(): string
312
    {
313 3
        return $this->password;
314
    }
315
316
    /**
317
     * Set first name
318
     *
319
     * @param string $firstName
320
     */
321 2
    public function setFirstName($firstName): void
322
    {
323 2
        $this->firstName = $firstName;
324 2
    }
325
326
    /**
327
     * Get first name
328
     *
329
     * @return string
330
     */
331 4
    public function getFirstName(): string
332
    {
333 4
        return (string) $this->firstName;
334
    }
335
336
    /**
337
     * Set last name
338
     *
339
     * @param string $lastName
340
     */
341 2
    public function setLastName($lastName): void
342
    {
343 2
        $this->lastName = $lastName;
344 2
    }
345
346
    /**
347
     * Get last name
348
     *
349
     * @return string
350
     */
351 1
    public function getLastName(): string
352
    {
353 1
        return (string) $this->lastName;
354
    }
355
356
    /**
357
     * Get full name
358
     *
359
     * @return string
360
     */
361 1
    public function getName(): string
362
    {
363 1
        return implode(' ', [$this->getFirstName(), $this->getLastName()]);
364
    }
365
366
    /**
367
     * Set email
368
     *
369
     * @API\Input(type="?Email")
370
     *
371
     * @param string $email
372
     */
373 3
    public function setEmail(string $email): void
374
    {
375 3
        $this->email = $email;
376 3
    }
377
378
    /**
379
     * Get email
380
     *
381
     * @API\Field(type="?Email")
382
     *
383
     * @return null|string
384
     */
385 5
    public function getEmail(): ?string
386
    {
387 5
        return $this->email;
388
    }
389
390
    /**
391
     * Returns whether the user is administrator and thus have can do anything.
392
     *
393
     * @API\Field(type="Application\Api\Enum\UserRoleType")
394
     */
395 31
    public function getRole(): string
396
    {
397 31
        return $this->role;
398
    }
399
400
    /**
401
     * Sets the user role
402
     *
403
     * The current user is allowed to promote another user up to the same role as himself. So
404
     * a Responsible can promote a Member to Responsible. Or an Admin can promote a Individual to Admin.
405
     *
406
     * But the current user is **not** allowed to demote a user who has a higher role than himself.
407
     * That means that a Responsible cannot demote an Admin to Individual.
408
     *
409
     * @param string $role
410
     */
411 7
    public function setRole(string $role): void
412
    {
413 7
        if ($role === $this->role) {
414 2
            return;
415
        }
416
417 5
        $currentRole = self::getCurrent() ? self::getCurrent()->getRole() : self::ROLE_ANONYMOUS;
418
        $orderedRoles = [
419 5
            self::ROLE_ANONYMOUS,
420 5
            self::ROLE_INDIVIDUAL,
421 5
            self::ROLE_MEMBER,
422 5
            self::ROLE_RESPONSIBLE,
423 5
            self::ROLE_ADMINISTRATOR,
424
        ];
425
426 5
        $newFound = false;
427 5
        $oldFound = false;
428 5
        foreach ($orderedRoles as $r) {
429 5
            if ($r === $this->role) {
430 3
                $oldFound = true;
431
            }
432 5
            if ($r === $role) {
433 2
                $newFound = true;
434
            }
435
436 5
            if ($r === $currentRole) {
437 5
                break;
438
            }
439
        }
440
441 5
        if (!$newFound || !$oldFound) {
442 3
            throw new Exception($currentRole . ' is not allowed to change role from ' . $this->role . ' to ' . $role);
443
        }
444
445 2
        $this->role = $role;
446 2
    }
447
448 5
    public function setOwner(self $owner = null): void
449
    {
450 5
        if ($owner && $owner !== $this) {
451 4
            if ($owner->getOwner() && $owner !== $owner->getOwner()) {
452 1
                throw new Exception('This user cannot be owned by a user who is himself owned by somebody else');
453
            }
454
455 4
            if ($this->users->count()) {
456 1
                throw new Exception('This user owns other users, so he cannot himself be owned by somebody else');
457
            }
458
        }
459
460 5
        if ($this->getOwner()) {
461
            $this->getOwner()->users->removeElement($this);
462
        }
463
464 5
        parent::setOwner($owner);
465
466 5
        if ($this->getOwner()) {
467 4
            $this->getOwner()->users->add($this);
468 4
            $this->setStatus($this->getOwner()->getStatus());
469
        }
470 5
    }
471
472
    /**
473
     * @API\Field(type="Application\Api\Enum\UserStatusType")
474
     *
475
     * @return string
476
     */
477 4
    public function getStatus(): string
478
    {
479 4
        return $this->status;
480
    }
481
482
    /**
483
     * @API\Input(type="Application\Api\Enum\UserStatusType")
484
     *
485
     * @param string $status
486
     */
487 6
    public function setStatus(string $status): void
488
    {
489 6
        $this->status = $status;
490 6
        $this->revokeToken();
491
492 6
        foreach ($this->users as $user) {
493 3
            if ($user !== $this) {
494 1
                $user->setStatus($status);
495
            }
496
        }
497 6
    }
498
499 1
    public function activate(): void
500
    {
501 1
        $this->role = self::ROLE_MEMBER; // Bypass security
502 1
        $this->setStatus(self::STATUS_ACTIVE);
503 1
    }
504
505
    /**
506
     * Get a list of global permissions for this user
507
     *
508
     * @API\Field(type="GlobalPermissionsList")
509
     *
510
     * @return array
511
     */
512 3
    public function getGlobalPermissions(): array
513
    {
514 3
        $acl = new Acl();
515
        $types = [
516 3
            Account::class,
517
            AccountingDocument::class,
518
            Bookable::class,
519
            BookableMetadata::class,
520
            BookableTag::class,
521
            Booking::class,
522
            Category::class,
523
            Country::class,
524
            ExpenseClaim::class,
525
            Image::class,
526
            License::class,
527
            Message::class,
528
            self::class,
529
            UserTag::class,
530
        ];
531
532 3
        $permissions = ['create'];
533 3
        $result = [];
534
535 3
        $previousUser = self::getCurrent();
536 3
        self::setCurrent($this);
537 3
        foreach ($types as $type) {
538 3
            $instance = new $type();
539
540 3
            if ($instance instanceof AccountingDocument) {
541 3
                $instance->setExpenseClaim(new ExpenseClaim());
542
            }
543
544 3
            $sh = lcfirst(Utility::getShortClassName($instance));
545 3
            $result[$sh] = [];
546
547 3
            foreach ($permissions as $p) {
548 3
                $result[$sh][$p] = $acl->isCurrentUserAllowed($instance, $p);
549
            }
550
        }
551
552 3
        self::setCurrent($previousUser);
553
554 3
        return $result;
555
    }
556
557
    /**
558
     * @return string
559
     */
560
    public function getPhone(): string
561
    {
562
        return $this->phone;
563
    }
564
565
    /**
566
     * @param string $phone
567
     */
568
    public function setPhone(string $phone): void
569
    {
570
        $this->phone = $phone;
571
    }
572
573
    /**
574
     * @return string
575
     */
576
    public function getMobilePhone(): string
577
    {
578
        return $this->mobilePhone;
579
    }
580
581
    /**
582
     * @param string $mobilePhone
583
     */
584
    public function setMobilePhone(string $mobilePhone): void
585
    {
586
        $this->mobilePhone = $mobilePhone;
587
    }
588
589
    /**
590
     * @return null|Date
591
     */
592
    public function getBirthday(): ?Date
593
    {
594
        return $this->birthday;
595
    }
596
597
    /**
598
     * @param null|Date $birthday
599
     */
600
    public function setBirthday(?Date $birthday): void
601
    {
602
        $this->birthday = $birthday;
603
    }
604
605
    /**
606
     * Get bookings
607
     *
608
     * @return Collection
609
     */
610 1
    public function getBookings(): Collection
611
    {
612 1
        return $this->bookings;
613
    }
614
615
    /**
616
     * Notify the user that it has a new booking.
617
     * This should only be called by Booking::setResponsible()
618
     *
619
     * @param Booking $booking
620
     */
621 8
    public function bookingAdded(Booking $booking): void
622
    {
623 8
        $this->bookings->add($booking);
624 8
    }
625
626
    /**
627
     * Notify the user that it has a booking was removed.
628
     * This should only be called by Booking::setResponsible()
629
     *
630
     * @param Booking $booking
631
     */
632 4
    public function bookingRemoved(Booking $booking): void
633
    {
634 4
        $this->bookings->removeElement($booking);
635 4
    }
636
637
    /**
638
     * @return Collection
639
     */
640 1
    public function getLicenses(): Collection
641
    {
642 1
        return $this->licenses;
643
    }
644
645
    /**
646
     * @return Collection
647
     */
648 1
    public function getUserTags(): Collection
649
    {
650 1
        return $this->userTags;
651
    }
652
653
    /**
654
     * Notify the user that it has a new license.
655
     * This should only be called by License::addUser()
656
     *
657
     * @param License $license
658
     */
659 1
    public function licenseAdded(License $license): void
660
    {
661 1
        $this->licenses->add($license);
662 1
    }
663
664
    /**
665
     * Notify the user that it a license was removed.
666
     * This should only be called by License::removeUser()
667
     *
668
     * @param License $license
669
     */
670 1
    public function licenseRemoved(License $license): void
671
    {
672 1
        $this->licenses->removeElement($license);
673 1
    }
674
675
    /**
676
     * Notify the user that it has a new userTag.
677
     * This should only be called by UserTag::addUser()
678
     *
679
     * @param UserTag $userTag
680
     */
681 1
    public function userTagAdded(UserTag $userTag): void
682
    {
683 1
        $this->userTags->add($userTag);
684 1
    }
685
686
    /**
687
     * Notify the user that a userTag was removed.
688
     * This should only be called by UserTag::removeUser()
689
     *
690
     * @param UserTag $userTag
691
     */
692 1
    public function userTagRemoved(UserTag $userTag): void
693
    {
694 1
        $this->userTags->removeElement($userTag);
695 1
    }
696
697
    /**
698
     * @return bool
699
     */
700
    public function isTermsAgreement(): bool
701
    {
702
        return $this->termsAgreement;
703
    }
704
705
    /**
706
     * @param bool $termsAgreement
707
     */
708 1
    public function setTermsAgreement(bool $termsAgreement): void
709
    {
710 1
        $this->termsAgreement = $termsAgreement;
711 1
    }
712
713
    /**
714
     * @return bool
715
     */
716
    public function getHasInsurance(): bool
717
    {
718
        return $this->hasInsurance;
719
    }
720
721
    /**
722
     * @param bool $hasInsurance
723
     */
724 1
    public function setHasInsurance(bool $hasInsurance): void
725
    {
726 1
        $this->hasInsurance = $hasInsurance;
727 1
    }
728
729
    /**
730
     * @return null|Chronos
731
     */
732
    public function getWelcomeSessionDate(): ?Chronos
733
    {
734
        return $this->welcomeSessionDate;
735
    }
736
737
    /**
738
     * @param null|Chronos $welcomeSessionDate
739
     */
740
    public function setWelcomeSessionDate(?Chronos $welcomeSessionDate): void
741
    {
742
        $this->welcomeSessionDate = $welcomeSessionDate;
743
    }
744
745
    /**
746
     * @return bool
747
     */
748
    public function isReceivesNewsletter(): bool
749
    {
750
        return $this->receivesNewsletter;
751
    }
752
753
    /**
754
     * @param bool $receivesNewsletter
755
     */
756
    public function setReceivesNewsletter(bool $receivesNewsletter): void
757
    {
758
        $this->receivesNewsletter = $receivesNewsletter;
759
    }
760
761
    /**
762
     * Get the ISO/IEC 5218 sex
763
     *
764
     * @API\Field(type="Sex")
765
     *
766
     * @return int
767
     */
768
    public function getSex(): int
769
    {
770
        return $this->sex;
771
    }
772
773
    /**
774
     * Set the ISO/IEC 5218 sex
775
     *
776
     * @API\Input(type="Sex")
777
     *
778
     * @param int $sex
779
     */
780
    public function setSex(int $sex): void
781
    {
782
        $this->sex = $sex;
783
    }
784
785
    /**
786
     * @return string
787
     */
788
    public function getIchtusSwissSailing(): string
789
    {
790
        return $this->ichtusSwissSailing;
791
    }
792
793
    /**
794
     * @param string $ichtusSwissSailing
795
     */
796
    public function setIchtusSwissSailing(string $ichtusSwissSailing): void
797
    {
798
        $this->ichtusSwissSailing = $ichtusSwissSailing;
799
    }
800
801
    /**
802
     * Get the last login
803
     *
804
     * @return null|Chronos
805
     */
806
    public function getLastLogin(): ?Chronos
807
    {
808
        return $this->lastLogin;
809
    }
810
811
    /**
812
     * @param null|Chronos $lastLogin
813
     */
814 3
    public function setLastLogin(?Chronos $lastLogin): void
815
    {
816 3
        $this->lastLogin = $lastLogin;
817 3
        $this->revokeToken();
818 3
    }
819
820
    /**
821
     * @API\Field(type="Relationship")
822
     *
823
     * @return string
824
     */
825 1
    public function getFamilyRelationship(): string
826
    {
827 1
        return $this->familyRelationship;
828
    }
829
830
    /**
831
     * @API\Input(type="Relationship")
832
     *
833
     * @param string $familyRelationship
834
     */
835
    public function setFamilyRelationship(string $familyRelationship): void
836
    {
837
        $this->familyRelationship = $familyRelationship;
838
    }
839
840
    /**
841
     * @return string
842
     */
843
    public function getBillingType(): string
844
    {
845
        return $this->billingType;
846
    }
847
848
    /**
849
     * @param string $billingType
850
     */
851
    public function setBillingType(string $billingType): void
852
    {
853
        $this->billingType = $billingType;
854
    }
855
856
    /**
857
     * Get the user transaction account
858
     *
859
     * @return null|Account
860
     */
861 1
    public function getAccount(): ?Account
862
    {
863 1
        return $this->accounts->count() ? $this->accounts->first() : null;
864
    }
865
866
    /**
867
     * Notify the user that it has a new account
868
     * This should only be called by Account::setOwner()
869
     *
870
     * @param Account $account
871
     */
872 1
    public function accountAdded(Account $account): void
873
    {
874 1
        $this->accounts->clear();
875 1
        $this->accounts->add($account);
876 1
    }
877
878
    /**
879
     * Notify the user that a account was removed
880
     * This should only be called by Account::setOwner()
881
     */
882 1
    public function accountRemoved(): void
883
    {
884 1
        $this->accounts->clear();
885 1
    }
886
887
    /**
888
     * Get messages sent to the user
889
     *
890
     * @return Collection
891
     */
892 1
    public function getMessages(): Collection
893
    {
894 1
        return $this->messages;
895
    }
896
897
    /**
898
     * Notify the user that it has a new message
899
     * This should only be called by Message::setRecipient()
900
     *
901
     * @param Message $message
902
     */
903 4
    public function messageAdded(Message $message): void
904
    {
905 4
        $this->messages->add($message);
906 4
    }
907
908
    /**
909
     * Notify the user that a message was removed
910
     * This should only be called by Message::setRecipient()
911
     *
912
     * @param Message $message
913
     */
914 1
    public function messageRemoved(Message $message): void
915
    {
916 1
        $this->messages->removeElement($message);
917 1
    }
918
919
    /**
920
     * Generate a new random token to reset password
921
     */
922 4
    public function createToken(): string
923
    {
924 4
        $this->token = bin2hex(random_bytes(16));
925 4
        $this->tokenCreationDate = new Chronos();
926
927 4
        return $this->token;
928
    }
929
930
    /**
931
     * Destroy existing token
932
     */
933 10
    private function revokeToken(): void
934
    {
935 10
        $this->token = null;
936 10
        $this->tokenCreationDate = null;
937 10
    }
938
939
    /**
940
     * Check if token is valid.
941
     *
942
     * @API\Exclude
943
     *
944
     * @return bool
945
     */
946 3
    public function isTokenValid(): bool
947
    {
948 3
        if (!$this->tokenCreationDate) {
949 1
            return false;
950
        }
951
952 3
        $timeLimit = $this->tokenCreationDate->addMinutes(30);
953
954 3
        return $timeLimit->isFuture();
955
    }
956
957
    /**
958
     * Check if the user can *really* open a door
959
     * This also takes into account the user status, role and IP address
960
     *
961
     * @API\Field(args={@API\Argument(name="door", type="?Application\Api\Enum\DoorType")})
962
     *
963
     * @param null|string $door a particular door, or null for any
964
     *
965
     * @return bool
966
     */
967
    public function getCanOpenDoor(?string $door = null): bool
968
    {
969
        global $container;
970
971
        $allowedStatus = [self::STATUS_ACTIVE];
972
        $allowedRoles = [self::ROLE_MEMBER, self::ROLE_RESPONSIBLE, self::ROLE_ADMINISTRATOR];
973
        if ($door && !$this->$door) {
974
            return false;
975
        }
976
        if (!in_array($this->status, $allowedStatus, true) || !in_array($this->role, $allowedRoles, true)) {
977
            return false;
978
        }
979
        $apiConfig = $container->get('config')['doorsApi'];
980
        foreach ($apiConfig['authorizedIps'] as $host) {
981
            if (filter_var($host, FILTER_VALIDATE_DOMAIN) && in_array($_SERVER['REMOTE_ADDR'], gethostbynamel($host), true)) {
982
                return true;
983
            }
984
            if (filter_var($host, FILTER_VALIDATE_IP) && $_SERVER['REMOTE_ADDR'] === $host) {
985
                return true;
986
            }
987
        }
988
989
        return false;
990
    }
991
}
992