*/ use HasFactory, HasRoles, Notifiable, TwoFactorAuthenticatable; /** * The attributes that are mass assignable. * * @var list */ protected $fillable = [ 'name', 'email', 'password', 'email_verified_at', ]; /** * The attributes that should be hidden for serialization. * * @var list */ protected $hidden = [ 'password', 'remember_token', 'app_authentication_secret', 'app_authentication_recovery_codes', ]; /** * Get the attributes that should be cast. * * @return array */ protected function casts(): array { return [ 'email_verified_at' => 'datetime', 'password' => 'hashed', 'app_authentication_secret' => 'encrypted', 'app_authentication_recovery_codes' => 'encrypted:array', 'has_email_authentication' => 'boolean', ]; } /** * Get the user's initials */ public function initials(): string { return Str::of($this->name) ->explode(' ') ->take(2) ->map(fn ($word) => Str::substr($word, 0, 1)) ->implode(''); } public function canAccessPanel(Panel $panel): bool { return $this->hasPermissionTo('manage panels'); } public function getAppAuthenticationSecret(): ?string { return $this->app_authentication_secret; } public function saveAppAuthenticationSecret(?string $secret): void { $this->app_authentication_secret = $secret; $this->save(); } public function getAppAuthenticationHolderName(): string { return $this->email; } public function getAppAuthenticationRecoveryCodes(): ?array { return $this->app_authentication_recovery_codes; } public function saveAppAuthenticationRecoveryCodes(?array $codes): void { $this->app_authentication_recovery_codes = $codes; $this->save(); } public function hasEmailAuthentication(): bool { return $this->has_email_authentication; } public function toggleEmailAuthentication(bool $condition): void { $this->has_email_authentication = $condition; $this->save(); } // ─── Tier Checking Helpers ─────────────────────────────────── public function isFree(): bool { return $this->hasRole('free'); } public function isPro(): bool { return $this->hasRole('pro'); } public function isEnterprise(): bool { return $this->hasRole('enterprise'); } public function isAdmin(): bool { return $this->hasRole('admin'); } /** * Returns the domain `allowed_types` values this user's tier can access. * Used by Domain::scopeAccessibleBy() to filter domains. * * Mapping: * free → ['public'] * pro → ['public', 'custom', 'premium'] * enterprise → ['public', 'custom', 'premium', 'private'] * admin → ['public', 'custom', 'premium', 'private'] * * @return array */ public function allowedDomainTypes(): array { return match (true) { $this->isAdmin() => ['public', 'custom', 'premium', 'private'], $this->isEnterprise() => ['public', 'custom', 'premium', 'private'], $this->isPro() => ['public', 'custom', 'premium'], default => ['public'], // free or no role }; } /** * Domain types accessible by guest (non-authenticated) users. * Called when auth()->user() is null. * * @return array */ public static function guestDomainTypes(): array { return ['public']; } /** * Human-readable tier label for sidebar display. * Returns UPPERCASE string like "FREE", "PRO", "ADMIN". */ public function tierLabel(): string { return match (true) { $this->isAdmin() => 'ADMIN', $this->isEnterprise() => 'ENTERPRISE', $this->isPro() => 'PRO', default => 'FREE', }; } // ─── Eloquent Scopes ───────────────────────────────────────── /** * Scope to users with the 'free' Spatie role. * Usage: User::free()->get() */ public function scopeFree(Builder $query): Builder { return $query->role('free'); } /** * Scope to users with the 'pro' Spatie role. * Usage: User::pro()->get() */ public function scopePro(Builder $query): Builder { return $query->role('pro'); } /** * Scope to users with the 'enterprise' Spatie role. * Usage: User::enterprise()->get() */ public function scopeEnterprise(Builder $query): Builder { return $query->role('enterprise'); } }