Skip to content

Commit

Permalink
[1.x] Add X-Retry-After to /user/confirm-password/status response (
Browse files Browse the repository at this point in the history
…#565)

* [1.x] Add `X-Retry-After` to `/user/confirm-password/status` response

This would be useful for SPA application where we can register a timeout
before checking the endpoint again.

Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>

* Update ConfirmedPasswordStatusController.php

---------

Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>
Co-authored-by: Taylor Otwell <taylor@laravel.com>
  • Loading branch information
crynobone and taylorotwell authored Aug 28, 2024
1 parent eeeeda0 commit dd2c276
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 2 deletions.
17 changes: 15 additions & 2 deletions src/Http/Controllers/ConfirmedPasswordStatusController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Date;

class ConfirmedPasswordStatusController extends Controller
{
Expand All @@ -15,8 +16,20 @@ class ConfirmedPasswordStatusController extends Controller
*/
public function show(Request $request)
{
$lastConfirmation = $request->session()->get(
'auth.password_confirmed_at', 0
);

$lastConfirmed = (Date::now()->unix() - $lastConfirmation);

$confirmed = $lastConfirmed < $request->input(
'seconds', config('auth.password_timeout', 900)
);

return response()->json([
'confirmed' => (time() - $request->session()->get('auth.password_confirmed_at', 0)) < $request->input('seconds', config('auth.password_timeout', 900)),
]);
'confirmed' => $confirmed,
], headers: array_filter([
'X-Retry-After' => $confirmed ? $lastConfirmed : null,
]));
}
}
52 changes: 52 additions & 0 deletions tests/ConfirmablePasswordControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@

use Illuminate\Foundation\Auth\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Date;
use Laravel\Fortify\Contracts\ConfirmPasswordViewResponse;
use Laravel\Fortify\Fortify;
use Orchestra\Testbench\Attributes\WithConfig;
use Orchestra\Testbench\Attributes\WithMigration;

#[WithMigration]
Expand Down Expand Up @@ -153,6 +155,56 @@ public function test_password_confirmation_can_fail_with_json()
$response->assertJsonValidationErrors('password');
}

#[WithConfig('auth.password_timeout', 120)]
public function test_password_confirmation_status_has_been_confirmed()
{
Carbon::setTestNow();

$response = $this->withoutExceptionHandling()
->actingAs($this->user)
->withSession(['auth.password_confirmed_at' => now()->subMinute(1)->unix()])
->get(
'/user/confirmed-password-status',
);

$response->assertOk()
->assertJson(['confirmed' => true])
->assertHeader('X-Retry-After', 60);
}

#[WithConfig('auth.password_timeout', 120)]
public function test_password_confirmation_status_has_expired()
{
Carbon::setTestNow();

$response = $this->withoutExceptionHandling()
->actingAs($this->user)
->withSession(['auth.password_confirmed_at' => now()->subMinutes(10)->unix()])
->get(
'/user/confirmed-password-status',
);

$response->assertOk()
->assertJson(['confirmed' => false])
->assertHeaderMissing('X-Retry-After');
}

#[WithConfig('auth.password_timeout', 120)]
public function test_password_confirmation_status_has_not_confirmed()
{
Carbon::setTestNow();

$response = $this->withoutExceptionHandling()
->actingAs($this->user)
->get(
'/user/confirmed-password-status',
);

$response->assertOk()
->assertJson(['confirmed' => false])
->assertHeaderMissing('X-Retry-After');
}

protected function defineEnvironment($app)
{
parent::defineEnvironment($app);
Expand Down

0 comments on commit dd2c276

Please sign in to comment.