4.7 KiB
c77_rbac Usage Guide
This guide helps beginner developers use the c77_rbac
PostgreSQL extension to secure database tables with role-based access control (RBAC). All tables and functions are in the public
schema with c77_rbac_
prefixes (e.g., c77_rbac_subjects
, c77_rbac_apply_policy
) to avoid conflicts with Laravel or other packages. Your application tables should use custom schemas (e.g., myapp.orders
).
What is c77_rbac?
c77_rbac
uses row-level security (RLS) to control table access. For example, a Chicago manager sees only Chicago orders, while an admin sees all orders. Admin rights use a global/all
scope, so any user ID (e.g., '2'
, '999'
) can be an admin.
Prerequisites
- PostgreSQL 14 or later.
- A superuser (e.g.,
homestead
) for installation. - A database (e.g.,
c77_rbac_test
). - Basic SQL knowledge.
Step 1: Install the Extension
-
Log in as the superuser:
psql -h 192.168.49.115 -p 5432 -U homestead -d c77_rbac_test
-
Create the extension:
CREATE EXTENSION c77_rbac SCHEMA public;
This sets up
c77_rbac_
tables and functions inpublic
. -
Exit:
\q
Step 2: Set Up Your Application Schema
Use a custom schema (e.g., myapp
) for your tables.
-
Log in as your application user (e.g.,
app_user
):psql -h 192.168.49.115 -p 5432 -U app_user -d c77_rbac_test
-
Create the myapp schema:
CREATE SCHEMA myapp;
-
Create a test table:
CREATE TABLE myapp.orders ( id SERIAL PRIMARY KEY, campus TEXT NOT NULL, amount NUMERIC );
-
Insert test data:
INSERT INTO myapp.orders (campus, amount) VALUES ('chicago', 500), ('miami', 1500);
Step 3: Apply Row-Level Security (RLS)
-
Apply an RLS policy:
SELECT public.c77_rbac_apply_policy('myapp.orders', 'view_sales_page', 'campus', 'campus');
myapp.orders
: Table to secure.view_sales_page
: Required permission.campus
: Scope type.campus
: Column for scope (e.g.,chicago
).
A
NOTICE: policy "c77_rbac_policy" ... does not exist
is normal for new tables. -
Check the policy:
\dp myapp.orders
Expect
c77_rbac_policy
with:c77_rbac_can_access('view_sales_page'::text, current_setting('c77_rbac.external_id'::text, true), 'campus'::text, campus)
Step 4: Assign Roles to Users
Users have an external_id
(e.g., '1'
, '2'
). Admin rights use global/all
.
-
Assign a sales manager role (Chicago):
SELECT public.c77_rbac_assign_subject('1', 'sales_manager', 'campus', 'chicago'); SELECT public.c77_rbac_grant_feature('sales_manager', 'view_sales_page');
-
Assign an admin role (all data):
SELECT public.c77_rbac_assign_subject('999', 'admin', 'global', 'all'); SELECT public.c77_rbac_grant_feature('admin', 'view_sales_page');
For another admin (e.g.,
'2'
):SELECT public.c77_rbac_assign_subject('2', 'admin', 'global', 'all'); SELECT public.c77_rbac_grant_feature('admin', 'view_sales_page');
Step 5: Test Access
-
Chicago manager:
SET "c77_rbac.external_id" TO '1'; SELECT * FROM myapp.orders;
Expected:
id | campus | amount ----+---------+-------- 1 | chicago | 500
-
Admin (e.g.,
'2'
):SET "c77_rbac.external_id" TO '2'; SELECT * FROM myapp.orders;
Expected:
id | campus | amount ----+---------+-------- 1 | chicago | 500 2 | miami | 1500
-
Unauthorized user:
SET "c77_rbac.external_id" TO 'unknown'; SELECT * FROM myapp.orders;
Expected:
id | campus | amount ----+--------+--------
Step 6: Use in Your Application
For Laravel:
-
Set user ID:
DB::statement("SET c77_rbac.external_id TO '1'");
-
Query:
SELECT * FROM myapp.orders;
Troubleshooting
- No rows: Check role (
c77_rbac_assign_subject
) and feature (c77_rbac_grant_feature
). - Policy missing: Verify
\dp myapp.orders
. Re-runc77_rbac_apply_policy
. - NOTICE messages: Normal for new tables.
- Display quirk:
\dp
may showcampus
instead ofmyapp.orders.campus
. This is cosmetic.
Notes
- Use
schema.table
(e.g.,myapp.orders
) withc77_rbac_apply_policy
. public
is forc77_rbac_
, Laravel, and third-party packages. Usemyapp
for app tables.c77_rbac_
tables are accessible to all database users. Manage roles responsibly.- This covers
c77_rbac
only, notc77_rbac_laravel
.
For help, ask your database administrator or the c77_rbac
community.