Skip to content

Commit 8f49fdb

Browse files
QSchlegelclaude
andcommitted
fix: make RLS migration conditional on Supabase roles existing
The migration was failing on Railway with "role anon does not exist" because it assumed Supabase-specific roles. Wrap policy creation in conditional checks so it works on any PostgreSQL instance. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 0258b24 commit 8f49fdb

1 file changed

Lines changed: 51 additions & 218 deletions

File tree

  • prisma/migrations/20251215090000_enable_rls_disable_postgrest
Lines changed: 51 additions & 218 deletions
Original file line numberDiff line numberDiff line change
@@ -1,221 +1,54 @@
11
-- Enable Row Level Security (RLS) and deny-all policies for PostgREST roles
2-
-- This migration is designed for Supabase:
3-
-- - Blocks access for `anon` and `authenticated` roles (used by PostgREST)
2+
-- This migration is designed for Supabase but is safe to run on any PostgreSQL:
3+
-- - Enables RLS on all tables unconditionally
4+
-- - Only creates deny-all policies for `anon` and `authenticated` roles if they exist
45
-- - Allows Prisma (using the service role) to continue bypassing RLS
56

6-
-- Helper comment:
7-
-- Pattern applied for each table:
8-
-- ALTER TABLE "TableName" ENABLE ROW LEVEL SECURITY;
9-
-- CREATE POLICY "deny_all_anon_TableName" ON "TableName"
10-
-- FOR ALL TO anon USING (false) WITH CHECK (false);
11-
-- CREATE POLICY "deny_all_authenticated_TableName" ON "TableName"
12-
-- FOR ALL TO authenticated USING (false) WITH CHECK (false);
13-
14-
-- =========================
15-
-- User
16-
-- =========================
17-
ALTER TABLE "User" ENABLE ROW LEVEL SECURITY;
18-
19-
CREATE POLICY "deny_all_anon_User" ON "User"
20-
FOR ALL
21-
TO anon
22-
USING (false)
23-
WITH CHECK (false);
24-
25-
CREATE POLICY "deny_all_authenticated_User" ON "User"
26-
FOR ALL
27-
TO authenticated
28-
USING (false)
29-
WITH CHECK (false);
30-
31-
-- =========================
32-
-- Wallet
33-
-- =========================
34-
ALTER TABLE "Wallet" ENABLE ROW LEVEL SECURITY;
35-
36-
CREATE POLICY "deny_all_anon_Wallet" ON "Wallet"
37-
FOR ALL
38-
TO anon
39-
USING (false)
40-
WITH CHECK (false);
41-
42-
CREATE POLICY "deny_all_authenticated_Wallet" ON "Wallet"
43-
FOR ALL
44-
TO authenticated
45-
USING (false)
46-
WITH CHECK (false);
47-
48-
-- =========================
49-
-- Transaction
50-
-- =========================
51-
ALTER TABLE "Transaction" ENABLE ROW LEVEL SECURITY;
52-
53-
CREATE POLICY "deny_all_anon_Transaction" ON "Transaction"
54-
FOR ALL
55-
TO anon
56-
USING (false)
57-
WITH CHECK (false);
58-
59-
CREATE POLICY "deny_all_authenticated_Transaction" ON "Transaction"
60-
FOR ALL
61-
TO authenticated
62-
USING (false)
63-
WITH CHECK (false);
64-
65-
-- =========================
66-
-- Signable
67-
-- =========================
68-
ALTER TABLE "Signable" ENABLE ROW LEVEL SECURITY;
69-
70-
CREATE POLICY "deny_all_anon_Signable" ON "Signable"
71-
FOR ALL
72-
TO anon
73-
USING (false)
74-
WITH CHECK (false);
75-
76-
CREATE POLICY "deny_all_authenticated_Signable" ON "Signable"
77-
FOR ALL
78-
TO authenticated
79-
USING (false)
80-
WITH CHECK (false);
81-
82-
-- =========================
83-
-- NewWallet
84-
-- =========================
85-
ALTER TABLE "NewWallet" ENABLE ROW LEVEL SECURITY;
86-
87-
CREATE POLICY "deny_all_anon_NewWallet" ON "NewWallet"
88-
FOR ALL
89-
TO anon
90-
USING (false)
91-
WITH CHECK (false);
92-
93-
CREATE POLICY "deny_all_authenticated_NewWallet" ON "NewWallet"
94-
FOR ALL
95-
TO authenticated
96-
USING (false)
97-
WITH CHECK (false);
98-
99-
-- =========================
100-
-- Nonce
101-
-- =========================
102-
ALTER TABLE "Nonce" ENABLE ROW LEVEL SECURITY;
103-
104-
CREATE POLICY "deny_all_anon_Nonce" ON "Nonce"
105-
FOR ALL
106-
TO anon
107-
USING (false)
108-
WITH CHECK (false);
109-
110-
CREATE POLICY "deny_all_authenticated_Nonce" ON "Nonce"
111-
FOR ALL
112-
TO authenticated
113-
USING (false)
114-
WITH CHECK (false);
115-
116-
-- =========================
117-
-- Ballot
118-
-- =========================
119-
ALTER TABLE "Ballot" ENABLE ROW LEVEL SECURITY;
120-
121-
CREATE POLICY "deny_all_anon_Ballot" ON "Ballot"
122-
FOR ALL
123-
TO anon
124-
USING (false)
125-
WITH CHECK (false);
126-
127-
CREATE POLICY "deny_all_authenticated_Ballot" ON "Ballot"
128-
FOR ALL
129-
TO authenticated
130-
USING (false)
131-
WITH CHECK (false);
132-
133-
-- =========================
134-
-- Proxy
135-
-- =========================
136-
ALTER TABLE "Proxy" ENABLE ROW LEVEL SECURITY;
137-
138-
CREATE POLICY "deny_all_anon_Proxy" ON "Proxy"
139-
FOR ALL
140-
TO anon
141-
USING (false)
142-
WITH CHECK (false);
143-
144-
CREATE POLICY "deny_all_authenticated_Proxy" ON "Proxy"
145-
FOR ALL
146-
TO authenticated
147-
USING (false)
148-
WITH CHECK (false);
149-
150-
-- =========================
151-
-- BalanceSnapshot
152-
-- =========================
153-
ALTER TABLE "BalanceSnapshot" ENABLE ROW LEVEL SECURITY;
154-
155-
CREATE POLICY "deny_all_anon_BalanceSnapshot" ON "BalanceSnapshot"
156-
FOR ALL
157-
TO anon
158-
USING (false)
159-
WITH CHECK (false);
160-
161-
CREATE POLICY "deny_all_authenticated_BalanceSnapshot" ON "BalanceSnapshot"
162-
FOR ALL
163-
TO authenticated
164-
USING (false)
165-
WITH CHECK (false);
166-
167-
-- =========================
168-
-- Migration
169-
-- =========================
170-
ALTER TABLE "Migration" ENABLE ROW LEVEL SECURITY;
171-
172-
CREATE POLICY "deny_all_anon_Migration" ON "Migration"
173-
FOR ALL
174-
TO anon
175-
USING (false)
176-
WITH CHECK (false);
177-
178-
CREATE POLICY "deny_all_authenticated_Migration" ON "Migration"
179-
FOR ALL
180-
TO authenticated
181-
USING (false)
182-
WITH CHECK (false);
183-
184-
-- =========================
185-
-- Crowdfund
186-
-- =========================
187-
-- Note: Crowdfund table exists in the database but is not defined in the current Prisma schema.
188-
-- We still enable RLS and deny-all policies to secure its PostgREST exposure.
189-
ALTER TABLE "Crowdfund" ENABLE ROW LEVEL SECURITY;
190-
191-
CREATE POLICY "deny_all_anon_Crowdfund" ON "Crowdfund"
192-
FOR ALL
193-
TO anon
194-
USING (false)
195-
WITH CHECK (false);
196-
197-
CREATE POLICY "deny_all_authenticated_Crowdfund" ON "Crowdfund"
198-
FOR ALL
199-
TO authenticated
200-
USING (false)
201-
WITH CHECK (false);
202-
203-
-- =========================
204-
-- _prisma_migrations (optional system table)
205-
-- =========================
206-
-- While Prisma typically manages this table without RLS, enabling RLS here
207-
-- and denying anon/authenticated helps ensure it is not exposed via PostgREST.
208-
ALTER TABLE "_prisma_migrations" ENABLE ROW LEVEL SECURITY;
209-
210-
CREATE POLICY "deny_all_anon__prisma_migrations" ON "_prisma_migrations"
211-
FOR ALL
212-
TO anon
213-
USING (false)
214-
WITH CHECK (false);
215-
216-
CREATE POLICY "deny_all_authenticated__prisma_migrations" ON "_prisma_migrations"
217-
FOR ALL
218-
TO authenticated
219-
USING (false)
220-
WITH CHECK (false);
221-
7+
DO $$
8+
BEGIN
9+
-- Enable RLS on all tables
10+
ALTER TABLE "User" ENABLE ROW LEVEL SECURITY;
11+
ALTER TABLE "Wallet" ENABLE ROW LEVEL SECURITY;
12+
ALTER TABLE "Transaction" ENABLE ROW LEVEL SECURITY;
13+
ALTER TABLE "Signable" ENABLE ROW LEVEL SECURITY;
14+
ALTER TABLE "NewWallet" ENABLE ROW LEVEL SECURITY;
15+
ALTER TABLE "Nonce" ENABLE ROW LEVEL SECURITY;
16+
ALTER TABLE "Ballot" ENABLE ROW LEVEL SECURITY;
17+
ALTER TABLE "Proxy" ENABLE ROW LEVEL SECURITY;
18+
ALTER TABLE "BalanceSnapshot" ENABLE ROW LEVEL SECURITY;
19+
ALTER TABLE "Migration" ENABLE ROW LEVEL SECURITY;
20+
ALTER TABLE "Crowdfund" ENABLE ROW LEVEL SECURITY;
21+
ALTER TABLE "_prisma_migrations" ENABLE ROW LEVEL SECURITY;
22+
23+
-- Create deny-all policies for anon role (Supabase PostgREST)
24+
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'anon') THEN
25+
CREATE POLICY "deny_all_anon_User" ON "User" FOR ALL TO anon USING (false) WITH CHECK (false);
26+
CREATE POLICY "deny_all_anon_Wallet" ON "Wallet" FOR ALL TO anon USING (false) WITH CHECK (false);
27+
CREATE POLICY "deny_all_anon_Transaction" ON "Transaction" FOR ALL TO anon USING (false) WITH CHECK (false);
28+
CREATE POLICY "deny_all_anon_Signable" ON "Signable" FOR ALL TO anon USING (false) WITH CHECK (false);
29+
CREATE POLICY "deny_all_anon_NewWallet" ON "NewWallet" FOR ALL TO anon USING (false) WITH CHECK (false);
30+
CREATE POLICY "deny_all_anon_Nonce" ON "Nonce" FOR ALL TO anon USING (false) WITH CHECK (false);
31+
CREATE POLICY "deny_all_anon_Ballot" ON "Ballot" FOR ALL TO anon USING (false) WITH CHECK (false);
32+
CREATE POLICY "deny_all_anon_Proxy" ON "Proxy" FOR ALL TO anon USING (false) WITH CHECK (false);
33+
CREATE POLICY "deny_all_anon_BalanceSnapshot" ON "BalanceSnapshot" FOR ALL TO anon USING (false) WITH CHECK (false);
34+
CREATE POLICY "deny_all_anon_Migration" ON "Migration" FOR ALL TO anon USING (false) WITH CHECK (false);
35+
CREATE POLICY "deny_all_anon_Crowdfund" ON "Crowdfund" FOR ALL TO anon USING (false) WITH CHECK (false);
36+
CREATE POLICY "deny_all_anon__prisma_migrations" ON "_prisma_migrations" FOR ALL TO anon USING (false) WITH CHECK (false);
37+
END IF;
38+
39+
-- Create deny-all policies for authenticated role (Supabase PostgREST)
40+
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'authenticated') THEN
41+
CREATE POLICY "deny_all_authenticated_User" ON "User" FOR ALL TO authenticated USING (false) WITH CHECK (false);
42+
CREATE POLICY "deny_all_authenticated_Wallet" ON "Wallet" FOR ALL TO authenticated USING (false) WITH CHECK (false);
43+
CREATE POLICY "deny_all_authenticated_Transaction" ON "Transaction" FOR ALL TO authenticated USING (false) WITH CHECK (false);
44+
CREATE POLICY "deny_all_authenticated_Signable" ON "Signable" FOR ALL TO authenticated USING (false) WITH CHECK (false);
45+
CREATE POLICY "deny_all_authenticated_NewWallet" ON "NewWallet" FOR ALL TO authenticated USING (false) WITH CHECK (false);
46+
CREATE POLICY "deny_all_authenticated_Nonce" ON "Nonce" FOR ALL TO authenticated USING (false) WITH CHECK (false);
47+
CREATE POLICY "deny_all_authenticated_Ballot" ON "Ballot" FOR ALL TO authenticated USING (false) WITH CHECK (false);
48+
CREATE POLICY "deny_all_authenticated_Proxy" ON "Proxy" FOR ALL TO authenticated USING (false) WITH CHECK (false);
49+
CREATE POLICY "deny_all_authenticated_BalanceSnapshot" ON "BalanceSnapshot" FOR ALL TO authenticated USING (false) WITH CHECK (false);
50+
CREATE POLICY "deny_all_authenticated_Migration" ON "Migration" FOR ALL TO authenticated USING (false) WITH CHECK (false);
51+
CREATE POLICY "deny_all_authenticated_Crowdfund" ON "Crowdfund" FOR ALL TO authenticated USING (false) WITH CHECK (false);
52+
CREATE POLICY "deny_all_authenticated__prisma_migrations" ON "_prisma_migrations" FOR ALL TO authenticated USING (false) WITH CHECK (false);
53+
END IF;
54+
END $$;

0 commit comments

Comments
 (0)