feat: custom login

This commit is contained in:
Yoga Pangestu 2025-11-19 14:52:07 +07:00
parent 3486231739
commit dd368e3c48
2 changed files with 155 additions and 1 deletions

View File

@ -0,0 +1,153 @@
<?php
namespace App\Filament\Pages;
use DanHarrin\LivewireRateLimiting\Exceptions\TooManyRequestsException;
use Filament\Auth\Http\Responses\Contracts\LoginResponse;
use Filament\Auth\MultiFactor\Contracts\HasBeforeChallengeHook;
use Filament\Auth\Pages\Login;
use Filament\Facades\Filament;
use Filament\Forms\Components\TextInput;
use Filament\Models\Contracts\FilamentUser;
use Filament\Notifications\Notification;
use Filament\Schemas\Schema;
use Illuminate\Auth\SessionGuard;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\HtmlString;
use Illuminate\Validation\ValidationException;
use SensitiveParameter;
class CustomLogin extends Login
{
public function getHeading(): string|Htmlable
{
return '';
}
public function form(Schema $schema): Schema
{
return $schema
->components([
TextInput::make('login')
->label('Nama Pengguna atau Alamat Surel')
->placeholder('johndoe@puskesmas.com')
->required()
->autocomplete(false)
->autofocus(),
TextInput::make('password')
->label('Kata Sandi')
->placeholder('********')
->password()
->revealable(filament()->arePasswordsRevealable())
->required()
->autocomplete(false)
->extraInputAttributes(['tabindex' => 2])
->hint(
filament()->hasPasswordReset()
? new HtmlString(Blade::render('<x-filament::link :href="filament()->getRequestPasswordResetUrl()" tabindex="3">{{ __(\'filament-panels::auth/pages/login.actions.request_password_reset.label\') }}</x-filament::link>'))
: null
),
]);
}
protected function getCredentialsFromFormData(#[SensitiveParameter] array $data): array
{
$loginType = filter_var($data['login'], FILTER_VALIDATE_EMAIL) ? 'email' : 'username';
return [
$loginType => $data['login'],
'password' => $data['password'],
];
}
public function authenticate(): ?LoginResponse
{
try {
$this->rateLimit(5);
} catch (TooManyRequestsException $exception) {
$this->getRateLimitedNotification($exception)?->send();
return null;
}
$data = $this->form->getState();
/** @var SessionGuard $authGuard */
$authGuard = Filament::auth();
$authProvider = $authGuard->getProvider();
/** @phpstan-ignore-line */
$credentials = $this->getCredentialsFromFormData($data);
$user = $authProvider->retrieveByCredentials($credentials);
if ((! $user) || (! $authProvider->validateCredentials($user, $credentials))) {
$this->userUndertakingMultiFactorAuthentication = null;
$this->fireFailedEvent($authGuard, $user, $credentials);
$this->throwFailureValidationException();
}
if (
filled($this->userUndertakingMultiFactorAuthentication) &&
(decrypt($this->userUndertakingMultiFactorAuthentication) === $user->getAuthIdentifier())
) {
$this->multiFactorChallengeForm->validate();
} else {
foreach (Filament::getMultiFactorAuthenticationProviders() as $multiFactorAuthenticationProvider) {
if (! $multiFactorAuthenticationProvider->isEnabled($user)) {
continue;
}
$this->userUndertakingMultiFactorAuthentication = encrypt($user->getAuthIdentifier());
if ($multiFactorAuthenticationProvider instanceof HasBeforeChallengeHook) {
$multiFactorAuthenticationProvider->beforeChallenge($user);
}
break;
}
if (filled($this->userUndertakingMultiFactorAuthentication)) {
$this->multiFactorChallengeForm->fill();
return null;
}
}
if (! $authGuard->attemptWhen($credentials, function (Authenticatable $user): bool {
if (! ($user instanceof FilamentUser)) {
return true;
}
return $user->canAccessPanel(Filament::getCurrentOrDefaultPanel());
}, $data['remember'] ?? false)) {
$this->fireFailedEvent($authGuard, $user, $credentials);
$this->throwFailureValidationException();
}
session()->regenerate();
Notification::make()
->title('Berhasil Masuk')
->body('Selamat datang, '.$user->name.'!')
->success()
->send();
return app(LoginResponse::class);
}
protected function throwFailureValidationException(): never
{
Notification::make()
->title('Gagal Masuk')
->body('Alamat surel, nama pengguna atau kata sandi salah. Silakan coba lagi.')
->danger()
->send();
throw ValidationException::withMessages([]);
}
}

View File

@ -2,6 +2,7 @@
namespace App\Providers\Filament;
use App\Filament\Pages\CustomLogin;
use Filament\Http\Middleware\Authenticate;
use Filament\Http\Middleware\AuthenticateSession;
use Filament\Http\Middleware\DisableBladeIconComponents;
@ -28,7 +29,7 @@ public function panel(Panel $panel): Panel
->default()
->id('dashboard')
->path('dashboard')
->login()
->login(CustomLogin::class)
->colors([
'primary' => Color::Blue,
])