<?php namespace App\Models; use App\Enums\UserRole; use App\Traits\HasTimezoneTimestamps; use Carbon\Carbon; use Filament\Models\Contracts\FilamentUser; use Filament\Panel; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Illuminate\Support\Collection; use Laravel\Fortify\TwoFactorAuthenticatable; use Laravel\Sanctum\HasApiTokens; /** * @property int $id * @property string $name * @property string $email * @property string $password * @property string $profile_photo_path * @property string $two_factor_recovery_codes * @property string $two_factor_secret * @property Collection<int, SshKey> $sshKeys * @property Collection<int, SourceControl> $sourceControls * @property Collection<int, ServerProvider> $serverProviders * @property Collection<int, Server> $servers * @property Collection<int, Script> $scripts * @property Collection<int, StorageProvider> $storageProviders * @property Collection<int, StorageProvider> $connectedStorageProviders * @property Collection<int, PersonalAccessToken> $tokens * @property string $profile_photo_url * @property string $timezone * @property ?int $current_project_id * @property ?Project $currentProject * @property Collection<int, Project> $projects * @property string $role * @property Carbon $created_at * @property Carbon $updated_at */ class User extends Authenticatable implements FilamentUser { use HasApiTokens; /** @use HasFactory<\Database\Factories\UserFactory> */ use HasFactory; use HasTimezoneTimestamps; use Notifiable; use TwoFactorAuthenticatable; protected $fillable = [ 'name', 'email', 'password', 'timezone', 'current_project_id', 'role', ]; protected $hidden = [ 'password', 'remember_token', 'two_factor_recovery_codes', 'two_factor_secret', ]; protected $appends = [ ]; /** * @return HasMany<Server, covariant $this> */ public function servers(): HasMany { return $this->hasMany(Server::class); } /** * @return HasMany<SshKey, covariant $this> */ public function sshKeys(): HasMany { return $this->hasMany(SshKey::class); } /** * @return HasMany<SourceControl, covariant $this> */ public function sourceControls(): HasMany { return $this->hasMany(SourceControl::class); } /** * @return HasMany<ServerProvider, covariant $this> */ public function serverProviders(): HasMany { return $this->hasMany(ServerProvider::class); } /** * @return HasOne<SourceControl, covariant $this> */ public function sourceControl(string $provider): HasOne { return $this->hasOne(SourceControl::class)->where('provider', $provider); } /** * @return HasMany<StorageProvider, covariant $this> */ public function storageProviders(): HasMany { return $this->hasMany(StorageProvider::class); } /** * @return HasOne<StorageProvider, covariant $this> */ public function storageProvider(string $provider): HasOne { return $this->hasOne(StorageProvider::class)->where('provider', $provider); } /** * @return Builder<Project>|BelongsToMany<Project, covariant $this> */ public function allProjects(): Builder|BelongsToMany { if ($this->isAdmin()) { return Project::query(); } return $this->projects(); } /** * @return BelongsToMany<Project, covariant $this> */ public function projects(): BelongsToMany { return $this->belongsToMany(Project::class, 'user_project') ->withTimestamps(); } /** * @return HasOne<Project, covariant $this> */ public function currentProject(): HasOne { return $this->HasOne(Project::class, 'id', 'current_project_id'); } public function createDefaultProject(): Project { /** @var ?Project $project */ $project = $this->projects()->first(); if (! $project) { $project = new Project; $project->name = 'default'; $project->save(); $project->users()->attach($this->id); } $this->current_project_id = $project->id; $this->save(); return $project; } public function isAdmin(): bool { return $this->role === UserRole::ADMIN; } /** * @return HasMany<Script, covariant $this> */ public function scripts(): HasMany { return $this->hasMany(Script::class); } /** * @return Builder<Server> */ public function allServers(): Builder { /** @var Builder<Server> $query */ $query = Server::query(); return $query->whereHas('project', function (Builder $query): void { $query->whereHas('users', function ($query): void { $query->where('user_id', $this->id); }); }); } public function canAccessPanel(Panel $panel): bool { return true; } }