Completed
Push — master ( 5e7707...6e3d76 )
by Igor
03:56
created

User::authorize()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 9
ccs 5
cts 5
cp 1
rs 9.6666
cc 2
eloc 5
nc 1
nop 1
crap 2
1
<?php
2
3
namespace app\models;
4
5
use Yii;
6
use yii\base\NotSupportedException;
7
use yii\db\ActiveRecord;
8
use yii\web\IdentityInterface;
9
use yii\behaviors\TimestampBehavior;
10
use app\models\UserProfile;
11
use app\models\UserProvider;
12
use app\models\query\UserQuery;
13
14
/**
15
 * This is the model class for table "user".
16
 *
17
 * @property integer $id
18
 * @property string $username
19
 * @property string $email
20
 * @property string $password
21
 * @property string $password_reset_token
22
 * @property string $email_confirm_token
23
 * @property string $auth_key
24
 * @property string $date_confirm
25
 * @property string $date_create
26
 * @property string $date_update
27
 * @property string $date_login
28
 * @property integer $ip
29
 * @property string $role
30
 * @property integer $status
31
 */
32
class User extends \yii\db\ActiveRecord implements IdentityInterface
33
{
34
    const STATUS_DELETED = 0;
35
    const STATUS_ACTIVE  = 1;
36
    const STATUS_BLOCKED = 2;
37
38
    const ROLE_SUPERUSER = 'SuperUser';
39
40
    /**
41
     * @var string
42
     */
43
    public $passwordNew;
44
45
    /**
46
     * @inheritdoc
47
     */
48
    public static function tableName()
49
    {
50
        return 'user';
51
    }
52
53
    /**
54
     * @inheritdoc
55
     */
56
    public function rules()
57
    {
58
        return [
59
            ['username', 'string', 'min' => 3, 'max' => 40],
60
            ['username', 'match', 'pattern' => '/^[a-zA-Z0-9_-]+$/'],
61
            ['username', 'unique'],
62
            ['username', 'default', 'value' => null],
63
64
            ['email', 'email'],
65
            ['email', 'required'],
66
            ['email', 'string', 'max' => 255],
67
            ['email', 'unique'],
68
            ['email', 'default', 'value' => null],
69
70
            ['role', 'string'],
71
            [
72
                'role',
73
                'exist',
74
                'targetClass' => AuthItem::class,
75
                'targetAttribute' => ['role' => 'name'],
76
                'filter' => ['type' => \yii\rbac\Item::TYPE_ROLE]
77
            ],
78
79
            ['status', 'integer'],
80
            ['status', 'default', 'value' => self::STATUS_ACTIVE],
81
            ['status', 'in', 'range' => array_keys(self::getStatuses())],
82
83
            ['passwordNew', 'string', 'min' => 6],
84
        ];
85
    }
86
87
    /**
88
     * @inheritdoc
89
     */
90 36
    public function attributeLabels()
91
    {
92
        return [
93 36
            'id' => Yii::t('app', 'ID'),
94 36
            'username' => Yii::t('app', 'Username'),
95 36
            'email' => Yii::t('app', 'Email'),
96 36
            'password' => Yii::t('app', 'Password'),
97 36
            'date_create' => Yii::t('app', 'Date create'),
98 36
            'date_update' => Yii::t('app', 'Date update'),
99 36
            'date_login' => Yii::t('app', 'Last login'),
100 36
            'ip' => Yii::t('app', 'IP'),
101 36
            'role' => Yii::t('app', 'Role'),
102 36
            'status' => Yii::t('app', 'Status'),
103
104 36
            'passwordNew' => Yii::t('app', 'New password'),
105
        ];
106
    }
107
108
    /**
109
     * @inheritdoc
110
     * @codeCoverageIgnore
111
     */
112
    public function attributeHints()
113
    {
114
        return [
115
            'username' => Yii::t('app.validators', 'Only letters, numbers, symbols _ and -'),
116
            'passwordNew' => Yii::t('app.validators', 'Set a new password')
117
        ];
118
    }
119
120
    /**
121
     * @inheritdoc
122
     */
123 36
    public function behaviors()
124
    {
125
        return [
126
            [
127 36
                'class' => TimestampBehavior::class,
128 36
                'createdAtAttribute' => 'date_create',
129 36
                'updatedAtAttribute' => 'date_update',
130 36
                'value' => new \yii\db\Expression('NOW()'),
131
            ],
132
        ];
133
    }
134
135
    /**
136
     * @inheritdoc
137
     * @codeCoverageIgnore
138
     */
139
    public function events()
140
    {
141
        return [
142
            ActiveRecord::EVENT_BEFORE_DELETE => 'beforeDelete',
143
        ];
144
    }
145
146
    public function transactions()
147
    {
148
        return [
149
            'create' => self::OP_ALL,
150
            'update' => self::OP_ALL,
151
            'delete' => self::OP_ALL,
152
        ];
153
    }
154
155
    /**
156
     * @return \yii\db\ActiveQuery
157
     */
158
    public function getProfile()
159
    {
160
        return $this->hasOne(UserProfile::class, ['user_id' => 'id']);
161
    }
162
163
    /**
164
     * @param array $attributes
165
     */
166
    public function setProfile($attributes = [])
167
    {
168
        return $this->populateRelation('profile', new UserProfile($attributes));
169
    }
170
171
    /**
172
     * @return \yii\db\ActiveQuery
173
     */
174
    public function getProviders()
175
    {
176
        return $this->hasMany(UserProvider::class, ['user_id' => 'id']);
177
    }
178
179
    /**
180
     * @param array $attributes
181
     */
182
    public function setProviders($attributes = [])
183
    {
184
        return $this->populateRelation('providers', [new UserProvider($attributes)]);
185
    }
186
187
    /**
188
     * @return \yii\db\ActiveQuery
189
     */
190
    public function getRoles()
191
    {
192
        return $this->hasOne(AuthItem::class, ['name' => 'role']);
193
    }
194
195
    /**
196
     * @inheritdoc
197
     * @return UserQuery
198
     */
199
    public static function find()
200
    {
201
        return new UserQuery(get_called_class());
202
    }
203
204
    /**
205
     * @inheritdoc
206
     */
207
    public function beforeSave($insert)
208
    {
209
        if (parent::beforeSave($insert)) {
210
            if ($insert) {
211
                $this->generateAuthKey();
212
                if (!Yii::$app instanceof \yii\console\Application) {
213
                    $this->ip = ip2long(Yii::$app->request->getUserIP());
214
                }
215
216
                if ($this->profile === null) {
217
                    $this->setProfile();
218
                }
219
            }
220
221
            if (!empty($this->passwordNew)) {
222
                $this->setPassword($this->passwordNew);
223
            }
224
225
            return true;
226
        } // @codeCoverageIgnore
227
228
        return false; // @codeCoverageIgnore
229
    }
230
231
    /**
232
     * @inheritdoc
233
     * @property \app\models\UserProfile $profile
234
     * @property \app\models\UserProvider $providers
235
     */
236
    public function afterSave($insert, $changedAttributes)
237
    {
238
        parent::afterSave($insert, $changedAttributes);
239
240
        if ($this->profile !== null) {
241
            $this->link('profile', $this->profile);
242
        }
243
244
        if ($this->providers !== null && count($this->providers)) {
245
            foreach ($this->providers as $provider) {
246
                if ($provider) {
247
                    $this->link('providers', $provider);
248
                }
249
            }
250
        }
251
    }
252
253
    /**
254
     * @inheritdoc
255
     * @param boolean $runValidation
256
     * @param array $attributeNames
257
     * @return boolean
258
     */
259
    public function save($runValidation = true, $attributeNames = null)
260
    {
261
        return $this->getDb()->transaction(function () use ($runValidation, $attributeNames) {
262
            return parent::save($runValidation, $attributeNames);
263
        });
264
    }
265
266
    /**
267
     * Get all statuses
268
     *
269
     * @param string[]
270
     */
271
    public static function getStatuses(): array
272
    {
273
        return [
274
            self::STATUS_DELETED => Yii::t('app', 'Deleted'),
275
            self::STATUS_BLOCKED => Yii::t('app', 'Locked'),
276
            self::STATUS_ACTIVE  => Yii::t('app', 'Active'),
277
        ];
278
    }
279
280
    /**
281
     * Get statuse name
282
     *
283
     * @return string
284
     */
285
    public function getStatusName(): string
286
    {
287
        $statuses = self::getStatuses();
288
        return isset($statuses[$this->status]) ? $statuses[$this->status] : '';
289
    }
290
291
    /**
292
     * Is it deleted?
293
     *
294
     * @param bool
295
     */
296
    public function isDeleted(): bool
297
    {
298
        return $this->status == self::STATUS_DELETED;
299
    }
300
301
    /**
302
     * Is it blocked?
303
     *
304
     * @param bool
305
     */
306
    public function isBlocked(): bool
307
    {
308
        return $this->status == self::STATUS_BLOCKED;
309
    }
310
311
    /**
312
     * Is it active?
313
     *
314
     * @param bool
315
     */
316
    public function isActive(): bool
317
    {
318
        return $this->status == self::STATUS_ACTIVE;
319
    }
320
321
    /**
322
     * Is it confirmed?
323
     *
324
     * @param bool
325
     */
326
    public function isConfirmed(): bool
327
    {
328
        return strtotime($this->date_confirm) > 0;
329
    }
330
331
    /**
332
     * Is SuperUser?
333
     *
334
     * @return bool
335
     */
336
    public function isSuperUser(): bool
337
    {
338
        return $this->role === self::ROLE_SUPERUSER;
339
    }
340
341
    /**
342
     * Set confirmed
343
     */
344
    public function setConfirmed(): void
345
    {
346
        $this->email_confirm_token = null;
347
        $this->date_confirm = new \yii\db\Expression('NOW()');
348
    }
349
350
    /**
351
     * Get status description
352
     *
353
     * @return string
354
     */
355
    public function getStatusDescription(): string
356
    {
357
        if ($this->status == self::STATUS_BLOCKED) {
358
            return Yii::t('app', 'Your account has been suspended');
359
        } elseif ($this->status == self::STATUS_DELETED) {
360
            return Yii::t('app', 'Your account has been deleted');
361
        }
362
        return Yii::t('app', 'Your account is activated');
363
    }
364
365
    /**
366
     * @inheritdoc
367
     */
368
    public function getId()
369
    {
370
        return $this->id;
371
    }
372
373
    /**
374
     * @inheritdoc
375
     */
376
    public function getAuthKey()
377
    {
378
        return $this->auth_key;
379
    }
380
381
    /**
382
     * @inheritdoc
383
     */
384
    public function validateAuthKey($authKey)
385
    {
386
        return $this->getAuthKey() === $authKey;
387
    }
388
389
    /**
390
     * Generates "remember me" authentication key
391
     */
392
    public function generateAuthKey()
393
    {
394
        $this->auth_key = Yii::$app->security->generateRandomString();
395
    }
396
397
    /**
398
     * Validates password
399
     *
400
     * @param string $password password to validate
401
     * @return boolean if password provided is valid for current user
402
     */
403
    public function validatePassword(string $password): bool
404
    {
405
        if (empty($this->password)) {
406
            return false;
407
        }
408
409
        return Yii::$app->security->validatePassword($password, $this->password);
410
    }
411
412
    /**
413
     * Set a new password
414
     *
415
     * @param string $password
416
     */
417
    public function setPassword(string $password): void
418
    {
419
        $this->password = Yii::$app->security->generatePasswordHash($password);
420
    }
421
422
    /**
423
     * Set new password reset token
424
     *
425
     * @param string $token
426
     */
427
    public function setPasswordResetToken(string $token): void
428
    {
429
        $this->password_reset_token = $token;
430
    }
431
432
    /**
433
     * Removes password reset token
434
     */
435
    public function removePasswordResetToken(): void
436
    {
437
        $this->password_reset_token = null;
438
    }
439
440
    /**
441
     * Set new confirm email token
442
     *
443
     * @param string $token
444
     */
445
    public function setEmailConfirmToken(string $token): void
446
    {
447
        $this->email_confirm_token = $token;
448
        $this->date_confirm = null;
449
    }
450
451
    /**
452
     * @inheritdoc
453
     */
454
    public static function findIdentity($id)
455
    {
456
        return static::findOne([$id]);
457
    }
458
459
    /**
460
     * @inheritdoc
461
     */
462
    public static function findIdentityByAccessToken($token, $type = null)
463
    {
464
        throw new NotSupportedException('findIdentityByAccessToken is not implemented.');
465
    }
466
467
    /**
468
     * Update date login
469
     */
470
    public function updateDateLogin(): void
471
    {
472
        $this->updateAttributes([
473
            'date_login' => new \yii\db\Expression('NOW()'),
474
            'ip' => ip2long(Yii::$app->request->getUserIP())
475
        ]);
476
    }
477
478
    /**
479
     * @return bool
480
     */
481
    public function beforeDelete()
482
    {
483
        Yii::$app->authManager->revokeAll($this->id);
484
485
        if ($this->profile !== null) {
486
            $this->profile->delete();
487
        }
488
489
        return true;
490
    }
491
}
492