Completed
Push — master ( 4b5cac...cb75bf )
by Charles
03:12
created

ResetPassword::rules()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 13
rs 9.4285
cc 1
eloc 9
nc 1
nop 0
1
<?php
2
3
namespace yrc\api\forms;
4
5
use Base32\Base32;
6
use Yii;
7
8
abstract class ResetPassword extends \yii\base\model
9
{
10
    const SCENARIO_INIT = 'init';
11
    const SCENARIO_RESET = 'reset';
12
13
    const EXPIRY_TIME = '+4 hours';
14
15
    /**
16
     * The email
17
     * @var string $email
18
     */
19
    public $email;
20
21
    /**
22
     * The reset token
23
     * @var string $reset_token
24
     */
25
    public $reset_token;
26
27
    /**
28
     * The new password
29
     * @var string $password
30
     */
31
    public $password;
32
33
    /**
34
     * The new password (again)
35
     * @var string $password_verify
36
     */
37
    public $password_verify;
38
39
    /**
40
     * The user associated to the email
41
     * @var User $user
42
     */
43
    private $user = null;
44
45
    /**
46
     * Validation scenarios
47
     * @return array
48
     */
49
    public function scenarios()
50
    {
51
        return [
52
            self::SCENARIO_INIT => ['email'],
53
            self::SCENARIO_RESET => ['reset_token'],
54
        ];
55
    }
56
57
    /**
58
     * Validation rules
59
     * @return array
60
     */
61
    public function rules()
62
    {
63
        return [
64
            [['email'], 'required', 'on' => self::SCENARIO_INIT],
65
            [['email'], 'email', 'on' =>  self::SCENARIO_INIT],
66
            [['email'], 'validateUser', 'on' =>  self::SCENARIO_INIT],
67
68
            [['reset_token'], 'required', 'on' => self::SCENARIO_RESET],
69
            [['reset_token'], 'validateResetToken', 'on' => self::SCENARIO_RESET],
70
            [['password', 'password_verify'], 'string', 'min' => 8, 'on' => self::SCENARIO_RESET],
71
            [['password_verify'], 'compare', 'compareAttribute' => 'password', 'on' => self::SCENARIO_RESET]
72
        ];
73
    }
74
75
    /**
76
     * Validates the users email
77
     * @inheritdoc
78
     */
79
    public function validateUser($attributes, $params)
0 ignored issues
show
Unused Code introduced by
The parameter $attributes is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $params is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
80
    {
81
        if (!$this->hasErrors()) {
82
            $this->user = Yii::$app->yrc->userClass::findOne(['email' => $this->email]);
83
84
            if ($this->user === null) {
85
                $this->addError('email', 'The provided email address is not valid');
86
            }
87
        }
88
    }
89
90
    /**
91
     * Reset token validator
92
     * @inheritdoc
93
     */
94
    public function validateResetToken($attributes, $params)
0 ignored issues
show
Unused Code introduced by
The parameter $attributes is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $params is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
95
    {
96
        if (!$this->hasErrors()) {
97
            $tokenInfo = Yii::$app->cache->get(
98
                hash('sha256', $this->reset_token . '_reset_token')
99
            );
100
            
101
            if ($tokenInfo === null) {
102
                $this->addError('reset_token', 'The password reset token provided is not valid.');
103
            }
104
105
            $this->user = Yii::$app->yrc->userClass::find()->where(['id' => $tokenInfo['id']])->one();
106
107
            if ($this->user === null) {
108
                $this->addError('reset_token', 'The password reset token provided is not valid.');
109
            }
110
        }
111
    }
112
113
    /**
114
     * Sets the user object
115
     * @param User $user
116
     */
117
    public function setUser($user)
118
    {
119
        $this->user = $user;
120
        $this->email = $user->email;
121
    }
122
123
    /**
124
     * Changes the password for the user
125
     * @return boolean
126
     */
127
    public function reset()
128
    {
129
        if ($this->validate()) {
130
            if ($this->getScenario() === self::SCENARIO_INIT) {
131
                // Create an reset token for the user, and store it in the cache
132
                $token = Base32::encode(\random_bytes(64));
133
                
134
                Yii::$app->cache->set(hash('sha256', $token . '_reset_token'), [
135
                    'id' => $this->user->id
136
                ], strtotime(self::EXPIRY_TIME));
137
138
                return Yii::$app->yrc->userClass::sendPasswordResetEmail($this->user->email, $token);
139
            } elseif ($this->getScenario() === self::SCENARIO_RESET) {
140
                $this->user->password = $this->password;
141
142
                if ($this->user->save()) {
143
                    return Yii::$app->yrc->userClass::sendPasswordChangedEmail($this->email);
144
                }
145
            }
146
        }
147
148
        return false;
149
    }
150
}