Completed
Push — master ( 09d2e6...3ecb6c )
by ARCANEDEV
11s
created

User::isMember()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php namespace Arcanedev\LaravelAuth\Models;
2
3
use Arcanedev\LaravelAuth\Events\Users as UserEvents;
4
use Arcanedev\LaravelAuth\Exceptions\UserConfirmationException;
5
use Arcanedev\LaravelAuth\Models\Traits\Activatable;
6
use Arcanedev\LaravelAuth\Models\Traits\Roleable;
7
use Arcanedev\LaravelAuth\Services\SocialAuthenticator;
8
use Arcanedev\LaravelAuth\Services\UserConfirmator;
9
use Arcanesoft\Contracts\Auth\Models\Permission as PermissionContract;
10
use Arcanesoft\Contracts\Auth\Models\Role as RoleContract;
11
use Arcanesoft\Contracts\Auth\Models\User as UserContract;
12
use Carbon\Carbon;
13
use Illuminate\Auth\Authenticatable;
14
use Illuminate\Auth\Passwords\CanResetPassword;
15
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
16
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
17
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
18
use Illuminate\Database\Eloquent\SoftDeletes;
19
use Illuminate\Foundation\Auth\Access\Authorizable;
20
use Illuminate\Support\Str;
21
22
/**
23
 * Class     User
24
 *
25
 * @package  Arcanedev\LaravelAuth\Models
26
 * @author   ARCANEDEV <[email protected]>
27
 *
28
 * @property  int                                       id
29
 * @property  string                                    username
30
 * @property  string                                    first_name
31
 * @property  string                                    last_name
32
 * @property  string                                    full_name
33
 * @property  string                                    email
34
 * @property  string                                    password
35
 * @property  string                                    remember_token
36
 * @property  bool                                      is_admin
37
 * @property  bool                                      is_active
38
 * @property  bool                                      is_confirmed       (Optional)
39
 * @property  string                                    confirmation_code  (Optional)
40
 * @property  \Carbon\Carbon                            confirmed_at       (Optional)
41
 * @property  \Carbon\Carbon                            last_activity
42
 * @property  \Carbon\Carbon                            created_at
43
 * @property  \Carbon\Carbon                            updated_at
44
 * @property  \Carbon\Carbon                            deleted_at
45
 *
46
 * @property  \Illuminate\Database\Eloquent\Collection       roles
47
 * @property  \Illuminate\Support\Collection                 permissions
48
 * @property  \Arcanedev\LaravelAuth\Models\Pivots\RoleUser  pivot
49
 *
50
 * @method  static  bool                                   insert(array $values)
51
 * @method          \Illuminate\Database\Eloquent\Builder  unconfirmed(string $code)
52
 * @method          \Illuminate\Database\Eloquent\Builder  lastActive(int $minutes = null)
53
 */
54
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...
55
    extends AbstractModel
56
    implements UserContract, AuthenticatableContract, AuthorizableContract, CanResetPasswordContract
