Skip to content

Commit 0b1945d

Browse files
ralyodioclaude
andauthored
Restore storage.objects policies lost in the dev2 move (#262)
The 2026-09-25 move to the self-hosted stack on dev2 dumped DDL for the app schemas only, so all 14 policies on storage.objects (avatars and encrypted-files buckets) were dropped. This re-creates the final state from the migrations, idempotently. Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1 parent 91e03ba commit 0b1945d

1 file changed

Lines changed: 165 additions & 0 deletions

File tree

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
-- Restore the RLS policies on storage.objects that the 2026-09-25 move to the
2+
-- self-hosted Supabase stack on dev2 left behind.
3+
--
4+
-- The move dumped DDL for the app schemas only, and pg_dump files a policy
5+
-- under its table's schema, so every policy ON storage.objects was dropped
6+
-- while the buckets (copied as data) survived. With RLS on and no policy,
7+
-- storage.objects denies everything to anon and authenticated: avatar
8+
-- uploads and encrypted-file uploads/downloads fail for every user, and the
9+
-- public avatars bucket only keeps working through the public URL path.
10+
--
11+
-- This is the final state after replaying every migration in order:
12+
-- 20250823223015_add_user_avatar_support.sql 4 avatar policies (singular names)
13+
-- 20250824005053_fix_avatar_storage_rls_policies.sql 4 avatar policies (plural names)
14+
-- 20250921060226_fix_storage_rls_for_internal_user_ids.sql 3 encrypted-files policies
15+
-- 20250926094631_fix_large_file_upload_limits.sql 3 encrypted-files bucket policies
16+
-- The singular avatar policies were never dropped (the fix migration drops
17+
-- the plural names only), so both sets existed on the cloud project.
18+
--
19+
-- Definitions are verbatim, except that the tables inside the encrypted-files
20+
-- SELECT policy are schema-qualified (public.*), so the policy resolves the
21+
-- same whatever search_path this is applied under.
22+
--
23+
-- The repo never created a trigger on auth.* or storage.* tables, so only
24+
-- policies are restored here.
25+
--
26+
-- Idempotent: safe to re-run.
27+
28+
-- ---------------------------------------------------------------------------
29+
-- avatars bucket, 20250823223015_add_user_avatar_support.sql
30+
-- ---------------------------------------------------------------------------
31+
32+
DROP POLICY IF EXISTS "Users can upload their own avatar" ON storage.objects;
33+
CREATE POLICY "Users can upload their own avatar" ON storage.objects
34+
FOR INSERT WITH CHECK (
35+
bucket_id = 'avatars'
36+
AND auth.uid()::text = (storage.foldername(name))[1]
37+
);
38+
39+
DROP POLICY IF EXISTS "Users can update their own avatar" ON storage.objects;
40+
CREATE POLICY "Users can update their own avatar" ON storage.objects
41+
FOR UPDATE USING (
42+
bucket_id = 'avatars'
43+
AND auth.uid()::text = (storage.foldername(name))[1]
44+
);
45+
46+
DROP POLICY IF EXISTS "Users can delete their own avatar" ON storage.objects;
47+
CREATE POLICY "Users can delete their own avatar" ON storage.objects
48+
FOR DELETE USING (
49+
bucket_id = 'avatars'
50+
AND auth.uid()::text = (storage.foldername(name))[1]
51+
);
52+
53+
DROP POLICY IF EXISTS "Anyone can view avatars" ON storage.objects;
54+
CREATE POLICY "Anyone can view avatars" ON storage.objects
55+
FOR SELECT USING (bucket_id = 'avatars');
56+
57+
-- ---------------------------------------------------------------------------
58+
-- avatars bucket, 20250824005053_fix_avatar_storage_rls_policies.sql
59+
-- ---------------------------------------------------------------------------
60+
61+
DROP POLICY IF EXISTS "Users can upload their own avatars" ON storage.objects;
62+
CREATE POLICY "Users can upload their own avatars"
63+
ON storage.objects FOR INSERT
64+
TO authenticated
65+
WITH CHECK (
66+
bucket_id = 'avatars'
67+
AND (storage.foldername(name))[1] = auth.uid()::text
68+
);
69+
70+
DROP POLICY IF EXISTS "Users can view all avatars" ON storage.objects;
71+
CREATE POLICY "Users can view all avatars"
72+
ON storage.objects FOR SELECT
73+
TO public
74+
USING (bucket_id = 'avatars');
75+
76+
DROP POLICY IF EXISTS "Users can update their own avatars" ON storage.objects;
77+
CREATE POLICY "Users can update their own avatars"
78+
ON storage.objects FOR UPDATE
79+
TO authenticated
80+
USING (
81+
bucket_id = 'avatars'
82+
AND (storage.foldername(name))[1] = auth.uid()::text
83+
)
84+
WITH CHECK (
85+
bucket_id = 'avatars'
86+
AND (storage.foldername(name))[1] = auth.uid()::text
87+
);
88+
89+
DROP POLICY IF EXISTS "Users can delete their own avatars" ON storage.objects;
90+
CREATE POLICY "Users can delete their own avatars"
91+
ON storage.objects FOR DELETE
92+
TO authenticated
93+
USING (
94+
bucket_id = 'avatars'
95+
AND (storage.foldername(name))[1] = auth.uid()::text
96+
);
97+
98+
-- ---------------------------------------------------------------------------
99+
-- encrypted-files bucket, 20250921060226_fix_storage_rls_for_internal_user_ids.sql
100+
-- ---------------------------------------------------------------------------
101+
102+
DROP POLICY IF EXISTS "Users can upload encrypted files" ON storage.objects;
103+
CREATE POLICY "Users can upload encrypted files"
104+
ON storage.objects FOR INSERT
105+
WITH CHECK (
106+
bucket_id = 'encrypted-files'
107+
AND auth.uid()::text = (storage.foldername(name))[1]
108+
);
109+
110+
DROP POLICY IF EXISTS "Users can view encrypted files they have access to" ON storage.objects;
111+
CREATE POLICY "Users can view encrypted files they have access to"
112+
ON storage.objects FOR SELECT
113+
USING (
114+
bucket_id = 'encrypted-files'
115+
AND (
116+
-- User can access files they uploaded (auth user ID matches first folder)
117+
auth.uid()::text = (storage.foldername(name))[1]
118+
OR
119+
-- User can access files from conversations they participate in
120+
EXISTS (
121+
SELECT 1 FROM public.encrypted_files ef
122+
JOIN public.messages m ON ef.message_id = m.id
123+
JOIN public.conversation_participants cp ON m.conversation_id = cp.conversation_id
124+
JOIN public.users u ON cp.user_id = u.id
125+
WHERE ef.storage_path = name
126+
AND u.auth_user_id = auth.uid()
127+
)
128+
)
129+
);
130+
131+
DROP POLICY IF EXISTS "Users can delete their own encrypted files" ON storage.objects;
132+
CREATE POLICY "Users can delete their own encrypted files"
133+
ON storage.objects FOR DELETE
134+
USING (
135+
bucket_id = 'encrypted-files'
136+
AND auth.uid()::text = (storage.foldername(name))[1]
137+
);
138+
139+
-- ---------------------------------------------------------------------------
140+
-- encrypted-files bucket, 20250926094631_fix_large_file_upload_limits.sql
141+
-- ---------------------------------------------------------------------------
142+
143+
DROP POLICY IF EXISTS "Users can upload files to encrypted-files bucket" ON storage.objects;
144+
CREATE POLICY "Users can upload files to encrypted-files bucket"
145+
ON storage.objects FOR INSERT
146+
WITH CHECK (
147+
bucket_id = 'encrypted-files'
148+
AND auth.uid()::text = (storage.foldername(name))[1]
149+
);
150+
151+
DROP POLICY IF EXISTS "Users can view their own files in encrypted-files bucket" ON storage.objects;
152+
CREATE POLICY "Users can view their own files in encrypted-files bucket"
153+
ON storage.objects FOR SELECT
154+
USING (
155+
bucket_id = 'encrypted-files'
156+
AND auth.uid()::text = (storage.foldername(name))[1]
157+
);
158+
159+
DROP POLICY IF EXISTS "Users can delete their own files in encrypted-files bucket" ON storage.objects;
160+
CREATE POLICY "Users can delete their own files in encrypted-files bucket"
161+
ON storage.objects FOR DELETE
162+
USING (
163+
bucket_id = 'encrypted-files'
164+
AND auth.uid()::text = (storage.foldername(name))[1]
165+
);

0 commit comments

Comments
 (0)