fix(auth): remove dummy login route, validate locale allowlist
- Remove no-op POST /login route that caused named-route collision and was testing throttle:5,1 middleware against a null handler. - Rewrite LoginRateLimitTest to drive the real Volt login component via Volt::test(), verifying the RateLimiter blocks the 6th attempt with auth.throttle message; throttle is Laravel core, test confirms wiring. - Add supported_locales allowlist to config/app.php ['de', 'en']. - LocaleFromUser middleware now validates user locale against allowlist and falls back to app.locale for unknown/unsupported values. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>main
parent
9d5d5af24d
commit
ee0824302a
|
|
@ -11,7 +11,11 @@ class LocaleFromUser
|
|||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
if ($user = $request->user()) {
|
||||
App::setLocale($user->locale ?? config('app.locale'));
|
||||
$supported = config('app.supported_locales', [config('app.locale')]);
|
||||
$locale = in_array($user->locale, $supported, true)
|
||||
? $user->locale
|
||||
: config('app.locale');
|
||||
App::setLocale($locale);
|
||||
}
|
||||
return $next($request);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,6 +80,8 @@ return [
|
|||
|
||||
'locale' => env('APP_LOCALE', 'en'),
|
||||
|
||||
'supported_locales' => ['de', 'en'],
|
||||
|
||||
'fallback_locale' => env('APP_FALLBACK_LOCALE', 'en'),
|
||||
|
||||
'faker_locale' => env('APP_FAKER_LOCALE', 'en_US'),
|
||||
|
|
|
|||
|
|
@ -11,8 +11,6 @@ Route::middleware('guest')->group(function () {
|
|||
Volt::route('login', 'pages.auth.login')
|
||||
->name('login');
|
||||
|
||||
Route::post('login', fn () => null)->middleware('throttle:5,1')->name('login.post');
|
||||
|
||||
Volt::route('forgot-password', 'pages.auth.forgot-password')
|
||||
->name('password.request');
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,34 @@
|
|||
<?php
|
||||
|
||||
it('throttles login after 5 failed attempts', function () {
|
||||
$this->withoutMiddleware(\Illuminate\Foundation\Http\Middleware\ValidateCsrfToken::class);
|
||||
use Illuminate\Support\Facades\RateLimiter;
|
||||
use Illuminate\Support\Str;
|
||||
use Livewire\Volt\Volt;
|
||||
|
||||
it('throttles login after 5 failed attempts', function () {
|
||||
$email = 'test@test.com';
|
||||
|
||||
// The throttle key LoginForm uses: Str::transliterate(Str::lower($email) . '|' . request()->ip())
|
||||
// In the test environment request()->ip() returns '127.0.0.1'
|
||||
$throttleKey = Str::transliterate(Str::lower($email) . '|127.0.0.1');
|
||||
RateLimiter::clear($throttleKey);
|
||||
|
||||
// Make 5 failed attempts through the real Volt component
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$this->post('/login', ['email' => 'test@test.com', 'password' => 'wrong']);
|
||||
Volt::test('pages.auth.login')
|
||||
->set('form.email', $email)
|
||||
->set('form.password', 'wrong' . $i)
|
||||
->call('login');
|
||||
}
|
||||
$response = $this->post('/login', ['email' => 'test@test.com', 'password' => 'wrong']);
|
||||
$response->assertStatus(429);
|
||||
|
||||
// 6th attempt must be rate-limited — error on form.email with throttle message
|
||||
$component = Volt::test('pages.auth.login')
|
||||
->set('form.email', $email)
|
||||
->set('form.password', 'wrong6')
|
||||
->call('login');
|
||||
|
||||
$component->assertHasErrors(['form.email']);
|
||||
|
||||
$errors = $component->errors();
|
||||
expect($errors->has('form.email'))->toBeTrue();
|
||||
expect($errors->first('form.email'))->toContain('Too many login attempts');
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue