*/ #[Locked] public array $passkeys = []; public bool $showDeleteModal = false; #[Locked] public ?int $deletingPasskeyId = null; #[Locked] public string $deletingPasskeyName = ''; /** * Mount the component. */ public function mount(DisableTwoFactorAuthentication $disableTwoFactorAuthentication): void { $this->canManageTwoFactor = Features::canManageTwoFactorAuthentication(); if ($this->canManageTwoFactor) { if (Fortify::confirmsTwoFactorAuthentication() && is_null(auth()->user()->two_factor_confirmed_at)) { $disableTwoFactorAuthentication(auth()->user()); } $this->twoFactorEnabled = auth()->user()->hasEnabledTwoFactorAuthentication(); $this->requiresConfirmation = Features::optionEnabled(Features::twoFactorAuthentication(), 'confirm'); } $this->canManagePasskeys = Features::canManagePasskeys(); if ($this->canManagePasskeys) { $this->loadPasskeys(); } } /** * Update the password for the currently authenticated user. */ public function updatePassword(): void { try { $validated = $this->validate([ 'current_password' => $this->currentPasswordRules(), 'password' => $this->passwordRules(), ]); } catch (ValidationException $e) { $this->reset('current_password', 'password', 'password_confirmation'); throw $e; } Auth::user()->update([ 'password' => $validated['password'], ]); $this->reset('current_password', 'password', 'password_confirmation'); $this->toast()->success(__('Password updated.'))->send(); } /** * Load the user's passkeys. */ public function loadPasskeys(): void { $this->passkeys = Auth::user()->passkeys() ->select(['id', 'name', 'credential', 'created_at', 'last_used_at']) ->latest() ->get() ->map(fn ($passkey) => [ 'id' => $passkey->id, 'name' => $passkey->name, 'authenticator' => $passkey->authenticator, 'created_at_diff' => $passkey->created_at->diffForHumans(), 'last_used_at_diff' => $passkey->last_used_at?->diffForHumans(), ]) ->all(); } /** * Show the delete confirmation modal. */ public function confirmDelete(int $passkeyId): void { $passkey = Auth::user()->passkeys()->findOrFail($passkeyId); $this->deletingPasskeyId = $passkey->id; $this->deletingPasskeyName = $passkey->name; $this->showDeleteModal = true; } /** * Delete the passkey. */ public function deletePasskey(DeletePasskey $deletePasskey): void { if (! $this->deletingPasskeyId) { return; } $user = Auth::user(); $passkey = $user->passkeys()->findOrFail($this->deletingPasskeyId); $deletePasskey($user, $passkey); $this->closeDeleteModal(); $this->loadPasskeys(); } /** * Close the delete confirmation modal. */ public function closeDeleteModal(): void { $this->showDeleteModal = false; $this->deletingPasskeyId = null; $this->deletingPasskeyName = ''; } /** * Enable two-factor authentication for the user. */ public function enable(EnableTwoFactorAuthentication $enableTwoFactorAuthentication): void { $enableTwoFactorAuthentication(auth()->user()); if (! $this->requiresConfirmation) { $this->twoFactorEnabled = auth()->user()->hasEnabledTwoFactorAuthentication(); } $this->loadSetupData(); $this->showModal = true; } /** * Load the two-factor authentication setup data for the user. */ private function loadSetupData(): void { $user = auth()->user(); try { $this->qrCodeSvg = $user?->twoFactorQrCodeSvg(); $this->manualSetupKey = decrypt($user->two_factor_secret); } catch (Exception) { $this->addError('setupData', 'Failed to fetch setup data.'); $this->reset('qrCodeSvg', 'manualSetupKey'); } } /** * Show the two-factor verification step if necessary. */ public function showVerificationIfNecessary(): void { if ($this->requiresConfirmation) { $this->showVerificationStep = true; $this->resetErrorBag(); return; } $this->closeModal(); } /** * Confirm two-factor authentication for the user. */ public function confirmTwoFactor(ConfirmTwoFactorAuthentication $confirmTwoFactorAuthentication): void { $this->validate(); $confirmTwoFactorAuthentication(auth()->user(), $this->code); $this->closeModal(); $this->twoFactorEnabled = true; } /** * Reset two-factor verification state. */ public function resetVerification(): void { $this->reset('code', 'showVerificationStep'); $this->resetErrorBag(); } /** * Disable two-factor authentication for the user. */ public function disable(DisableTwoFactorAuthentication $disableTwoFactorAuthentication): void { $disableTwoFactorAuthentication(auth()->user()); $this->twoFactorEnabled = false; } /** * Close the two-factor authentication modal. */ public function closeModal(): void { $this->reset( 'code', 'manualSetupKey', 'qrCodeSvg', 'showModal', 'showVerificationStep', ); $this->resetErrorBag(); if (! $this->requiresConfirmation) { $this->twoFactorEnabled = auth()->user()->hasEnabledTwoFactorAuthentication(); } } /** * Get the current modal configuration state. * * @return array{title: string, description: string, buttonText: string} */ #[Computed] public function modalConfig(): array { if ($this->twoFactorEnabled) { return [ 'title' => __('Two-factor authentication enabled'), 'description' => __('Two-factor authentication is now enabled. Scan the QR code or enter the setup key in your authenticator app.'), 'buttonText' => __('Close'), ]; } if ($this->showVerificationStep) { return [ 'title' => __('Verify authentication code'), 'description' => __('Enter the 6-digit code from your authenticator app.'), 'buttonText' => __('Continue'), ]; } return [ 'title' => __('Enable two-factor authentication'), 'description' => __('To finish enabling two-factor authentication, scan the QR code or enter the setup key in your authenticator app.'), 'buttonText' => __('Continue'), ]; } }