Completed
Push — master ( f8a22c...480ba6 )
by ARCANEDEV
12s
created

User   C

Complexity

Total Complexity 37

Size/Duplication

Total Lines 525
Duplicated Lines 0 %

Coupling/Cohesion

Components 7
Dependencies 21

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 37
lcom 7
cbo 21
dl 0
loc 525
ccs 123
cts 123
cp 1
rs 5.2554
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
     * Allows for object-based events for native Eloquent events.
147
     *
148
     * @var array
149
     */
150
    protected $events = [
151
        'creating'  => CreatingUser::class,
152
        'created'   => CreatedUser::class,
153
        'updating'  => UpdatingUser::class,
154
        'updated'   => UpdatedUser::class,
155
        'saving'    => SavingUser::class,
156
        'saved'     => SavedUser::class,
157
        'deleting'  => DeletingUser::class,
158
        'deleted'   => DeletedUser::class,
159
        'restoring' => RestoringUser::class,
160
        'restored'  => RestoredUser::class,
161
    ];
162
163
    /* -----------------------------------------------------------------
164
     |  Constructor
165
     | -----------------------------------------------------------------
166
     */
167
168
    /**
169
     * Create a new Eloquent model instance.
170
     *
171
     * @param  array  $attributes
172
     */
173 102
    public function __construct(array $attributes = [])
174
    {
175 102
        parent::__construct($attributes);
176
177 102
        $this->setupModel();
178 102
    }
179
180
    /**
181
     * Setup the model.
182
     */
183 102
    protected function setupModel()
184
    {
185 102
        $this->setTable(config('laravel-auth.users.table', 'users'));
186
187 102
        if (SocialAuthenticator::isEnabled()) {
188 102
            $this->hidden   = array_merge($this->hidden, ['social_provider_id']);
189 102
            $this->fillable = array_merge($this->fillable, ['social_provider', 'social_provider_id']);
190 34
        }
191 102
    }
192
193
    /* -----------------------------------------------------------------
194
     |  Relationships
195
     | -----------------------------------------------------------------
196
     */
197
198
    /**
199
     * User belongs to many roles.
200
     *
201
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
202
     */
203 42
    public function roles()
204
    {
205 42
        return $this->belongsToMany(
206 42
                config('laravel-auth.roles.model', Role::class),
207 42
                $this->getPrefix().config('laravel-auth.role-user.table', 'role_user')
208 14
            )
209 42
            ->using(Pivots\RoleUser::class)
210 42
            ->withTimestamps();
211
    }
212
213
    /**
214
     * Get all user permissions.
215
     *
216
     * @return \Illuminate\Support\Collection
217
     */
218 9
    public function getPermissionsAttribute()
219
    {
220 9
        return $this->active_roles
221 9
            ->pluck('permissions')
222 9
            ->flatten()
223
            ->unique(function (PermissionContract $permission) {
224 9
                return $permission->getKey();
225 9
            });
226
    }
227
228
    /* -----------------------------------------------------------------
229
     |  Scopes
230
     | -----------------------------------------------------------------
231
     */
232
233
    /**
234
     * Scope unconfirmed users by code.
235
     *
236
     * @param  \Illuminate\Database\Eloquent\Builder  $query
237
     * @param  string                                 $code
238
     *
239
     * @return \Illuminate\Database\Eloquent\Builder
240
     */
241 12
    public function scopeUnconfirmed($query, $code)
242
    {
243 12
        return $query->where('is_confirmed', false)
244 12
                     ->where('confirmation_code', $code)
245 12
                     ->whereNull('confirmed_at');
246
    }
247
248
    /**
249
     * Scope last active users.
250
     *
251
     * @param  \Illuminate\Database\Eloquent\Builder  $query
252
     * @param  int|null                               $minutes
253
     *
254
     * @return \Illuminate\Database\Eloquent\Builder
255
     */
256 3
    public function scopeLastActive($query, $minutes = null)
257
    {
258 3
        $date = Carbon::now()->subMinutes(
259 3
            $minutes ?: config('laravel_auth.track-activity.minutes', 5)
260 1
        );
261
262 3
        return $query->where('last_activity', '>=', $date->toDateTimeString());
263
    }
264
265
    /* -----------------------------------------------------------------
266
     |  Getters & Setters
267
     | -----------------------------------------------------------------
268
     */
269
270
    /**
271
     * Set the `email` attribute.
272
     *
273
     * @param  string  $email
274
     */
275 81
    public function setEmailAttribute($email)
276
    {
277 81
        $this->attributes['email'] = Str::lower($email);
278 81
    }