57
{
58
    /* ------------------------------------------------------------------------------------------------
59
     |  Traits
60
     | ------------------------------------------------------------------------------------------------
61
     */
62
    use Roleable,
63
        Authenticatable,
64
        Authorizable,
65
        CanResetPassword,
66
        Activatable,
67
        SoftDeletes;
68
69
    /* ------------------------------------------------------------------------------------------------
70
     |  Properties
71
     | ------------------------------------------------------------------------------------------------
72
     */
73
    /**
74
     * The attributes that are mass assignable.
75
     *
76
     * @var array
77
     */
78
    protected $fillable = [
79
        'username',
80
        'first_name',
81
        'last_name',
82
        'email',
83
        'password',
84
    ];
85
86
    /**
87
     * The attributes excluded from the model's JSON form.
88
     *
89
     * @var array
90
     */
91
    protected $hidden   = [
92
        'password',
93
        'remember_token',
94
        'confirmation_code',
95
    ];
96
97
    /**
98
     * The attributes that should be casted to native types.
99
     *
100
     * @var array
101
     */
102
    protected $casts = [
103
        'is_admin'     => 'boolean',
104
        'is_active'    => 'boolean',
105
        'is_confirmed' => 'boolean',
106
    ];
107
108
    /**
109
     * The attributes that should be mutated to dates.
110
     *
111
     * @var array
112
     */
113
    protected $dates = [
114
        'confirmed_at',
115
        'last_activity',
116
        'deleted_at',
117
    ];
118
119
    /* ------------------------------------------------------------------------------------------------
120
     |  Constructor
121
     | ------------------------------------------------------------------------------------------------
122
     */
123
    /**
124
     * Create a new Eloquent model instance.
125
     *
126
     * @param  array  $attributes
127
     */
128 225
    public function __construct(array $attributes = [])
129
    {
130 225
        parent::__construct($attributes);
131
132 225
        $this->setupModel();
133 225
    }
134
135
    /**
136
     * Setup the model.
137
     */
138 225
    protected function setupModel()
139
    {
140 225
        $this->setTable(config('laravel-auth.users.table', 'users'));
141
142 225
        if (SocialAuthenticator::isEnabled()) {
143 225
            $this->hidden   = array_merge($this->hidden, ['social_provider_id']);
144 225
            $this->fillable = array_merge($this->fillable, ['social_provider', 'social_provider_id']);
145
        }
146 225
    }
147
148
    /* ------------------------------------------------------------------------------------------------
149
     |  Relationships
150
     | ------------------------------------------------------------------------------------------------
151
     */
152
    /**
153
     * User belongs to many roles.
154
     *
155
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
156
     */
157 39
    public function roles()
158
    {
159
        return $this
160 39
            ->belongsToMany(
161 39
                config('laravel-auth.roles.model', Role::class),
162 39
                $this->getPrefix().config('laravel-auth.role-user.table', 'role_user')
163
            )
164 39
            ->using(Pivots\RoleUser::class)
165 39
            ->withTimestamps();
166
    }
167
168
    /**
169
     * Get all user permissions.
170
     *
171
     * @return \Illuminate\Support\Collection
172
     */
173 9
    public function getPermissionsAttribute()
174
    {
175 9
        return $this->roles->pluck('permissions')
176 9
            ->flatten()
177
            ->unique(function (PermissionContract $permission) {
178 9
                return $permission->getKey();
179 9
            });
180
    }
181
182
    /* ------------------------------------------------------------------------------------------------
183
     |  Scopes
184
     | ------------------------------------------------------------------------------------------------
185
     */
186
    /**
187
     * Scope unconfirmed users by code.
188
     *
189
     * @param  \Illuminate\Database\Eloquent\Builder  $query
190
     * @param  string                                 $code
191
     *
192
     * @return \Illuminate\Database\Eloquent\Builder
193
     */
194 12
    public function scopeUnconfirmed($query, $code)
195
    {
196 12
        return $query->where('is_confirmed', false)
197 12
                     ->where('confirmation_code', $code)
198 12
                     ->whereNull('confirmed_at');
199
    }
200
201
    /**
202
     * Scope last active users.
203
     *
204
     * @param  \Illuminate\Database\Eloquent\Builder  $query
205
     * @param  int|null                               $minutes
206
     *
207
     * @return \Illuminate\Database\Eloquent\Builder
208
     */
209 3
    public function scopeLastActive($query, $minutes = null)
210
    {
211 3
        $minutes = $minutes ?: config('laravel_auth.track-activity.minutes', 5);
212
213 3
        $date = Carbon::now()->subMinutes($minutes);
214
215 3
        return $query->where('last_activity', '>=', $date->toDateTimeString());
216
    }
217
218
    /* ------------------------------------------------------------------------------------------------
219
     |  Getters & Setters
220
     | ------------------------------------------------------------------------------------------------
221
     */
222
    /**
223
     * Set the `username` attribute.
224
     *
225
     * @param  string  $username
226
     */
227 69
    public function setUsernameAttribute($username)
228
    {
229 69
        $this->attributes['username'] = $this->slugify($username);
230 69
    }
231
232
    /**
233
     * Get the `full_name` attribute.
234
     *
235
     * @return string
236
     */
237 3
    public function getFullNameAttribute()
238
    {
239 3
        return $this->first_name.' '.$this->last_name;
240
    }
241
242
    /**
243
     * Set the `password` attribute.
244
     *
245
     * @param  string  $password
246
     */
247 69
    public function setPasswordAttribute($password)
248
    {
249 69
        $this->attributes['password'] = bcrypt($password);
250 69
    }
251
252
    /* -----------------------------------------------------------------
253
     |  Main Methods
254
     | -----------------------------------------------------------------
255
     */
256
    /**
257
     * Attach a role to a user.
258
     *
259
     * @param  \Arcanesoft\Contracts\Auth\Models\Role|int  $role
260
     * @param  bool                                        $reload
261
     */
262 27
    public function attachRole($role, $reload = true)
263
    {
264 27
        if ($this->hasRole($role)) return;
265
266 27
        event(new UserEvents\AttachingRoleToUser($this, $role));
267 27
        $this->roles()->attach($role);
268 27
        event(new UserEvents\AttachedRoleToUser($this, $role));
269
270 27
        $this->loadRoles($reload);
271 27
    }
272
273
    /**
274
     * Sync the roles by its slugs.
275
     *
276
     * @param  array|\Illuminate\Support\Collection  $slugs
277
     * @param  bool                                  $reload
278
     *
279
     * @return array
280
     */
281 3
    public function syncRoles($slugs, $reload = true)
282
    {
283
        /** @var  \Illuminate\Database\Eloquent\Collection  $roles */
284 3
        $roles = app(RoleContract::class)->whereIn('slug', $slugs)->get();
285
286 3
        event(new UserEvents\SyncingUserWithRoles($this, $roles));
287 3
        $synced = $this->roles()->sync($roles->pluck('id'));
288 3
        event(new UserEvents\SyncedUserWithRoles($this, $roles, $synced));
289
290 3
        $this->loadRoles($reload);
291
292 3
        return $synced;
293
    }
294
295
    /**
296
     * Detach a role from a user.
297
     *
298
     * @param  \Arcanesoft\Contracts\Auth\Models\Role|int  $role
299
     * @param  bool                                        $reload
300
     *
301
     * @return int
302
     */
303 3
    public function detachRole($role, $reload = true)
304
    {
305 3
        event(new UserEvents\DetachingRole($this, $role));
306 3
        $results = $this->roles()->detach($role);
307 3
        event(new UserEvents\DetachedRole($this, $role, $results));
308
309 3
        $this->loadRoles($reload);
310
311 3
        return $results;
312
    }
313
314
    /**
315
     * Detach all roles from a user.
316
     *
317
     * @param  bool  $reload
318
     *
319
     * @return int
320
     */
321 3
    public function detachAllRoles($reload = true)
322
    {
323 3
        event(new UserEvents\DetachingRoles($this));
324 3
        $results = $this->roles()->detach();
325 3
        event(new UserEvents\DetachedRoles($this, $results));
326
327 3
        $this->loadRoles($reload);
328
329 3
        return $results;
330
    }
331
332
    /**
333
     * Confirm the unconfirmed user account by confirmation code.
334
     *
335
     * @param  string  $code
336
     *
337
     * @return \Arcanesoft\Contracts\Auth\Models\User
338
     *
339
     * @throws \Arcanedev\LaravelAuth\Exceptions\UserConfirmationException
340
     */
341 12
    public function findUnconfirmed($code)
342
    {
343
        /** @var  \Arcanesoft\Contracts\Auth\Models\User|null  $unconfirmed */
344 12
        $unconfirmed = static::unconfirmed($code)->first();
345
346 12
        if ( ! $unconfirmed instanceof self)
347 3
            throw (new UserConfirmationException)->setModel(static::class);
348
349 9
        return $unconfirmed;
350
    }
351
352
    /**
353
     * Confirm the new user account.
354
     *
355
     * @param  \Arcanesoft\Contracts\Auth\Models\User|string  $code
356
     *
357
     * @return \Arcanesoft\Contracts\Auth\Models\User
358
     */
359 6
    public function confirm($code)
360
    {
361 6
        if ($code instanceof self)
362 3
            $code = $code->confirmation_code;
363
364 6
        return (new UserConfirmator)->confirm(
365 6
            $this->findUnconfirmed($code)
366
        );
367
    }
368
369
    /**
370
     * Update the user's last activity.
371
     *
372
     * @param  bool  $save
373
     */
374 6
    public function updateLastActivity($save = true)
375
    {
376 6
        $this->forceFill(['last_activity' => Carbon::now()]);
377
378 6
        if ($save) $this->save();
379 6
    }
380
381
    /* -----------------------------------------------------------------
382
     |  Permission Check Methods
383
     | -----------------------------------------------------------------
384
     */
385
    /**
386
     * Check if the user has a permission.
387
     *
388
     * @param  string  $slug
389
     *
390
     * @return bool
391
     */
392 9
    public function may($slug)
393
    {
394 9
        return ! $this->permissions->filter->hasSlug($slug)->isEmpty();
395
    }
396
397
    /**
398
     * Check if the user has at least one permission.
399
     *
400
     * @param  \Illuminate\Support\Collection|array  $permissions
401
     * @param  \Illuminate\Support\Collection        &$failed
402
     *
403
     * @return bool
404
     */
405 6
    public function mayOne($permissions, &$failed = null)
406
    {
407 6
        $permissions = is_array($permissions) ? collect($permissions) : $permissions;
408
409 6
        $failed = $permissions->reject(function ($permission) {
410 6
            return $this->may($permission);
411 6
        })->values();
412
413 6
        return $permissions->count() !== $failed->count();
414
    }
415
416
    /**
417
     * Check if the user has all permissions.
418
     *
419
     * @param  \Illuminate\Support\Collection|array  $permissions
420
     * @param  \Illuminate\Support\Collection        &$failed
421
     *
422
     * @return bool
423
     */
424 3
    public function mayAll($permissions, &$failed = null)
425
    {
426 3
        $this->mayOne($permissions, $failed);
427
428 3
        return $failed instanceof \Illuminate\Support\Collection
429 3
            ? $failed->isEmpty()
430 3
            : false;
431
    }
432
433
    /* -----------------------------------------------------------------
434
     |  Check Methods
435
     | -----------------------------------------------------------------
436
     */
437
    /**
438
     * Check if user is an administrator.
439
     *
440
     * @return bool
441
     */
442 18
    public function isAdmin()
443
    {
444 18
        return $this->is_admin;
445
    }
446
447
    /**
448
     * Check if user is a moderator.
449
     *
450
     * @return bool
451
     */
452 6
    public function isModerator()
453
    {
454
        // Override this method to give more privileges than members.
455 6
        return false;
456
    }
457
458
    /**
459
     * Check if user is a member.
460
     *
461
     * @return bool
462
     */
463 9
    public function isMember()
464
    {
465 9
        return ! $this->isAdmin();
466
    }
467
468
    /**
469
     * Check if user has a confirmed account.
470
     *
471
     * @return bool
472
     */
473 9
    public function isConfirmed()
474
    {
475 9
        return $this->is_confirmed;
476
    }
477
478
    /**
479
     * Check if user can be impersonated.
480
     *
481
     * @return bool
482
     */
483 3
    public function canBeImpersonated()
484
    {
485 3
        return $this->isMember();
486
    }
487
488
    /* ------------------------------------------------------------------------------------------------
489
     |  Other Functions
490
     | ------------------------------------------------------------------------------------------------
491
     */
492
    /**
493
     * Slugify the value.
494
     *
495
     * @param  string  $value
496
     *
497
     * @return string
498
     */
499 69
    protected function slugify($value)
500
    {
501 69
        return Str::slug($value, config('laravel-auth.users.slug-separator', '.'));
502
    }
503
}
504