Add 2fa setup

This commit is contained in:
Lance Pioch 2024-05-31 01:26:28 -04:00
parent aa82c6dd04
commit ef1a208b95

View File

@ -2,10 +2,12 @@
namespace App\Filament\Resources\UserResource\Pages; namespace App\Filament\Resources\UserResource\Pages;
use App\Exceptions\Service\User\TwoFactorAuthenticationTokenInvalid;
use App\Facades\Activity; use App\Facades\Activity;
use App\Models\ActivityLog; use App\Models\ActivityLog;
use App\Models\ApiKey; use App\Models\ApiKey;
use App\Models\User; use App\Models\User;
use App\Services\Users\ToggleTwoFactorService;
use App\Services\Users\TwoFactorSetupService; use App\Services\Users\TwoFactorSetupService;
use chillerlan\QRCode\Common\EccLevel; use chillerlan\QRCode\Common\EccLevel;
use chillerlan\QRCode\Common\Version; use chillerlan\QRCode\Common\Version;
@ -22,6 +24,7 @@ use Filament\Forms\Components\TagsInput;
use Filament\Forms\Components\Tabs\Tab; use Filament\Forms\Components\Tabs\Tab;
use Filament\Forms\Components\TextInput; use Filament\Forms\Components\TextInput;
use Filament\Forms\Get; use Filament\Forms\Get;
use Filament\Notifications\Notification;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
use Illuminate\Support\HtmlString; use Illuminate\Support\HtmlString;
@ -99,12 +102,20 @@ class EditProfile extends \Filament\Pages\Auth\EditProfile
if ($this->getUser()->use_totp) { if ($this->getUser()->use_totp) {
return [ return [
Placeholder::make('2FA already enabled!'), Placeholder::make('2fa-already-enabled')
->label('Two Factor Authentication is currently enabled!'),
TextInput::make('2fa-disable-code')
->label('Disable 2FA')
->helperText('Enter your current 2FA code to disable Two Factor Authentication'),
]; ];
} }
$setupService = app(TwoFactorSetupService::class); $setupService = app(TwoFactorSetupService::class);
['image_url_data' => $url] = $setupService->handle($this->getUser()); ['image_url_data' => $url, 'secret' => $secret] = cache()->remember(
'current-two-factor-state',
now()->addMinutes(5), fn () =>
$setupService->handle($this->getUser())
);
$options = new QROptions([ $options = new QROptions([
'svgLogo' => public_path('pelican.svg'), 'svgLogo' => public_path('pelican.svg'),
@ -149,7 +160,15 @@ class EditProfile extends \Filament\Pages\Auth\EditProfile
->content(fn () => new HtmlString(" ->content(fn () => new HtmlString("
<div style='width: 300px'>$image</div> <div style='width: 300px'>$image</div>
")) "))
->default('asdfasdf'), ->helperText($secret),
TextInput::make('2facode')
->requiredWith('2fapassword')
->helperText('Scan the QR code above using your two-step authentication app, then enter the code generated.'),
TextInput::make('2fapassword')
->requiredWith('2facode')
->currentPassword()
->password()
->helperText('Enter your current password to verify.'),
]; ];
}), }),
@ -235,4 +254,40 @@ class EditProfile extends \Filament\Pages\Auth\EditProfile
), ),
]; ];
} }
protected function handleRecordUpdate($record, $data): \Illuminate\Database\Eloquent\Model
{
if ($token = $data['2facode'] ?? null) {
/** @var ToggleTwoFactorService $service */
$service = resolve(ToggleTwoFactorService::class);
$service->handle($record, $token, true);
}
if ($token = $data['2fa-disable-code'] ?? null) {
/** @var ToggleTwoFactorService $service */
$service = resolve(ToggleTwoFactorService::class);
$service->handle($record, $token, false);
cache()->forget('current-two-factor-state');
}
return parent::handleRecordUpdate($record, $data);
}
public function exception($e, $stopPropagation): void
{
if ($e instanceof TwoFactorAuthenticationTokenInvalid) {
Notification::make()
->title('Invalid 2FA Code')
->body($e->getMessage())
->color('danger')
->icon('tabler-2fa')
->danger()
->send();
$stopPropagation();
}
}
} }