Failed Conditions
Push — master ( f78e48...913fd9 )
by Adrien
15:58
created

HasPassword   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 96
Duplicated Lines 0 %

Test Coverage

Coverage 95.45%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 21
c 2
b 0
f 0
dl 0
loc 96
ccs 21
cts 22
cp 0.9545
rs 10
wmc 8

5 Methods

Rating   Name   Duplication   Size   Complexity  
A createToken() 0 6 1
A isTokenValid() 0 9 2
A revokeToken() 0 4 1
A setPassword() 0 16 3
A getPassword() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Ecodev\Felix\Model\Traits;
6
7
use Cake\Chronos\Chronos;
8
use Doctrine\ORM\Mapping as ORM;
9
use Exception;
10
use GraphQL\Doctrine\Annotation as API;
11
12
/**
13
 * Trait for a user with a password and password reset capabilities.
14
 */
15
trait HasPassword
16
{
17
    /**
18
     * @var string
19
     *
20
     * @API\Exclude
21
     *
22
     * @ORM\Column(type="string", length=255)
23
     */
24
    private $password = '';
25
26
    /**
27
     * @var null|string
28
     *
29
     * @API\Exclude
30
     *
31
     * @ORM\Column(type="string", length=32, nullable=true, unique=true)
32
     */
33
    private $token;
34
35
    /**
36
     * The time when user asked to reset password.
37
     *
38
     * @var null|Chronos
39
     *
40
     * @API\Exclude
41
     *
42
     * @ORM\Column(type="datetime", nullable=true)
43
     */
44
    private $tokenCreationDate;
45
46
    /**
47
     * Hash and change the user password.
48
     */
49 2
    public function setPassword(string $password): void
50
    {
51
        // Ignore empty password that could be sent "by mistake" by the client
52
        // when agreeing to terms
53 2
        if ($password === '') {
54 1
            return;
55
        }
56
57 2
        $this->revokeToken();
58
59 2
        $password = password_hash($password, PASSWORD_DEFAULT);
60 2
        if (!is_string($password)) {
61
            throw new Exception('Could not hash password');
62
        }
63
64 2
        $this->password = $password;
65
    }
66
67
    /**
68
     * Returns the hashed password.
69
     *
70
     * @API\Exclude
71
     */
72 1
    public function getPassword(): string
73
    {
74 1
        return $this->password;
75
    }
76
77
    /**
78
     * Generate a new random token to reset password.
79
     */
80 1
    public function createToken(): string
81
    {
82 1
        $this->token = bin2hex(random_bytes(16));
83 1
        $this->tokenCreationDate = new Chronos();
84
85 1
        return $this->token;
86
    }
87
88
    /**
89
     * Destroy existing token.
90
     */
91 2
    public function revokeToken(): void
92
    {
93 2
        $this->token = null;
94 2
        $this->tokenCreationDate = null;
95
    }
96
97
    /**
98
     * Check if token is valid.
99
     *
100
     * @API\Exclude
101
     */
102 1
    public function isTokenValid(): bool
103
    {
104 1
        if (!$this->tokenCreationDate) {
105 1
            return false;
106
        }
107
108 1
        $timeLimit = $this->tokenCreationDate->addMinutes(30);
109
110 1
        return $timeLimit->isFuture();
111
    }
112
}
113