-- Phase 3: Fix Submission Tables RLS Policies -- Secure contact_submissions, park_submissions, company_submissions, photo_submissions -- ============================================================================ -- 1. FIX contact_submissions TABLE -- ============================================================================ -- Drop any overly permissive policies DROP POLICY IF EXISTS "Public read access to contact_submissions" ON contact_submissions; DROP POLICY IF EXISTS "Anyone can view contact submissions" ON contact_submissions; DROP POLICY IF EXISTS "Public can insert contact submissions" ON contact_submissions; -- Keep existing good policies, add missing ones if needed -- Note: Existing policies already restrict to user's own submissions and moderators -- Verify no direct INSERT is possible without proper validation CREATE POLICY "Authenticated users insert own contact submissions" ON contact_submissions FOR INSERT TO authenticated WITH CHECK ( user_id = auth.uid() OR user_id IS NULL ); -- ============================================================================ -- 2. FIX park_submissions TABLE -- ============================================================================ -- Drop any overly permissive policies DROP POLICY IF EXISTS "Public read access to park_submissions" ON park_submissions; DROP POLICY IF EXISTS "Anyone can view park submissions" ON park_submissions; -- Drop and recreate with proper restrictions DROP POLICY IF EXISTS "Users can view own park submissions" ON park_submissions; DROP POLICY IF EXISTS "Moderators can view all park submissions" ON park_submissions; DROP POLICY IF EXISTS "Moderators can update park submissions" ON park_submissions; DROP POLICY IF EXISTS "Moderators can delete park submissions" ON park_submissions; -- Users can only view their own park submissions CREATE POLICY "Users can view own park submissions" ON park_submissions FOR SELECT TO authenticated USING ( EXISTS ( SELECT 1 FROM content_submissions cs WHERE cs.id = park_submissions.submission_id AND cs.user_id = auth.uid() ) ); -- Moderators can view all park submissions with MFA CREATE POLICY "Moderators can view all park submissions" ON park_submissions FOR SELECT TO authenticated USING ( is_moderator(auth.uid()) AND ((NOT has_mfa_enabled(auth.uid())) OR has_aal2()) ); -- Moderators can update park submissions with MFA CREATE POLICY "Moderators can update park submissions" ON park_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 park submissions with MFA CREATE POLICY "Moderators can delete park submissions" ON park_submissions FOR DELETE TO authenticated USING ( is_moderator(auth.uid()) AND has_aal2() ); -- ============================================================================ -- 3. FIX company_submissions TABLE -- ============================================================================ -- Drop any overly permissive policies DROP POLICY IF EXISTS "Public read access to company_submissions" ON company_submissions; DROP POLICY IF EXISTS "Anyone can view company submissions" ON company_submissions; -- Drop and recreate with proper restrictions DROP POLICY IF EXISTS "Users can view own company submissions" ON company_submissions; DROP POLICY IF EXISTS "Users can view their own company submissions" ON company_submissions; DROP POLICY IF EXISTS "Moderators can view all company submissions" ON company_submissions; DROP POLICY IF EXISTS "Moderators can update company submissions" ON company_submissions; DROP POLICY IF EXISTS "Moderators can delete company submissions" ON company_submissions; -- Users can only view their own company submissions CREATE POLICY "Users can view own company submissions" ON company_submissions FOR SELECT TO authenticated USING ( EXISTS ( SELECT 1 FROM content_submissions cs WHERE cs.id = company_submissions.submission_id AND cs.user_id = auth.uid() ) ); -- Moderators can view all company submissions with MFA CREATE POLICY "Moderators can view all company submissions" ON company_submissions FOR SELECT TO authenticated USING ( is_moderator(auth.uid()) AND ((NOT has_mfa_enabled(auth.uid())) OR has_aal2()) ); -- Moderators can update company submissions with MFA CREATE POLICY "Moderators can update company submissions" ON company_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 company submissions with MFA CREATE POLICY "Moderators can delete company submissions" ON company_submissions FOR DELETE TO authenticated USING ( is_moderator(auth.uid()) AND has_aal2() ); -- ============================================================================ -- 4. FIX photo_submissions TABLE -- ============================================================================ -- Drop any overly permissive policies DROP POLICY IF EXISTS "Public read access to photo_submissions" ON photo_submissions; DROP POLICY IF EXISTS "Anyone can view photo submissions" ON photo_submissions; -- Drop and recreate with proper restrictions DROP POLICY IF EXISTS "Users can view own photo submissions" ON photo_submissions; DROP POLICY IF EXISTS "Moderators can view all photo submissions" ON photo_submissions; DROP POLICY IF EXISTS "Moderators can update photo submissions" ON photo_submissions; DROP POLICY IF EXISTS "Moderators can delete photo submissions" ON photo_submissions; -- Users can only view their own photo submissions CREATE POLICY "Users can view own photo submissions" ON photo_submissions FOR SELECT TO authenticated USING ( EXISTS ( SELECT 1 FROM content_submissions cs WHERE cs.id = photo_submissions.submission_id AND cs.user_id = auth.uid() ) ); -- Moderators can view all photo submissions with MFA CREATE POLICY "Moderators can view all photo submissions" ON photo_submissions FOR SELECT TO authenticated USING ( is_moderator(auth.uid()) AND ((NOT has_mfa_enabled(auth.uid())) OR has_aal2()) ); -- Moderators can update photo submissions with MFA CREATE POLICY "Moderators can update photo submissions" ON photo_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 photo submissions with MFA CREATE POLICY "Moderators can delete photo submissions" ON photo_submissions FOR DELETE TO authenticated USING ( is_moderator(auth.uid()) AND has_aal2() ); -- ============================================================================ -- 5. AUDIT: Verify RLS is enabled on all submission tables -- ============================================================================ ALTER TABLE contact_submissions ENABLE ROW LEVEL SECURITY; ALTER TABLE park_submissions ENABLE ROW LEVEL SECURITY; ALTER TABLE company_submissions ENABLE ROW LEVEL SECURITY; ALTER TABLE photo_submissions ENABLE ROW LEVEL SECURITY; DO $$ BEGIN RAISE NOTICE '✅ Phase 3 Complete: Secured 4 submission tables'; RAISE NOTICE '🔒 contact_submissions: Protected user emails and messages'; RAISE NOTICE '🔒 park_submissions: Business contact info restricted'; RAISE NOTICE '🔒 company_submissions: Company data restricted to submitters'; RAISE NOTICE '🔒 photo_submissions: Photo metadata properly scoped'; RAISE NOTICE '🛡️ All submission data now requires authentication + proper authorization'; END $$;