-- Phase 0: Fix critical bug - Users can't create submissions -- Add missing INSERT policy for submission_items CREATE POLICY "Users can insert their own submission items" ON public.submission_items FOR INSERT TO authenticated WITH CHECK ( EXISTS ( SELECT 1 FROM content_submissions cs WHERE cs.id = submission_items.submission_id AND cs.user_id = auth.uid() ) ); -- Phase 1: Complete Database-Level AAL2 Enforcement -- Add AAL2 checks to all moderator-accessible tables -- 1.1 Submission Review Tables -- park_submissions DROP POLICY IF EXISTS "Moderators can update park submissions" ON public.park_submissions; CREATE POLICY "Moderators can update park submissions" ON public.park_submissions FOR UPDATE TO authenticated USING ( is_moderator(auth.uid()) AND ( NOT EXISTS ( SELECT 1 FROM auth.mfa_factors WHERE user_id = auth.uid() AND status = 'verified' ) OR has_aal2() ) ); DROP POLICY IF EXISTS "Moderators can delete park submissions" ON public.park_submissions; CREATE POLICY "Moderators can delete park submissions" ON public.park_submissions FOR DELETE TO authenticated USING ( is_moderator(auth.uid()) AND ( NOT EXISTS ( SELECT 1 FROM auth.mfa_factors WHERE user_id = auth.uid() AND status = 'verified' ) OR has_aal2() ) ); DROP POLICY IF EXISTS "Moderators can view all park submissions" ON public.park_submissions; CREATE POLICY "Moderators can view all park submissions" ON public.park_submissions FOR SELECT TO authenticated USING ( is_moderator(auth.uid()) AND ( NOT EXISTS ( SELECT 1 FROM auth.mfa_factors WHERE user_id = auth.uid() AND status = 'verified' ) OR has_aal2() ) ); -- ride_submissions DROP POLICY IF EXISTS "Moderators can update ride submissions" ON public.ride_submissions; CREATE POLICY "Moderators can update ride submissions" ON public.ride_submissions FOR UPDATE TO authenticated USING ( is_moderator(auth.uid()) AND ( NOT EXISTS ( SELECT 1 FROM auth.mfa_factors WHERE user_id = auth.uid() AND status = 'verified' ) OR has_aal2() ) ); DROP POLICY IF EXISTS "Moderators can delete ride submissions" ON public.ride_submissions; CREATE POLICY "Moderators can delete ride submissions" ON public.ride_submissions FOR DELETE TO authenticated USING ( is_moderator(auth.uid()) AND ( NOT EXISTS ( SELECT 1 FROM auth.mfa_factors WHERE user_id = auth.uid() AND status = 'verified' ) OR has_aal2() ) ); DROP POLICY IF EXISTS "Moderators can view all ride submissions" ON public.ride_submissions; CREATE POLICY "Moderators can view all ride submissions" ON public.ride_submissions FOR SELECT TO authenticated USING ( is_moderator(auth.uid()) AND ( NOT EXISTS ( SELECT 1 FROM auth.mfa_factors WHERE user_id = auth.uid() AND status = 'verified' ) OR has_aal2() ) ); -- company_submissions DROP POLICY IF EXISTS "Moderators can update company submissions" ON public.company_submissions; CREATE POLICY "Moderators can update company submissions" ON public.company_submissions FOR UPDATE TO authenticated USING ( is_moderator(auth.uid()) AND ( NOT EXISTS ( SELECT 1 FROM auth.mfa_factors WHERE user_id = auth.uid() AND status = 'verified' ) OR has_aal2() ) ); DROP POLICY IF EXISTS "Moderators can delete company submissions" ON public.company_submissions; CREATE POLICY "Moderators can delete company submissions" ON public.company_submissions FOR DELETE TO authenticated USING ( is_moderator(auth.uid()) AND ( NOT EXISTS ( SELECT 1 FROM auth.mfa_factors WHERE user_id = auth.uid() AND status = 'verified' ) OR has_aal2() ) ); DROP POLICY IF EXISTS "Moderators can view all company submissions" ON public.company_submissions; CREATE POLICY "Moderators can view all company submissions" ON public.company_submissions FOR SELECT TO authenticated USING ( is_moderator(auth.uid()) AND ( NOT EXISTS ( SELECT 1 FROM auth.mfa_factors WHERE user_id = auth.uid() AND status = 'verified' ) OR has_aal2() ) ); -- photo_submissions DROP POLICY IF EXISTS "Moderators can update photo submissions" ON public.photo_submissions; CREATE POLICY "Moderators can update photo submissions" ON public.photo_submissions FOR UPDATE TO authenticated USING ( is_moderator(auth.uid()) AND ( NOT EXISTS ( SELECT 1 FROM auth.mfa_factors WHERE user_id = auth.uid() AND status = 'verified' ) OR has_aal2() ) ); DROP POLICY IF EXISTS "Moderators can delete photo submissions" ON public.photo_submissions; CREATE POLICY "Moderators can delete photo submissions" ON public.photo_submissions FOR DELETE TO authenticated USING ( is_moderator(auth.uid()) AND ( NOT EXISTS ( SELECT 1 FROM auth.mfa_factors WHERE user_id = auth.uid() AND status = 'verified' ) OR has_aal2() ) ); DROP POLICY IF EXISTS "Moderators can view all photo submissions" ON public.photo_submissions; CREATE POLICY "Moderators can view all photo submissions" ON public.photo_submissions FOR SELECT TO authenticated USING ( is_moderator(auth.uid()) AND ( NOT EXISTS ( SELECT 1 FROM auth.mfa_factors WHERE user_id = auth.uid() AND status = 'verified' ) OR has_aal2() ) ); -- photo_submission_items DROP POLICY IF EXISTS "Moderators can update photo submission items" ON public.photo_submission_items; CREATE POLICY "Moderators can update photo submission items" ON public.photo_submission_items FOR UPDATE TO authenticated USING ( is_moderator(auth.uid()) AND ( NOT EXISTS ( SELECT 1 FROM auth.mfa_factors WHERE user_id = auth.uid() AND status = 'verified' ) OR has_aal2() ) ); DROP POLICY IF EXISTS "Moderators can delete photo submission items" ON public.photo_submission_items; CREATE POLICY "Moderators can delete photo submission items" ON public.photo_submission_items FOR DELETE TO authenticated USING ( is_moderator(auth.uid()) AND ( NOT EXISTS ( SELECT 1 FROM auth.mfa_factors WHERE user_id = auth.uid() AND status = 'verified' ) OR has_aal2() ) ); DROP POLICY IF EXISTS "Moderators can view all photo submission items" ON public.photo_submission_items; CREATE POLICY "Moderators can view all photo submission items" ON public.photo_submission_items FOR SELECT TO authenticated USING ( is_moderator(auth.uid()) AND ( NOT EXISTS ( SELECT 1 FROM auth.mfa_factors WHERE user_id = auth.uid() AND status = 'verified' ) OR has_aal2() ) ); -- 1.2 User Management Tables -- profiles (moderator banning) DROP POLICY IF EXISTS "Moderators can update profiles for banning" ON public.profiles; CREATE POLICY "Moderators can update profiles for banning" ON public.profiles FOR UPDATE TO authenticated USING ( is_moderator(auth.uid()) AND ( NOT EXISTS ( SELECT 1 FROM auth.mfa_factors WHERE user_id = auth.uid() AND status = 'verified' ) OR has_aal2() ) ); -- 1.3 Reports & Moderation -- reports DROP POLICY IF EXISTS "Moderators can update reports" ON public.reports; CREATE POLICY "Moderators can update reports" ON public.reports FOR UPDATE TO authenticated USING ( is_moderator(auth.uid()) AND ( NOT EXISTS ( SELECT 1 FROM auth.mfa_factors WHERE user_id = auth.uid() AND status = 'verified' ) OR has_aal2() ) ); DROP POLICY IF EXISTS "Moderators can delete reports" ON public.reports; CREATE POLICY "Moderators can delete reports" ON public.reports FOR DELETE TO authenticated USING ( is_moderator(auth.uid()) AND ( NOT EXISTS ( SELECT 1 FROM auth.mfa_factors WHERE user_id = auth.uid() AND status = 'verified' ) OR has_aal2() ) ); DROP POLICY IF EXISTS "Moderators can view all reports" ON public.reports; CREATE POLICY "Moderators can view all reports" ON public.reports FOR SELECT TO authenticated USING ( is_moderator(auth.uid()) AND ( NOT EXISTS ( SELECT 1 FROM auth.mfa_factors WHERE user_id = auth.uid() AND status = 'verified' ) OR has_aal2() ) ); -- 1.4 Blog Management -- blog_posts (admin/superuser only) DROP POLICY IF EXISTS "Admins and superusers can manage blog posts" ON public.blog_posts; CREATE POLICY "Admins and superusers can manage blog posts" ON public.blog_posts FOR ALL TO authenticated USING ( (has_role(auth.uid(), 'admin'::app_role) OR has_role(auth.uid(), 'superuser'::app_role)) AND ( NOT EXISTS ( SELECT 1 FROM auth.mfa_factors WHERE user_id = auth.uid() AND status = 'verified' ) OR has_aal2() ) ); -- 1.5 Admin Audit & Settings -- admin_audit_log (already has AAL2, verify it's correct) DROP POLICY IF EXISTS "Admins can insert audit log with MFA" ON public.admin_audit_log; CREATE POLICY "Admins can insert audit log with MFA" ON public.admin_audit_log FOR INSERT TO authenticated WITH CHECK ( is_moderator(auth.uid()) AND has_aal2() ); DROP POLICY IF EXISTS "Admins can view audit log" ON public.admin_audit_log; CREATE POLICY "Admins can view audit log" ON public.admin_audit_log FOR SELECT TO authenticated USING ( is_moderator(auth.uid()) AND ( NOT EXISTS ( SELECT 1 FROM auth.mfa_factors WHERE user_id = auth.uid() AND status = 'verified' ) OR has_aal2() ) ); -- admin_settings (superuser only) DROP POLICY IF EXISTS "Superusers can manage settings with MFA" ON public.admin_settings; CREATE POLICY "Superusers can manage settings with MFA" ON public.admin_settings FOR ALL TO authenticated USING ( is_superuser(auth.uid()) AND has_aal2() );