From e1b86584146d4566e0cc60bef327994471c56d35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20=C5=A0tancl?= Date: Tue, 14 Oct 2025 17:11:47 +0200 Subject: [PATCH] Fix #1404: support universal routes in CheckTenantForMaintenanceMode This commit also corrects an Event::fake() call in a separate test, as general Event::fake() calls without specified events can lead to incorrect (and difficult to debug) behavior in some cases, since Tenancy depends on the event system being functional. --- .../CheckTenantForMaintenanceMode.php | 8 +++- tests/MaintenanceModeTest.php | 40 ++++++++++++++++--- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/Middleware/CheckTenantForMaintenanceMode.php b/src/Middleware/CheckTenantForMaintenanceMode.php index 58fcd184..3e91902f 100644 --- a/src/Middleware/CheckTenantForMaintenanceMode.php +++ b/src/Middleware/CheckTenantForMaintenanceMode.php @@ -14,7 +14,13 @@ class CheckTenantForMaintenanceMode extends CheckForMaintenanceMode public function handle($request, Closure $next) { if (! tenant()) { - throw new TenancyNotInitializedException; + // If there's no tenant, there's no tenant to check for maintenance mode. + // Since tenant identification middleware has higher priority than this + // middleware, a missing tenant would have already lead to request termination. + // (And even if priority were misconfigured, the request would simply get + // terminated *after* this middleware.) + // Therefore, we are likely on a universal route, in central context. + return $next($request); } if (tenant('maintenance_mode')) { diff --git a/tests/MaintenanceModeTest.php b/tests/MaintenanceModeTest.php index 9c90f0d3..9959992b 100644 --- a/tests/MaintenanceModeTest.php +++ b/tests/MaintenanceModeTest.php @@ -6,6 +6,8 @@ use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Event; use Stancl\Tenancy\Database\Concerns\MaintenanceMode; use Illuminate\Support\Facades\Route; +use Stancl\Tenancy\Events\TenantMaintenanceModeDisabled; +use Stancl\Tenancy\Events\TenantMaintenanceModeEnabled; use Stancl\Tenancy\Middleware\CheckTenantForMaintenanceMode; use Stancl\Tenancy\Middleware\InitializeTenancyByDomain; use function Stancl\Tenancy\Tests\pest; @@ -38,18 +40,46 @@ test('tenants can be in maintenance mode', function () { pest()->get('http://acme.localhost/foo')->assertStatus(200); }); -test('maintenance mode events are fired', function () { - $tenant = MaintenanceTenant::create(); +test('maintenance mode middleware can be used with universal routes', function () { + Route::get('/foo', function () { + return 'bar'; + })->middleware(['universal', InitializeTenancyByDomain::class, CheckTenantForMaintenanceMode::class]); - Event::fake(); + $tenant = MaintenanceTenant::create(); + $tenant->domains()->create([ + 'domain' => 'acme.localhost', + ]); + + // Revert to central context after each request so that the tenant context + // from the request doesn't persist + $run = function (Closure $callback) { $callback(); tenancy()->end(); }; + + $run(fn () => pest()->get('http://acme.localhost/foo')->assertStatus(200)); + $run(fn () => pest()->get('http://localhost/foo')->assertStatus(200)); $tenant->putDownForMaintenance(); - Event::assertDispatched(\Stancl\Tenancy\Events\TenantMaintenanceModeEnabled::class); + $run(fn () => pest()->get('http://acme.localhost/foo')->assertStatus(503)); + $run(fn () => pest()->get('http://localhost/foo')->assertStatus(200)); // Not affected by a tenant's maintenance mode $tenant->bringUpFromMaintenance(); - Event::assertDispatched(\Stancl\Tenancy\Events\TenantMaintenanceModeDisabled::class); + $run(fn () => pest()->get('http://acme.localhost/foo')->assertStatus(200)); + $run(fn () => pest()->get('http://localhost/foo')->assertStatus(200)); +}); + +test('maintenance mode events are fired', function () { + $tenant = MaintenanceTenant::create(); + + Event::fake([TenantMaintenanceModeEnabled::class, TenantMaintenanceModeDisabled::class]); + + $tenant->putDownForMaintenance(); + + Event::assertDispatched(TenantMaintenanceModeEnabled::class); + + $tenant->bringUpFromMaintenance(); + + Event::assertDispatched(TenantMaintenanceModeDisabled::class); }); test('tenants can be put into maintenance mode using artisan commands', function() {