*/ use HasApiTokens, HasFactory, Notifiable, SoftDeletes; protected $guarded = ['id']; protected static function booted(): void { static::creating(function (self $user) { if (empty($user->ulid)) { $user->ulid = \Illuminate\Support\Str::ulid(); } }); } /** * 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', 'two_factor_confirmed_at' => 'datetime', 'password' => 'hashed', ]; } public function workspaces(): HasMany { return $this->hasMany(\App\Domains\Workspace\Models\Workspace::class, 'owner_id'); } public function defaultWorkspace(): BelongsTo { return $this->belongsTo(\App\Domains\Workspace\Models\Workspace::class, 'default_workspace_id'); } public function workspaceMemberships(): HasMany { return $this->hasMany(\App\Domains\Workspace\Models\WorkspaceMember::class); } public function enableTwoFactor(string $secret): array { $recoveryCodes = collect(range(1, 8))->map(fn() => implode('-', [ strtoupper(substr(bin2hex(random_bytes(5)), 0, 5)), strtoupper(substr(bin2hex(random_bytes(5)), 0, 5)), ]))->all(); $this->update([ 'two_factor_secret' => encrypt($secret), 'two_factor_recovery' => encrypt(json_encode($recoveryCodes)), ]); return $recoveryCodes; } public function disableTwoFactor(): void { $this->update([ 'two_factor_secret' => null, 'two_factor_recovery' => null, 'two_factor_confirmed_at' => null, ]); } public function hasTwoFactorEnabled(): bool { return $this->two_factor_confirmed_at !== null; } public function verifyTwoFactor(string $code): bool { if (! $this->two_factor_secret) { return false; } $secret = decrypt($this->two_factor_secret); $google2fa = new Google2FA; return $google2fa->verifyKey($secret, $code) !== false; } }