Passed
Push — master ( 05bedf...5523e7 )
by Alexey
03:12
created

BaseUser::getAuthKey()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 1
c 2
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
4
namespace modules\users\models;
5
6
use modules\users\Module;
7
use Yii;
8
use yii\base\Exception;
9
use yii\db\ActiveRecord;
10
use yii\helpers\ArrayHelper;
11
use yii\helpers\Html;
12
use yii\web\IdentityInterface;
13
14
/**
15
 * Class BaseUser
16
 * @package modules\users\models
17
 *
18
 * @property int $id ID
19
 * @property string $auth_key Authorization Key
20
 * @property string $email_confirm_token Email Confirm Token
21
 * @property int $status
22
 * @property string $statusLabelName
23
 * @property string $statusName
24
 * @property array $statusesArray
25
 * @property array $labelsArray
26
 */
27
class BaseUser extends ActiveRecord implements IdentityInterface
28
{
29
    // Statuses
30
    const STATUS_BLOCKED = 0;
31
    const STATUS_ACTIVE = 1;
32
    const STATUS_WAIT = 2;
33
    const STATUS_DELETED = 3;
34
35
    /**
36
     * {@inheritdoc}
37
     * @return string
38
     */
39
    public static function tableName()
40
    {
41
        return '{{%user}}';
42
    }
43
44
    /**
45
     * @param string|int $id
46
     * @return yii\db\ActiveRecord
47
     */
48
    public static function findIdentity($id)
49
    {
50
        return static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]);
0 ignored issues
show
Bug Best Practice introduced by
The expression return static::findOne(a...> self::STATUS_ACTIVE)) returns the type yii\db\ActiveRecord which is incompatible with the return type mandated by yii\web\IdentityInterface::findIdentity() of null|yii\web\IdentityInterface.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
51
    }
52
53
    /**
54
     * @param mixed $token
55
     * @param mixed $type
56
     * @return yii\db\ActiveRecord
57
     */
58
    public static function findIdentityByAccessToken($token, $type = null)
59
    {
60
        return static::findOne(['auth_key' => $token, 'status' => self::STATUS_ACTIVE]);
0 ignored issues
show
Bug Best Practice introduced by
The expression return static::findOne(a...> self::STATUS_ACTIVE)) returns the type yii\db\ActiveRecord which is incompatible with the return type mandated by yii\web\IdentityInterfac...IdentityByAccessToken() of null|yii\web\IdentityInterface.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
61
    }
62
63
    /**
64
     * {@inheritdoc}
65
     * @return int|string
66
     */
67
    public function getId()
68
    {
69
        return $this->id;
70
    }
71
72
    /**
73
     * {@inheritdoc}
74
     * @return string
75
     */
76
    public function getAuthKey()
77
    {
78
        return $this->auth_key;
79
    }
80
81
    /**
82
     * {@inheritdoc}
83
     * @param string $authKey
84
     * @return bool
85
     */
86
    public function validateAuthKey($authKey)
87
    {
88
        return $this->getAuthKey() === $authKey;
89
    }
90
91
    /**
92
     * Generates "remember me" authentication key
93
     * @throws Exception
94
     */
95
    public function generateAuthKey()
96
    {
97
        $this->auth_key = $this->generateUniqueRandomString('auth_key');
98
    }
99
100
    /**
101
     * Generates email confirmation token
102
     * @throws Exception
103
     */
104
    public function generateEmailConfirmToken()
105
    {
106
        $this->email_confirm_token = $this->generateUniqueRandomString('email_confirm_token');
107
    }
108
109
    /**
110
     * Generate Unique Random String
111
     * @param string $attribute
112
     * @param int $maxIteration
113
     * @return string
114
     * @throws Exception
115
     */
116
    public function generateUniqueRandomString($attribute, $maxIteration = 10)
117
    {
118
        $security = Yii::$app->security;
119
        if ($attribute && $maxIteration > 0) {
120
            $i = 0;
121
            while($i <= $maxIteration) {
122
                $string = $security->generateRandomString();
123
                if (isset($string) && (static::findOne([$attribute => $string])) === null) {
124
                    return $string;
125
                }
126
                $i++;
127
            }
128
            throw new Exception('Failed to generate unique value, try increasing the number of iterations.');
129
        }
130
        return $security->generateRandomString();
131
    }
132
133
    /**
134
     * Finds out if password reset token is valid
135
     *
136
     * @param mixed $token password reset token
137
     * @return boolean
138
     */
139
    public static function isPasswordResetTokenValid($token)
140
    {
141
        if (empty($token)) {
142
            return false;
143
        }
144
        $expire = Module::$passwordResetTokenExpire;
145
        $parts = explode('_', $token);
146
        $timestamp = (int)end($parts);
147
        return $timestamp + $expire >= time();
148
    }
149
150
    /**
151
     * Finds user by password reset token
152
     *
153
     * @param mixed $token password reset token
154
     * @return static|null
155
     */
156
    public static function findByPasswordResetToken($token)
157
    {
158
        if (!static::isPasswordResetTokenValid($token)) {
159
            return null;
160
        }
161
        return static::findOne([
162
            'password_reset_token' => $token,
163
            'status' => self::STATUS_ACTIVE
164
        ]);
165
    }
166
167
    /**
168
     * @return array
169
     */
170
    public static function getStatusesArray()
171
    {
172
        return [
173
            self::STATUS_BLOCKED => Module::t('module', 'Blocked'),
174
            self::STATUS_ACTIVE => Module::t('module', 'Active'),
175
            self::STATUS_WAIT => Module::t('module', 'Wait'),
176
            self::STATUS_DELETED => Module::t('module', 'Deleted')
177
        ];
178
    }
179
180
    /**
181
     * @return array
182
     */
183
    public static function getLabelsArray()
184
    {
185
        return [
186
            self::STATUS_BLOCKED => 'default',
187
            self::STATUS_ACTIVE => 'success',
188
            self::STATUS_WAIT => 'warning',
189
            self::STATUS_DELETED => 'danger'
190
        ];
191
    }
192
193
    /**
194
     * @return mixed
195
     */
196
    public function getStatusName()
197
    {
198
        return ArrayHelper::getValue(self::getStatusesArray(), $this->status);
199
    }
200
201
    /**
202
     * Return <span class="label label-success">Active</span>
203
     * @return string
204
     */
205
    public function getStatusLabelName()
206
    {
207
        $name = ArrayHelper::getValue(self::getLabelsArray(), $this->status);
208
        return Html::tag('span', $this->getStatusName(), ['class' => 'label label-' . $name]);
209
    }
210
}