mirror of
https://github.com/archtechx/tenancy.git
synced 2025-12-13 02:04:03 +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]);
|
})->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) {
|
test('user without BYPASSRLS can only query owned tables if forceRls is true', function(bool $forceRls) {
|
||||||
CreateUserWithRLSPolicies::$forceRls = $forceRls;
|
CreateUserWithRLSPolicies::$forceRls = $forceRls;
|
||||||
|
|
||||||
// Drop all tables created in beforeEach
|
// Drop all tables created in beforeEach
|
||||||
DB::statement("DROP TABLE authors, categories, posts, comments, reactions, articles;");
|
DB::statement("DROP TABLE authors, categories, posts, comments, reactions, articles;");
|
||||||
|
|
||||||
try {
|
[$username, $password] = createPostgresUser('administrator');
|
||||||
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");
|
|
||||||
|
|
||||||
config(['database.connections.central' => array_merge(
|
config(['database.connections.central' => array_merge(
|
||||||
config('database.connections.pgsql'),
|
config('database.connections.pgsql'),
|
||||||
['username' => 'administrator', 'password' => 'password']
|
['username' => $username, 'password' => $password]
|
||||||
)]);
|
)]);
|
||||||
|
|
||||||
DB::reconnect();
|
DB::reconnect();
|
||||||
|
|
@ -583,21 +617,11 @@ test('user without BYPASSRLS can only query owned tables if forceRls is true', f
|
||||||
});
|
});
|
||||||
|
|
||||||
$tenant1 = Tenant::create();
|
$tenant1 = Tenant::create();
|
||||||
$tenant2 = Tenant::create();
|
|
||||||
|
|
||||||
// Create RLS policy for the orders table
|
// Create RLS policy for the orders table
|
||||||
pest()->artisan('tenants:rls');
|
pest()->artisan('tenants:rls');
|
||||||
|
|
||||||
tenancy()->initialize($tenant1);
|
|
||||||
|
|
||||||
Order::create(['name' => 'order1', 'tenant_id' => $tenant1->getTenantKey()]);
|
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) {
|
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.
|
// 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);
|
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
|
class Post extends Model
|
||||||
{
|
{
|
||||||
protected $guarded = [];
|
protected $guarded = [];
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue