diff --git a/supabase/migrations/20251105165731_c259bfdb-2fe2-4bf7-9336-4ae8d800101b.sql b/supabase/migrations/20251105165731_c259bfdb-2fe2-4bf7-9336-4ae8d800101b.sql new file mode 100644 index 00000000..0b349e6e --- /dev/null +++ b/supabase/migrations/20251105165731_c259bfdb-2fe2-4bf7-9336-4ae8d800101b.sql @@ -0,0 +1,228 @@ +-- Fix all direct auth.mfa_factors queries by replacing with has_mfa_enabled() function +-- This prevents "permission denied for table mfa_factors" errors for non-superuser roles + +-- ============================================================================ +-- BLOG POSTS +-- ============================================================================ + +DROP POLICY IF EXISTS "Admins can insert blog posts with MFA" ON public.blog_posts; +DROP POLICY IF EXISTS "Admins can create blog posts with AAL2" ON public.blog_posts; +CREATE POLICY "Admins can insert blog posts with MFA" +ON public.blog_posts +FOR INSERT +TO authenticated +WITH CHECK ( + (has_role(auth.uid(), 'admin'::app_role) OR has_role(auth.uid(), 'superuser'::app_role)) + AND ((NOT has_mfa_enabled((SELECT auth.uid()))) OR has_aal2()) +); + +DROP POLICY IF EXISTS "Admins can update blog posts with MFA" ON public.blog_posts; +DROP POLICY IF EXISTS "Admins can update blog posts with AAL2" ON public.blog_posts; +CREATE POLICY "Admins can update blog posts with MFA" +ON public.blog_posts +FOR UPDATE +TO authenticated +USING ( + (has_role(auth.uid(), 'admin'::app_role) OR has_role(auth.uid(), 'superuser'::app_role)) + AND ((NOT has_mfa_enabled((SELECT auth.uid()))) OR has_aal2()) +); + +DROP POLICY IF EXISTS "Admins can delete blog posts with MFA" ON public.blog_posts; +DROP POLICY IF EXISTS "Admins can delete blog posts with AAL2" ON public.blog_posts; +CREATE POLICY "Admins can delete blog posts with MFA" +ON public.blog_posts +FOR DELETE +TO authenticated +USING ( + (has_role(auth.uid(), 'admin'::app_role) OR has_role(auth.uid(), 'superuser'::app_role)) + AND ((NOT has_mfa_enabled((SELECT auth.uid()))) OR has_aal2()) +); + +-- ============================================================================ +-- ADMIN AUDIT LOG - Only fix the SELECT policy +-- ============================================================================ + +-- Note: INSERT policy already uses has_aal2() correctly, no need to change +-- We're only fixing policies that query auth.mfa_factors directly + +-- ============================================================================ +-- COMPANY SUBMISSIONS +-- ============================================================================ + +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((SELECT auth.uid())) + AND ((NOT has_mfa_enabled((SELECT auth.uid()))) OR has_aal2()) +); + +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((SELECT auth.uid())) + AND ((NOT has_mfa_enabled((SELECT auth.uid()))) 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((SELECT auth.uid())) + AND ((NOT has_mfa_enabled((SELECT auth.uid()))) OR has_aal2()) +); + +-- ============================================================================ +-- PARK SUBMISSIONS +-- ============================================================================ + +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((SELECT auth.uid())) + AND ((NOT has_mfa_enabled((SELECT auth.uid()))) OR has_aal2()) +); + +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((SELECT auth.uid())) + AND ((NOT has_mfa_enabled((SELECT auth.uid()))) 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((SELECT auth.uid())) + AND ((NOT has_mfa_enabled((SELECT auth.uid()))) OR has_aal2()) +); + +-- ============================================================================ +-- PHOTO SUBMISSION ITEMS +-- ============================================================================ + +DROP POLICY IF EXISTS "Moderators can manage photo submission items" ON public.photo_submission_items; +CREATE POLICY "Moderators can manage photo submission items" +ON public.photo_submission_items +FOR ALL +TO authenticated +USING ( + is_moderator((SELECT auth.uid())) + AND ((NOT has_mfa_enabled((SELECT auth.uid()))) OR has_aal2()) +); + +-- ============================================================================ +-- PHOTO SUBMISSIONS +-- ============================================================================ + +DROP POLICY IF EXISTS "Moderators can manage photo submissions" ON public.photo_submissions; +CREATE POLICY "Moderators can manage photo submissions" +ON public.photo_submissions +FOR ALL +TO authenticated +USING ( + is_moderator((SELECT auth.uid())) + AND ((NOT has_mfa_enabled((SELECT auth.uid()))) OR has_aal2()) +); + +-- ============================================================================ +-- REPORTS +-- ============================================================================ + +DROP POLICY IF EXISTS "Moderators can manage reports" ON public.reports; +CREATE POLICY "Moderators can manage reports" +ON public.reports +FOR ALL +TO authenticated +USING ( + is_moderator((SELECT auth.uid())) + AND ((NOT has_mfa_enabled((SELECT auth.uid()))) OR has_aal2()) +); + +-- ============================================================================ +-- RIDE MODEL SUBMISSIONS +-- ============================================================================ + +DROP POLICY IF EXISTS "Moderators can manage ride model submissions" ON public.ride_model_submissions; +CREATE POLICY "Moderators can manage ride model submissions" +ON public.ride_model_submissions +FOR ALL +TO authenticated +USING ( + is_moderator((SELECT auth.uid())) + AND ((NOT has_mfa_enabled((SELECT auth.uid()))) OR has_aal2()) +); + +-- ============================================================================ +-- RIDE SUBMISSIONS +-- ============================================================================ + +DROP POLICY IF EXISTS "Moderators can manage ride submissions" ON public.ride_submissions; +CREATE POLICY "Moderators can manage ride submissions" +ON public.ride_submissions +FOR ALL +TO authenticated +USING ( + is_moderator((SELECT auth.uid())) + AND ((NOT has_mfa_enabled((SELECT auth.uid()))) OR has_aal2()) +); + +-- ============================================================================ +-- SUBMISSION ITEMS +-- ============================================================================ + +DROP POLICY IF EXISTS "Moderators can view all submission items" ON public.submission_items; +CREATE POLICY "Moderators can view all submission items" +ON public.submission_items +FOR SELECT +TO authenticated +USING ( + is_moderator((SELECT auth.uid())) + AND ((NOT has_mfa_enabled((SELECT auth.uid()))) OR has_aal2()) +); + +DROP POLICY IF EXISTS "Moderators can update submission items" ON public.submission_items; +CREATE POLICY "Moderators can update submission items" +ON public.submission_items +FOR UPDATE +TO authenticated +USING ( + is_moderator((SELECT auth.uid())) + AND ((NOT has_mfa_enabled((SELECT auth.uid()))) OR has_aal2()) +); + +-- ============================================================================ +-- TIMELINE EVENT SUBMISSIONS +-- ============================================================================ + +DROP POLICY IF EXISTS "Moderators can manage timeline event submissions" ON public.timeline_event_submissions; +CREATE POLICY "Moderators can manage timeline event submissions" +ON public.timeline_event_submissions +FOR ALL +TO authenticated +USING ( + is_moderator((SELECT auth.uid())) + AND ((NOT has_mfa_enabled((SELECT auth.uid()))) OR has_aal2()) +); + +-- ============================================================================ +-- VERIFICATION +-- ============================================================================ + +COMMENT ON FUNCTION public.has_mfa_enabled IS 'Security definer function to safely check MFA enrollment without granting direct access to auth.mfa_factors table';