mirror of
https://github.com/archtechx/tenancy.git
synced 2025-12-12 20:54:04 +00:00
Add test for $forceRls = false, refactor BYPASSRLS test
This commit is contained in:
parent
3fabdf8f33
commit
d531c972b6
1 changed files with 74 additions and 28 deletions
|
|
@ -541,33 +541,67 @@ test('table rls manager generates relationship trees with tables related to the
|
|||
]);
|
||||
})->with([true, false]);
|
||||
|
||||
test('table owner sees all the records when forceRls is false while other users only see records scoped to them', function() {
|
||||
CreateUserWithRLSPolicies::$forceRls = false;
|
||||
|
||||
// Drop all tables created in beforeEach
|
||||
DB::statement("DROP TABLE authors, categories, posts, comments, reactions, articles;");
|
||||
|
||||
[$username, $password] = createPostgresUser('central_user');
|
||||
|
||||
config(['database.connections.central' => array_merge(
|
||||
config('database.connections.pgsql'),
|
||||
['username' => $username, 'password' => $password]
|
||||
)]);
|
||||
|
||||
DB::reconnect();
|
||||
|
||||
Schema::create('orders', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name');
|
||||
|
||||
$table->string('tenant_id')->comment('rls');
|
||||
$table->foreign('tenant_id')->references('id')->on('tenants')->onUpdate('cascade')->onDelete('cascade');
|
||||
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
[$tenant1, $tenant2] = [Tenant::create(), Tenant::create()];
|
||||
|
||||
pest()->artisan('tenants:rls');
|
||||
|
||||
[$order1, $order2] = [
|
||||
Order::create(['name' => 'order1', 'tenant_id' => $tenant1->getTenantKey()]),
|
||||
Order::create(['name' => 'order2', 'tenant_id' => $tenant2->getTenantKey()]),
|
||||
];
|
||||
|
||||
// The table owner should see all the records
|
||||
expect(Order::all())->toHaveCount(2);
|
||||
|
||||
tenancy()->initialize($tenant1);
|
||||
|
||||
// The tenant users should only see their records
|
||||
expect(Order::count())->toBe(1);
|
||||
expect(Order::first()->name)->toBe($order1->name);
|
||||
|
||||
tenancy()->initialize($tenant2);
|
||||
|
||||
expect(Order::count())->toBe(1);
|
||||
expect(Order::first()->name)->toBe($order2->name);
|
||||
});
|
||||
|
||||
// https://github.com/tenancy-for-laravel/v4/issues/63
|
||||
test('user without BYPASSRLS can only query owned tables if forceRls is true', function(bool $forceRls) {
|
||||
CreateUserWithRLSPolicies::$forceRls = $forceRls;
|
||||
|
||||
// Drop all tables created in beforeEach
|
||||
DB::statement("DROP TABLE authors, categories, posts, comments, reactions, articles;");
|
||||
|
||||
try {
|
||||
DB::statement("DROP OWNED BY administrator;");
|
||||
} catch (\Throwable $th) {}
|
||||
|
||||
DB::statement("DROP USER IF EXISTS administrator;");
|
||||
|
||||
// Create new central user (without superuser and bypassrls privileges)
|
||||
DB::statement("CREATE USER administrator WITH ENCRYPTED PASSWORD 'password'");
|
||||
DB::statement("ALTER USER administrator CREATEDB");
|
||||
DB::statement("ALTER USER administrator CREATEROLE");
|
||||
|
||||
// Grant privileges to the new central user
|
||||
DB::statement("GRANT ALL PRIVILEGES ON DATABASE main to administrator");
|
||||
DB::statement("GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO administrator");
|
||||
DB::statement("GRANT ALL ON SCHEMA public TO administrator");
|
||||
DB::statement("ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL PRIVILEGES ON TABLES TO administrator");
|
||||
DB::statement("GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO administrator");
|
||||
[$username, $password] = createPostgresUser('administrator');
|
||||
|
||||
config(['database.connections.central' => array_merge(
|
||||
config('database.connections.pgsql'),
|
||||
['username' => 'administrator', 'password' => 'password']
|
||||
['username' => $username, 'password' => $password]
|
||||
)]);
|
||||
|
||||
DB::reconnect();
|
||||
|
|
@ -583,21 +617,11 @@ test('user without BYPASSRLS can only query owned tables if forceRls is true', f
|
|||
});
|
||||
|
||||
$tenant1 = Tenant::create();
|
||||
$tenant2 = Tenant::create();
|
||||
|
||||
// Create RLS policy for the orders table
|
||||
pest()->artisan('tenants:rls');
|
||||
|
||||
tenancy()->initialize($tenant1);
|
||||
|
||||
Order::create(['name' => 'order1', 'tenant_id' => $tenant1->getTenantKey()]);
|
||||
expect(Order::first())->not()->toBeNull();
|
||||
|
||||
tenancy()->initialize($tenant2);
|
||||
|
||||
expect(Order::first())->toBeNull(); // RLS works
|
||||
|
||||
tenancy()->end();
|
||||
|
||||
if ($forceRls) {
|
||||
// RLS is forced, so by default, not even the table owner should be able to query the table protected by the RLS policy.
|
||||
|
|
@ -725,6 +749,28 @@ test('table manager throws an exception when encountering a recursive relationsh
|
|||
expect(fn () => app(TableRLSManager::class)->generateTrees())->toThrow(RecursiveRelationshipException::class);
|
||||
});
|
||||
|
||||
function createPostgresUser(string $username, string $password = 'password'): array
|
||||
{
|
||||
try {
|
||||
DB::statement("DROP OWNED BY {$username};");
|
||||
} catch (\Throwable $th) {}
|
||||
|
||||
DB::statement("DROP USER IF EXISTS {$username};");
|
||||
|
||||
DB::statement("CREATE USER {$username} WITH ENCRYPTED PASSWORD '{$password}'");
|
||||
DB::statement("ALTER USER {$username} CREATEDB");
|
||||
DB::statement("ALTER USER {$username} CREATEROLE");
|
||||
|
||||
// Grant privileges to the new central user
|
||||
DB::statement("GRANT ALL PRIVILEGES ON DATABASE main to {$username}");
|
||||
DB::statement("GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO {$username}");
|
||||
DB::statement("GRANT ALL ON SCHEMA public TO {$username}");
|
||||
DB::statement("ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL PRIVILEGES ON TABLES TO {$username}");
|
||||
DB::statement("GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO {$username}");
|
||||
|
||||
return [$username, $password];
|
||||
}
|
||||
|
||||
class Post extends Model
|
||||
{
|
||||
protected $guarded = [];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue