*/ use HasFactory; use HasPdnEncryption; use HasRoles; use Notifiable; use SoftDeletes; protected $fillable = [ 'name', 'email', 'password', ]; protected $hidden = [ 'password', 'remember_token', 'mfa_secret', 'mfa_recovery_codes', ]; /** * Поля ПДн/секреты, шифруемые на уровне приложения (мера ЗНИ). * * @var array */ protected array $encrypted = [ 'mfa_secret', 'mfa_recovery_codes', ]; protected function casts(): array { return [ 'email_verified_at' => 'datetime', 'password' => 'hashed', 'password_changed_at' => 'datetime', 'mfa_confirmed_at' => 'datetime', 'last_login_at' => 'datetime', 'is_blocked' => 'boolean', ]; } /* |-------------------------------------------------------------------------- | Многофакторная аутентификация (ИАФ.4) |-------------------------------------------------------------------------- */ public function hasMfaEnabled(): bool { return $this->mfa_secret !== null && $this->mfa_confirmed_at !== null; } /** * @return array */ public function recoveryCodes(): array { $raw = $this->mfa_recovery_codes; return $raw ? (array) json_decode($raw, true) : []; } /** * @param array $codes */ public function setRecoveryCodes(array $codes): void { $this->mfa_recovery_codes = (string) json_encode(array_values($codes), JSON_UNESCAPED_UNICODE); } /* |-------------------------------------------------------------------------- | Парольная политика (ИАФ.3) |-------------------------------------------------------------------------- */ public function passwordExpired(): bool { $maxAge = (int) config('security.password.max_age_days'); if ($maxAge <= 0) { return false; } $changedAt = $this->password_changed_at ?? $this->created_at; return $changedAt === null || $changedAt->lt(now()->subDays($maxAge)); } /** * @return HasMany */ public function passwordHistories(): HasMany { return $this->hasMany(PasswordHistory::class); } /* |-------------------------------------------------------------------------- | Состояние учётной записи (ИАФ.2, УПД.1) |-------------------------------------------------------------------------- */ public function isBlocked(): bool { return (bool) $this->is_blocked; } }