Files
SealShare/resources/views/pages/settings/two-factor/⚡recovery-codes.blade.php
T
Andreas Reinhold / reiniandClaude Opus 5 c4a17b65c8 Move SealShare onto Livewire Material
Replaces maryUI and daisyUI with nonameweb/livewire-material: the Vibrant
indigo scheme, a system/light/dark theme under sealshare-theme, one top
app bar with the account menu, the upload drop zone and link-ready
moments, M3 fields, dialogs instead of wire:confirm, snackbars instead of
flashed messages, a sortable admin table, and the starter-kit cleanup.
Docker builds assets after Composer; CI drops the Flux step.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V9NnLxnPp8vaaurb3Z1MFy
2026-09-13 10:49:38 +02:00

93 lines
3.5 KiB
PHP

<?php
use Laravel\Fortify\Actions\GenerateNewRecoveryCodes;
use Livewire\Attributes\Locked;
use Livewire\Component;
new class extends Component {
#[Locked]
public array $recoveryCodes = [];
/**
* Mount the component.
*/
public function mount(): void
{
$this->loadRecoveryCodes();
}
/**
* Generate new recovery codes for the user.
*/
public function regenerateRecoveryCodes(GenerateNewRecoveryCodes $generateNewRecoveryCodes): void
{
$generateNewRecoveryCodes(auth()->user());
$this->loadRecoveryCodes();
}
/**
* Load the recovery codes for the user.
*/
private function loadRecoveryCodes(): void
{
$user = auth()->user();
if ($user->hasEnabledTwoFactorAuthentication() && $user->two_factor_recovery_codes) {
try {
$this->recoveryCodes = json_decode(decrypt($user->two_factor_recovery_codes), true);
} catch (Exception) {
$this->addError('recoveryCodes', 'Failed to load recovery codes');
$this->recoveryCodes = [];
}
}
}
}; ?>
<x-card variant="outlined" wire:cloak x-data="{ showRecoveryCodes: false }">
<div class="grid gap-4">
<div>
<div class="flex items-center gap-2">
<x-icon name="lock" class="size-5 text-on-surface-variant" />
<h3 class="type-title-md">{{ __('2FA Recovery Codes') }}</h3>
</div>
<p class="mt-1 type-body-md text-on-surface-variant">
{{ __('Recovery codes let you regain access if you lose your 2FA device. Store them in a secure password manager.') }}
</p>
</div>
<div class="flex flex-wrap items-center gap-2">
<span x-show="! showRecoveryCodes" class="inline-flex">
<x-button icon="visibility" :label="__('View Recovery Codes')" variant="tonal" x-on:click="showRecoveryCodes = true" />
</span>
<span x-show="showRecoveryCodes" x-cloak class="inline-flex">
<x-button icon="visibility_off" :label="__('Hide Recovery Codes')" variant="tonal" x-on:click="showRecoveryCodes = false" />
</span>
@if (filled($recoveryCodes))
<span x-show="showRecoveryCodes" x-cloak class="inline-flex">
<x-button icon="refresh" :label="__('Regenerate Codes')" variant="outlined" wire:click="regenerateRecoveryCodes" />
</span>
@endif
</div>
<div x-show="showRecoveryCodes" x-cloak id="recovery-codes-section" class="grid gap-3">
@error('recoveryCodes')
<x-alert color="error">{{ $message }}</x-alert>
@enderror
@if (filled($recoveryCodes))
<div class="grid gap-1 rounded-corner-md bg-surface-container-highest p-4 font-mono type-body-md" role="list" aria-label="{{ __('Recovery codes') }}">
@foreach ($recoveryCodes as $code)
<div role="listitem" class="select-text" wire:loading.class="animate-pulse opacity-50">{{ $code }}</div>
@endforeach
</div>
<p class="type-body-sm text-on-surface-variant">
{{ __('Each recovery code can be used once to access your account and will be removed after use. If you need more, click Regenerate Codes above.') }}
</p>
@endif
</div>
</div>
</x-card>