mirror of
https://github.com/archtechx/tenancy.git
synced 2025-12-12 09:34:04 +00:00
Add identification section to config, refactor static properties
This commit is contained in:
parent
e5bc8ddb77
commit
ccaba05272
17 changed files with 153 additions and 97 deletions
|
|
@ -144,16 +144,8 @@ class TenancyServiceProvider extends ServiceProvider
|
||||||
|
|
||||||
protected function makeTenancyMiddlewareHighestPriority()
|
protected function makeTenancyMiddlewareHighestPriority()
|
||||||
{
|
{
|
||||||
$tenancyMiddleware = [
|
// Even higher priority than the initialization middleware
|
||||||
// Even higher priority than the initialization middleware
|
$tenancyMiddleware = array_merge([Middleware\PreventAccessFromCentralDomains::class], config('tenancy.identification.middleware'));
|
||||||
Middleware\PreventAccessFromCentralDomains::class,
|
|
||||||
|
|
||||||
Middleware\InitializeTenancyByDomain::class,
|
|
||||||
Middleware\InitializeTenancyBySubdomain::class,
|
|
||||||
Middleware\InitializeTenancyByDomainOrSubdomain::class,
|
|
||||||
Middleware\InitializeTenancyByPath::class,
|
|
||||||
Middleware\InitializeTenancyByRequestData::class,
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach (array_reverse($tenancyMiddleware) as $middleware) {
|
foreach (array_reverse($tenancyMiddleware) as $middleware) {
|
||||||
$this->app[\Illuminate\Contracts\Http\Kernel::class]->prependToMiddlewarePriority($middleware);
|
$this->app[\Illuminate\Contracts\Http\Kernel::class]->prependToMiddlewarePriority($middleware);
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ declare(strict_types=1);
|
||||||
|
|
||||||
use Stancl\Tenancy\Database\Models\Domain;
|
use Stancl\Tenancy\Database\Models\Domain;
|
||||||
use Stancl\Tenancy\Database\Models\Tenant;
|
use Stancl\Tenancy\Database\Models\Tenant;
|
||||||
|
use Stancl\Tenancy\Middleware;
|
||||||
|
use Stancl\Tenancy\Resolvers;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'tenant_model' => Tenant::class,
|
'tenant_model' => Tenant::class,
|
||||||
|
|
@ -21,6 +23,56 @@ return [
|
||||||
'localhost',
|
'localhost',
|
||||||
],
|
],
|
||||||
|
|
||||||
|
'identification' => [
|
||||||
|
/**
|
||||||
|
* The default middleware used for tenant identification.
|
||||||
|
*
|
||||||
|
* If you use multiple forms of identification, you can set this to the "main" approach you use.
|
||||||
|
*/
|
||||||
|
'default_middleware' => Middleware\InitializeTenancyByDomain::class,// todo@identification add this to a 'tenancy' mw group
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All of the identification middleware used by the package.
|
||||||
|
*
|
||||||
|
* If you write your own, make sure to add them to this array.
|
||||||
|
*/
|
||||||
|
'middleware' => [
|
||||||
|
Middleware\InitializeTenancyByDomain::class,
|
||||||
|
Middleware\InitializeTenancyBySubdomain::class,
|
||||||
|
Middleware\InitializeTenancyByDomainOrSubdomain::class,
|
||||||
|
Middleware\InitializeTenancyByPath::class,
|
||||||
|
Middleware\InitializeTenancyByRequestData::class,
|
||||||
|
],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tenant resolvers used by the package.
|
||||||
|
*
|
||||||
|
* Resolvers which implement the CachedTenantResolver contract have options for configuring the caching details.
|
||||||
|
* If you add your own resolvers, do not add the 'cache' key unless your resolver is based on CachedTenantResolver.
|
||||||
|
*/
|
||||||
|
'resolvers' => [
|
||||||
|
Resolvers\DomainTenantResolver::class => [
|
||||||
|
'cache' => false,
|
||||||
|
'cache_ttl' => 3600, // seconds
|
||||||
|
'cache_store' => null, // default
|
||||||
|
],
|
||||||
|
Resolvers\PathTenantResolver::class => [
|
||||||
|
'tenant_parameter_name' => 'tenant',
|
||||||
|
|
||||||
|
'cache' => false,
|
||||||
|
'cache_ttl' => 3600, // seconds
|
||||||
|
'cache_store' => null, // default
|
||||||
|
],
|
||||||
|
Resolvers\RequestDataTenantResolver::class => [
|
||||||
|
'cache' => false,
|
||||||
|
'cache_ttl' => 3600, // seconds
|
||||||
|
'cache_store' => null, // default
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
// todo@docs update integration guides to use Stancl\Tenancy::defaultMiddleware()
|
||||||
|
],
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tenancy bootstrappers are executed when tenancy is initialized.
|
* Tenancy bootstrappers are executed when tenancy is initialized.
|
||||||
* Their responsibility is making Laravel features tenant-aware.
|
* Their responsibility is making Laravel features tenant-aware.
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,8 @@
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
|
use Stancl\Tenancy\Controllers\TenantAssetController;
|
||||||
|
|
||||||
Route::get('/tenancy/assets/{path?}', 'Stancl\Tenancy\Controllers\TenantAssetsController@asset')
|
Route::get('/tenancy/assets/{path?}', [TenantAssetController::class, 'asset'])
|
||||||
->where('path', '(.*)')
|
->where('path', '(.*)')
|
||||||
->name('stancl.tenancy.asset');
|
->name('stancl.tenancy.asset');
|
||||||
|
|
|
||||||
|
|
@ -4,18 +4,16 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Controllers;
|
namespace Stancl\Tenancy\Controllers;
|
||||||
|
|
||||||
use Closure;
|
|
||||||
use Illuminate\Routing\Controller;
|
use Illuminate\Routing\Controller;
|
||||||
|
use Stancl\Tenancy\Tenancy;
|
||||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
|
||||||
class TenantAssetsController extends Controller // todo rename this to TenantAssetController & update references in docs
|
class TenantAssetController extends Controller // todo@docs this was renamed from TenantAssetsController
|
||||||
{
|
{
|
||||||
public static string|array|Closure $tenancyMiddleware = \Stancl\Tenancy\Middleware\InitializeTenancyByDomain::class;
|
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->middleware(static::$tenancyMiddleware);
|
$this->middleware(Tenancy::defaultMiddleware());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -5,22 +5,15 @@ declare(strict_types=1);
|
||||||
namespace Stancl\Tenancy\Database\Concerns;
|
namespace Stancl\Tenancy\Database\Concerns;
|
||||||
|
|
||||||
use Stancl\Tenancy\Contracts\Tenant;
|
use Stancl\Tenancy\Contracts\Tenant;
|
||||||
use Stancl\Tenancy\Resolvers;
|
|
||||||
use Stancl\Tenancy\Resolvers\Contracts\CachedTenantResolver;
|
use Stancl\Tenancy\Resolvers\Contracts\CachedTenantResolver;
|
||||||
|
use Stancl\Tenancy\Tenancy;
|
||||||
|
|
||||||
trait InvalidatesResolverCache
|
trait InvalidatesResolverCache
|
||||||
{
|
{
|
||||||
/** @var array<class-string<CachedTenantResolver>> */
|
|
||||||
public static $resolvers = [ // todo@deprecated, move this to a config key? related to a todo in InvalidatesTenantsResolverCache
|
|
||||||
Resolvers\DomainTenantResolver::class,
|
|
||||||
Resolvers\PathTenantResolver::class,
|
|
||||||
Resolvers\RequestDataTenantResolver::class,
|
|
||||||
];
|
|
||||||
|
|
||||||
public static function bootInvalidatesResolverCache(): void
|
public static function bootInvalidatesResolverCache(): void
|
||||||
{
|
{
|
||||||
static::saved(function (Tenant $tenant) {
|
static::saved(function (Tenant $tenant) {
|
||||||
foreach (static::$resolvers as $resolver) {
|
foreach (Tenancy::cachedResolvers() as $resolver) {
|
||||||
/** @var CachedTenantResolver $resolver */
|
/** @var CachedTenantResolver $resolver */
|
||||||
$resolver = app($resolver);
|
$resolver = app($resolver);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,25 +5,18 @@ declare(strict_types=1);
|
||||||
namespace Stancl\Tenancy\Database\Concerns;
|
namespace Stancl\Tenancy\Database\Concerns;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Stancl\Tenancy\Resolvers;
|
|
||||||
use Stancl\Tenancy\Resolvers\Contracts\CachedTenantResolver;
|
use Stancl\Tenancy\Resolvers\Contracts\CachedTenantResolver;
|
||||||
|
use Stancl\Tenancy\Tenancy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Meant to be used on models that belong to tenants.
|
* Meant to be used on models that belong to tenants.
|
||||||
*/
|
*/
|
||||||
trait InvalidatesTenantsResolverCache
|
trait InvalidatesTenantsResolverCache
|
||||||
{
|
{
|
||||||
/** @var array<class-string<CachedTenantResolver>> */
|
|
||||||
public static array $resolvers = [ // todo single source of truth for this here and in InvalidatesResolverCache
|
|
||||||
Resolvers\DomainTenantResolver::class,
|
|
||||||
Resolvers\PathTenantResolver::class,
|
|
||||||
Resolvers\RequestDataTenantResolver::class,
|
|
||||||
];
|
|
||||||
|
|
||||||
public static function bootInvalidatesTenantsResolverCache(): void
|
public static function bootInvalidatesTenantsResolverCache(): void
|
||||||
{
|
{
|
||||||
static::saved(function (Model $model) {
|
static::saved(function (Model $model) {
|
||||||
foreach (static::$resolvers as $resolver) {
|
foreach (Tenancy::cachedResolvers() as $resolver) {
|
||||||
/** @var CachedTenantResolver $resolver */
|
/** @var CachedTenantResolver $resolver */
|
||||||
$resolver = app($resolver);
|
$resolver = app($resolver);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ class RouteIsMissingTenantParameterException extends Exception
|
||||||
{
|
{
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$parameter = PathTenantResolver::$tenantParameterName;
|
$parameter = PathTenantResolver::tenantParameterName();
|
||||||
|
|
||||||
parent::__construct("The route's first argument is not the tenant id (configured paramter name: $parameter).");
|
parent::__construct("The route's first argument is not the tenant id (configured paramter name: $parameter).");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,14 +34,8 @@ class InitializeTenancyByPath extends IdentificationMiddleware
|
||||||
// Only initialize tenancy if tenant is the first parameter
|
// Only initialize tenancy if tenant is the first parameter
|
||||||
// We don't want to initialize tenancy if the tenant is
|
// We don't want to initialize tenancy if the tenant is
|
||||||
// simply injected into some route controller action.
|
// simply injected into some route controller action.
|
||||||
if ($route->parameterNames()[0] === PathTenantResolver::$tenantParameterName) {
|
if ($route->parameterNames()[0] === PathTenantResolver::tenantParameterName()) {
|
||||||
// Set tenant as a default parameter for the URLs in the current request
|
$this->setDefaultTenantForRouteParametersWhenTenancyIsInitialized();
|
||||||
Event::listen(InitializingTenancy::class, function (InitializingTenancy $event) {
|
|
||||||
/** @var Tenant $tenant */
|
|
||||||
$tenant = $event->tenancy->tenant;
|
|
||||||
|
|
||||||
URL::defaults([PathTenantResolver::$tenantParameterName => $tenant->getTenantKey()]);
|
|
||||||
});
|
|
||||||
|
|
||||||
return $this->initializeTenancy(
|
return $this->initializeTenancy(
|
||||||
$request,
|
$request,
|
||||||
|
|
@ -54,4 +48,16 @@ class InitializeTenancyByPath extends IdentificationMiddleware
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function setDefaultTenantForRouteParametersWhenTenancyIsInitialized(): void
|
||||||
|
{
|
||||||
|
Event::listen(InitializingTenancy::class, function (InitializingTenancy $event) {
|
||||||
|
/** @var Tenant $tenant */
|
||||||
|
$tenant = $event->tenancy->tenant;
|
||||||
|
|
||||||
|
URL::defaults([
|
||||||
|
PathTenantResolver::tenantParameterName() => $tenant->getTenantKey(),
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,23 +11,17 @@ use Stancl\Tenancy\Contracts\TenantResolver;
|
||||||
|
|
||||||
abstract class CachedTenantResolver implements TenantResolver
|
abstract class CachedTenantResolver implements TenantResolver
|
||||||
{
|
{
|
||||||
public static bool $shouldCache = false; // todo docblocks for these
|
|
||||||
|
|
||||||
public static int $cacheTTL = 3600; // seconds
|
|
||||||
|
|
||||||
public static string|null $cacheStore = null; // default
|
|
||||||
|
|
||||||
/** @var Repository */
|
/** @var Repository */
|
||||||
protected $cache;
|
protected $cache;
|
||||||
|
|
||||||
public function __construct(Factory $cache)
|
public function __construct(Factory $cache)
|
||||||
{
|
{
|
||||||
$this->cache = $cache->store(static::$cacheStore);
|
$this->cache = $cache->store(static::cacheStore());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function resolve(mixed ...$args): Tenant
|
public function resolve(mixed ...$args): Tenant
|
||||||
{
|
{
|
||||||
if (! static::$shouldCache) {
|
if (! static::shouldCache()) {
|
||||||
return $this->resolveWithoutCache(...$args);
|
return $this->resolveWithoutCache(...$args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -42,14 +36,14 @@ abstract class CachedTenantResolver implements TenantResolver
|
||||||
}
|
}
|
||||||
|
|
||||||
$tenant = $this->resolveWithoutCache(...$args);
|
$tenant = $this->resolveWithoutCache(...$args);
|
||||||
$this->cache->put($key, $tenant, static::$cacheTTL);
|
$this->cache->put($key, $tenant, static::cacheTTL());
|
||||||
|
|
||||||
return $tenant;
|
return $tenant;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function invalidateCache(Tenant $tenant): void
|
public function invalidateCache(Tenant $tenant): void
|
||||||
{
|
{
|
||||||
if (! static::$shouldCache) {
|
if (! static::shouldCache()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -75,4 +69,19 @@ abstract class CachedTenantResolver implements TenantResolver
|
||||||
* @return array[]
|
* @return array[]
|
||||||
*/
|
*/
|
||||||
abstract public function getArgsForTenant(Tenant $tenant): array;
|
abstract public function getArgsForTenant(Tenant $tenant): array;
|
||||||
|
|
||||||
|
public static function shouldCache(): bool
|
||||||
|
{
|
||||||
|
return config('tenancy.identification.resolvers.' . static::class . '.cache') ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function cacheTTL(): int
|
||||||
|
{
|
||||||
|
return config('tenancy.identification.resolvers.' . static::class . '.cache_ttl') ?? 3600;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function cacheStore(): string|null
|
||||||
|
{
|
||||||
|
return config('tenancy.identification.resolvers.' . static::class . '.cache_store');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,12 +14,6 @@ class DomainTenantResolver extends Contracts\CachedTenantResolver
|
||||||
/** The model representing the domain that the tenant was identified on. */
|
/** The model representing the domain that the tenant was identified on. */
|
||||||
public static Domain $currentDomain; // todo |null?
|
public static Domain $currentDomain; // todo |null?
|
||||||
|
|
||||||
public static bool $shouldCache = false;
|
|
||||||
|
|
||||||
public static int $cacheTTL = 3600; // seconds
|
|
||||||
|
|
||||||
public static string|null $cacheStore = null; // default
|
|
||||||
|
|
||||||
public function resolveWithoutCache(mixed ...$args): Tenant
|
public function resolveWithoutCache(mixed ...$args): Tenant
|
||||||
{
|
{
|
||||||
$domain = $args[0];
|
$domain = $args[0];
|
||||||
|
|
|
||||||
|
|
@ -10,21 +10,13 @@ use Stancl\Tenancy\Exceptions\TenantCouldNotBeIdentifiedByPathException;
|
||||||
|
|
||||||
class PathTenantResolver extends Contracts\CachedTenantResolver
|
class PathTenantResolver extends Contracts\CachedTenantResolver
|
||||||
{
|
{
|
||||||
public static string $tenantParameterName = 'tenant';
|
|
||||||
|
|
||||||
public static bool $shouldCache = false;
|
|
||||||
|
|
||||||
public static int $cacheTTL = 3600; // seconds
|
|
||||||
|
|
||||||
public static string|null $cacheStore = null; // default
|
|
||||||
|
|
||||||
public function resolveWithoutCache(mixed ...$args): Tenant
|
public function resolveWithoutCache(mixed ...$args): Tenant
|
||||||
{
|
{
|
||||||
/** @var Route $route */
|
/** @var Route $route */
|
||||||
$route = $args[0];
|
$route = $args[0];
|
||||||
|
|
||||||
if ($id = (string) $route->parameter(static::$tenantParameterName)) {
|
if ($id = (string) $route->parameter(static::tenantParameterName())) {
|
||||||
$route->forgetParameter(static::$tenantParameterName);
|
$route->forgetParameter(static::tenantParameterName());
|
||||||
|
|
||||||
if ($tenant = tenancy()->find($id)) {
|
if ($tenant = tenancy()->find($id)) {
|
||||||
return $tenant;
|
return $tenant;
|
||||||
|
|
@ -40,4 +32,9 @@ class PathTenantResolver extends Contracts\CachedTenantResolver
|
||||||
[$tenant->getTenantKey()],
|
[$tenant->getTenantKey()],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function tenantParameterName(): string
|
||||||
|
{
|
||||||
|
return config('tenancy.identification.resolvers.' . static::class . '.tenant_parameter_name') ?? 'tenant';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ class Tenancy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo0 for phpstan this should be $this->tenant?, but first I want to clean up the $initialized logic and explore removing the property
|
// todo1 for phpstan this should be $this->tenant?, but first I want to clean up the $initialized logic and explore removing the property
|
||||||
if ($this->initialized && $this->tenant->getTenantKey() === $tenant->getTenantKey()) {
|
if ($this->initialized && $this->tenant->getTenantKey() === $tenant->getTenantKey()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -157,7 +157,7 @@ class Tenancy
|
||||||
$tenants = is_string($tenants) ? [$tenants] : $tenants;
|
$tenants = is_string($tenants) ? [$tenants] : $tenants;
|
||||||
|
|
||||||
// Use all tenants if $tenants is falsey
|
// Use all tenants if $tenants is falsey
|
||||||
$tenants = $tenants ?: $this->model()->cursor(); // todo0 phpstan thinks this isn't needed, but tests fail without it
|
$tenants = $tenants ?: $this->model()->cursor(); // todo1 phpstan thinks this isn't needed, but tests fail without it
|
||||||
|
|
||||||
$originalTenant = $this->tenant;
|
$originalTenant = $this->tenant;
|
||||||
|
|
||||||
|
|
@ -177,4 +177,41 @@ class Tenancy
|
||||||
$this->end();
|
$this->end();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cached tenant resolvers used by the package.
|
||||||
|
*
|
||||||
|
* @return array<class-string<Resolvers\Contracts\CachedTenantResolver>>
|
||||||
|
*/
|
||||||
|
public static function cachedResolvers(): array
|
||||||
|
{
|
||||||
|
$resolvers = config('tenancy.identification.resolvers', []);
|
||||||
|
|
||||||
|
$cachedResolvers = array_filter($resolvers, function (array $options) {
|
||||||
|
// Resolvers based on CachedTenantResolver have the 'cache' option in the resolver config
|
||||||
|
return isset($options['cache']);
|
||||||
|
});
|
||||||
|
|
||||||
|
return array_keys($cachedResolvers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tenant identification middleware used by the package.
|
||||||
|
*
|
||||||
|
* @return array<class-string<Middleware\IdentificationMiddleware>>
|
||||||
|
*/
|
||||||
|
public static function middleware(): array
|
||||||
|
{
|
||||||
|
return config('tenancy.identification.middleware', []);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default tenant identification middleware used by the package.
|
||||||
|
*
|
||||||
|
* @return class-string<Middleware\IdentificationMiddleware>
|
||||||
|
*/
|
||||||
|
public static function defaultMiddleware(): string
|
||||||
|
{
|
||||||
|
return config('tenancy.identification.default_middleware', Middleware\InitializeTenancyByDomain::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ class TenancyServiceProvider extends ServiceProvider
|
||||||
if ($event instanceof TenancyEvent) {
|
if ($event instanceof TenancyEvent) {
|
||||||
match (tenancy()->logMode()) {
|
match (tenancy()->logMode()) {
|
||||||
LogMode::SILENT => tenancy()->logEvent($event),
|
LogMode::SILENT => tenancy()->logEvent($event),
|
||||||
LogMode::INSTANT => dump($event), // todo0 perhaps still log
|
LogMode::INSTANT => dump($event), // todo1 perhaps still log
|
||||||
default => null,
|
default => null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,7 @@ use Illuminate\Support\Facades\DB;
|
||||||
use Stancl\Tenancy\Resolvers\DomainTenantResolver;
|
use Stancl\Tenancy\Resolvers\DomainTenantResolver;
|
||||||
use Stancl\Tenancy\Tests\Etc\Tenant;
|
use Stancl\Tenancy\Tests\Etc\Tenant;
|
||||||
|
|
||||||
afterEach(function () {
|
// todo@v4 test this with other resolvers as well?
|
||||||
DomainTenantResolver::$shouldCache = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
test('tenants can be resolved using the cached resolver', function () {
|
test('tenants can be resolved using the cached resolver', function () {
|
||||||
$tenant = Tenant::create();
|
$tenant = Tenant::create();
|
||||||
|
|
@ -27,14 +25,14 @@ test('the underlying resolver is not touched when using the cached resolver', fu
|
||||||
|
|
||||||
DB::enableQueryLog();
|
DB::enableQueryLog();
|
||||||
|
|
||||||
DomainTenantResolver::$shouldCache = false;
|
config(['tenancy.identification.resolvers.' . DomainTenantResolver::class . '.cache' => false]);
|
||||||
|
|
||||||
expect($tenant->is(app(DomainTenantResolver::class)->resolve('acme')))->toBeTrue();
|
expect($tenant->is(app(DomainTenantResolver::class)->resolve('acme')))->toBeTrue();
|
||||||
DB::flushQueryLog();
|
DB::flushQueryLog();
|
||||||
expect($tenant->is(app(DomainTenantResolver::class)->resolve('acme')))->toBeTrue();
|
expect($tenant->is(app(DomainTenantResolver::class)->resolve('acme')))->toBeTrue();
|
||||||
pest()->assertNotEmpty(DB::getQueryLog()); // not empty
|
pest()->assertNotEmpty(DB::getQueryLog()); // not empty
|
||||||
|
|
||||||
DomainTenantResolver::$shouldCache = true;
|
config(['tenancy.identification.resolvers.' . DomainTenantResolver::class . '.cache' => true]);
|
||||||
|
|
||||||
expect($tenant->is(app(DomainTenantResolver::class)->resolve('acme')))->toBeTrue();
|
expect($tenant->is(app(DomainTenantResolver::class)->resolve('acme')))->toBeTrue();
|
||||||
DB::flushQueryLog();
|
DB::flushQueryLog();
|
||||||
|
|
@ -50,7 +48,7 @@ test('cache is invalidated when the tenant is updated', function () {
|
||||||
|
|
||||||
DB::enableQueryLog();
|
DB::enableQueryLog();
|
||||||
|
|
||||||
DomainTenantResolver::$shouldCache = true;
|
config(['tenancy.identification.resolvers.' . DomainTenantResolver::class . '.cache' => true]);
|
||||||
|
|
||||||
expect($tenant->is(app(DomainTenantResolver::class)->resolve('acme')))->toBeTrue();
|
expect($tenant->is(app(DomainTenantResolver::class)->resolve('acme')))->toBeTrue();
|
||||||
DB::flushQueryLog();
|
DB::flushQueryLog();
|
||||||
|
|
@ -74,7 +72,7 @@ test('cache is invalidated when a tenants domain is changed', function () {
|
||||||
|
|
||||||
DB::enableQueryLog();
|
DB::enableQueryLog();
|
||||||
|
|
||||||
DomainTenantResolver::$shouldCache = true;
|
config(['tenancy.identification.resolvers.' . DomainTenantResolver::class . '.cache' => true]);
|
||||||
|
|
||||||
expect($tenant->is(app(DomainTenantResolver::class)->resolve('acme')))->toBeTrue();
|
expect($tenant->is(app(DomainTenantResolver::class)->resolve('acme')))->toBeTrue();
|
||||||
DB::flushQueryLog();
|
DB::flushQueryLog();
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,6 @@ use Stancl\Tenancy\Resolvers\PathTenantResolver;
|
||||||
use Stancl\Tenancy\Tests\Etc\Tenant;
|
use Stancl\Tenancy\Tests\Etc\Tenant;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
PathTenantResolver::$tenantParameterName = 'tenant';
|
|
||||||
|
|
||||||
Route::group([
|
Route::group([
|
||||||
'prefix' => '/{tenant}',
|
'prefix' => '/{tenant}',
|
||||||
'middleware' => InitializeTenancyByPath::class,
|
'middleware' => InitializeTenancyByPath::class,
|
||||||
|
|
@ -26,11 +24,6 @@ beforeEach(function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function () {
|
|
||||||
// Global state cleanup
|
|
||||||
PathTenantResolver::$tenantParameterName = 'tenant';
|
|
||||||
});
|
|
||||||
|
|
||||||
test('tenant can be identified by path', function () {
|
test('tenant can be identified by path', function () {
|
||||||
Tenant::create([
|
Tenant::create([
|
||||||
'id' => 'acme',
|
'id' => 'acme',
|
||||||
|
|
@ -101,7 +94,7 @@ test('an exception is thrown when the routes first parameter is not tenant', fun
|
||||||
});
|
});
|
||||||
|
|
||||||
test('tenant parameter name can be customized', function () {
|
test('tenant parameter name can be customized', function () {
|
||||||
PathTenantResolver::$tenantParameterName = 'team';
|
config(['tenancy.identification.resolvers.' . PathTenantResolver::class . '.tenant_parameter_name' => 'team']);
|
||||||
|
|
||||||
Route::group([
|
Route::group([
|
||||||
'prefix' => '/{team}',
|
'prefix' => '/{team}',
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,8 @@ use Illuminate\Support\Facades\Event;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Stancl\Tenancy\Bootstrappers\FilesystemTenancyBootstrapper;
|
use Stancl\Tenancy\Bootstrappers\FilesystemTenancyBootstrapper;
|
||||||
use Stancl\Tenancy\Controllers\TenantAssetsController;
|
|
||||||
use Stancl\Tenancy\Events\TenancyInitialized;
|
use Stancl\Tenancy\Events\TenancyInitialized;
|
||||||
use Stancl\Tenancy\Listeners\BootstrapTenancy;
|
use Stancl\Tenancy\Listeners\BootstrapTenancy;
|
||||||
use Stancl\Tenancy\Middleware\InitializeTenancyByDomain;
|
|
||||||
use Stancl\Tenancy\Middleware\InitializeTenancyByRequestData;
|
use Stancl\Tenancy\Middleware\InitializeTenancyByRequestData;
|
||||||
use Stancl\Tenancy\Tests\Etc\Tenant;
|
use Stancl\Tenancy\Tests\Etc\Tenant;
|
||||||
|
|
||||||
|
|
@ -21,13 +19,8 @@ beforeEach(function () {
|
||||||
Event::listen(TenancyInitialized::class, BootstrapTenancy::class);
|
Event::listen(TenancyInitialized::class, BootstrapTenancy::class);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function () {
|
|
||||||
// Cleanup
|
|
||||||
TenantAssetsController::$tenancyMiddleware = InitializeTenancyByDomain::class;
|
|
||||||
});
|
|
||||||
|
|
||||||
test('asset can be accessed using the url returned by the tenant asset helper', function () {
|
test('asset can be accessed using the url returned by the tenant asset helper', function () {
|
||||||
TenantAssetsController::$tenancyMiddleware = InitializeTenancyByRequestData::class;
|
config(['tenancy.identification.default_middleware' => InitializeTenancyByRequestData::class]);
|
||||||
|
|
||||||
$tenant = Tenant::create();
|
$tenant = Tenant::create();
|
||||||
tenancy()->initialize($tenant);
|
tenancy()->initialize($tenant);
|
||||||
|
|
@ -95,7 +88,7 @@ test('asset helper tenancy can be disabled', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('test asset controller returns a 404 when no path is provided', function () {
|
test('test asset controller returns a 404 when no path is provided', function () {
|
||||||
TenantAssetsController::$tenancyMiddleware = InitializeTenancyByRequestData::class;
|
config(['tenancy.identification.default_middleware' => InitializeTenancyByRequestData::class]);
|
||||||
|
|
||||||
$tenant = Tenant::create();
|
$tenant = Tenant::create();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ abstract class TestCase extends \Orchestra\Testbench\TestCase
|
||||||
'--realpath' => true,
|
'--realpath' => true,
|
||||||
'--force' => true,
|
'--force' => true,
|
||||||
],
|
],
|
||||||
'tenancy.bootstrappers.redis' => RedisTenancyBootstrapper::class, // todo0 change this to []? two tests in TenantDatabaseManagerTest are failing with that
|
'tenancy.bootstrappers.redis' => RedisTenancyBootstrapper::class, // todo1 change this to []? two tests in TenantDatabaseManagerTest are failing with that
|
||||||
'queue.connections.central' => [
|
'queue.connections.central' => [
|
||||||
'driver' => 'sync',
|
'driver' => 'sync',
|
||||||
'central' => true,
|
'central' => true,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue