*/ use HasApiTokens, HasFactory, Notifiable, HasUuids; /** * The attributes that are mass assignable. * * @var list */ protected $fillable = [ 'name', 'email', 'avatar', 'oidc_id', ]; /** * The attributes that should be hidden for serialization. * * @var list */ protected $hidden = [ 'password', 'remember_token', ]; /** * Get the attributes that should be cast. * * @return array */ protected function casts(): array { return [ 'email_verified_at' => 'datetime', 'password' => 'hashed', ]; } public function roles() { return $this->belongsToMany(Role::class)->withTimestamps(); } public function permissions() { return $this->belongsToMany(Permission::class)->withPivot('granted')->withTimestamps(); } public function hasRole($role) { if (is_string($role)) { return $this->roles->contains('name', $role); } return $this->roles->contains($role); } public function hasAnyRole($roles) { if (is_array($roles)) { return $this->roles->whereIn('name', $roles)->isNotEmpty(); } return $this->hasRole($roles); } public function hasPermission($permission) { // Check direct permissions if ($this->hasDirectPermission($permission)) { return true; } // Check role-based permissions return $this->hasRolePermission($permission); } private function hasDirectPermission($permission) { // Check exact match with granted if ($this->permissions->where('pivot.granted', true)->contains('name', $permission)) { return true; } // Check wildcard permissions with granted $wildcardPermissions = $this->permissions->where('is_wildcard', true)->where('pivot.granted', true); foreach ($wildcardPermissions as $wildcardPermission) { if ($wildcardPermission->matches($permission)) { return true; } } return false; } private function hasRolePermission($permission) { foreach ($this->roles as $role) { if ($role->hasPermission($permission)) { return true; } } return false; } public function assignRole($role) { if (is_string($role)) { $role = Role::where('name', $role)->firstOrFail(); } $this->roles()->syncWithoutDetaching([$role->id]); return $this; } public function removeRole($role) { if (is_string($role)) { $role = Role::where('name', $role)->firstOrFail(); } $this->roles()->detach($role->id); return $this; } public function givePermission($permission) { if (is_string($permission)) { $permission = Permission::where('name', $permission)->firstOrFail(); } $this->permissions()->syncWithoutDetaching([$permission->id => ['granted' => true]]); return $this; } public function revokePermission($permission) { if (is_string($permission)) { $permission = Permission::where('name', $permission)->firstOrFail(); } $this->permissions()->updateExistingPivot($permission->id, ['granted' => false]); return $this; } }