mirror of
https://github.com/archtechx/tenancy.git
synced 2026-02-05 12:54:05 +00:00
Scope queries using Postgres RLS (WIP)
This commit is contained in:
parent
3c098dc78e
commit
17d779e130
6 changed files with 71 additions and 33 deletions
|
|
@ -35,7 +35,7 @@ class CreateRLSPoliciesForTenantTables extends Command
|
|||
{$parentKey} IN (
|
||||
SELECT id
|
||||
FROM {$parentTable}
|
||||
WHERE ({$tenantKey}::TEXT = (
|
||||
WHERE ({$tenantKey}::UUID = (
|
||||
SELECT {$tenantKey}
|
||||
FROM {$parentTable}
|
||||
WHERE id = {$parentKey}
|
||||
|
|
@ -43,7 +43,7 @@ class CreateRLSPoliciesForTenantTables extends Command
|
|||
)
|
||||
)");
|
||||
|
||||
DB::statement("ALTER TABLE {$table} FORCE ROW LEVEL SECURITY");
|
||||
$this->makeTableUseRls($table);
|
||||
} else {
|
||||
$modelName = $model::class;
|
||||
$this->components->info("Table '$table' is not related to tenant. Make sure $modelName uses the BelongsToPrimaryModel trait.");
|
||||
|
|
@ -51,7 +51,7 @@ class CreateRLSPoliciesForTenantTables extends Command
|
|||
} else {
|
||||
DB::statement("CREATE POLICY {$table}_rls_policy ON {$table} USING ({$tenantKey}::TEXT = current_user);");
|
||||
|
||||
DB::statement("ALTER TABLE {$table} FORCE ROW LEVEL SECURITY");
|
||||
$this->makeTableUseRls($table);
|
||||
|
||||
$this->components->info("Created RLS policy for table '$table'");
|
||||
}
|
||||
|
|
@ -64,4 +64,10 @@ class CreateRLSPoliciesForTenantTables extends Command
|
|||
{
|
||||
return array_map(fn (string $modelName) => (new $modelName), config('tenancy.models.rls'));
|
||||
}
|
||||
|
||||
protected function makeTableUseRls(string $table): void
|
||||
{
|
||||
DB::statement("ALTER TABLE {$table} ENABLE ROW LEVEL SECURITY");
|
||||
DB::statement("ALTER TABLE {$table} FORCE ROW LEVEL SECURITY");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,11 @@ trait BelongsToTenant
|
|||
|
||||
public static function bootBelongsToTenant(): void
|
||||
{
|
||||
static::addGlobalScope(new TenantScope);
|
||||
// The queries performed for models present in the tenancy.models.rls are scoped using Postgres RLS instead of the global scope
|
||||
if (! in_array(static::class, config('tenancy.models.rls'))) {
|
||||
static::addGlobalScope(new TenantScope);
|
||||
}
|
||||
|
||||
|
||||
static::creating(function ($model) {
|
||||
if (! $model->getAttribute(Tenancy::tenantKeyColumn()) && ! $model->relationLoaded('tenant')) {
|
||||
|
|
|
|||
|
|
@ -43,5 +43,20 @@ class CreatePostgresUserForTenant implements ShouldQueue
|
|||
if (! count(DB::select("SELECT usename FROM pg_user WHERE usename = '$name';")) > 0) {
|
||||
DB::statement("CREATE USER \"$name\" LOGIN PASSWORD '$password';");
|
||||
}
|
||||
|
||||
$this->grantPermissions($name);
|
||||
}
|
||||
|
||||
protected function grantPermissions(string $userName): void
|
||||
{
|
||||
/**
|
||||
* @var \Stancl\Tenancy\Database\Contracts\StatefulTenantDatabaseManager $databaseManager
|
||||
*/
|
||||
$databaseManager = $this->tenant->database()->manager();
|
||||
foreach (array_map(fn (string $modelName) => (new $modelName), config('tenancy.models.rls')) as $model) {
|
||||
$table = $model->getTable();
|
||||
|
||||
$databaseManager->database()->statement("GRANT ALL ON {$table} TO \"{$userName}\"");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@ declare(strict_types=1);
|
|||
namespace Stancl\Tenancy;
|
||||
|
||||
use Illuminate\Cache\CacheManager;
|
||||
use Illuminate\Database\Console\Migrations\FreshCommand;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Stancl\Tenancy\Bootstrappers\FilesystemTenancyBootstrapper;
|
||||
use Stancl\Tenancy\Contracts\Domain;
|
||||
use Stancl\Tenancy\Contracts\Tenant;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Stancl\Tenancy\Resolvers\DomainTenantResolver;
|
||||
use Illuminate\Database\Console\Migrations\FreshCommand;
|
||||
use Stancl\Tenancy\Bootstrappers\FilesystemTenancyBootstrapper;
|
||||
|
||||
class TenancyServiceProvider extends ServiceProvider
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue