diff --git a/src/Concerns/DealsWithRouteContexts.php b/src/Concerns/DealsWithRouteContexts.php index 1ca43e00..0b647000 100644 --- a/src/Concerns/DealsWithRouteContexts.php +++ b/src/Concerns/DealsWithRouteContexts.php @@ -22,18 +22,32 @@ use Stancl\Tenancy\Enums\RouteMode; trait DealsWithRouteContexts { /** - * Get route's middleware context (tenant, central or universal). - * The context is determined by the route's middleware. + * Get the middleware context of a route (tenant, central, or universal). * * If the route has the 'universal' middleware, the context is universal, * and the route is accessible from both contexts. + * * The universal flag has the highest priority. * - * If the route has the 'central' middleware, the context is central. - * If the route has the 'tenant' middleware, or any tenancy identification middleware, the context is tenant. + * If you want a universal route to be accessible from the tenant context, + * you still have to provide an identification middleware either using + * route-level middleware or in the global middleware stack. * - * If the route doesn't have any of the mentioned middleware, + * If the 'tenant' group has identification middleware, you can use it in + * combination with the 'universal' flag, the route will still be universal. + * + * If the route has the 'tenant' middleware, or any tenancy identification + * middleware, the context is tenant (assuming the route doesn't also have + * the 'universal' flag). + * + * If the route has the 'central' middleware, the context is central. + * + * If the route doesn't have any of the mentioned flags/middleware, * the context is determined by the `tenancy.default_route_mode` config. + * + * If the default route mode is tenant, all unflagged routes will be tenant by default, + * but they will still have to have an identification midddleware (route-level + * or global) to be accessible. Same applies for universal default route mode. */ public static function getRouteMode(Route $route): RouteMode { diff --git a/tests/Bootstrappers/DatabaseSessionBootstrapperTest.php b/tests/Bootstrappers/DatabaseSessionBootstrapperTest.php index baca93ac..f249c975 100644 --- a/tests/Bootstrappers/DatabaseSessionBootstrapperTest.php +++ b/tests/Bootstrappers/DatabaseSessionBootstrapperTest.php @@ -93,8 +93,14 @@ test('central helper can be used in tenant requests', function (bool $enabled, b } } })->with([ - ['enabled' => false, 'shouldThrow' => true], - ['enabled' => true, 'shouldThrow' => false], + [ + false, // Disabled + true // Should throw + ], + [ + true, // Enabled + false // Should not throw + ], ]); test('tenant run helper can be used on central requests', function (bool $enabled, bool $shouldThrow) { @@ -140,6 +146,12 @@ test('tenant run helper can be used on central requests', function (bool $enable } } })->with([ - ['enabled' => false, 'shouldThrow' => true], - ['enabled' => true, 'shouldThrow' => false], + [ + false, // Disabled + true // Should throw + ], + [ + true, // Enabled + false // Should not throw + ], ]); diff --git a/tests/CloneActionTest.php b/tests/CloneActionTest.php index 3625266b..8be8881b 100644 --- a/tests/CloneActionTest.php +++ b/tests/CloneActionTest.php @@ -331,19 +331,19 @@ class CustomInitializeTenancyByPath extends InitializeTenancyByPath dataset('path identification types', [ 'kernel identification' => [ - 'route_middleware' => ['universal'], - 'global_middleware' => [InitializeTenancyByPath::class], + ['universal'], // Route middleware + [InitializeTenancyByPath::class], // Global Global middleware ], 'route-level identification' => [ - 'route_middleware' => ['universal', InitializeTenancyByPath::class], - 'global_middleware' => [], + ['universal', InitializeTenancyByPath::class], // Route middleware + [], // Global middleware ], 'kernel identification + defaulting to universal routes' => [ - 'route_middleware' => [], - 'global_middleware' => ['universal', InitializeTenancyByPath::class], + [], // Route middleware + ['universal', InitializeTenancyByPath::class], // Global middleware ], 'route-level identification + defaulting to universal routes' => [ - 'route_middleware' => [InitializeTenancyByPath::class], - 'global_middleware' => ['universal'], + [InitializeTenancyByPath::class], // Route middleware + ['universal'], // Global middleware ], ]); diff --git a/tests/EarlyIdentificationTest.php b/tests/EarlyIdentificationTest.php index 2cd9cd19..4fbf6e3a 100644 --- a/tests/EarlyIdentificationTest.php +++ b/tests/EarlyIdentificationTest.php @@ -15,6 +15,7 @@ use Stancl\Tenancy\Middleware\InitializeTenancyByPath; use Stancl\Tenancy\Middleware\InitializeTenancyByDomain; use Stancl\Tenancy\Middleware\InitializeTenancyBySubdomain; use Stancl\Tenancy\Bootstrappers\DatabaseTenancyBootstrapper; +use Stancl\Tenancy\Exceptions\NotASubdomainException; use Stancl\Tenancy\Middleware\InitializeTenancyByRequestData; use Stancl\Tenancy\Tests\Etc\EarlyIdentification\Models\Post; use Stancl\Tenancy\Middleware\PreventAccessFromUnwantedDomains; @@ -22,6 +23,7 @@ use Stancl\Tenancy\Middleware\InitializeTenancyByDomainOrSubdomain; use Stancl\Tenancy\Middleware\InitializeTenancyByOriginHeader; use Stancl\Tenancy\Tests\Etc\EarlyIdentification\ControllerWithMiddleware; use Stancl\Tenancy\Tests\Etc\EarlyIdentification\ControllerWithRouteMiddleware; +use Stancl\Tenancy\Exceptions\TenantCouldNotBeIdentifiedOnDomainException; beforeEach(function () { config()->set([ @@ -35,6 +37,30 @@ beforeEach(function () { }); }); +dataset('identification_middleware', [ + InitializeTenancyByDomain::class, + InitializeTenancyBySubdomain::class, + InitializeTenancyByDomainOrSubdomain::class, + InitializeTenancyByPath::class, + InitializeTenancyByRequestData::class, +]); + +dataset('domain_identification_middleware', [ + InitializeTenancyByDomain::class, + InitializeTenancyBySubdomain::class, + InitializeTenancyByDomainOrSubdomain::class, +]); + +dataset('default_route_modes', [ + RouteMode::TENANT, + RouteMode::CENTRAL, +]); + +dataset('global_and_route_level_identification', [ + false, // Route-level identification + true, // Global identification +]); + test('early identification works with path identification', function (bool $useKernelIdentification, RouteMode $defaultRouteMode) { $identificationMiddleware = InitializeTenancyByPath::class; @@ -117,14 +143,8 @@ test('early identification works with path identification', function (bool $useK ->assertOk() ->assertContent($tenantPost->title . '-' . $tenantComment->comment); assertTenancyInitializedInEarlyIdentificationRequest(); -})->with([ - 'route-level identification' => false, - 'kernel identification' => true, -// Creates a matrix (multiple with()) -])->with([ - 'default to tenant routes' => RouteMode::TENANT, - 'default to central routes' => RouteMode::CENTRAL, -]); +})->with('global_and_route_level_identification') + ->with('default_route_modes'); test('early identification works with request data identification', function (string $type, bool $useKernelIdentification, RouteMode $defaultRouteMode) { $identificationMiddleware = InitializeTenancyByRequestData::class; @@ -168,14 +188,8 @@ test('early identification works with request data identification', function (st 'using request header parameter' => 'header', 'using request query parameter' => 'queryParameter', 'using request cookie parameter' => 'cookie', -// Creates a matrix (multiple with()) -])->with([ - 'route-level identification' => false, - 'kernel identification' => true, -])->with([ - 'default to tenant routes' => RouteMode::TENANT, - 'default to central routes' => RouteMode::CENTRAL, -]); +])->with('global_and_route_level_identification')->with('default_route_modes'); + test('early identification works with origin identification', function (bool $useKernelIdentification, RouteMode $defaultRouteMode) { $identificationMiddleware = InitializeTenancyByOriginHeader::class; @@ -209,85 +223,111 @@ test('early identification works with origin identification', function (bool $us $response = pest()->post('/tenant-route', headers: ['Origin' => 'foo.localhost']); $response->assertOk()->assertSee('token:' . $tenantKey); -})->with([ - 'route-level identification' => false, - 'kernel identification' => true, -])->with([ - 'default to tenant routes' => RouteMode::TENANT, - 'default to central routes' => RouteMode::CENTRAL, -]); +})->with('global_and_route_level_identification')->with('default_route_modes'); -test('early identification works with domain identification', function (string $middleware, string $domain, bool $useKernelIdentification, RouteMode $defaultRouteMode) { - config(['tenancy.default_route_mode' => $defaultRouteMode]); +test('early identification works with domain identification', function (string $middleware, bool $useKernelIdentification) { + $tenant = Tenant::create(); + + // Create domain and a subdomain for the tenant + $tenant->createDomain('foo.test'); + $tenant->createDomain('foo'); if ($useKernelIdentification) { - $controller = ControllerWithMiddleware::class; app(Kernel::class)->pushMiddleware($middleware); app(Kernel::class)->pushMiddleware(PreventAccessFromUnwantedDomains::class); + + RouteFacade::get('/tenant-route', [ControllerWithMiddleware::class, 'index'])->middleware('tenant'); } else { - $controller = ControllerWithRouteMiddleware::class; - RouteFacade::middlewareGroup('tenant', [$middleware, PreventAccessFromUnwantedDomains::class]); + RouteFacade::get('/tenant-route', [ControllerWithRouteMiddleware::class, 'index'])->middleware([$middleware, PreventAccessFromUnwantedDomains::class]); } - // Tenant route - $tenantRoute = RouteFacade::get('/tenant-route', [$controller, 'index']); + $domainUrl = 'http://foo.test/tenant-route'; + $subdomainUrl = str(config('app.url'))->replaceFirst('://', "://foo.")->toString() . '/tenant-route'; - // Central route - $centralRoute = RouteFacade::get('/central-route', function () { - return 'central route'; + $tenantUrls = Arr::wrap(match ($middleware) { + InitializeTenancyByDomain::class => $domainUrl, + InitializeTenancyBySubdomain::class => $subdomainUrl, + InitializeTenancyByDomainOrSubdomain::class => [$domainUrl, $subdomainUrl], // Domain or subdomain -- try visiting both }); - $defaultToTenantRoutes = $defaultRouteMode === RouteMode::TENANT; + foreach ($tenantUrls as $url) { + $response = pest()->get($url); - // Test defaulting to route mode (central/tenant context) - if ($useKernelIdentification) { - $routeThatShouldReceiveMiddleware = $defaultToTenantRoutes ? $centralRoute : $tenantRoute; - $routeThatShouldReceiveMiddleware->middleware($defaultToTenantRoutes ? 'central' : 'tenant'); - } elseif (! $defaultToTenantRoutes) { - $tenantRoute->middleware('tenant'); - } else { - // Route-level identification + defaulting to tenant routes - // We still have to apply the tenant middleware to the routes, so they aren't really tenant by default - $tenantRoute->middleware([$middleware, PreventAccessFromUnwantedDomains::class]); + $response->assertOk(); + + assertTenancyInitializedInEarlyIdentificationRequest(); + + // Expect tenancy is initialized (or not) for the right tenant at the tenant route + expect($response->getContent())->toBe('token:' . tenant()->getTenantKey()); } +})->with('domain_identification_middleware') + ->with('global_and_route_level_identification'); + +test('using different default route modes works with global domain identification', function(string $middleware, RouteMode $defaultRouteMode) { + config(['tenancy.default_route_mode' => $defaultRouteMode]); $tenant = Tenant::create(); - $tenant->domains()->create([ - 'domain' => $domain, - ]); + // Create domain and a subdomain for the tenant + $tenant->createDomain('foo.test'); + $tenant->createDomain('foo'); - if ($domain === 'foo') { - $domain = 'foo.localhost'; + // Create central and tenant routes, without any identification middleware or tags + $centralRoute = RouteFacade::get('/central-route', fn () => 'central route'); + RouteFacade::get('/tenant-route', [ControllerWithMiddleware::class, 'index']); + + // Add the domain identification middleware to the kernel MW + app(Kernel::class)->pushMiddleware($middleware); + app(Kernel::class)->pushMiddleware(PreventAccessFromUnwantedDomains::class); + + $domainUrl = 'http://foo.test/tenant-route'; + $subdomainUrl = str(config('app.url'))->replaceFirst('://', "://foo.")->toString() . '/tenant-route'; + + $tenantUrls = Arr::wrap(match ($middleware) { + InitializeTenancyByDomain::class => $domainUrl, + InitializeTenancyBySubdomain::class => $subdomainUrl, + InitializeTenancyByDomainOrSubdomain::class => [$domainUrl, $subdomainUrl], // Domain or subdomain -- try visiting both + }); + + if ($defaultRouteMode === RouteMode::TENANT) { + // When defaulting to tenant routes and using kernel identification, + // the central route should not be accessible if not flagged as central. + + // Since central-route is considered tenant by default, and there's tenant ID MW, + // expect that an exception specific to that ID MW to be thrown when trying to access the route. + $exception = match ($middleware) { + InitializeTenancyByDomain::class => TenantCouldNotBeIdentifiedOnDomainException::class, + InitializeTenancyBySubdomain::class => NotASubdomainException::class, + InitializeTenancyByDomainOrSubdomain::class => NotASubdomainException::class, + }; + + expect(fn () => $this->withoutExceptionHandling()->get('http://localhost/central-route'))->toThrow($exception); + + // Flagging the central route as central should make it accessible, + // even if the default route mode is tenant + $centralRoute = $centralRoute->middleware('central'); + + pest()->get('http://localhost/central-route')->assertOk()->assertSee('central route'); } - pest()->get('http://localhost/central-route')->assertOk()->assertContent('central route'); // Central route is accessible + foreach ($tenantUrls as $url) { + $response = pest()->get($url); - $response = pest()->get("http://{$domain}/tenant-route"); + // If the default route mode is tenant, only the tenant route should be accessible + // and tenancy should be initialized using early identification for the correct tenant + if ($defaultRouteMode === RouteMode::TENANT) { + $response->assertOk(); - if ($defaultToTenantRoutes === $useKernelIdentification || $useKernelIdentification) { - $response->assertOk(); - assertTenancyInitializedInEarlyIdentificationRequest(); - } elseif (! $defaultToTenantRoutes) { - $response->assertNotFound(); - assertTenancyInitializedInEarlyIdentificationRequest(false); + assertTenancyInitializedInEarlyIdentificationRequest(); + + // Expect tenancy is initialized for the right tenant at the tenant route + expect($response->getContent())->toBe('token:' . tenant()->getTenantKey()); + } else { + $response->assertNotFound(); + } } - - // Expect tenancy is initialized (or not) for the right tenant at the tenant route - expect($response->getContent())->toBe('token:' . tenant()->getTenantKey()); -})->with([ - 'domain identification' => ['middleware' => InitializeTenancyByDomain::class, 'domain' => 'foo.test'], - 'subdomain identification' => ['middleware' => InitializeTenancyBySubdomain::class, 'domain' => 'foo'], - 'domainOrSubdomain identification using domain' => ['middleware' => InitializeTenancyByDomainOrSubdomain::class, 'domain' => 'foo.test'], - 'domainOrSubdomain identification using subdomain' => ['middleware' => InitializeTenancyByDomainOrSubdomain::class, 'domain' => 'foo'], -// Creates a matrix (multiple with()) -])->with([ - 'route-level identification' => false, - 'kernel identification' => true, -])->with([ - 'default to tenant routes' => RouteMode::TENANT, - 'default to central routes' => RouteMode::CENTRAL, -]); +})->with('domain_identification_middleware') + ->with('default_route_modes'); test('the tenant parameter is only removed from tenant routes when using path identification', function (bool $kernelIdentification, bool $pathIdentification) { if ($kernelIdentification) { @@ -373,62 +413,97 @@ test('the tenant parameter is only removed from tenant routes when using path id } } })->with([ - 'kernel path identification' => ['kernelIdentification' => true, 'pathIdentification' => true], - 'route-level path identification' => ['kernelIdentification' => false, 'pathIdentification' => true], - 'kernel domain identification' => ['kernelIdentification' => true, 'pathIdentification' => false], - 'route-level domain identification' => ['kernelIdentification' => false, 'pathIdentification' => false], + 'kernel path identification' => [ + true, // Kernel identification + true // Path identification + ], + 'route-level path identification' => [ + false, // Kernel identification + true // Path identification + ], + 'kernel domain identification' => [ + true, + false // Path identification + ], + 'route-level domain identification' => [ + false, // Kernel identification + false // Path identification + ], ]); -test('route level identification is prioritized over kernel identification', function ( - string|array $kernelIdentificationMiddleware, - string|array $routeIdentificationMiddleware, - string $routeUri, - string $domainToVisit, - string|null $domain = null, +test('route level domain identification is prioritized over kernel identification', function ( + string $kernelIdentificationMiddleware, + string $routeIdentificationMiddleware, RouteMode $defaultRouteMode, ) { $tenant = Tenant::create(); - $domainToVisit = str_replace('{tenantKey}', $tenant->getTenantKey(), $domainToVisit); config(['tenancy.default_route_mode' => $defaultRouteMode]); - if ($domain) { - $tenant->domains()->create(['domain' => str_replace('{tenantKey}', $tenant->getTenantKey(), $domain)]); + // Subdomain + $tenant->createDomain($subdomain = $tenant->getTenantKey()); + $tenant->createDomain($domain = $subdomain . '.test'); + + app(Kernel::class)->pushMiddleware(PreventAccessFromUnwantedDomains::class)->pushMiddleware($kernelIdentificationMiddleware); + + // We're testing *non-early* route-level identification so that we can assert that early kernel identification got skipped + // Also, ignore the defaulting when the identification MW is applied directly on the route + // Because the route is automatically considered tenant if it has identification middleware (unless it also has the 'universal' middleware) + RouteFacade::get('tenant-route', [ControllerWithMiddleware::class, 'index']) + ->middleware([PreventAccessFromUnwantedDomains::class, $routeIdentificationMiddleware]); + + $domainIdUrl = "http://{$domain}/tenant-route"; + $subdomainIdUrl = str(config('app.url'))->replaceFirst('://', "://{$subdomain}.")->append("/tenant-route")->toString(); + + $urlsToVisit = Arr::wrap(match ($routeIdentificationMiddleware) { + InitializeTenancyByDomain::class => $domainIdUrl, + InitializeTenancyBySubdomain::class => $subdomainIdUrl, + InitializeTenancyByDomainOrSubdomain::class => [$domainIdUrl, $subdomainIdUrl], // Domain or subdomain -- try visiting both + }); + + foreach ($urlsToVisit as $url) { + pest()->get($url)->assertOk(); + + // Kernel (early) identification skipped + expect(app()->make('controllerRunsInTenantContext'))->toBeFalse(); + } +})->with('identification_middleware') + ->with('domain_identification_middleware') + ->with('default_route_modes'); + +test('route level path and request data identification is prioritized over kernel identification', function ( + string $kernelIdentificationMiddleware, + string $routeIdentificationMiddleware, + RouteMode $defaultRouteMode, +) { + $tenant = Tenant::create(); + config(['tenancy.default_route_mode' => $defaultRouteMode]); + + if (in_array($kernelIdentificationMiddleware, config('tenancy.identification.domain_identification_middleware'))) { + // If a domain identification middleware is used, the prevent access MW is used too + app(Kernel::class)->pushMiddleware(PreventAccessFromUnwantedDomains::class); } - foreach (Arr::wrap($kernelIdentificationMiddleware) as $identificationMiddleware) { - app(Kernel::class)->pushMiddleware($identificationMiddleware); - } + app(Kernel::class)->pushMiddleware($kernelIdentificationMiddleware); // We're testing *non-early* route-level identification so that we can assert that early kernel identification got skipped // Also, ignore the defaulting when the identification MW is applied directly on the route // The route is automatically considered tenant if it has identification middleware (unless it also has the 'universal' middleware) - RouteFacade::get($routeUri, [ControllerWithMiddleware::class, 'index'])->middleware($routeIdentificationMiddleware); + $route = RouteFacade::get('/tenant-route', [ControllerWithMiddleware::class, 'index'])->middleware($routeIdentificationMiddleware)->name('tenant-route'); - pest()->get($domainToVisit)->assertOk(); + if ($routeIdentificationMiddleware === InitializeTenancyByPath::class) { + $route = $route->prefix('{tenant}'); + } + + pest()->get(route('tenant-route', ['tenant' => $tenant->getTenantKey()]))->assertOk(); // Kernel (early) identification skipped expect(app()->make('controllerRunsInTenantContext'))->toBeFalse(); -})->with([ - 'kernel request data identification mw' => ['kernelMiddleware' => InitializeTenancyByRequestData::class], - 'kernel path identification mw' => ['kernelMiddleware' => InitializeTenancyByPath::class], - 'kernel domain identification mw' => ['kernelMiddleware' => [PreventAccessFromUnwantedDomains::class, InitializeTenancyByDomain::class]], - 'kernel subdomain identification mw' => ['kernelMiddleware' => [PreventAccessFromUnwantedDomains::class, InitializeTenancyBySubdomain::class]], - 'kernel domainOrSubdomain identification mw using domain' => ['kernelMiddleware' => [PreventAccessFromUnwantedDomains::class, InitializeTenancyByDomainOrSubdomain::class]], - 'kernel domainOrSubdomain identification mw using subdomain' => ['kernelMiddleware' => [PreventAccessFromUnwantedDomains::class, InitializeTenancyByDomainOrSubdomain::class]], -// Creates a matrix (multiple with()) -])->with([ - 'route level request data identification mw' => ['routeLevelMiddleware' => InitializeTenancyByRequestData::class, 'routeUri' => '/tenant-route', 'domainToVisit' => 'http://localhost/tenant-route?tenant={tenantKey}', 'domain' => null], - 'route level path identification mw' => ['routeLevelMiddleware' => InitializeTenancyByPath::class, 'routeUri' => '/{tenant}/tenant-route', 'domainToVisit' => 'http://localhost/{tenantKey}/tenant-route', 'domain' => null], - 'route level domain identification mw' => ['routeLevelMiddleware' => [PreventAccessFromUnwantedDomains::class, InitializeTenancyByDomain::class], 'routeUri' => '/tenant-route', 'domainToVisit' => 'http://{tenantKey}.test/tenant-route', 'domain' => '{tenantKey}.test'], - 'route level subdomain identification mw' => ['routeLevelMiddleware' => [PreventAccessFromUnwantedDomains::class, InitializeTenancyBySubdomain::class], 'routeUri' => '/tenant-route', 'domainToVisit' => 'http://{tenantKey}.localhost/tenant-route', 'domain' => '{tenantKey}'], - 'route level domainOrSubdomain identification mw using domain' => ['routeLevelMiddleware' => [PreventAccessFromUnwantedDomains::class, InitializeTenancyByDomainOrSubdomain::class], 'routeUri' => '/tenant-route', 'domainToVisit' => 'http://{tenantKey}.test/tenant-route', 'domain' => '{tenantKey}.test'], - 'route level domainOrSubdomain identification mw using subdomain' => ['routeLevelMiddleware' => [PreventAccessFromUnwantedDomains::class, InitializeTenancyByDomainOrSubdomain::class], 'routeUri' => '/tenant-route', 'domainToVisit' => 'http://{tenantKey}.localhost/tenant-route', 'domain' => '{tenantKey}'], -]) -->with([ - 'default to tenant routes' => RouteMode::TENANT, - 'default to central routes' => RouteMode::CENTRAL, -]); +})->with('identification_middleware') + ->with([ + 'route level request data identification' => InitializeTenancyByRequestData::class, + 'route level path identification' => InitializeTenancyByPath::class, +])->with('default_route_modes'); function assertTenancyInitializedInEarlyIdentificationRequest(bool $expect = true): void { diff --git a/tests/PreventAccessFromUnwantedDomainsTest.php b/tests/PreventAccessFromUnwantedDomainsTest.php index 18c0daaa..99d0c2fe 100644 --- a/tests/PreventAccessFromUnwantedDomainsTest.php +++ b/tests/PreventAccessFromUnwantedDomainsTest.php @@ -180,8 +180,8 @@ test('kernel PreventAccessFromUnwantedDomains does not get skipped when route le ]); test('placement of domain identification and access prevention middleware can get mixed', function ( - array $globalMiddleware, array $routeMiddleware, + array $globalMiddleware, array $centralRouteMiddleware ) { config([ @@ -214,16 +214,16 @@ test('placement of domain identification and access prevention middleware can ge expect(tenancy()->initialized)->toBeFalse(); })->with([ 'route-level identification, kernel access prevention' => [ - 'global_middleware' => [PreventAccessFromUnwantedDomains::class], - 'route_middleware' => [InitializeTenancyBySubdomain::class], + [InitializeTenancyBySubdomain::class], // Route middleware + [PreventAccessFromUnwantedDomains::class], // Global middleware ], 'kernel identification, kernel access prevention' => [ - 'global_middleware' => [PreventAccessFromUnwantedDomains::class, InitializeTenancyBySubdomain::class], - 'route_middleware' => [], + [], // Route middleware + [PreventAccessFromUnwantedDomains::class, InitializeTenancyBySubdomain::class], // Global middleware ], 'route-level identification, route-level access prevention' => [ - 'global_middleware' => [], - 'route_middleware' => [PreventAccessFromUnwantedDomains::class, InitializeTenancyBySubdomain::class], + [PreventAccessFromUnwantedDomains::class, InitializeTenancyBySubdomain::class], // Route middleware + [], // Global middleware ], // Creates a matrix (multiple with()) ])->with([ diff --git a/tests/SingleDomainTenantTest.php b/tests/SingleDomainTenantTest.php index 3c976821..3a68ee8b 100644 --- a/tests/SingleDomainTenantTest.php +++ b/tests/SingleDomainTenantTest.php @@ -123,11 +123,11 @@ test('single domain tenant can be identified by domain or subdomain', function ( expect(tenant('id'))->toBe($tenant->id); })->with([ [ - 'domain' => 'acme.localhost', - 'identification middleware' => [PreventAccessFromUnwantedDomains::class, InitializeTenancyByDomain::class], + 'acme.localhost', // Domain + [PreventAccessFromUnwantedDomains::class, InitializeTenancyByDomain::class], // Identification middleware ], [ - 'subdomain' => 'acme', - 'identification middleware' => [PreventAccessFromUnwantedDomains::class, InitializeTenancyBySubdomain::class], + 'acme', // Subdomain + [PreventAccessFromUnwantedDomains::class, InitializeTenancyBySubdomain::class], // Identification middleware ], ]); diff --git a/tests/UniversalRouteTest.php b/tests/UniversalRouteTest.php index 2c731881..528d46bf 100644 --- a/tests/UniversalRouteTest.php +++ b/tests/UniversalRouteTest.php @@ -327,20 +327,20 @@ foreach ([ ] as $datasetName => $middleware) { dataset($datasetName, [ 'kernel identification' => [ - 'route_middleware' => ['universal'], - 'global_middleware' => $middleware, + ['universal'], // Route middleware + $middleware, // Global middleware ], 'route-level identification' => [ - 'route_middleware' => ['universal', ...$middleware], - 'global_middleware' => [], + ['universal', ...$middleware], // Route middleware + [], // Global middleware ], 'kernel identification + defaulting to universal routes' => [ - 'route_middleware' => [], - 'global_middleware' => ['universal', ...$middleware], + [], // Route middleware + ['universal', ...$middleware], // Global middleware ], 'route-level identification + defaulting to universal routes' => [ - 'route_middleware' => $middleware, - 'global_middleware' => ['universal'], + $middleware, // Route middleware + ['universal'], // Global middleware ], ]); }