Completed
Push — master ( cd4c7e...5cee32 )
by ARCANEDEV
06:36
created

User   D

Complexity

Total Complexity 37

Size/Duplication

Total Lines 523
Duplicated Lines 0 %

Coupling/Cohesion

Components 7
Dependencies 22

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 37
lcom 7
cbo 22
dl 0
loc 523
ccs 120
cts 120
cp 1
rs 4.9789
c 0
b 0
f 0

29 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A setupModel() 0 9 2
A roles() 0 9 1
A getPermissionsAttribute() 0 9 1
A scopeUnconfirmed() 0 6 1
A scopeLastActive() 0 8 2
A setEmailAttribute() 0 4 1
A setUsernameAttribute() 0 4 1
A setFirstNameAttribute() 0 4 1
A setLastNameAttribute() 0 4 1
A getFullNameAttribute() 0 4 1
A setPasswordAttribute() 0 4 1
A activate() 0 8 1
A deactivate() 0 8 1
A attachRole() 0 10 2
A syncRoles() 0 13 1
A detachRole() 0 10 1
A detachAllRoles() 0 10 1
A findUnconfirmed() 0 10 2
A confirm() 0 9 2
A updateLastActivity() 0 6 2
A may() 0 6 1
A mayOne() 0 10 2
A mayAll() 0 6 2
A isAdmin() 0 4 1
A isModerator() 0 5 1
A isMember() 0 4 1
A isConfirmed() 0 4 1
A canBeImpersonated() 0 4 1
1
<?php namespace Arcanedev\LaravelAuth\Models;
2
3
use Arcanedev\LaravelAuth\Events\Users\ActivatedUser;
4
use Arcanedev\LaravelAuth\Events\Users\ActivatingUser;
5
use Arcanedev\LaravelAuth\Events\Users\AttachedRoleToUser;
6
use Arcanedev\LaravelAuth\Events\Users\AttachingRoleToUser;
7
use Arcanedev\LaravelAuth\Events\Users\CreatedUser;
8
use Arcanedev\LaravelAuth\Events\Users\CreatingUser;
9
use Arcanedev\LaravelAuth\Events\Users\DeactivatedUser;
10
use Arcanedev\LaravelAuth\Events\Users\DeactivatingUser;
11
use Arcanedev\LaravelAuth\Events\Users\DeletedUser;
12
use Arcanedev\LaravelAuth\Events\Users\DeletingUser;
13
use Arcanedev\LaravelAuth\Events\Users\DetachedRoleFromUser;
14
use Arcanedev\LaravelAuth\Events\Users\DetachedRolesFromUser;
15
use Arcanedev\LaravelAuth\Events\Users\DetachingRoleFromUser;
16
use Arcanedev\LaravelAuth\Events\Users\DetachingRolesFromUser;
17
use Arcanedev\LaravelAuth\Events\Users\RestoredUser;
18
use Arcanedev\LaravelAuth\Events\Users\RestoringUser;
19
use Arcanedev\LaravelAuth\Events\Users\SavedUser;
20
use Arcanedev\LaravelAuth\Events\Users\SavingUser;
21
use Arcanedev\LaravelAuth\Events\Users\SyncedUserWithRoles;
22
use Arcanedev\LaravelAuth\Events\Users\SyncingUserWithRoles;
23
use Arcanedev\LaravelAuth\Events\Users\UpdatedUser;
24
use Arcanedev\LaravelAuth\Events\Users\UpdatingUser;
25
use Arcanedev\LaravelAuth\Exceptions\UserConfirmationException;
26
use Arcanedev\LaravelAuth\Models\Traits\Activatable;
27
use Arcanedev\LaravelAuth\Models\Traits\Roleable;
28
use Arcanedev\LaravelAuth\Services\SocialAuthenticator;
29
use Arcanedev\LaravelAuth\Services\UserConfirmator;
30
use Arcanesoft\Contracts\Auth\Models\Permission as PermissionContract;
31
use Arcanesoft\Contracts\Auth\Models\Role as RoleContract;
32
use Arcanesoft\Contracts\Auth\Models\User as UserContract;
33
use Carbon\Carbon;
34
use Illuminate\Auth\Authenticatable;
35
use Illuminate\Auth\Passwords\CanResetPassword;
36
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
37
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
38
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
39
use Illuminate\Database\Eloquent\SoftDeletes;
40
use Illuminate\Foundation\Auth\Access\Authorizable;
41
use Illuminate\Support\Collection;
42
use Illuminate\Support\Str;
43
44
/**
45
 * Class     User
46
 *
47
 * @package  Arcanedev\LaravelAuth\Models
48
 * @author   ARCANEDEV <[email protected]>
49
 *
50
 * @property  int                                       id
51
 * @property  string                                    username
52
 * @property  string                                    first_name
53
 * @property  string                                    last_name
54
 * @property  string                                    full_name
55
 * @property  string                                    email
56
 * @property  string                                    password
57
 * @property  string                                    remember_token
58
 * @property  bool                                      is_admin
59
 * @property  bool                                      is_active
60
 * @property  bool                                      is_confirmed       (Optional)
61
 * @property  string                                    confirmation_code  (Optional)
62
 * @property  \Carbon\Carbon                            confirmed_at       (Optional)
63
 * @property  \Carbon\Carbon                            last_activity
64
 * @property  \Carbon\Carbon                            created_at
65
 * @property  \Carbon\Carbon                            updated_at
66
 * @property  \Carbon\Carbon                            deleted_at
67
 *
68
 * @property  \Illuminate\Database\Eloquent\Collection       roles
69
 * @property  \Illuminate\Support\Collection                 permissions
70
 * @property  \Arcanedev\LaravelAuth\Models\Pivots\RoleUser  pivot
71
 *
72
 * @method    \Illuminate\Database\Eloquent\Builder  unconfirmed(string $code)
73
 * @method    \Illuminate\Database\Eloquent\Builder  lastActive(int $minutes = null)
74
 */
