fix: add storage RLS policies for 360ghar-storage bucket#17
fix: add storage RLS policies for 360ghar-storage bucket#17RaviSahu1520 wants to merge 1 commit into
Conversation
Flutter uploads directly to Supabase Storage (listings, profile, chats)
but no RLS policies existed on storage.objects, causing:
'new row violates row-level security policy'
Adds policies:
- users_insert_own (INSERT for authenticated users into own folder)
- users_select_own (SELECT own files)
- users_update_own (UPDATE own files)
- users_delete_own (DELETE own files)
- authenticated_read_listings (cross-user read for listing photos)
- public_read_agent_avatars (public read for agent avatars)
- authenticated_read_tours (authenticated read for tour content)
Covers all Flutter upload paths: users/{uid}/listings/*, profile/*, chats/*
Run via Supabase Dashboard SQL Editor (migrations lack owner perms
on storage.objects).
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more → On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
📝 WalkthroughWalkthroughThis PR introduces a Supabase Storage migration that enables row-level security and defines seven access policies for the ChangesStorage RLS Configuration
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@supabase/migrations/20260516000000_configure_storage_rls_policies.sql`:
- Around line 14-15: Remove the manual-only note and convert the out-of-band
step into a proper SQL migration under supabase/migrations/ (so it runs via
supabase db push); add statements to enable RLS and create/replace the necessary
policies for the storage.objects table (e.g., ALTER TABLE storage.objects ENABLE
ROW LEVEL SECURITY; CREATE OR REPLACE POLICY "<policy_name>" ON storage.objects
FOR SELECT USING (<condition>) WITH CHECK (<condition>); and any required
GRANTs), ensuring the migration file name follows the existing timestamped
pattern and contains the full DDL/DDL POLICY changes so no manual Dashboard SQL
Editor step is required.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: e43384b1-76e8-4af2-b3ca-5b986ddfd4e2
📒 Files selected for processing (1)
supabase/migrations/20260516000000_configure_storage_rls_policies.sql
| -- ⚠️ Run this via the Supabase Dashboard SQL Editor | ||
| -- (SQL migrations lack owner permissions on storage.objects). |
There was a problem hiding this comment.
Don't ship this as a manual-only migration.
Documenting an out-of-band SQL Editor step here makes the change non-reproducible and easy to miss in later environments. Please rework this so the RLS policies are applied by the normal migration path instead of requiring a separate manual run after merge.
As per coding guidelines, supabase/migrations/**/*: All migrations must be placed in supabase/migrations/ and applied via supabase db push
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@supabase/migrations/20260516000000_configure_storage_rls_policies.sql` around
lines 14 - 15, Remove the manual-only note and convert the out-of-band step into
a proper SQL migration under supabase/migrations/ (so it runs via supabase db
push); add statements to enable RLS and create/replace the necessary policies
for the storage.objects table (e.g., ALTER TABLE storage.objects ENABLE ROW
LEVEL SECURITY; CREATE OR REPLACE POLICY "<policy_name>" ON storage.objects FOR
SELECT USING (<condition>) WITH CHECK (<condition>); and any required GRANTs),
ensuring the migration file name follows the existing timestamped pattern and
contains the full DDL/DDL POLICY changes so no manual Dashboard SQL Editor step
is required.
| USING ( | ||
| bucket_id = '360ghar-storage' | ||
| AND auth.uid() IS NOT NULL | ||
| AND name ~ ('^users/' || auth.uid()::text || '/[^/]+/[^/]+$') | ||
| ); | ||
|
|
||
| -- ── UPDATE: authenticated users can update their own files ── | ||
| DROP POLICY IF EXISTS "users_update_own" ON storage.objects; |
There was a problem hiding this comment.
Missing cross-user SELECT for chat photos
The users_select_own policy only grants SELECT to the file owner (auth.uid() matches). When a chat recipient tries to display a received photo at users/{sender_uid}/chats/{filename}, they get an RLS denial because their UID doesn't match. An authenticated_read_chats policy (mirroring authenticated_read_listings) is needed unless all chat photo reads are exclusively mediated by backend-generated signed URLs (service role bypasses RLS). The PR description and existing SELECT comment say Flutter calls createSignedUrl itself, which also requires SELECT on the object.
| bucket_id = '360ghar-storage' | ||
| AND auth.uid() IS NOT NULL |
There was a problem hiding this comment.
10-year signed URL expiry is functionally a permanent public link
The comment "signed URLs (10-year expiry) as a fallback" describes a URL that effectively never expires. If one of these URLs leaks via logs, browser history, a forwarded message, or a bug that exposes the URL in an API response, the file remains accessible indefinitely to anyone with the URL, defeating the private bucket and the RLS policies. Consider using much shorter expiries (hours or days) with a backend endpoint to regenerate signed URLs on demand.
There was a problem hiding this comment.
No issues found across 1 file
Requires human review: This is a SQL migration that adds RLS policies on storage.objects, which is a security-sensitive database change with potential to break image uploads across the app, so it requires human review.
Re-trigger cubic
Problem
Flutter uploads listing/profile/chat photos directly to Supabase Storage but no RLS policies existed on
storage.objects, causing:This blocked all image uploads from the mobile app (listing photos, profile photos, chat photos).
Root Cause
360ghar-storageis private with RLS enabled onstorage.objects20260115000100) noted that RLS policies must be created manually via the Supabase Dashboard but this was never donelistings/, and was never appliedFix
Adds comprehensive RLS policies for the
360ghar-storagebucket:users_insert_ownusers/{uid}/*users_select_ownusers/{uid}/*users_update_ownusers/{uid}/*users_delete_ownusers/{uid}/*authenticated_read_listingsusers/*/listings/*public_read_agent_avatarsagents/*/avatars/*authenticated_read_toursusers/*/tours/*Covers all Flutter upload paths:
listings/,profile/,chats/.Post-Merge Action Required
supabase/migrations/20260516000000_configure_storage_rls_policies.sqlUploads will start working immediately after the policies are applied.
Files Changed
supabase/migrations/20260516000000_configure_storage_rls_policies.sql(new file, 115 lines)Summary by cubic
Add RLS policies for
360ghar-storageto fix “new row violates row-level security policy” and restore listing, profile, and chat image uploads from Flutter.Bug Fixes
storage.objectsand added INSERT/SELECT/UPDATE/DELETE forusers/{uid}/*.users/*/listings/*andusers/*/tours/*; public SELECT foragents/*/avatars/*.users/{uid}/listings/*,users/{uid}/profile/*,users/{uid}/chats/*; removed old narrow policies.Migration
supabase/migrations/20260516000000_configure_storage_rls_policies.sqlin the Supabase Dashboard SQL Editor (needed forstorage.objectspermissions).Written for commit 7630275. Summary will update on new commits. Review in cubic
Summary by CodeRabbit
Greptile Summary
This PR adds a new SQL migration (
20260516000000_configure_storage_rls_policies.sql) that creates seven RLS policies onstorage.objectsfor the360ghar-storageSupabase bucket, unblocking Flutter direct uploads of listing, profile, and chat photos. It must be applied manually via the Supabase Dashboard SQL Editor rather than the standard migration pipeline.users/{uid}/<subfolder>/<file>(exactly one subfolder deep).listings/andtours/paths, and allow public (anon) access toagents/*/avatars/*.users/{sender_uid}/chats/*files from the Flutter client.Confidence Score: 3/5
Safe to merge as SQL, but the missing chat cross-user SELECT policy means chat photo recipients may hit access denials if Flutter fetches those objects directly or calls createSignedUrl client-side.
The own-folder CRUD policies and cross-user listing/tour/avatar reads are well-constructed with tight regex depth. The gap is that users//chats/ has no SELECT policy for non-owners, leaving a real risk of silent breakage for the chat photo feature this PR is meant to fix.
supabase/migrations/20260516000000_configure_storage_rls_policies.sql — specifically the absence of a cross-user SELECT for the chats path and the 10-year signed URL expiry note.
Security Review
users/*/chats/*paths, so chat recipients cannot directly fetch or sign those objects from the client — a present access-control gap if Flutter ever callscreateSignedUrlclient-side for received chat photos.Important Files Changed
Reviews (1): Last reviewed commit: "fix: add storage RLS policies for 360gha..." | Re-trigger Greptile