diff --git a/supabase/migrations/20251107141539_1ef07617-10b1-4c36-9088-bf31b05e8970.sql b/supabase/migrations/20251107141539_1ef07617-10b1-4c36-9088-bf31b05e8970.sql new file mode 100644 index 00000000..4c413997 --- /dev/null +++ b/supabase/migrations/20251107141539_1ef07617-10b1-4c36-9088-bf31b05e8970.sql @@ -0,0 +1,202 @@ +-- Phase 3b: Fix Remaining Submission Tables RLS Policies +-- Secure ride_submissions, ride_model_submissions, timeline_event_submissions + +-- ============================================================================ +-- 1. FIX ride_submissions TABLE +-- ============================================================================ + +-- Drop any overly permissive policies +DROP POLICY IF EXISTS "Public read access to ride_submissions" ON ride_submissions; +DROP POLICY IF EXISTS "Anyone can view ride submissions" ON ride_submissions; + +-- Drop and recreate with proper restrictions +DROP POLICY IF EXISTS "Users can view own ride submissions" ON ride_submissions; +DROP POLICY IF EXISTS "Moderators can view all ride submissions" ON ride_submissions; +DROP POLICY IF EXISTS "Moderators can update ride submissions" ON ride_submissions; +DROP POLICY IF EXISTS "Moderators can delete ride submissions" ON ride_submissions; + +-- Users can only view their own ride submissions +CREATE POLICY "Users can view own ride submissions" +ON ride_submissions +FOR SELECT +TO authenticated +USING ( + EXISTS ( + SELECT 1 FROM content_submissions cs + WHERE cs.id = ride_submissions.submission_id + AND cs.user_id = auth.uid() + ) +); + +-- Moderators can view all ride submissions with MFA +CREATE POLICY "Moderators can view all ride submissions" +ON ride_submissions +FOR SELECT +TO authenticated +USING ( + is_moderator(auth.uid()) + AND ((NOT has_mfa_enabled(auth.uid())) OR has_aal2()) +); + +-- Moderators can update ride submissions with MFA +CREATE POLICY "Moderators can update ride submissions" +ON ride_submissions +FOR UPDATE +TO authenticated +USING ( + is_moderator(auth.uid()) + AND ((NOT has_mfa_enabled(auth.uid())) OR has_aal2()) +) +WITH CHECK ( + is_moderator(auth.uid()) + AND ((NOT has_mfa_enabled(auth.uid())) OR has_aal2()) +); + +-- Moderators can delete ride submissions with MFA +CREATE POLICY "Moderators can delete ride submissions" +ON ride_submissions +FOR DELETE +TO authenticated +USING ( + is_moderator(auth.uid()) + AND has_aal2() +); + +-- ============================================================================ +-- 2. FIX ride_model_submissions TABLE +-- ============================================================================ + +-- Drop any overly permissive policies +DROP POLICY IF EXISTS "Public read access to ride_model_submissions" ON ride_model_submissions; +DROP POLICY IF EXISTS "Anyone can view ride_model submissions" ON ride_model_submissions; + +-- Drop and recreate with proper restrictions +DROP POLICY IF EXISTS "Users can view own ride_model submissions" ON ride_model_submissions; +DROP POLICY IF EXISTS "Moderators can view all ride_model submissions" ON ride_model_submissions; +DROP POLICY IF EXISTS "Moderators can update ride_model submissions" ON ride_model_submissions; +DROP POLICY IF EXISTS "Moderators can delete ride_model submissions" ON ride_model_submissions; + +-- Users can only view their own ride_model submissions +CREATE POLICY "Users can view own ride_model submissions" +ON ride_model_submissions +FOR SELECT +TO authenticated +USING ( + EXISTS ( + SELECT 1 FROM content_submissions cs + WHERE cs.id = ride_model_submissions.submission_id + AND cs.user_id = auth.uid() + ) +); + +-- Moderators can view all ride_model submissions with MFA +CREATE POLICY "Moderators can view all ride_model submissions" +ON ride_model_submissions +FOR SELECT +TO authenticated +USING ( + is_moderator(auth.uid()) + AND ((NOT has_mfa_enabled(auth.uid())) OR has_aal2()) +); + +-- Moderators can update ride_model submissions with MFA +CREATE POLICY "Moderators can update ride_model submissions" +ON ride_model_submissions +FOR UPDATE +TO authenticated +USING ( + is_moderator(auth.uid()) + AND ((NOT has_mfa_enabled(auth.uid())) OR has_aal2()) +) +WITH CHECK ( + is_moderator(auth.uid()) + AND ((NOT has_mfa_enabled(auth.uid())) OR has_aal2()) +); + +-- Moderators can delete ride_model submissions with MFA +CREATE POLICY "Moderators can delete ride_model submissions" +ON ride_model_submissions +FOR DELETE +TO authenticated +USING ( + is_moderator(auth.uid()) + AND has_aal2() +); + +-- ============================================================================ +-- 3. FIX timeline_event_submissions TABLE +-- ============================================================================ + +-- Drop any overly permissive policies +DROP POLICY IF EXISTS "Public read access to timeline_event_submissions" ON timeline_event_submissions; +DROP POLICY IF EXISTS "Anyone can view timeline_event submissions" ON timeline_event_submissions; + +-- Drop and recreate with proper restrictions +DROP POLICY IF EXISTS "Users can view own timeline_event submissions" ON timeline_event_submissions; +DROP POLICY IF EXISTS "Moderators can view all timeline_event submissions" ON timeline_event_submissions; +DROP POLICY IF EXISTS "Moderators can update timeline_event submissions" ON timeline_event_submissions; +DROP POLICY IF EXISTS "Moderators can delete timeline_event submissions" ON timeline_event_submissions; + +-- Users can only view their own timeline_event submissions +CREATE POLICY "Users can view own timeline_event submissions" +ON timeline_event_submissions +FOR SELECT +TO authenticated +USING ( + EXISTS ( + SELECT 1 FROM content_submissions cs + WHERE cs.id = timeline_event_submissions.submission_id + AND cs.user_id = auth.uid() + ) +); + +-- Moderators can view all timeline_event submissions with MFA +CREATE POLICY "Moderators can view all timeline_event submissions" +ON timeline_event_submissions +FOR SELECT +TO authenticated +USING ( + is_moderator(auth.uid()) + AND ((NOT has_mfa_enabled(auth.uid())) OR has_aal2()) +); + +-- Moderators can update timeline_event submissions with MFA +CREATE POLICY "Moderators can update timeline_event submissions" +ON timeline_event_submissions +FOR UPDATE +TO authenticated +USING ( + is_moderator(auth.uid()) + AND ((NOT has_mfa_enabled(auth.uid())) OR has_aal2()) +) +WITH CHECK ( + is_moderator(auth.uid()) + AND ((NOT has_mfa_enabled(auth.uid())) OR has_aal2()) +); + +-- Moderators can delete timeline_event submissions with MFA +CREATE POLICY "Moderators can delete timeline_event submissions" +ON timeline_event_submissions +FOR DELETE +TO authenticated +USING ( + is_moderator(auth.uid()) + AND has_aal2() +); + +-- ============================================================================ +-- 4. AUDIT: Verify RLS is enabled on all submission tables +-- ============================================================================ + +ALTER TABLE ride_submissions ENABLE ROW LEVEL SECURITY; +ALTER TABLE ride_model_submissions ENABLE ROW LEVEL SECURITY; +ALTER TABLE timeline_event_submissions ENABLE ROW LEVEL SECURITY; + +DO $$ +BEGIN + RAISE NOTICE '✅ Phase 3b Complete: Secured 3 additional submission tables'; + RAISE NOTICE '🔒 ride_submissions: Ride data restricted to submitters'; + RAISE NOTICE '🔒 ride_model_submissions: Ride model data restricted'; + RAISE NOTICE '🔒 timeline_event_submissions: Timeline events restricted'; + RAISE NOTICE '🎉 ALL 7 entity submission tables now fully secured!'; +END $$; \ No newline at end of file