diff --git a/src/Commands/CreateRLSPoliciesForTenantTables.php b/src/Commands/CreateRLSPoliciesForTenantTables.php index 5a1a2d56..ad7aa70c 100644 --- a/src/Commands/CreateRLSPoliciesForTenantTables.php +++ b/src/Commands/CreateRLSPoliciesForTenantTables.php @@ -7,6 +7,7 @@ namespace Stancl\Tenancy\Commands; use Illuminate\Console\Command; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; +use Illuminate\Database\Eloquent\Model; use Stancl\Tenancy\Database\Concerns\BelongsToPrimaryModel; class CreateRLSPoliciesForTenantTables extends Command @@ -21,35 +22,19 @@ class CreateRLSPoliciesForTenantTables extends Command foreach ($tenantModels as $model) { $table = $model->getTable(); - DB::statement("DROP POLICY IF EXISTS {$table}_rls_policy ON {$table}"); + DB::transaction(fn () => DB::statement("DROP POLICY IF EXISTS {$table}_rls_policy ON {$table}")); if (! Schema::hasColumn($table, $tenantKey)) { // Table is not directly related to tenant if (in_array(BelongsToPrimaryModel::class, class_uses_recursive($model::class))) { - $parentName = $model->getRelationshipToPrimaryModel(); - $parentKey = $model->$parentName()->getForeignKeyName(); - $parentModel = $model->$parentName()->make(); - $parentTable = str($parentModel->getTable())->toString(); - - DB::statement("CREATE POLICY {$table}_rls_policy ON {$table} USING ( - {$parentKey} IN ( - SELECT id - FROM {$parentTable} - WHERE ({$tenantKey} = ( - SELECT {$tenantKey} - FROM {$parentTable} - WHERE id = {$parentKey} - )) - ) - )"); - - $this->makeTableUseRls($table); + $this->makeModelUseRls($model); } else { $modelName = $model::class; + $this->components->info("Table '$table' is not related to tenant. Make sure $modelName uses the BelongsToPrimaryModel trait."); } } else { - DB::statement("CREATE POLICY {$table}_rls_policy ON {$table} USING ({$tenantKey}::TEXT = current_user);"); + DB::transaction(fn () => DB::statement("CREATE POLICY {$table}_rls_policy ON {$table} USING ({$tenantKey}::TEXT = current_user);")); $this->makeTableUseRls($table); @@ -65,9 +50,36 @@ class CreateRLSPoliciesForTenantTables extends Command return array_map(fn (string $modelName) => (new $modelName), config('tenancy.models.rls')); } + protected function makeModelUseRls(Model $model): void + { + $table = $model->getTable(); + $tenantKey = tenancy()->tenantKeyColumn(); + + $parentName = $model->getRelationshipToPrimaryModel(); + $parentKey = $model->$parentName()->getForeignKeyName(); + $parentModel = $model->$parentName()->make(); + $parentTable = str($parentModel->getTable())->toString(); + + DB::transaction(fn () => DB::statement("CREATE POLICY {$table}_rls_policy ON {$table} USING ( + {$parentKey} IN ( + SELECT id + FROM {$parentTable} + WHERE ({$tenantKey} = ( + SELECT {$tenantKey} + FROM {$parentTable} + WHERE id = {$parentKey} + )) + ) + )")); + + $this->makeTableUseRls($table); + } + protected function makeTableUseRls(string $table): void { - DB::statement("ALTER TABLE {$table} ENABLE ROW LEVEL SECURITY"); - DB::statement("ALTER TABLE {$table} FORCE ROW LEVEL SECURITY"); + DB::transaction(function () use ($table) { + DB::statement("ALTER TABLE {$table} ENABLE ROW LEVEL SECURITY"); + DB::statement("ALTER TABLE {$table} FORCE ROW LEVEL SECURITY"); + }); } }