Skip to content

Commit 8964e62

Browse files
committed
Update: Login page improve readability
1 parent a9cf74d commit 8964e62

File tree

4 files changed

+118
-49
lines changed

4 files changed

+118
-49
lines changed

README.md

+18-20
Original file line numberDiff line numberDiff line change
@@ -119,26 +119,24 @@ public function panel(Panel $panel): Panel
119119
->login(Login::class)
120120
->userMenuItems([
121121
/**
122-
* All users page to configure their 2fa
123-
*/
124-
MenuItem::make('two-factor')
125-
->url(config('filament-2fa.navigation.url'))
126-
->label(config('filament-2fa.navigation.label'))
127-
->icon(config('filament-2fa.navigation.icon'))
128-
->sort(config('filament-2fa.navigation.sort')),
129-
130-
/**
131-
* This allows editing system wide banners - should only be available to admins
132-
* May need to think about other logic to restrict access
133-
*/
134-
MenuItem::make('two-factor-banner')
135-
->url(config('filament-2fa.banner.navigation.url'))
136-
->label(config('filament-2fa.banner.navigation.label'))
137-
->icon(config('filament-2fa.banner.navigation.icon'))
138-
->sort(config('filament-2fa.banner.navigation.sort')),
139-
->visible(config('filament-2fa.banner.auth_guards.web.can_manage')),
140-
])
141-
}
122+
* 2FA setup and manage link
123+
*/
124+
MenuItem::make('two-factor')
125+
->url('/two-factor-authentication')
126+
->label('Two Factor Auth')
127+
->icon('heroicon-o-key')
128+
->sort(1),
129+
130+
/**
131+
* Banner manager
132+
* Ensure you limit access to who can change banners
133+
*/
134+
MenuItem::make('two-factor-banner')
135+
->url(config('filament-2fa.banner.navigation.url'))
136+
->label(config('filament-2fa.banner.navigation.label'))
137+
->icon(config('filament-2fa.banner.navigation.icon'))
138+
->sort(2)
139+
->visible(fn() => Filament::auth()->user()->hasRole(['Developer', 'Super Admin'],'web'))
142140
```
143141

144142
### Step 4:

config/filament-2fa.php

+19-1
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,23 @@
2020
'confirm_totp_page_url' => 'confirm-2fa'
2121
],
2222

23+
/**
24+
* 2FA link options
25+
*/
2326
'navigation' => [
2427
'visible_on_navbar' => true,
2528
'icon' => 'heroicon-o-key',
2629
'group' => 'Auth Security',
2730
'label' => 'Two Factor Auth',
28-
'url' => '/two-factor-authentication',
31+
'url' => 'two-factor-authentication',
2932
'cluster' => null,
3033
'sort' => 1,
3134
'subnav_position' => SubNavigationPosition::Top
3235
],
3336

37+
/**
38+
* Configure which auth guards 2fa should apply to
39+
*/
3440
'auth_guards' => [
3541
'web' => [
3642
'enabled' => 'true',
@@ -39,18 +45,30 @@
3945
],
4046

4147
'banner' => [
48+
49+
/**
50+
* Configure which auth guards banners should apply to
51+
* This will change the dropdown in the banner editor
52+
*/
4253
'auth_guards' => [
4354
'web' => [
4455
'can_manage' => true,
4556
'can_see_banner' => true,
4657
]
4758
],
59+
60+
/**
61+
* Navigation link options
62+
*/
4863
'navigation' => [
4964
'icon' => 'heroicon-m-megaphone',
5065
'label' => 'Banners',
5166
'url' => 'banner-manager',
5267
'sort' => 50,
5368
],
69+
/**
70+
* Do not show banners on these routes
71+
*/
5472
'excluded_routes' => [
5573
'two-factor-authentication',
5674
'confirm-2fa',

src/Filament/Pages/Login.php

+80-27
Original file line numberDiff line numberDiff line change
@@ -10,64 +10,117 @@
1010
use Visualbuilder\Filament2fa\TwoFactorAuthResponse;
1111
use Visualbuilder\Filament2fa\Contracts\TwoFactorAuthenticatable;
1212
use Illuminate\Support\Facades\Crypt;
13+
use Illuminate\Contracts\Auth\Authenticatable;
1314

1415
class Login extends BaseLogin
1516
{
1617
public function authenticate(): null|TwoFactorAuthResponse|LoginResponse
1718
{
18-
try {
19-
$this->rateLimit(5);
20-
} catch (TooManyRequestsException $exception) {
21-
$this->getRateLimitedNotification($exception)?->send();
22-
23-
return null;
19+
if ($response = $this->handleRateLimiting()) {
20+
return $response;
2421
}
2522

2623
$data = $this->form->getState();
24+
$credentials = $this->getCredentialsFromFormData($data);
25+
$remember = $data['remember'] ?? false;
2726

28-
$responseClass = LoginResponse::class;
29-
30-
if (! Filament::auth()->attempt($this->getCredentialsFromFormData($data), $data['remember'] ?? false)) {
27+
if (! $this->attemptLogin($credentials, $remember)) {
3128
$this->throwFailureValidationException();
3229
}
3330

3431
$user = Filament::auth()->user();
3532

36-
/** Check If user loggedin with unsafe device redirecting to 2fa verification page */
37-
if ($user instanceof TwoFactorAuthenticatable && $user->hasTwoFactorEnabled() && !$user->isSafeDevice(request())) {
38-
$responseClass = TwoFactorAuthResponse::class;
39-
$this->flashData($this->getCredentialsFromFormData($data), $data['remember'] ?? false);
40-
Filament::auth()->logout();
41-
goto response;
33+
if ($response = $this->handleTwoFactorAuthentication($user, $credentials, $remember)) {
34+
return $response;
4235
}
4336

44-
response:
45-
if (
46-
($user instanceof FilamentUser) &&
47-
(! $user->canAccessPanel(Filament::getCurrentPanel()))
48-
) {
37+
if (! $this->userCanAccessPanel($user)) {
4938
Filament::auth()->logout();
5039
$this->throwFailureValidationException();
5140
}
5241

5342
session()->regenerate();
5443

55-
return app($responseClass);
44+
return app(LoginResponse::class);
5645
}
5746

5847
/**
59-
* Flashes the credentials into the session, encrypted.
48+
* Handle rate limiting for login attempts.
6049
*/
61-
protected function flashData(array $credentials, bool $remember): void
50+
protected function handleRateLimiting(): ?LoginResponse
6251
{
63-
foreach ($credentials as $key => $value) {
64-
$credentials[$key] = Crypt::encryptString($value);
52+
try {
53+
$this->rateLimit(5);
54+
} catch (TooManyRequestsException $exception) {
55+
$this->getRateLimitedNotification($exception)?->send();
56+
return null;
6557
}
6658

59+
return null;
60+
}
61+
62+
/**
63+
* Attempt to authenticate the user.
64+
*/
65+
protected function attemptLogin(array $credentials, bool $remember): bool
66+
{
67+
return Filament::auth()->attempt($credentials, $remember);
68+
}
69+
70+
/**
71+
* Handle two-factor authentication if required.
72+
*/
73+
protected function handleTwoFactorAuthentication(Authenticatable $user, array $credentials, bool $remember): ?TwoFactorAuthResponse
74+
{
75+
if ($this->needsTwoFactorAuthentication($user)) {
76+
$this->flashCredentials($credentials, $remember);
77+
Filament::auth()->logout();
78+
79+
return app(TwoFactorAuthResponse::class);
80+
}
81+
82+
return null;
83+
}
84+
85+
/**
86+
* Determine if two-factor authentication is required.
87+
*/
88+
protected function needsTwoFactorAuthentication(Authenticatable $user): bool
89+
{
90+
return $user instanceof TwoFactorAuthenticatable
91+
&& $user->hasTwoFactorEnabled()
92+
&& ! $user->isSafeDevice(request());
93+
}
94+
95+
/**
96+
* Check if the authenticated user can access the current panel.
97+
*/
98+
protected function userCanAccessPanel(Authenticatable $user): bool
99+
{
100+
return ! ($user instanceof FilamentUser && ! $user->canAccessPanel(Filament::getCurrentPanel()));
101+
}
102+
103+
/**
104+
* Flash the credentials into the session, encrypted.
105+
*/
106+
protected function flashCredentials(array $credentials, bool $remember): void
107+
{
108+
$encryptedCredentials = array_map(
109+
fn($value) => Crypt::encryptString($value),
110+
$credentials
111+
);
112+
113+
$sessionData = [
114+
'credentials' => $encryptedCredentials,
115+
'remember' => $remember,
116+
];
117+
118+
$credentialKey = config('filament-2fa.login.credential_key');
119+
67120
if (config('filament-2fa.login.flashLoginCredentials')) {
68-
request()->session()->flash(config('filament-2fa.login.credential_key'), ['credentials' => $credentials, 'remember' => $remember]);
121+
request()->session()->flash($credentialKey, $sessionData);
69122
} else {
70-
session([config('filament-2fa.login.credential_key') => ['credentials' => $credentials, 'remember' => $remember]]);
123+
session([$credentialKey => $sessionData]);
71124
}
72125
}
73126
}

src/Http/Middleware/SetRenderLocation.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ private function filterBannersForUser($banners, $user)
3939
{
4040
return $banners->filter(function (Banner $banner) use ($user) {
4141
return $banner->isVisible()
42-
&& $banner->sApplicableForUser($user)
42+
&& $banner->isApplicableForUser($user)
4343
&& $banner->checkGuard()
4444
&& $this->checkCurrentAuth();
4545
});

0 commit comments

Comments
 (0)