mirror of
https://github.com/vitodeploy/vito.git
synced 2025-04-19 09:51:37 +00:00
Two factor (#383)
This commit is contained in:
parent
d4ec4c66ed
commit
1b741070b3
@ -3,6 +3,7 @@
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Http\Middleware\HasProjectMiddleware;
|
||||
use App\Web\Pages\Login;
|
||||
use App\Web\Pages\Settings\Profile;
|
||||
use App\Web\Pages\Settings\Projects\Widgets\SelectProject;
|
||||
use Exception;
|
||||
@ -111,7 +112,7 @@ public function panel(Panel $panel): Panel
|
||||
'profile' => MenuItem::make()
|
||||
->url(fn (): string => Profile\Index::getUrl()),
|
||||
])
|
||||
->login()
|
||||
->login(Login::class)
|
||||
->spa()
|
||||
->globalSearchKeyBindings(['command+k', 'ctrl+k'])
|
||||
->sidebarCollapsibleOnDesktop()
|
||||
|
143
app/Web/Pages/Login.php
Normal file
143
app/Web/Pages/Login.php
Normal file
@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
namespace App\Web\Pages;
|
||||
|
||||
use App\Models\User;
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Facades\Filament;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Http\Responses\Auth\Contracts\LoginResponse;
|
||||
use Filament\Support\Facades\FilamentView;
|
||||
use Filament\View\PanelsRenderHook;
|
||||
use Illuminate\Support\Facades\Blade;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Laravel\Fortify\Http\Requests\TwoFactorLoginRequest;
|
||||
|
||||
class Login extends \Filament\Pages\Auth\Login
|
||||
{
|
||||
public function mount(): void
|
||||
{
|
||||
if (Filament::auth()->check()) {
|
||||
redirect()->intended(Filament::getUrl());
|
||||
}
|
||||
|
||||
$this->initTwoFactor();
|
||||
|
||||
$this->form->fill();
|
||||
}
|
||||
|
||||
public function logoutAction(): Action
|
||||
{
|
||||
return Action::make('logout')
|
||||
->label('Logout')
|
||||
->color('danger')
|
||||
->link()
|
||||
->action(function () {
|
||||
Filament::auth()->logout();
|
||||
|
||||
session()->forget('login.id');
|
||||
|
||||
$this->redirect(Filament::getLoginUrl());
|
||||
});
|
||||
}
|
||||
|
||||
protected function getForms(): array
|
||||
{
|
||||
if (request()->session()->has('login.id')) {
|
||||
return [
|
||||
'form' => $this->form(
|
||||
$this->makeForm()
|
||||
->schema([
|
||||
TextInput::make('code')
|
||||
->label('2FA Code')
|
||||
->autofocus(),
|
||||
TextInput::make('recovery_code')
|
||||
->label('Recovery Code')
|
||||
->autofocus(),
|
||||
])
|
||||
->statePath('data'),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
return parent::getForms();
|
||||
}
|
||||
|
||||
public function authenticate(): ?LoginResponse
|
||||
{
|
||||
if (request()->session()->has('login.id')) {
|
||||
return $this->confirmTwoFactor();
|
||||
}
|
||||
|
||||
$loginResponse = parent::authenticate();
|
||||
|
||||
/** @var ?User $user */
|
||||
$user = Filament::auth()->getUser();
|
||||
if ($user && $user->two_factor_secret) {
|
||||
Filament::auth()->logout();
|
||||
|
||||
request()->session()->put([
|
||||
'login.id' => $user->getKey(),
|
||||
'login.remember' => $this->data['remember'] ?? false,
|
||||
]);
|
||||
|
||||
$this->redirect(Filament::getLoginUrl());
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return $loginResponse;
|
||||
}
|
||||
|
||||
private function confirmTwoFactor(): ?LoginResponse
|
||||
{
|
||||
$request = TwoFactorLoginRequest::createFrom(request())->merge([
|
||||
'code' => $this->data['code'],
|
||||
'recovery_code' => $this->data['recovery_code'],
|
||||
]);
|
||||
|
||||
/** @var ?User $user */
|
||||
$user = $request->challengedUser();
|
||||
|
||||
if ($code = $request->validRecoveryCode()) {
|
||||
$user->replaceRecoveryCode($code);
|
||||
} elseif (! $request->hasValidCode()) {
|
||||
$field = $request->input('recovery_code') ? 'recovery_code' : 'code';
|
||||
|
||||
$this->initTwoFactor();
|
||||
|
||||
throw ValidationException::withMessages([
|
||||
'data.'.$field => 'Invalid code!',
|
||||
]);
|
||||
}
|
||||
|
||||
Filament::auth()->login($user, $request->remember());
|
||||
|
||||
return app(LoginResponse::class);
|
||||
}
|
||||
|
||||
protected function getAuthenticateFormAction(): Action
|
||||
{
|
||||
if (request()->session()->has('login.id')) {
|
||||
return Action::make('verify')
|
||||
->label('Verify')
|
||||
->submit('authenticate');
|
||||
}
|
||||
|
||||
return parent::getAuthenticateFormAction();
|
||||
}
|
||||
|
||||
private function initTwoFactor(): void
|
||||
{
|
||||
if (request()->session()->has('login.id')) {
|
||||
FilamentView::registerRenderHook(
|
||||
PanelsRenderHook::AUTH_LOGIN_FORM_BEFORE,
|
||||
fn (): string => Blade::render(
|
||||
<<<BLADE
|
||||
<x-slot name="subheading">{$this->logoutAction()->render()}</x-slot>
|
||||
BLADE
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user