1
0
Fork 0
mirror of https://github.com/archtechx/tenancy.git synced 2025-12-12 23:14:03 +00:00

Improve early identification tests (#66)

* Separate route-level domain identification test from path/request to improve readability WIP

* Get rid of confusing datasets in route-level identifcation tests

* Clean up updated tests

* Simplify early id tests

* Reduce dataset duplication

* Improve test readability, fix false positive,  polish details

* Separate early ID test from defaulting test (WIP)

* Finish improving and correcting the early identification/default route mode tests

* Make flag/default mode usage more clear by improving the docblock in DealsWithRouteContexts

* Fix PHPUnit deprecation warnings

* code review

* code review

---------

Co-authored-by: Samuel Štancl <samuel@archte.ch>
This commit is contained in:
lukinovec 2024-12-20 03:42:23 +01:00 committed by GitHub
parent 48b916e182
commit cb0d7e2902
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 248 additions and 147 deletions

View file

@ -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
{

View file

@ -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
],
]);

View file

@ -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
],
]);

View file

@ -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,
]);
test('early identification works with domain identification', function (string $middleware, string $domain, bool $useKernelIdentification, RouteMode $defaultRouteMode) {
config(['tenancy.default_route_mode' => $defaultRouteMode]);
if ($useKernelIdentification) {
$controller = ControllerWithMiddleware::class;
app(Kernel::class)->pushMiddleware($middleware);
app(Kernel::class)->pushMiddleware(PreventAccessFromUnwantedDomains::class);
} else {
$controller = ControllerWithRouteMiddleware::class;
RouteFacade::middlewareGroup('tenant', [$middleware, PreventAccessFromUnwantedDomains::class]);
}
// Tenant route
$tenantRoute = RouteFacade::get('/tenant-route', [$controller, 'index']);
// Central route
$centralRoute = RouteFacade::get('/central-route', function () {
return 'central route';
});
$defaultToTenantRoutes = $defaultRouteMode === RouteMode::TENANT;
// 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]);
}
})->with('global_and_route_level_identification')->with('default_route_modes');
test('early identification works with domain identification', function (string $middleware, bool $useKernelIdentification) {
$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';
if ($useKernelIdentification) {
app(Kernel::class)->pushMiddleware($middleware);
app(Kernel::class)->pushMiddleware(PreventAccessFromUnwantedDomains::class);
RouteFacade::get('/tenant-route', [ControllerWithMiddleware::class, 'index'])->middleware('tenant');
} else {
RouteFacade::get('/tenant-route', [ControllerWithRouteMiddleware::class, 'index'])->middleware([$middleware, PreventAccessFromUnwantedDomains::class]);
}
pest()->get('http://localhost/central-route')->assertOk()->assertContent('central route'); // Central route is accessible
$domainUrl = 'http://foo.test/tenant-route';
$subdomainUrl = str(config('app.url'))->replaceFirst('://', "://foo.")->toString() . '/tenant-route';
$response = pest()->get("http://{$domain}/tenant-route");
$tenantUrls = Arr::wrap(match ($middleware) {
InitializeTenancyByDomain::class => $domainUrl,
InitializeTenancyBySubdomain::class => $subdomainUrl,
InitializeTenancyByDomainOrSubdomain::class => [$domainUrl, $subdomainUrl], // Domain or subdomain -- try visiting both
});
foreach ($tenantUrls as $url) {
$response = pest()->get($url);
if ($defaultToTenantRoutes === $useKernelIdentification || $useKernelIdentification) {
$response->assertOk();
assertTenancyInitializedInEarlyIdentificationRequest();
} elseif (! $defaultToTenantRoutes) {
$response->assertNotFound();
assertTenancyInitializedInEarlyIdentificationRequest(false);
}
// 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('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();
// Create domain and a subdomain for the tenant
$tenant->createDomain('foo.test');
$tenant->createDomain('foo');
// 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');
}
foreach ($tenantUrls as $url) {
$response = pest()->get($url);
// 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();
assertTenancyInitializedInEarlyIdentificationRequest();
// Expect tenancy is initialized for the right tenant at the tenant route
expect($response->getContent())->toBe('token:' . tenant()->getTenantKey());
} else {
$response->assertNotFound();
}
}
})->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('identification_middleware')
->with([
'default to tenant routes' => RouteMode::TENANT,
'default to central routes' => RouteMode::CENTRAL,
]);
'route level request data identification' => InitializeTenancyByRequestData::class,
'route level path identification' => InitializeTenancyByPath::class,
])->with('default_route_modes');
function assertTenancyInitializedInEarlyIdentificationRequest(bool $expect = true): void
{

View file

@ -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([

View file

@ -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
],
]);

View file

@ -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
],
]);
}