279
280
    /**
281
     * Set the `username` attribute.
282
     *
283
     * @param  string  $username
284
     */
285 78
    public function setUsernameAttribute($username)
286
    {
287 78
        $this->attributes['username'] = Str::slug($username, config('laravel-auth.users.slug-separator', '.'));
288 78
    }
289
290
    /**
291
     * Set the `first_name` attribute.
292
     *
293
     * @param  string  $firstName
294
     */
295 81
    public function setFirstNameAttribute($firstName)
296
    {
297 81
        $this->attributes['first_name'] = Str::title(Str::lower($firstName));
298 81
    }
299
300
    /**
301
     * Set the `last_name` attribute.
302
     *
303
     * @param  string  $lastName
304
     */
305 81
    public function setLastNameAttribute($lastName)
306
    {
307 81
        $this->attributes['last_name'] = Str::upper($lastName);
308 81
    }
309
310
    /**
311
     * Get the `full_name` attribute.
312
     *
313
     * @return string
314
     */
315 6
    public function getFullNameAttribute()
316
    {
317 6
        return $this->first_name.' '.$this->last_name;
318
    }
319
320
    /**
321
     * Set the `password` attribute.
322
     *
323
     * @param  string  $password
324
     */
325 78
    public function setPasswordAttribute($password)
326
    {
327 78
        $this->attributes['password'] = bcrypt($password);
328 78
    }
329
330
    /* -----------------------------------------------------------------
331
     |  Main Methods
332
     | -----------------------------------------------------------------
333
     */
334
335
    /**
336
     * Activate the model.
337
     *
338
     * @param  bool  $save
339
     *
340
     * @return bool
341
     */
342 3
    public function activate($save = true)
343
    {
344 3
        event(new ActivatingUser($this));
345 3
        $result = $this->switchActive(true, $save);
346 3
        event(new ActivatedUser($this));
347
348 3
        return $result;
349
    }
350
351
    /**
352
     * Deactivate the model.
353
     *
354
     * @param  bool  $save
355
     *
356
     * @return bool
357
     */
358 3
    public function deactivate($save = true)
359
    {
360 3
        event(new DeactivatingUser($this));
361 3
        $result = $this->switchActive(false, $save);
362 3
        event(new DeactivatedUser($this));
363
364 3
        return $result;
365
    }
366
367
    /**
368
     * Attach a role to a user.
369
     *
370
     * @param  \Arcanesoft\Contracts\Auth\Models\Role|int  $role
371
     * @param  bool                                        $reload
372
     */
373 33
    public function attachRole($role, $reload = true)
374
    {
375 33
        if ($this->hasRole($role)) return;
376
377 33
        event(new AttachingRoleToUser($this, $role));
378 33
        $this->roles()->attach($role);
379 33
        event(new AttachedRoleToUser($this, $role));
380
381 33
        $this->loadRoles($reload);
382 33
    }
383
384
    /**
385
     * Sync the roles by its slugs.
386
     *
387
     * @param  array|\Illuminate\Support\Collection  $slugs
388
     * @param  bool                                  $reload
389
     *
390
     * @return array
391
     */
392 3
    public function syncRoles($slugs, $reload = true)
393
    {
394
        /** @var  \Illuminate\Database\Eloquent\Collection  $roles */
395 3
        $roles = app(RoleContract::class)->whereIn('slug', $slugs)->get();
396
397 3
        event(new SyncingUserWithRoles($this, $roles));
398 3
        $synced = $this->roles()->sync($roles->pluck('id'));
399 3
        event(new SyncedUserWithRoles($this, $roles, $synced));
400
401 3
        $this->loadRoles($reload);
402
403 3
        return $synced;
404
    }
405
406
    /**
407
     * Detach a role from a user.
408
     *
409
     * @param  \Arcanesoft\Contracts\Auth\Models\Role|int  $role
410
     * @param  bool                                        $reload
411
     *
412
     * @return int
413
     */
414 3
    public function detachRole($role, $reload = true)
415
    {
416 3
        event(new DetachingRoleFromUser($this, $role));
417 3
        $results = $this->roles()->detach($role);
418 3
        event(new DetachedRoleFromUser($this, $role, $results));
419
420 3
        $this->loadRoles($reload);
421
422 3
        return $results;
423
    }
424
425
    /**
426
     * Detach all roles from a user.
427
     *
428
     * @param  bool  $reload
429
     *
430
     * @return int
431
     */
432 3
    public function detachAllRoles($reload = true)
