*/ use HasFactory, Notifiable, TwoFactorAuthenticatable; /** * @var list */ protected $appends = [ 'avatar', ]; /** * @var array */ protected $attributes = [ 'avatar_is_generated' => false, ]; protected static function booted(): void { static::deleting(function (self $user): void { app(UpdateUserAvatar::class)->delete($user); $user->permissionAssignments()->delete(); }); } /** * Get the attributes that should be cast. * * @return array */ protected function casts(): array { return [ 'avatar_is_generated' => 'bool', 'email_verified_at' => 'datetime', 'must_change_password_on_next_login' => 'bool', 'password' => 'hashed', 'two_factor_confirmed_at' => 'datetime', ]; } public function hasUploadedAvatar(): bool { return filled($this->avatar_path) && ! $this->avatar_is_generated; } /** * @return Attribute */ protected function avatar(): Attribute { return Attribute::get( fn (): ?string => filled($this->avatar_path) ? Storage::disk('public')->url($this->avatar_path) : null, ); } public function permissionAssignments(): MorphMany { return $this->morphMany(PermissionAssignment::class, 'assignee'); } public function teams(): BelongsToMany { return $this->belongsToMany(Team::class) ->withTimestamps(); } public function gitConnections(): HasMany { return $this->hasMany(UserGitConnection::class) ->orderBy('provider') ->orderBy('base_url'); } public function userApplications(): HasMany { return $this->hasMany(UserApplication::class) ->orderBy('name') ->orderBy('id'); } public function assignedTickets(): HasMany { return $this->hasMany(Ticket::class, 'assignee_user_id'); } public function authoredTickets(): HasMany { return $this->hasMany(Ticket::class, 'author_user_id'); } public function scopeVisibleToProject(Builder $query, Project $project): Builder { $permissionService = app(PermissionService::class); $allowedUserIds = User::query() ->select('id') ->cursor() ->filter(fn (User $candidate) => $permissionService->allows( $candidate, Permission::ProjectRead, $project )) ->pluck('id') ->all(); return $query->whereKey($allowedUserIds); } }