mirror of
https://github.com/archtechx/tenancy.git
synced 2025-12-12 08:24:04 +00:00
misc improvements - stronger types, exception refactor
This commit is contained in:
parent
ddc7cf49c3
commit
55d0a9ab87
34 changed files with 179 additions and 209 deletions
|
|
@ -5,12 +5,6 @@ ARG PHP_VERSION=8.1
|
|||
|
||||
WORKDIR /var/www/html
|
||||
|
||||
LABEL org.opencontainers.image.source=https://github.com/stancl/tenancy \
|
||||
org.opencontainers.image.vendor="Samuel Štancl" \
|
||||
org.opencontainers.image.licenses="MIT" \
|
||||
org.opencontainers.image.title="PHP ${PHP_VERSION} with modules for laravel support" \
|
||||
org.opencontainers.image.description="PHP ${PHP_VERSION} with a set of php/os packages suitable for running Laravel apps"
|
||||
|
||||
# our default timezone and langauge
|
||||
ENV TZ=Europe/London
|
||||
ENV LANG=en_GB.UTF-8
|
||||
|
|
|
|||
|
|
@ -6,11 +6,16 @@ namespace Stancl\Tenancy\Contracts;
|
|||
|
||||
use Stancl\Tenancy\DatabaseConfig;
|
||||
|
||||
// todo possibly move to Database namespace, along with other classes
|
||||
|
||||
interface ManagesDatabaseUsers extends TenantDatabaseManager
|
||||
{
|
||||
/** Create a database user. */
|
||||
public function createUser(DatabaseConfig $databaseConfig): bool;
|
||||
|
||||
/** Delete a database user. */
|
||||
public function deleteUser(DatabaseConfig $databaseConfig): bool;
|
||||
|
||||
/** Does a database user exist? */
|
||||
public function userExists(string $username): bool;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ namespace Stancl\Tenancy\Contracts;
|
|||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
|
||||
// todo move all resource syncing-related things to a separate namespace?
|
||||
|
||||
/**
|
||||
* @property-read Tenant[]|Collection $tenants
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -4,11 +4,11 @@ declare(strict_types=1);
|
|||
|
||||
namespace Stancl\Tenancy\Contracts;
|
||||
|
||||
use Closure;
|
||||
|
||||
/**
|
||||
* @see \Stancl\Tenancy\Database\Models\Tenant
|
||||
*
|
||||
* @method __call(string $method, array $parameters) IDE support. This will be a model.
|
||||
* @method static __callStatic(string $method, array $parameters) IDE support. This will be a model.
|
||||
* @mixin \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
interface Tenant
|
||||
|
|
@ -17,14 +17,14 @@ interface Tenant
|
|||
public function getTenantKeyName(): string;
|
||||
|
||||
/** Get the value of the key used for identifying the tenant. */
|
||||
public function getTenantKey();
|
||||
public function getTenantKey(): int|string;
|
||||
|
||||
/** Get the value of an internal key. */
|
||||
public function getInternal(string $key);
|
||||
public function getInternal(string $key): mixed;
|
||||
|
||||
/** Set the value of an internal key. */
|
||||
public function setInternal(string $key, $value);
|
||||
public function setInternal(string $key, mixed $value): static;
|
||||
|
||||
/** Run a callback in this tenant's environment. */
|
||||
public function run(callable $callback);
|
||||
public function run(Closure $callback): mixed;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,50 @@ declare(strict_types=1);
|
|||
namespace Stancl\Tenancy\Contracts;
|
||||
|
||||
use Exception;
|
||||
use Facade\IgnitionContracts\BaseSolution;
|
||||
use Facade\IgnitionContracts\ProvidesSolution;
|
||||
use Facade\IgnitionContracts\Solution;
|
||||
|
||||
abstract class TenantCouldNotBeIdentifiedException extends Exception
|
||||
abstract class TenantCouldNotBeIdentifiedException extends Exception implements ProvidesSolution
|
||||
{
|
||||
/** Default solution title. */
|
||||
protected string $solutionTitle = 'Tenant could not be identified';
|
||||
|
||||
/** Default solution description. */
|
||||
protected string $solutionDescription = 'Are you sure this tenant exists?';
|
||||
|
||||
/** Set the message. */
|
||||
protected function tenantCouldNotBeIdentified(string $how): static
|
||||
{
|
||||
$this->message = "Tenant could not be identified " . $how;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** Set the solution title. */
|
||||
protected function title(string $solutionTitle): static
|
||||
{
|
||||
$this->solutionTitle = $solutionTitle;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** Set the solution description. */
|
||||
protected function description(string $solutionDescription): static
|
||||
{
|
||||
$this->solutionDescription = $solutionDescription;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** Get the Ignition description. */
|
||||
public function getSolution(): Solution
|
||||
{
|
||||
return BaseSolution::create($this->solutionTitle)
|
||||
->setSolutionDescription($this->solutionDescription)
|
||||
->setDocumentationLinks([
|
||||
'Tenants' => 'https://tenancyforlaravel.com/docs/v3/tenants',
|
||||
'Tenant Identification' => 'https://tenancyforlaravel.com/docs/v3/tenant-identification',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,24 +8,16 @@ use Stancl\Tenancy\Exceptions\NoConnectionSetException;
|
|||
|
||||
interface TenantDatabaseManager
|
||||
{
|
||||
/**
|
||||
* Create a database.
|
||||
*/
|
||||
/** Create a database. */
|
||||
public function createDatabase(TenantWithDatabase $tenant): bool;
|
||||
|
||||
/**
|
||||
* Delete a database.
|
||||
*/
|
||||
/** Delete a database. */
|
||||
public function deleteDatabase(TenantWithDatabase $tenant): bool;
|
||||
|
||||
/**
|
||||
* Does a database exist.
|
||||
*/
|
||||
/** Does a database exist? */
|
||||
public function databaseExists(string $name): bool;
|
||||
|
||||
/**
|
||||
* Make a DB connection config array.
|
||||
*/
|
||||
/** Construct a DB connection config array. */
|
||||
public function makeConnectionConfig(array $baseConfig, string $databaseName): array;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -11,5 +11,5 @@ interface TenantWithDatabase extends Tenant
|
|||
public function database(): DatabaseConfig;
|
||||
|
||||
/** Get an internal key. */
|
||||
public function getInternal(string $key);
|
||||
public function getInternal(string $key): mixed;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,26 +6,20 @@ namespace Stancl\Tenancy\Database\Concerns;
|
|||
|
||||
trait HasInternalKeys
|
||||
{
|
||||
/**
|
||||
* Get the internal prefix.
|
||||
*/
|
||||
/** Get the internal prefix. */
|
||||
public static function internalPrefix(): string
|
||||
{
|
||||
return 'tenancy_';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an internal key.
|
||||
*/
|
||||
public function getInternal(string $key)
|
||||
/** Get an internal key. */
|
||||
public function getInternal(string $key): mixed
|
||||
{
|
||||
return $this->getAttribute(static::internalPrefix() . $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set internal key.
|
||||
*/
|
||||
public function setInternal(string $key, $value)
|
||||
/** Set internal key. */
|
||||
public function setInternal(string $key, mixed $value): static
|
||||
{
|
||||
$this->setAttribute(static::internalPrefix() . $key, $value);
|
||||
|
||||
|
|
|
|||
|
|
@ -4,15 +4,17 @@ declare(strict_types=1);
|
|||
|
||||
namespace Stancl\Tenancy\Database\Concerns;
|
||||
|
||||
use Closure;
|
||||
use Stancl\Tenancy\Contracts\Tenant;
|
||||
|
||||
trait TenantRun
|
||||
{
|
||||
/**
|
||||
* Run a callback in this tenant's context.
|
||||
* Atomic, safely reverts to previous context.
|
||||
*
|
||||
* This method is atomic and safely reverts to the previous context.
|
||||
*/
|
||||
public function run(callable $callback)
|
||||
public function run(Closure $callback): mixed
|
||||
{
|
||||
/** @var Tenant $this */
|
||||
$originalTenant = tenant();
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ use Stancl\Tenancy\Exceptions\DatabaseManagerNotRegisteredException;
|
|||
use Stancl\Tenancy\Exceptions\TenantDatabaseAlreadyExistsException;
|
||||
use Stancl\Tenancy\Exceptions\TenantDatabaseUserAlreadyExistsException;
|
||||
|
||||
// todo move to Database namespace
|
||||
|
||||
/**
|
||||
* @internal Class is subject to breaking changes in minor and patch versions.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -35,10 +35,8 @@ class ImpersonationToken extends Model
|
|||
'created_at',
|
||||
];
|
||||
|
||||
public static function boot()
|
||||
public static function booted()
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
static::creating(function ($model) {
|
||||
$model->created_at = $model->created_at ?? $model->freshTimestamp();
|
||||
$model->token = $model->token ?? Str::random(128);
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ class Tenant extends Model implements Contracts\Tenant
|
|||
return 'id';
|
||||
}
|
||||
|
||||
public function getTenantKey()
|
||||
public function getTenantKey(): int|string
|
||||
{
|
||||
return $this->getAttribute($this->getTenantKeyName());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,10 +9,8 @@ use Stancl\Tenancy\Contracts\Syncable;
|
|||
|
||||
class TenantPivot extends Pivot
|
||||
{
|
||||
public static function boot()
|
||||
public static function booted()
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
static::saved(function (self $pivot) {
|
||||
$parent = $pivot->pivotParent;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use Illuminate\Database\Eloquent\Scope;
|
|||
|
||||
class ParentModelScope implements Scope
|
||||
{
|
||||
public function apply(Builder $builder, Model $model)
|
||||
public function apply(Builder $builder, Model $model): void
|
||||
{
|
||||
if (! tenancy()->initialized) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace Stancl\Tenancy\Database;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Stancl\Tenancy\Contracts\Tenant;
|
||||
|
||||
|
|
@ -16,7 +17,7 @@ use Stancl\Tenancy\Contracts\Tenant;
|
|||
*/
|
||||
class TenantCollection extends Collection
|
||||
{
|
||||
public function runForEach(callable $callable): self
|
||||
public function runForEach(Closure $callable): self
|
||||
{
|
||||
tenancy()->runForMultiple($this->items, $callable);
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace Stancl\Tenancy;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Str;
|
||||
|
|
@ -48,17 +49,17 @@ class DatabaseConfig
|
|||
$this->tenant = $tenant;
|
||||
}
|
||||
|
||||
public static function generateDatabaseNamesUsing(callable $databaseNameGenerator): void
|
||||
public static function generateDatabaseNamesUsing(Closure $databaseNameGenerator): void
|
||||
{
|
||||
static::$databaseNameGenerator = $databaseNameGenerator;
|
||||
}
|
||||
|
||||
public static function generateUsernamesUsing(callable $usernameGenerator): void
|
||||
public static function generateUsernamesUsing(Closure $usernameGenerator): void
|
||||
{
|
||||
static::$usernameGenerator = $usernameGenerator;
|
||||
}
|
||||
|
||||
public static function generatePasswordsUsing(callable $passwordGenerator): void
|
||||
public static function generatePasswordsUsing(Closure $passwordGenerator): void
|
||||
{
|
||||
static::$passwordGenerator = $passwordGenerator;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Stancl\Tenancy\Exceptions;
|
||||
|
||||
use Facade\IgnitionContracts\BaseSolution;
|
||||
use Facade\IgnitionContracts\ProvidesSolution;
|
||||
use Facade\IgnitionContracts\Solution;
|
||||
use Stancl\Tenancy\Contracts\TenantCouldNotBeIdentifiedException;
|
||||
|
||||
// todo: in v4 this should be suffixed with Exception
|
||||
class TenantCouldNotBeIdentifiedById extends TenantCouldNotBeIdentifiedException implements ProvidesSolution
|
||||
{
|
||||
public function __construct($tenant_id)
|
||||
{
|
||||
parent::__construct("Tenant could not be identified with tenant_id: $tenant_id");
|
||||
}
|
||||
|
||||
public function getSolution(): Solution
|
||||
{
|
||||
return BaseSolution::create('Tenant could not be identified with that ID')
|
||||
->setSolutionDescription('Are you sure the ID is correct and the tenant exists?')
|
||||
->setDocumentationLinks([
|
||||
'Initializing Tenants' => 'https://tenancyforlaravel.com/docs/v3/tenants',
|
||||
]);
|
||||
}
|
||||
}
|
||||
18
src/Exceptions/TenantCouldNotBeIdentifiedByIdException.php
Normal file
18
src/Exceptions/TenantCouldNotBeIdentifiedByIdException.php
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Stancl\Tenancy\Exceptions;
|
||||
|
||||
use Stancl\Tenancy\Contracts\TenantCouldNotBeIdentifiedException;
|
||||
|
||||
class TenantCouldNotBeIdentifiedByIdException extends TenantCouldNotBeIdentifiedException
|
||||
{
|
||||
public function __construct(int|string $tenant_id)
|
||||
{
|
||||
$this
|
||||
->tenantCouldNotBeIdentified("by tenant id: $tenant_id")
|
||||
->title('Tenant could not be identified with that ID')
|
||||
->description('Are you sure the ID is correct and the tenant exists?');
|
||||
}
|
||||
}
|
||||
|
|
@ -4,24 +4,15 @@ declare(strict_types=1);
|
|||
|
||||
namespace Stancl\Tenancy\Exceptions;
|
||||
|
||||
use Facade\IgnitionContracts\BaseSolution;
|
||||
use Facade\IgnitionContracts\ProvidesSolution;
|
||||
use Facade\IgnitionContracts\Solution;
|
||||
use Stancl\Tenancy\Contracts\TenantCouldNotBeIdentifiedException;
|
||||
|
||||
class TenantCouldNotBeIdentifiedByPathException extends TenantCouldNotBeIdentifiedException implements ProvidesSolution
|
||||
class TenantCouldNotBeIdentifiedByPathException extends TenantCouldNotBeIdentifiedException
|
||||
{
|
||||
public function __construct($tenant_id)
|
||||
public function __construct(int|string $tenant_id)
|
||||
{
|
||||
parent::__construct("Tenant could not be identified on path with tenant_id: $tenant_id");
|
||||
}
|
||||
|
||||
public function getSolution(): Solution
|
||||
{
|
||||
return BaseSolution::create('Tenant could not be identified on this path')
|
||||
->setSolutionDescription('Did you forget to create a tenant for this path?')
|
||||
->setDocumentationLinks([
|
||||
'Creating Tenants' => 'https://tenancyforlaravel.com/docs/v3/tenants/',
|
||||
]);
|
||||
$this
|
||||
->tenantCouldNotBeIdentified("on path with tenant id: $tenant_id")
|
||||
->title('Tenant could not be identified on this path')
|
||||
->description('Did you forget to create a tenant for this path?');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,24 +4,15 @@ declare(strict_types=1);
|
|||
|
||||
namespace Stancl\Tenancy\Exceptions;
|
||||
|
||||
use Facade\IgnitionContracts\BaseSolution;
|
||||
use Facade\IgnitionContracts\ProvidesSolution;
|
||||
use Facade\IgnitionContracts\Solution;
|
||||
use Stancl\Tenancy\Contracts\TenantCouldNotBeIdentifiedException;
|
||||
|
||||
class TenantCouldNotBeIdentifiedByRequestDataException extends TenantCouldNotBeIdentifiedException implements ProvidesSolution
|
||||
class TenantCouldNotBeIdentifiedByRequestDataException extends TenantCouldNotBeIdentifiedException
|
||||
{
|
||||
public function __construct($tenant_id)
|
||||
public function __construct(mixed $payload)
|
||||
{
|
||||
parent::__construct("Tenant could not be identified by request data with payload: $tenant_id");
|
||||
}
|
||||
|
||||
public function getSolution(): Solution
|
||||
{
|
||||
return BaseSolution::create('Tenant could not be identified with this request data')
|
||||
->setSolutionDescription('Did you forget to create a tenant with this id?')
|
||||
->setDocumentationLinks([
|
||||
'Creating Tenants' => 'https://tenancyforlaravel.com/docs/v3/tenants/',
|
||||
]);
|
||||
$this
|
||||
->tenantCouldNotBeIdentified("by request data with payload: $payload")
|
||||
->title('Tenant could not be identified using this request data')
|
||||
->description('Did you forget to create a tenant with this id?');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,24 +4,15 @@ declare(strict_types=1);
|
|||
|
||||
namespace Stancl\Tenancy\Exceptions;
|
||||
|
||||
use Facade\IgnitionContracts\BaseSolution;
|
||||
use Facade\IgnitionContracts\ProvidesSolution;
|
||||
use Facade\IgnitionContracts\Solution;
|
||||
use Stancl\Tenancy\Contracts\TenantCouldNotBeIdentifiedException;
|
||||
|
||||
class TenantCouldNotBeIdentifiedOnDomainException extends TenantCouldNotBeIdentifiedException implements ProvidesSolution
|
||||
class TenantCouldNotBeIdentifiedOnDomainException extends TenantCouldNotBeIdentifiedException
|
||||
{
|
||||
public function __construct($domain)
|
||||
public function __construct(string $domain)
|
||||
{
|
||||
parent::__construct("Tenant could not be identified on domain $domain");
|
||||
}
|
||||
|
||||
public function getSolution(): Solution
|
||||
{
|
||||
return BaseSolution::create('Tenant could not be identified on this domain')
|
||||
->setSolutionDescription('Did you forget to create a tenant for this domain?')
|
||||
->setDocumentationLinks([
|
||||
'Creating Tenants' => 'https://tenancyforlaravel.com/docs/v3/tenants/',
|
||||
]);
|
||||
$this
|
||||
->tenantCouldNotBeIdentified("on domain $domain")
|
||||
->title('Tenant could not be identified on this domain')
|
||||
->description('Did you forget to create a tenant for this domain?');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,18 +8,14 @@ use Stancl\Tenancy\Contracts\TenantCannotBeCreatedException;
|
|||
|
||||
class TenantDatabaseAlreadyExistsException extends TenantCannotBeCreatedException
|
||||
{
|
||||
/** @var string */
|
||||
protected $database;
|
||||
public function __construct(
|
||||
protected string $database,
|
||||
) {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function reason(): string
|
||||
{
|
||||
return "Database {$this->database} already exists.";
|
||||
}
|
||||
|
||||
public function __construct(string $database)
|
||||
{
|
||||
$this->database = $database;
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use Exception;
|
|||
|
||||
class TenantDatabaseDoesNotExistException extends Exception
|
||||
{
|
||||
public function __construct($database)
|
||||
public function __construct(string $database)
|
||||
{
|
||||
parent::__construct("Database $database does not exist.");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,18 +8,14 @@ use Stancl\Tenancy\Contracts\TenantCannotBeCreatedException;
|
|||
|
||||
class TenantDatabaseUserAlreadyExistsException extends TenantCannotBeCreatedException
|
||||
{
|
||||
/** @var string */
|
||||
protected $user;
|
||||
public function __construct(
|
||||
protected string $user,
|
||||
) {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function reason(): string
|
||||
{
|
||||
return "Database user {$this->user} already exists.";
|
||||
}
|
||||
|
||||
public function __construct(string $user)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->user = $user;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ class CrossDomainRedirect implements Feature
|
|||
RedirectResponse::macro('domain', function (string $domain) {
|
||||
/** @var RedirectResponse $this */
|
||||
|
||||
// replace first occurance of hostname fragment with $domain
|
||||
// Replace first occurrence of the hostname fragment with $domain
|
||||
$url = $this->getTargetUrl();
|
||||
$hostname = parse_url($url, PHP_URL_HOST);
|
||||
$position = strpos($url, $hostname);
|
||||
|
|
|
|||
|
|
@ -13,9 +13,10 @@ use Stancl\Tenancy\Tenancy;
|
|||
|
||||
class UniversalRoutes implements Feature
|
||||
{
|
||||
public static $middlewareGroup = 'universal';
|
||||
public static string $middlewareGroup = 'universal';
|
||||
|
||||
public static $identificationMiddlewares = [
|
||||
// todo docblock
|
||||
public static array $identificationMiddlewares = [
|
||||
Middleware\InitializeTenancyByDomain::class,
|
||||
Middleware\InitializeTenancyBySubdomain::class,
|
||||
];
|
||||
|
|
@ -39,7 +40,7 @@ class UniversalRoutes implements Feature
|
|||
}
|
||||
}
|
||||
|
||||
public static function routeHasMiddleware(Route $route, $middleware): bool
|
||||
public static function routeHasMiddleware(Route $route, string $middleware): bool
|
||||
{
|
||||
if (in_array($middleware, $route->middleware(), true)) {
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ declare(strict_types=1);
|
|||
|
||||
namespace Stancl\Tenancy\Features;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Stancl\Tenancy\Contracts\Feature;
|
||||
|
|
@ -14,7 +13,8 @@ use Stancl\Tenancy\Tenancy;
|
|||
|
||||
class UserImpersonation implements Feature
|
||||
{
|
||||
public static $ttl = 60; // seconds
|
||||
/** The lifespan of impersonation tokens (in seconds). */
|
||||
public static int $ttl = 60;
|
||||
|
||||
public function bootstrap(Tenancy $tenancy): void
|
||||
{
|
||||
|
|
@ -28,25 +28,20 @@ class UserImpersonation implements Feature
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Impersonate a user and get an HTTP redirect response.
|
||||
*
|
||||
* @param string|ImpersonationToken $token
|
||||
* @param int $ttl
|
||||
*/
|
||||
public static function makeResponse($token, int $ttl = null): RedirectResponse
|
||||
/** Impersonate a user and get an HTTP redirect response. */
|
||||
public static function makeResponse(string|ImpersonationToken $token, int $ttl = null): RedirectResponse
|
||||
{
|
||||
$token = $token instanceof ImpersonationToken ? $token : ImpersonationToken::findOrFail($token);
|
||||
$ttl ??= static::$ttl;
|
||||
|
||||
if (((string) $token->tenant_id) !== ((string) tenant()->getTenantKey())) {
|
||||
abort(403);
|
||||
}
|
||||
$tokenExpired = $token->created_at->diffInSeconds(now()) > $ttl;
|
||||
|
||||
$ttl = $ttl ?? static::$ttl;
|
||||
abort_if($tokenExpired, 403);
|
||||
|
||||
if ($token->created_at->diffInSeconds(Carbon::now()) > $ttl) {
|
||||
abort(403);
|
||||
}
|
||||
$tokenTenantId = (string) $token->tenant_id;
|
||||
$currentTenantId = (string) tenant()->getTenantKey();
|
||||
|
||||
abort_unless($tokenTenantId === $currentTenantId, 403);
|
||||
|
||||
Auth::guard($token->auth_guard)->loginUsingId($token->user_id);
|
||||
|
||||
|
|
|
|||
|
|
@ -11,14 +11,11 @@ use Stancl\Tenancy\Contracts\TenantResolver;
|
|||
|
||||
abstract class CachedTenantResolver implements TenantResolver
|
||||
{
|
||||
/** @var bool */
|
||||
public static $shouldCache = false;
|
||||
public static bool $shouldCache = false; // todo docblocks for these
|
||||
|
||||
/** @var int */
|
||||
public static $cacheTTL = 3600; // seconds
|
||||
public static int $cacheTTL = 3600; // seconds
|
||||
|
||||
/** @var string|null */
|
||||
public static $cacheStore = null; // default
|
||||
public static string|null $cacheStore = null; // default
|
||||
|
||||
/** @var Repository */
|
||||
protected $cache;
|
||||
|
|
|
|||
|
|
@ -11,21 +11,14 @@ use Stancl\Tenancy\Exceptions\TenantCouldNotBeIdentifiedOnDomainException;
|
|||
|
||||
class DomainTenantResolver extends Contracts\CachedTenantResolver
|
||||
{
|
||||
/**
|
||||
* The model representing the domain that the tenant was identified on.
|
||||
*
|
||||
* @var Domain
|
||||
*/
|
||||
public static $currentDomain;
|
||||
/** The model representing the domain that the tenant was identified on. */
|
||||
public static Domain $currentDomain; // todo |null?
|
||||
|
||||
/** @var bool */
|
||||
public static $shouldCache = false;
|
||||
public static bool $shouldCache = false;
|
||||
|
||||
/** @var int */
|
||||
public static $cacheTTL = 3600; // seconds
|
||||
public static int $cacheTTL = 3600; // seconds
|
||||
|
||||
/** @var string|null */
|
||||
public static $cacheStore = null; // default
|
||||
public static string|null $cacheStore = null; // default
|
||||
|
||||
public function resolveWithoutCache(...$args): Tenant
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,16 +10,13 @@ use Stancl\Tenancy\Exceptions\TenantCouldNotBeIdentifiedByPathException;
|
|||
|
||||
class PathTenantResolver extends Contracts\CachedTenantResolver
|
||||
{
|
||||
public static $tenantParameterName = 'tenant';
|
||||
public static string $tenantParameterName = 'tenant';
|
||||
|
||||
/** @var bool */
|
||||
public static $shouldCache = false;
|
||||
public static bool $shouldCache = false;
|
||||
|
||||
/** @var int */
|
||||
public static $cacheTTL = 3600; // seconds
|
||||
public static int $cacheTTL = 3600; // seconds
|
||||
|
||||
/** @var string|null */
|
||||
public static $cacheStore = null; // default
|
||||
public static string|null $cacheStore = null; // default
|
||||
|
||||
public function resolveWithoutCache(...$args): Tenant
|
||||
{
|
||||
|
|
|
|||
|
|
@ -9,14 +9,11 @@ use Stancl\Tenancy\Exceptions\TenantCouldNotBeIdentifiedByRequestDataException;
|
|||
|
||||
class RequestDataTenantResolver extends Contracts\CachedTenantResolver
|
||||
{
|
||||
/** @var bool */
|
||||
public static $shouldCache = false;
|
||||
public static bool $shouldCache = false;
|
||||
|
||||
/** @var int */
|
||||
public static $cacheTTL = 3600; // seconds
|
||||
public static int $cacheTTL = 3600; // seconds
|
||||
|
||||
/** @var string|null */
|
||||
public static $cacheStore = null; // default
|
||||
public static string|null $cacheStore = null; // default
|
||||
|
||||
public function resolveWithoutCache(...$args): Tenant
|
||||
{
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use Illuminate\Support\Traits\Macroable;
|
|||
use Stancl\Tenancy\Concerns\Debuggable;
|
||||
use Stancl\Tenancy\Contracts\TenancyBootstrapper;
|
||||
use Stancl\Tenancy\Contracts\Tenant;
|
||||
use Stancl\Tenancy\Exceptions\TenantCouldNotBeIdentifiedById;
|
||||
use Stancl\Tenancy\Exceptions\TenantCouldNotBeIdentifiedByIdException;
|
||||
|
||||
class Tenancy
|
||||
{
|
||||
|
|
@ -38,7 +38,7 @@ class Tenancy
|
|||
$tenant = $this->find($tenantId);
|
||||
|
||||
if (! $tenant) {
|
||||
throw new TenantCouldNotBeIdentifiedById($tenantId);
|
||||
throw new TenantCouldNotBeIdentifiedByIdException($tenantId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -62,17 +62,17 @@ class Tenancy
|
|||
|
||||
public function end(): void
|
||||
{
|
||||
event(new Events\EndingTenancy($this));
|
||||
|
||||
if (! $this->initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
event(new Events\TenancyEnded($this));
|
||||
event(new Events\EndingTenancy($this));
|
||||
|
||||
$this->tenant = null;
|
||||
|
||||
$this->initialized = false;
|
||||
|
||||
$this->tenant = null;
|
||||
event(new Events\TenancyEnded($this));
|
||||
}
|
||||
|
||||
/** @return TenancyBootstrapper[] */
|
||||
|
|
@ -131,7 +131,7 @@ class Tenancy
|
|||
*
|
||||
* @param Tenant[]|\Traversable|string[]|null $tenants
|
||||
*/
|
||||
public function runForMultiple($tenants, callable $callback): void
|
||||
public function runForMultiple($tenants, Closure $callback): void
|
||||
{
|
||||
// Convert null to all tenants
|
||||
$tenants = is_null($tenants) ? $this->model()->cursor() : $tenants;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
// todo likely move all of these classes to Database\
|
||||
|
||||
namespace Stancl\Tenancy\TenantDatabaseManagers;
|
||||
|
||||
use Illuminate\Database\Connection;
|
||||
|
|
@ -12,10 +14,9 @@ use Stancl\Tenancy\Exceptions\NoConnectionSetException;
|
|||
|
||||
class MicrosoftSQLDatabaseManager implements TenantDatabaseManager
|
||||
{
|
||||
/** @var string */
|
||||
protected $connection;
|
||||
protected string $connection; // todo docblock, in all of these classes
|
||||
|
||||
protected function database(): Connection
|
||||
protected function database(): Connection // todo consider abstracting this method & setConnection() into a base class
|
||||
{
|
||||
if ($this->connection === null) {
|
||||
throw new NoConnectionSetException(static::class);
|
||||
|
|
@ -33,7 +34,7 @@ class MicrosoftSQLDatabaseManager implements TenantDatabaseManager
|
|||
{
|
||||
$database = $tenant->database()->getName();
|
||||
$charset = $this->database()->getConfig('charset');
|
||||
$collation = $this->database()->getConfig('collation');
|
||||
$collation = $this->database()->getConfig('collation'); // todo check why these are not used
|
||||
|
||||
return $this->database()->statement("CREATE DATABASE [{$database}]");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,23 +157,25 @@ class AnotherTenant extends Model implements Contracts\Tenant
|
|||
return 'id';
|
||||
}
|
||||
|
||||
public function getTenantKey()
|
||||
public function getTenantKey(): int|string
|
||||
{
|
||||
return $this->getAttribute('id');
|
||||
}
|
||||
|
||||
public function run(callable $callback)
|
||||
public function run(Closure $callback): mixed
|
||||
{
|
||||
$callback();
|
||||
}
|
||||
|
||||
public function getInternal(string $key)
|
||||
public function getInternal(string $key): mixed
|
||||
{
|
||||
return $this->$key;
|
||||
}
|
||||
|
||||
public function setInternal(string $key, $value)
|
||||
public function setInternal(string $key, mixed $value): static
|
||||
{
|
||||
$this->$key = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue