Skip to content

Commit 2a846f7

Browse files
committed
Formatting
1 parent 265d14f commit 2a846f7

File tree

7 files changed

+126
-50
lines changed

7 files changed

+126
-50
lines changed

app/Livewire/Auth/Login.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ class Login extends Component
2525

2626
public bool $remember = false;
2727

28+
/**
29+
* Handle an incoming authentication request.
30+
*/
2831
public function login(): void
2932
{
3033
$this->validate();
@@ -52,6 +55,9 @@ public function login(): void
5255
$this->redirectIntended(default: route('dashboard', absolute: false), navigate: true);
5356
}
5457

58+
/**
59+
* Validate the user's credentials.
60+
*/
5561
protected function validateCredentials(): User
5662
{
5763
$user = Auth::getProvider()->retrieveByCredentials(['email' => $this->email, 'password' => $this->password]);
@@ -67,6 +73,9 @@ protected function validateCredentials(): User
6773
return $user;
6874
}
6975

76+
/**
77+
* Ensure the authentication request is not rate limited.
78+
*/
7079
protected function ensureIsNotRateLimited(): void
7180
{
7281
if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) {
@@ -85,6 +94,9 @@ protected function ensureIsNotRateLimited(): void
8594
]);
8695
}
8796

97+
/**
98+
* Get the authentication rate limiting throttle key.
99+
*/
88100
protected function throttleKey(): string
89101
{
90102
return Str::transliterate(Str::lower($this->email).'|'.request()->ip());

app/Livewire/Settings/TwoFactor.php

Lines changed: 80 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ class TwoFactor extends Component
3434
#[Validate('required|string|size:6', onUpdate: false)]
3535
public string $code = '';
3636

37+
/**
38+
* Mount the component.
39+
*/
3740
public function mount(DisableTwoFactorAuthentication $disableTwoFactorAuthentication): void
3841
{
3942
abort_unless(Features::enabled(Features::twoFactorAuthentication()), Response::HTTP_FORBIDDEN);
@@ -46,6 +49,9 @@ public function mount(DisableTwoFactorAuthentication $disableTwoFactorAuthentica
4649
$this->requiresConfirmation = Features::optionEnabled(Features::twoFactorAuthentication(), 'confirm');
4750
}
4851

52+
/**
53+
* Enable two-factor authentication for the user.
54+
*/
4955
public function enable(EnableTwoFactorAuthentication $enableTwoFactorAuthentication): void
5056
{
5157
$enableTwoFactorAuthentication(auth()->user());
@@ -54,53 +60,36 @@ public function enable(EnableTwoFactorAuthentication $enableTwoFactorAuthenticat
5460
$this->twoFactorEnabled = auth()->user()->hasEnabledTwoFactorAuthentication();
5561
}
5662

57-
$this->loadTwoFactorData();
58-
$this->showModal = true;
59-
}
63+
$this->loadSetupData();
6064

61-
public function disable(DisableTwoFactorAuthentication $disableTwoFactorAuthentication): void
62-
{
63-
$disableTwoFactorAuthentication(auth()->user());
64-
$this->twoFactorEnabled = false;
65+
$this->showModal = true;
6566
}
6667

67-
public function confirmTwoFactor(ConfirmTwoFactorAuthentication $confirmTwoFactorAuthentication): void
68+
/**
69+
* Load the two-factor authentication setup data for the user.
70+
*/
71+
private function loadSetupData(): void
6872
{
69-
$this->validate();
70-
$confirmTwoFactorAuthentication(auth()->user(), $this->code);
71-
$this->closeModal();
72-
$this->twoFactorEnabled = true;
73-
}
73+
$user = auth()->user();
7474

75-
public function getModalConfigProperty(): array
76-
{
77-
if ($this->twoFactorEnabled) {
78-
return [
79-
'title' => __('Two-Factor Authentication Enabled'),
80-
'description' => __('Two-factor authentication is now enabled. Scan the QR code or enter the setup key in your authenticator app.'),
81-
'buttonText' => __('Close'),
82-
];
83-
}
75+
try {
76+
$this->qrCodeSvg = $user?->twoFactorQrCodeSvg();
77+
$this->manualSetupKey = decrypt($user->two_factor_secret);
78+
} catch (Exception) {
79+
$this->addError('setupData', 'Failed to fetch setup data.');
8480

85-
if ($this->showVerificationStep) {
86-
return [
87-
'title' => __('Verify Authentication Code'),
88-
'description' => __('Enter the 6-digit code from your authenticator app'),
89-
'buttonText' => __('Continue'),
90-
];
81+
$this->reset('qrCodeSvg', 'manualSetupKey');
9182
}
92-
93-
return [
94-
'title' => __('Enable Two-Factor Authentication'),
95-
'description' => __('To finish enabling two-factor authentication, scan the QR code or enter the setup key in your authenticator app'),
96-
'buttonText' => __('Continue'),
97-
];
9883
}
9984

100-
public function handleNextAction(): void
85+
/**
86+
* Show the two-factor verification step if necessary.
87+
*/
88+
public function showVerificationIfNecessary(): void
10189
{
10290
if ($this->requiresConfirmation) {
10391
$this->showVerificationStep = true;
92+
10493
$this->resetErrorBag();
10594

10695
return;
@@ -109,38 +98,85 @@ public function handleNextAction(): void
10998
$this->closeModal();
11099
}
111100

101+
/**
102+
* Confirm two-factor authentication for the user.
103+
*/
104+
public function confirmTwoFactor(ConfirmTwoFactorAuthentication $confirmTwoFactorAuthentication): void
105+
{
106+
$this->validate();
107+
108+
$confirmTwoFactorAuthentication(auth()->user(), $this->code);
109+
110+
$this->closeModal();
111+
112+
$this->twoFactorEnabled = true;
113+
}
114+
115+
/**
116+
* Reset two-factor verification state.
117+
*/
112118
public function resetVerification(): void
113119
{
114120
$this->reset('code', 'showVerificationStep');
121+
115122
$this->resetErrorBag();
116123
}
117124

125+
/**
126+
* Disable two-factor authentication for the user.
127+
*/
128+
public function disable(DisableTwoFactorAuthentication $disableTwoFactorAuthentication): void
129+
{
130+
$disableTwoFactorAuthentication(auth()->user());
131+
132+
$this->twoFactorEnabled = false;
133+
}
134+
135+
/**
136+
* Close the two-factor authentication modal.
137+
*/
118138
public function closeModal(): void
119139
{
120140
$this->reset(
121141
'code',
122-
'showVerificationStep',
123142
'manualSetupKey',
124143
'qrCodeSvg',
125144
'showModal',
145+
'showVerificationStep',
126146
);
147+
127148
$this->resetErrorBag();
128149

129150
if (! $this->requiresConfirmation) {
130151
$this->twoFactorEnabled = auth()->user()->hasEnabledTwoFactorAuthentication();
131152
}
132153
}
133154

134-
private function loadTwoFactorData(): void
155+
/**
156+
* Get the current modal configuration state.
157+
*/
158+
public function getModalConfigProperty(): array
135159
{
136-
$user = auth()->user();
160+
if ($this->twoFactorEnabled) {
161+
return [
162+
'title' => __('Two-Factor Authentication Enabled'),
163+
'description' => __('Two-factor authentication is now enabled. Scan the QR code or enter the setup key in your authenticator app.'),
164+
'buttonText' => __('Close'),
165+
];
166+
}
137167

138-
try {
139-
$this->qrCodeSvg = $user?->twoFactorQrCodeSvg();
140-
$this->manualSetupKey = decrypt($user->two_factor_secret);
141-
} catch (Exception) {
142-
$this->addError('setupData', 'Failed to fetch setup data.');
143-
$this->reset('qrCodeSvg', 'manualSetupKey');
168+
if ($this->showVerificationStep) {
169+
return [
170+
'title' => __('Verify Authentication Code'),
171+
'description' => __('Enter the 6-digit code from your authenticator app.'),
172+
'buttonText' => __('Continue'),
173+
];
144174
}
175+
176+
return [
177+
'title' => __('Enable Two-Factor Authentication'),
178+
'description' => __('To finish enabling two-factor authentication, scan the QR code or enter the setup key in your authenticator app.'),
179+
'buttonText' => __('Continue'),
180+
];
145181
}
146182
}

app/Livewire/Settings/TwoFactor/RecoveryCodes.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,27 @@ class RecoveryCodes extends Component
1212
#[Locked]
1313
public array $recoveryCodes = [];
1414

15+
/**
16+
* Mount the component.
17+
*/
1518
public function mount(): void
1619
{
1720
$this->loadRecoveryCodes();
1821
}
1922

23+
/**
24+
* Generate new recovery codes for the user.
25+
*/
2026
public function regenerateRecoveryCodes(GenerateNewRecoveryCodes $generateNewRecoveryCodes): void
2127
{
2228
$generateNewRecoveryCodes(auth()->user());
29+
2330
$this->loadRecoveryCodes();
2431
}
2532

33+
/**
34+
* Load the recovery codes for the user.
35+
*/
2636
private function loadRecoveryCodes(): void
2737
{
2838
$user = auth()->user();
@@ -32,6 +42,7 @@ private function loadRecoveryCodes(): void
3242
$this->recoveryCodes = json_decode(decrypt($user->two_factor_recovery_codes), true);
3343
} catch (Exception) {
3444
$this->addError('recoveryCodes', 'Failed to load recovery codes');
45+
3546
$this->recoveryCodes = [];
3647
}
3748
}

resources/views/livewire/auth/login.blade.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
/>
3030

3131
@if (Route::has('password.request'))
32-
<flux:link class="absolute end-0 top-0 text-sm" :href="route('password.request')" wire:navigate>
32+
<flux:link class="absolute top-0 text-sm end-0" :href="route('password.request')" wire:navigate>
3333
{{ __('Forgot your password?') }}
3434
</flux:link>
3535
@endif
@@ -39,12 +39,14 @@
3939
<flux:checkbox wire:model="remember" :label="__('Remember me')" />
4040

4141
<div class="flex items-center justify-end">
42-
<flux:button variant="primary" type="submit" class="w-full">{{ __('Log in') }}</flux:button>
42+
<flux:button variant="primary" type="submit" class="w-full" data-test="login-button">
43+
{{ __('Log in') }}
44+
</flux:button>
4345
</div>
4446
</form>
4547

4648
@if (Route::has('register'))
47-
<div class="space-x-1 rtl:space-x-reverse text-center text-sm text-zinc-600 dark:text-zinc-400">
49+
<div class="space-x-1 text-sm text-center rtl:space-x-reverse text-zinc-600 dark:text-zinc-400">
4850
<span>{{ __('Don\'t have an account?') }}</span>
4951
<flux:link :href="route('register')" wire:navigate>{{ __('Sign up') }}</flux:link>
5052
</div>

resources/views/livewire/auth/two-factor-challenge.blade.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@ class="relative w-full h-auto"
55
x-cloak
66
x-data="{
77
showRecoveryInput: @js($errors->has('recovery_code')),
8-
98
code: '',
109
recovery_code: '',
11-
1210
toggleInput() {
1311
this.showRecoveryInput = !this.showRecoveryInput;
12+
1413
this.code = '';
1514
this.recovery_code = '';
1615
@@ -58,6 +57,7 @@ class="relative w-full h-auto"
5857
</flux:text>
5958
@enderror
6059
</div>
60+
6161
<div x-show="showRecoveryInput">
6262
<div class="my-5">
6363
<flux:input

resources/views/livewire/settings/two-factor.blade.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,13 @@
1111
<div class="flex items-center gap-3">
1212
<flux:badge color="green">{{ __('Enabled') }}</flux:badge>
1313
</div>
14+
1415
<flux:text>
1516
{{ __('With two-factor authentication enabled, you will be prompted for a secure, random pin during login, which you can retrieve from the TOTP-supported application on your phone.') }}
1617
</flux:text>
18+
1719
<livewire:settings.two-factor.recovery-codes :$requiresConfirmation/>
20+
1821
<div class="flex justify-start">
1922
<flux:button
2023
variant="danger"
@@ -31,9 +34,11 @@
3134
<div class="flex items-center gap-3">
3235
<flux:badge color="red">{{ __('Disabled') }}</flux:badge>
3336
</div>
37+
3438
<flux:text variant="subtle">
3539
{{ __('When you enable two-factor authentication, you will be prompted for a secure pin during login. This pin can be retrieved from a TOTP-supported application on your phone.') }}
3640
</flux:text>
41+
3742
<flux:button
3843
variant="primary"
3944
icon="shield-check"
@@ -62,14 +67,17 @@ class="max-w-md md:min-w-md"
6267
<div></div>
6368
@endfor
6469
</div>
70+
6571
<div class="flex flex-col items-stretch absolute w-full h-full divide-y [&>div]:flex-1 inset-0 divide-stone-200 dark:divide-stone-300 justify-around opacity-50">
6672
@for ($i = 1; $i <= 5; $i++)
6773
<div></div>
6874
@endfor
6975
</div>
76+
7077
<flux:icon.qr-code class="relative z-20 dark:text-accent-foreground"/>
7178
</div>
7279
</div>
80+
7381
<div class="space-y-2 text-center">
7482
<flux:heading size="lg">{{ $this->modalConfig['title'] }}</flux:heading>
7583
<flux:text>{{ $this->modalConfig['description'] }}</flux:text>
@@ -100,6 +108,7 @@ class="flex-1"
100108
>
101109
{{ __('Back') }}
102110
</flux:button>
111+
103112
<flux:button
104113
variant="primary"
105114
class="flex-1"
@@ -128,23 +137,26 @@ class="flex-1"
128137
@endempty
129138
</div>
130139
</div>
140+
131141
<div>
132142
<flux:button
133143
:disabled="$errors->has('setupData')"
134144
variant="primary"
135145
class="w-full"
136-
wire:click="handleNextAction"
146+
wire:click="showVerificationIfNecessary"
137147
>
138148
{{ $this->modalConfig['buttonText'] }}
139149
</flux:button>
140150
</div>
151+
141152
<div class="space-y-4">
142153
<div class="relative flex items-center justify-center w-full">
143154
<div class="absolute inset-0 w-full h-px top-1/2 bg-stone-200 dark:bg-stone-600"></div>
144155
<span class="relative px-2 text-sm bg-white dark:bg-stone-800 text-stone-600 dark:text-stone-400">
145156
{{ __('or, enter the code manually') }}
146157
</span>
147158
</div>
159+
148160
<div
149161
class="flex items-center space-x-2"
150162
x-data="{
@@ -172,6 +184,7 @@ class="flex items-center space-x-2"
172184
value="{{ $manualSetupKey }}"
173185
class="w-full p-3 bg-transparent outline-none text-stone-900 dark:text-stone-100"
174186
/>
187+
175188
<button
176189
@click="copy()"
177190
class="px-3 transition-colors border-l cursor-pointer border-stone-200 dark:border-stone-600"

0 commit comments

Comments
 (0)