diff --git a/assets/config.php b/assets/config.php index db3820bf..9089974d 100644 --- a/assets/config.php +++ b/assets/config.php @@ -15,6 +15,7 @@ return [ 'models' => [ 'tenant' => Stancl\Tenancy\Database\Models\Tenant::class, 'domain' => Stancl\Tenancy\Database\Models\Domain::class, + 'impersonation_token' => Stancl\Tenancy\Database\Models\ImpersonationToken::class, /** * Name of the column used to relate models to tenants. diff --git a/src/Database/Models/ImpersonationToken.php b/src/Database/Models/ImpersonationToken.php index 6dabbd03..38d2463e 100644 --- a/src/Database/Models/ImpersonationToken.php +++ b/src/Database/Models/ImpersonationToken.php @@ -25,6 +25,9 @@ class ImpersonationToken extends Model { use CentralConnection; + /** You can set this property to customize the table name */ + public static string $tableName = 'tenant_user_impersonation_tokens'; + protected $guarded = []; public $timestamps = false; @@ -33,11 +36,15 @@ class ImpersonationToken extends Model public $incrementing = false; - protected $table = 'tenant_user_impersonation_tokens'; protected $casts = [ 'created_at' => 'datetime', ]; + public function getTable() + { + return static::$tableName; + } + public static function booted(): void { static::creating(function ($model) { diff --git a/src/Features/UserImpersonation.php b/src/Features/UserImpersonation.php index 2e0fedbf..3db563a4 100644 --- a/src/Features/UserImpersonation.php +++ b/src/Features/UserImpersonation.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Stancl\Tenancy\Features; +use Illuminate\Database\Eloquent\Model; use Illuminate\Http\RedirectResponse; use Illuminate\Support\Facades\Auth; use Stancl\Tenancy\Contracts\Feature; @@ -18,8 +19,8 @@ class UserImpersonation implements Feature public function bootstrap(Tenancy $tenancy): void { - $tenancy->macro('impersonate', function (Tenant $tenant, string $userId, string $redirectUrl, string|null $authGuard = null, bool $remember = false): ImpersonationToken { - return ImpersonationToken::create([ + $tenancy->macro('impersonate', function (Tenant $tenant, string $userId, string $redirectUrl, string|null $authGuard = null, bool $remember = false): Model { + return UserImpersonation::modelClass()::create([ Tenancy::tenantKeyColumn() => $tenant->getTenantKey(), 'user_id' => $userId, 'redirect_url' => $redirectUrl, @@ -30,10 +31,15 @@ class UserImpersonation implements Feature } /** Impersonate a user and get an HTTP redirect response. */ - public static function makeResponse(#[\SensitiveParameter] string|ImpersonationToken $token, ?int $ttl = null): RedirectResponse + public static function makeResponse(#[\SensitiveParameter] string|Model $token, ?int $ttl = null): RedirectResponse { - /** @var ImpersonationToken $token */ - $token = $token instanceof ImpersonationToken ? $token : ImpersonationToken::findOrFail($token); + /** + * The model does NOT have to extend ImpersonationToken, but usually it WILL be a child + * of ImpersonationToken and this makes it clear to phpstan that the model has a redirect_url property. + * + * @var ImpersonationToken $token + */ + $token = $token instanceof Model ? $token : static::modelClass()::findOrFail($token); $ttl ??= static::$ttl; $tokenExpired = $token->created_at->diffInSeconds(now()) > $ttl; @@ -54,6 +60,12 @@ class UserImpersonation implements Feature return redirect($token->redirect_url); } + /** @return class-string */ + public static function modelClass(): string + { + return config('tenancy.models.impersonation_token'); + } + public static function isImpersonating(): bool { return session()->has('tenancy_impersonating');