433
    {
434 3
        event(new DetachingRolesFromUser($this));
435 3
        $results = $this->roles()->detach();
436 3
        event(new DetachedRolesFromUser($this, $results));
437
438 3
        $this->loadRoles($reload);
439
440 3
        return $results;
441
    }
442
443
    /**
444
     * Confirm the unconfirmed user account by confirmation code.
445
     *
446
     * @param  string  $code
447
     *
448
     * @return \Arcanesoft\Contracts\Auth\Models\User
449
     *
450
     * @throws \Arcanedev\LaravelAuth\Exceptions\UserConfirmationException
451
     */
452 12
    public function findUnconfirmed($code)
453
    {
454
        /** @var  \Arcanesoft\Contracts\Auth\Models\User|null  $unconfirmed */
455 12
        $unconfirmed = static::unconfirmed($code)->first();
456
457 12
        if ( ! $unconfirmed instanceof self)
458 6
            throw (new UserConfirmationException)->setModel(static::class);
459
460 9
        return $unconfirmed;
461
    }
462
463
    /**
464
     * Confirm the new user account.
465
     *
466
     * @param  \Arcanesoft\Contracts\Auth\Models\User|string  $code
467
     *
468
     * @return \Arcanesoft\Contracts\Auth\Models\User
469
     */
470 6
    public function confirm($code)
471
    {
472 6
        if ($code instanceof self)
473 4
            $code = $code->confirmation_code;
474
475 6
        return (new UserConfirmator)->confirm(
476 6
            $this->findUnconfirmed($code)
477 2
        );
478
    }
479
480
    /**
481
     * Update the user's last activity.
482
     *
483
     * @param  bool  $save
484
     */
485 3
    public function updateLastActivity($save = true)
486
    {
487 3
        $this->forceFill(['last_activity' => Carbon::now()]);
488
489 3
        if ($save) $this->save();
490 3
    }
491
492
    /* -----------------------------------------------------------------
493
     |  Permission Check Methods
494
     | -----------------------------------------------------------------
495
     */
496
    /**
497
     * Check if the user has a permission.
498
     *
499
     * @param  string  $slug
500
     *
501
     * @return bool
502
     */
503 9
    public function may($slug)
504
    {
505
        return ! $this->permissions->filter(function (PermissionContract $permission) use ($slug) {
506 9
            return $permission->hasSlug($slug);
507 9
        })->isEmpty();
508
    }
509
510
    /**
511
     * Check if the user has at least one permission.
512
     *
513
     * @param  \Illuminate\Support\Collection|array  $permissions
514
     * @param  \Illuminate\Support\Collection        &$failed
515
     *
516
     * @return bool
517
     */
518 6
    public function mayOne($permissions, &$failed = null)
519
    {
520 6
        $permissions = is_array($permissions) ? collect($permissions) : $permissions;
521
522 6
        $failed = $permissions->reject(function ($permission) {
523 6
            return $this->may($permission);
524 6
        })->values();
525
526 6
        return $permissions->count() !== $failed->count();
527
    }
528
529
    /**
530
     * Check if the user has all permissions.
531
     *
532
     * @param  \Illuminate\Support\Collection|array  $permissions
533
     * @param  \Illuminate\Support\Collection        &$failed
534
     *
535
     * @return bool
536
     */
537 3
    public function mayAll($permissions, &$failed = null)
538
    {
539 3
        $this->mayOne($permissions, $failed);
540
541 3
        return $failed instanceof Collection ? $failed->isEmpty() : false;
542
    }
543
544
    /* -----------------------------------------------------------------
545
     |  Check Methods
546
     | -----------------------------------------------------------------
547
     */
548
549
    /**
550
     * Check if user is an administrator.
551
     *
552
     * @return bool
553
     */
554 12
    public function isAdmin()
555
    {
556 12
        return $this->is_admin;
557
    }
558
559
    /**
560
     * Check if user is a moderator.
561
     *
562
     * @return bool
563
     */
564 6
    public function isModerator()
565
    {
566
        // Override this method to give more privileges than members.
567 6
        return false;
568
    }
569
570
    /**
571
     * Check if user is a member.
572
     *
573
     * @return bool
574
     */
575 9
    public function isMember()
576
    {
577 9
        return ! $this->isAdmin();
578
    }
579
580
    /**
581
     * Check if user has a confirmed account.
582
     *
583
     * @return bool
584
     */
585 9
    public function isConfirmed()
586
    {
587 9
        return $this->is_confirmed;
588
    }
589
590
    /**
591
     * Check if user can be impersonated.
592
     *
593
     * @return bool
594
     */
595 3
    public function canBeImpersonated()
596
    {
597 3
        return $this->isMember();
598
    }
599
}
600