diff --git a/routes/web.php b/routes/web.php index 000558adc..9060ed139 100644 --- a/routes/web.php +++ b/routes/web.php @@ -496,7 +496,7 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['localization'])->grou // Laravel 13's Horizon no longer redirects the base path to its dashboard, // so /horizon 404s by default. Redirect admins from /horizon to /horizon/dashboard. - Route::redirect('horizon', 'horizon/dashboard')->middleware('admin'); + Route::redirect('horizon', '/horizon/dashboard')->middleware('admin'); Route::redirect('groups/', '/groups/home'); Route::redirect('groups/home', '/groups/feed'); diff --git a/tests/Feature/Admin/HorizonRedirectTest.php b/tests/Feature/Admin/HorizonRedirectTest.php new file mode 100644 index 000000000..416fcb108 --- /dev/null +++ b/tests/Feature/Admin/HorizonRedirectTest.php @@ -0,0 +1,57 @@ +admin()->create(); + $admin->refresh(); + + $response = $this->actingAs($admin)->get('/horizon'); + + $response->assertRedirect('/horizon/dashboard'); + + // The Location header must be absolute so a trailing-slash request cannot + // resolve it into a doubled /horizon/horizon/dashboard path. + expect($response->headers->get('Location'))->toEndWith('/horizon/dashboard'); + expect(parse_url($response->headers->get('Location'), PHP_URL_PATH)) + ->toBe('/horizon/dashboard'); +}); + +it('redirects with an absolute Location for a trailing-slash /horizon/ request', function () { + $admin = User::factory()->admin()->create(); + $admin->refresh(); + + $response = $this->actingAs($admin)->get('/horizon/'); + + // Regardless of the trailing slash, the redirect path is the absolute + // dashboard path, never a relative reference that would double up. + expect(parse_url($response->headers->get('Location'), PHP_URL_PATH)) + ->toBe('/horizon/dashboard'); +}); + +it('does not allow a non-admin to use the /horizon redirect', function () { + $user = User::factory()->create(['is_admin' => false]); + $user->refresh(); + + // The admin middleware bounces non-admins to the app root, not the dashboard. + $this->actingAs($user) + ->get('/horizon') + ->assertRedirect(config('app.url')); +});