Sikau

PostgreSQL · Day 13 · about 40 min

Roles and row-level security

Least privilege and per-row access rules.

Not everyone sees everything

The reporting tool should only read; the web app shouldn't drop tables; each branch manager should only see their branch's rows. PostgreSQL handles all three with roles, GRANTs and row-level security — enforced in the database, so a bug in one app can't leak everything.

GRANT and policies

CREATE TABLE branch_sales (branch text NOT NULL, amount int NOT NULL);
INSERT INTO branch_sales VALUES ('pokhara', 1200), ('pokhara', 900), ('kathmandu', 2000);

CREATE ROLE reporter;
GRANT SELECT ON branch_sales TO reporter;

CREATE ROLE pokhara;
GRANT SELECT ON branch_sales TO pokhara;
ALTER TABLE branch_sales ENABLE ROW LEVEL SECURITY;
CREATE POLICY own_branch ON branch_sales FOR SELECT USING (branch = current_user);
CREATE POLICY reporter_all ON branch_sales FOR SELECT TO reporter USING (true);

SET ROLE pokhara;
SELECT * FROM branch_sales;
RESET ROLE;

SET ROLE reporter;
SELECT count(*) FROM branch_sales;
RESET ROLE;
  • Supabase builds its whole security model on RLS policies like these.
  • WITH CHECK (…) on INSERT/UPDATE policies controls which rows may be written.
  • Apps often pass the user id with SET app.user_id = … and policies read current_setting('app.user_id').

The rest of this lesson

  • Roles for each kind of userexplain
  • Policies with the current userexplain
  • What does the role see?predict
  • Who gets what?match
  • Your turnwrite code
  • Badge quizquiz
  • What you learnedrecap

Continue this lesson free — run real code in your browser

Continue with Google

See all 16 lessons of PostgreSQL