Skip to content

Commit aeffd88

Browse files
committed
Move trait to form-request
1 parent 0b3afa0 commit aeffd88

File tree

5 files changed

+106
-91
lines changed

5 files changed

+106
-91
lines changed

app/Http/Controllers/Concerns/ConfirmsTwoFactorAuthentication.php

Lines changed: 0 additions & 71 deletions
This file was deleted.

app/Http/Controllers/Settings/TwoFactorAuthenticationController.php

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@
22

33
namespace App\Http\Controllers\Settings;
44

5-
use App\Http\Controllers\Concerns\ConfirmsTwoFactorAuthentication;
65
use App\Http\Controllers\Controller;
7-
use Illuminate\Http\Request;
8-
use Illuminate\Http\Response as HttpResponse;
6+
use App\Http\Requests\Auth\TwoFactorAuthenticationRequest;
97
use Illuminate\Routing\Controllers\HasMiddleware;
108
use Illuminate\Routing\Controllers\Middleware;
119
use Inertia\Inertia;
@@ -14,8 +12,6 @@
1412

1513
class TwoFactorAuthenticationController extends Controller implements HasMiddleware
1614
{
17-
use ConfirmsTwoFactorAuthentication;
18-
1915
/**
2016
* Get the middleware that should be assigned to the controller.
2117
*/
@@ -29,15 +25,9 @@ public static function middleware(): array
2925
/**
3026
* Show the user's two-factor authentication settings page.
3127
*/
32-
public function show(Request $request): Response
28+
public function show(TwoFactorAuthenticationRequest $request): Response
3329
{
34-
abort_if(
35-
! Features::enabled(Features::twoFactorAuthentication()),
36-
HttpResponse::HTTP_FORBIDDEN,
37-
'Two factor authentication is disabled.'
38-
);
39-
40-
$this->validateTwoFactorAuthenticationState($request);
30+
$request->validateState();
4131

4232
return Inertia::render('settings/TwoFactor', [
4333
'requiresConfirmation' => Features::optionEnabled(Features::twoFactorAuthentication(), 'confirm'),
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?php
2+
3+
namespace App\Http\Requests\Auth;
4+
5+
use Illuminate\Foundation\Http\FormRequest;
6+
use Illuminate\Support\Facades\Auth;
7+
use Laravel\Fortify\Actions\DisableTwoFactorAuthentication;
8+
use Laravel\Fortify\Features;
9+
10+
class TwoFactorAuthenticationRequest extends FormRequest
11+
{
12+
/**
13+
* Determine if the user is authorized to make this request.
14+
*/
15+
public function authorize(): bool
16+
{
17+
return Features::enabled(Features::twoFactorAuthentication());
18+
}
19+
20+
/**
21+
* Get the validation rules that apply to the request.
22+
*
23+
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
24+
*/
25+
public function rules(): array
26+
{
27+
return [];
28+
}
29+
30+
/**
31+
* Validate the two-factor authentication state for the request.
32+
*/
33+
public function validateState(): void
34+
{
35+
if (! Features::optionEnabled(Features::twoFactorAuthentication(), 'confirm')) {
36+
return;
37+
}
38+
39+
$currentTime = time();
40+
41+
// Notate totally disabled state in session...
42+
if ($this->twoFactorAuthenticationDisabled()) {
43+
$this->session()->put('two_factor_empty_at', $currentTime);
44+
}
45+
46+
// If was previously totally disabled this session but is now confirming, notate time...
47+
if ($this->hasJustBegunConfirmingTwoFactorAuthentication()) {
48+
$this->session()->put('two_factor_confirming_at', $currentTime);
49+
}
50+
51+
// If the profile is reloaded and is not confirmed but was previously in confirming state, disable...
52+
if ($this->neverFinishedConfirmingTwoFactorAuthentication($currentTime)) {
53+
app(DisableTwoFactorAuthentication::class)(Auth::user());
54+
55+
$this->session()->put('two_factor_empty_at', $currentTime);
56+
$this->session()->remove('two_factor_confirming_at');
57+
}
58+
}
59+
60+
/**
61+
* Determine if two-factor authentication is totally disabled.
62+
*/
63+
protected function twoFactorAuthenticationDisabled(): bool
64+
{
65+
return is_null($this->user()->two_factor_secret) &&
66+
is_null($this->user()->two_factor_confirmed_at);
67+
}
68+
69+
/**
70+
* Determine if two-factor authentication is just now being confirmed within the last request cycle.
71+
*/
72+
protected function hasJustBegunConfirmingTwoFactorAuthentication(): bool
73+
{
74+
return ! is_null($this->user()->two_factor_secret) &&
75+
is_null($this->user()->two_factor_confirmed_at) &&
76+
$this->session()->has('two_factor_empty_at') &&
77+
is_null($this->session()->get('two_factor_confirming_at'));
78+
}
79+
80+
/**
81+
* Determine if two-factor authentication was never totally confirmed once confirmation started.
82+
*/
83+
protected function neverFinishedConfirmingTwoFactorAuthentication(int $currentTime): bool
84+
{
85+
return ! array_key_exists('code', $this->session()->getOldInput()) &&
86+
is_null($this->user()->two_factor_confirmed_at) &&
87+
$this->session()->get('two_factor_confirming_at', 0) != $currentTime;
88+
}
89+
}

app/Providers/FortifyServiceProvider.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ public function register(): void
2424
*/
2525
public function boot(): void
2626
{
27-
Fortify::twoFactorChallengeView(fn() => Inertia::render('auth/TwoFactorChallenge'));
27+
Fortify::twoFactorChallengeView(fn () => Inertia::render('auth/TwoFactorChallenge'));
2828

29-
Fortify::confirmPasswordView(fn() => Inertia::render('auth/ConfirmPassword'));
29+
Fortify::confirmPasswordView(fn () => Inertia::render('auth/ConfirmPassword'));
3030

3131
RateLimiter::for(
3232
'two-factor',
33-
fn(Request $request) => Limit::perMinute(5)->by($request->session()->get('login.id')));
33+
fn (Request $request) => Limit::perMinute(5)->by($request->session()->get('login.id')));
3434
}
3535
}

tests/Feature/Auth/PasswordResetTest.php

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,17 @@ public function test_reset_password_screen_can_be_rendered()
3838

3939
$this->post(route('password.email'), ['email' => $user->email]);
4040

41-
Notification::assertSentTo($user, ResetPassword::class, function ($notification) {
42-
$response = $this->get(route('password.request', $notification->token));
43-
44-
$response->assertStatus(200);
41+
Notification::assertSentTo($user, ResetPassword::class, function ($notification) use ($user) {
42+
$response = $this->get(route('password.reset', $notification->token) . '?email=' . $user->email);
43+
44+
$response->assertStatus(200)
45+
->assertInertia(fn ($page) => $page
46+
->component('auth/ResetPassword')
47+
->has('email')
48+
->has('token')
49+
->where('email', $user->email)
50+
->where('token', $notification->token)
51+
);
4552

4653
return true;
4754
});

0 commit comments

Comments
 (0)