75
class User
0 ignored issues
show
Bug introduced by
There is at least one abstract method in this class. Maybe declare it as abstract, or implement the remaining methods: can, forceDelete, forceFill, getAuthIdentifier, getAuthIdentifierName, getAuthPassword, getEmailForPasswordReset, getKey, getRememberToken, getRememberTokenName, isForceDeleting, restore, sendPasswordResetNotification, setAttribute, setRememberToken, trashed
Loading history...
76
    extends AbstractModel
77
    implements UserContract, AuthenticatableContract, AuthorizableContract, CanResetPasswordContract
78
{
79
    /* -----------------------------------------------------------------
80
     |  Traits
81
     | -----------------------------------------------------------------
82
     */
83
84
    use Roleable,
85
        Authenticatable,
86
        Authorizable,
87
        CanResetPassword,
88
        Activatable,
89
        SoftDeletes;
90
91
    /* -----------------------------------------------------------------
92
     |  Properties
93
     | -----------------------------------------------------------------
94
95
     */
96
    /**
97
     * The attributes that are mass assignable.
98
     *
99
     * @var array
100
     */
101
    protected $fillable = [
102
        'username',
103
        'first_name',
104
        'last_name',
105
        'email',
106
        'password',
107
        'confirmation_code',
108
    ];
109
110
    /**
111
     * The attributes excluded from the model's JSON form.
112
     *
113
     * @var array
114
     */
115
    protected $hidden   = [
116
        'password',
117
        'remember_token',
118
        'confirmation_code',
119
    ];
120
121
    /**
122
     * The attributes that should be casted to native types.
123
     *
124
     * @var array
125
     */
126
    protected $casts = [
127
        'is_admin'     => 'boolean',
128
        'is_active'    => 'boolean',
129
        'is_confirmed' => 'boolean',
130
    ];
131
132
    /**
133
     * The attributes that should be mutated to dates.
134
     *
135
     * @var array
136
     */
137
    protected $dates = [
138
        'confirmed_at',
139
        'last_activity',
140
        'deleted_at',
141
    ];
142
143
    /**
144
     * The event map for the model.
145
     *
146
     * @var array
147
     */
148
    protected $dispatchesEvents = [
149
        'creating'  => CreatingUser::class,
150
        'created'   => CreatedUser::class,
151
        'updating'  => UpdatingUser::class,
152
        'updated'   => UpdatedUser::class,
153
        'saving'    => SavingUser::class,
154
        'saved'     => SavedUser::class,
155
        'deleting'  => DeletingUser::class,
156
        'deleted'   => DeletedUser::class,
157
        'restoring' => RestoringUser::class,
158
        'restored'  => RestoredUser::class,
159
    ];
160
161
    /* -----------------------------------------------------------------
162
     |  Constructor
163
     | -----------------------------------------------------------------
164
     */
165
166
    /**
167
     * Create a new Eloquent model instance.
168
     *
169
     * @param  array  $attributes
170
     */
171 68
    public function __construct(array $attributes = [])
172
    {
173 68
        parent::__construct($attributes);
174
175 68
        $this->setupModel();
176 68
    }
177
178
    /**
179
     * Setup the model.
180
     */
181 68
    protected function setupModel()
182
    {
183 68
        $this->setTable(config('laravel-auth.users.table', 'users'));
184
185 68
        if (SocialAuthenticator::isEnabled()) {
186 68
            $this->hidden   = array_merge($this->hidden, ['social_provider_id']);
187 68
            $this->fillable = array_merge($this->fillable, ['social_provider', 'social_provider_id']);
188
        }
189 68
    }
190
191
    /* -----------------------------------------------------------------
192
     |  Relationships
193
     | -----------------------------------------------------------------
194
     */
195
196
    /**
197
     * User belongs to many roles.
198
     *
199
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
200
     */
201 28
    public function roles()
202
    {
203 28
        return $this->belongsToMany(
204 28
                config('laravel-auth.roles.model', Role::class),
205 28
                $this->getPrefix().config('laravel-auth.role-user.table', 'role_user')
206
            )
207 28
            ->using(Pivots\RoleUser::class)
208 28
            ->withTimestamps();
209
    }
210
211
    /**
212
     * Get all user permissions.
213
     *
214
     * @return \Illuminate\Support\Collection
215
     */
216 6
    public function getPermissionsAttribute()
217
    {
218 6
        return $this->active_roles
219 6
            ->pluck('permissions')
220 6
            ->flatten()
221 6
            ->unique(function (PermissionContract $permission) {
222 6
                return $permission->getKey();
223 6
            });
224
    }
225
226
    /* -----------------------------------------------------------------
227
     |  Scopes
228
     | -----------------------------------------------------------------
229
     */
230
231
    /**
232
     * Scope unconfirmed users by code.
233
     *
234
     * @param  \Illuminate\Database\Eloquent\Builder  $query
235
     * @param  string                                 $code
236
     *
237
     * @return \Illuminate\Database\Eloquent\Builder
238
     */
239 8
    public function scopeUnconfirmed($query, $code)
240
    {
241 8
        return $query->where('is_confirmed', false)
242 8
                     ->where('confirmation_code', $code)
243 8
                     ->whereNull('confirmed_at');
244
    }
245
246
    /**
247
     * Scope last active users.
248
     *
249
     * @param  \Illuminate\Database\Eloquent\Builder  $query
250
     * @param  int|null                               $minutes
251
     *
252
     * @return \Illuminate\Database\Eloquent\Builder
253
     */
254 2
    public function scopeLastActive($query, $minutes = null)
255
    {
256 2
        $date = Carbon::now()->subMinutes(
257 2
            $minutes ?: config('laravel_auth.track-activity.minutes', 5)
258
        );
259
260 2
        return $query->where('last_activity', '>=', $date->toDateTimeString());
261
    }
262
263
    /* -----------------------------------------------------------------
264
     |  Getters & Setters
265
     | -----------------------------------------------------------------
266
     */
267
268
    /**
269
     * Set the `email` attribute.
270
     *
271
     * @param  string  $email
272
     */
273 54
    public function setEmailAttribute($email)
274
    {
275 54
        $this->attributes['email'] = Str::lower($email);
276 54
    }
277
278
    /**
279
     * Set the `username` attribute.
280
     *
281
     * @param  string  $username
282
     */
283 52
    public function setUsernameAttribute($username)
284
    {
285 52
        $this->attributes['username'] = Str::slug($username, config('laravel-auth.users.slug-separator', '.'));
286 52
    }
287
288
    /**
289
     * Set the `first_name` attribute.
290
     *
291
     * @param  string  $firstName
292
     */
293 54
    public function setFirstNameAttribute($firstName)
294
    {
295 54
        $this->attributes['first_name'] = Str::title(Str::lower($firstName));
296 54
    }
297
298
    /**
299
     * Set the `last_name` attribute.
300
     *
301
     * @param  string  $lastName
302
     */
303 54
    public function setLastNameAttribute($lastName)
304
    {
305 54
        $this->attributes['last_name'] = Str::upper($lastName);
306 54
    }
307
308
    /**
309
     * Get the `full_name` attribute.
310
     *
311
     * @return string
312
     */
313 4
    public function getFullNameAttribute()
314
    {
315 4
        return $this->first_name.' '.$this->last_name;
316
    }
317
318
    /**
319
     * Set the `password` attribute.
320
     *
321
     * @param  string  $password
322
     */
323 52
    public function setPasswordAttribute($password)
324
    {
325 52
        $this->attributes['password'] = bcrypt($password);
326 52
    }
327
328
    /* -----------------------------------------------------------------
329
     |  Main Methods
330
     | -----------------------------------------------------------------
331
     */
332
333
    /**
334
     * Activate the model.
335
     *
336
     * @param  bool  $save
337
     *
338
     * @return bool
339
     */
340 2
    public function activate($save = true)
341
    {
342 2
        event(new ActivatingUser($this));
343 2
        $result = $this->switchActive(true, $save);
344 2
        event(new ActivatedUser($this));
345
346 2
        return $result;
347
    }
348
349
    /**
350
     * Deactivate the model.
351
     *
352
     * @param  bool  $save
353
     *
354
     * @return bool
355
     */
356 2
    public function deactivate($save = true)
357
    {
358 2
        event(new DeactivatingUser($this));
359 2
        $result = $this->switchActive(false, $save);
360 2
        event(new DeactivatedUser($this));
361
362 2
        return $result;
363
    }
364
365
    /**
366
     * Attach a role to a user.
367
     *
368
     * @param  \Arcanesoft\Contracts\Auth\Models\Role|int  $role
369
     * @param  bool                                        $reload
370
     */
371 22
    public function attachRole($role, $reload = true)
372
    {
373 22
        if ($this->hasRole($role)) return;
374
375 22
        event(new AttachingRoleToUser($this, $role));
376 22
        $this->roles()->attach($role);
377 22
        event(new AttachedRoleToUser($this, $role));
378
379 22
        $this->loadRoles($reload);
380 22
    }
381
382
    /**
383
     * Sync the roles by its slugs.
384
     *
385
     * @param  array|\Illuminate\Support\Collection  $slugs
386
     * @param  bool                                  $reload
387
     *
388
     * @return array
389
     */
390 2
    public function syncRoles($slugs, $reload = true)
391
    {
392
        /** @var  \Illuminate\Database\Eloquent\Collection  $roles */
393 2
        $roles = app(RoleContract::class)->whereIn('slug', $slugs)->get();
394
395 2
        event(new SyncingUserWithRoles($this, $roles));
396 2
        $synced = $this->roles()->sync($roles->pluck('id'));
397 2
        event(new SyncedUserWithRoles($this, $roles, $synced));
398
399 2
        $this->loadRoles($reload);
400
401 2
        return $synced;
402
    }
403
404
    /**
405
     * Detach a role from a user.
406
     *
407
     * @param  \Arcanesoft\Contracts\Auth\Models\Role|int  $role
408
     * @param  bool                                        $reload
409
     *
410
     * @return int
411
     */
412 2
    public function detachRole($role, $reload = true)
413
    {
414 2
        event(new DetachingRoleFromUser($this, $role));
415 2
        $results = $this->roles()->detach($role);
416 2
        event(new DetachedRoleFromUser($this, $role, $results));
417
418 2
        $this->loadRoles($reload);
419
420 2
        return $results;
421
    }
422
423
    /**
424
     * Detach all roles from a user.
425
     *
426
     * @param  bool  $reload
427
     *
428
     * @return int
429
     */
430 2
    public function detachAllRoles($reload = true)
431
    {
432 2
        event(new DetachingRolesFromUser($this));
433 2
        $results = $this->roles()->detach();
434 2
        event(new DetachedRolesFromUser($this, $results));
435
436 2
        $this->loadRoles($reload);
437
438 2
        return $results;
439
    }
440
441
    /**
442
     * Confirm the unconfirmed user account by confirmation code.
443
     *
444
     * @param  string  $code
445
     *
446
     * @return \Arcanesoft\Contracts\Auth\Models\User
447
     *
448
     * @throws \Arcanedev\LaravelAuth\Exceptions\UserConfirmationException
449
     */
450 8
    public function findUnconfirmed($code)
451
    {
452
        /** @var  \Arcanesoft\Contracts\Auth\Models\User|null  $unconfirmed */
453 8
        $unconfirmed = static::unconfirmed($code)->first();
454
455 8
        if ( ! $unconfirmed instanceof self)
456 2
            throw (new UserConfirmationException)->setModel(static::class);
457
458 6
        return $unconfirmed;
459
    }
460
461
    /**
462
     * Confirm the new user account.
463
     *
464
     * @param  \Arcanesoft\Contracts\Auth\Models\User|string  $code
465
     *
466
     * @return \Arcanesoft\Contracts\Auth\Models\User
467
     */
468 4
    public function confirm($code)
469
    {
470 4
        if ($code instanceof self)
471 2
            $code = $code->confirmation_code;
472
473 4
        return (new UserConfirmator)->confirm(
474 4
            $this->findUnconfirmed($code)
475
        );
476
    }
477
478
    /**
479
     * Update the user's last activity.
480
     *
481
     * @param  bool  $save
482
     */
483 2
    public function updateLastActivity($save = true)
484
    {
485 2
        $this->forceFill(['last_activity' => Carbon::now()]);
486
487 2
        if ($save) $this->save();
488 2
    }
489
490
    /* -----------------------------------------------------------------
491
     |  Permission Check Methods
492
     | -----------------------------------------------------------------
493
     */
494
    /**
495
     * Check if the user has a permission.
496
     *
497
     * @param  string  $slug
498
     *
499
     * @return bool
500
     */
501
    public function may($slug)
502
    {
503 6
        return ! $this->permissions->filter(function (PermissionContract $permission) use ($slug) {
504 6
            return $permission->hasSlug($slug);
505 6
        })->isEmpty();
506
    }
507
508
    /**
509
     * Check if the user has at least one permission.
510
     *
511
     * @param  \Illuminate\Support\Collection|array  $permissions
512
     * @param  \Illuminate\Support\Collection        &$failed
513
     *
514
     * @return bool
515
     */
516 4
    public function mayOne($permissions, &$failed = null)
517
    {
518 4
        $permissions = is_array($permissions) ? collect($permissions) : $permissions;
519
520 4
        $failed = $permissions->reject(function ($permission) {
521 4
            return $this->may($permission);
522 4
        })->values();
523
524 4
        return $permissions->count() !== $failed->count();
525
    }
526
527
    /**
528
     * Check if the user has all permissions.
529
     *
530
     * @param  \Illuminate\Support\Collection|array  $permissions
531
     * @param  \Illuminate\Support\Collection        &$failed
532
     *
533
     * @return bool
534
     */
535 2
    public function mayAll($permissions, &$failed = null)
536
    {
537 2
        $this->mayOne($permissions, $failed);
538
539 2
        return $failed instanceof Collection ? $failed->isEmpty() : false;
540
    }
541
542
    /* -----------------------------------------------------------------
543
     |  Check Methods
544
     | -----------------------------------------------------------------
545
     */
546
547
    /**
548
     * Check if user is an administrator.
549
     *
550
     * @return bool
551
     */
552 8
    public function isAdmin()
553
    {
554 8
        return $this->is_admin;
555
    }
556
557
    /**
558
     * Check if user is a moderator.
559
     *
560
     * @return bool
561
     */
562 4
    public function isModerator()
563
    {
564
        // Override this method to give more privileges than members.
565 4
        return false;
566
    }
567
568
    /**
569
     * Check if user is a member.
570
     *
571
     * @return bool
572
     */
573 6
    public function isMember()
574
    {
575 6
        return ! $this->isAdmin();
576
    }
577
578
    /**
579
     * Check if user has a confirmed account.
580
     *
581
     * @return bool
582
     */
583 6
    public function isConfirmed()
584
    {
585 6
        return $this->is_confirmed;
586
    }
587
588
    /**
589
     * Check if user can be impersonated.
590
     *
591
     * @return bool
592
     */
593 2
    public function canBeImpersonated()
594
    {
595 2
        return $this->isMember();
596
    }
597
}
598