From bc82e552e0d355b2bb4912efeac411a2c8e11375 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Wed, 29 Oct 2025 01:35:41 +0000 Subject: [PATCH] feat: Optimize RLS policies --- ...9_84eab35d-9fd8-4ee2-93cc-5af4e4e42a5c.sql | 669 ++++++++++++++++++ 1 file changed, 669 insertions(+) create mode 100644 supabase/migrations/20251029013529_84eab35d-9fd8-4ee2-93cc-5af4e4e42a5c.sql diff --git a/supabase/migrations/20251029013529_84eab35d-9fd8-4ee2-93cc-5af4e4e42a5c.sql b/supabase/migrations/20251029013529_84eab35d-9fd8-4ee2-93cc-5af4e4e42a5c.sql new file mode 100644 index 00000000..ad566ae4 --- /dev/null +++ b/supabase/migrations/20251029013529_84eab35d-9fd8-4ee2-93cc-5af4e4e42a5c.sql @@ -0,0 +1,669 @@ +-- Optimize RLS policies to prevent auth.uid() re-evaluation per row +-- This migration drops and recreates all affected policies with optimized syntax +-- Pattern: auth.uid() → (SELECT auth.uid()) +-- Pattern: is_moderator(auth.uid()) → is_moderator((SELECT auth.uid())) + +-- ============================================================================ +-- CONTACT EMAIL THREADS +-- ============================================================================ + +DROP POLICY IF EXISTS "Admin staff can insert email threads" ON public.contact_email_threads; +DROP POLICY IF EXISTS "Admin staff can view all email threads" ON public.contact_email_threads; + +CREATE POLICY "Admin staff can insert email threads" +ON public.contact_email_threads +FOR INSERT +TO authenticated +WITH CHECK ( + has_role((SELECT auth.uid()), 'superuser'::app_role) OR + has_role((SELECT auth.uid()), 'admin'::app_role) OR + has_role((SELECT auth.uid()), 'moderator'::app_role) +); + +CREATE POLICY "Admin staff can view all email threads" +ON public.contact_email_threads +FOR SELECT +TO authenticated +USING ( + has_role((SELECT auth.uid()), 'superuser'::app_role) OR + has_role((SELECT auth.uid()), 'admin'::app_role) OR + has_role((SELECT auth.uid()), 'moderator'::app_role) +); + +-- ============================================================================ +-- PROFILES +-- ============================================================================ + +DROP POLICY IF EXISTS "Admins and moderators can view all profiles" ON public.profiles; +DROP POLICY IF EXISTS "Admins can update any profile with MFA" ON public.profiles; + +CREATE POLICY "Admins and moderators can view all profiles" +ON public.profiles +FOR SELECT +TO authenticated +USING (is_moderator((SELECT auth.uid()))); + +CREATE POLICY "Admins can update any profile with MFA" +ON public.profiles +FOR UPDATE +TO authenticated +USING (is_moderator((SELECT auth.uid())) AND has_aal2()); + +-- ============================================================================ +-- BLOG POSTS +-- ============================================================================ + +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((SELECT auth.uid()), 'admin'::app_role) OR has_role((SELECT auth.uid()), 'superuser'::app_role)) + AND ((NOT EXISTS ( + SELECT 1 FROM auth.mfa_factors + WHERE mfa_factors.user_id = (SELECT auth.uid()) AND mfa_factors.status = 'verified'::auth.factor_status + )) OR has_aal2()) +); + +-- ============================================================================ +-- USER ROLES +-- ============================================================================ + +DROP POLICY IF EXISTS "Admins can delete user roles with MFA" ON public.user_roles; +DROP POLICY IF EXISTS "Admins can insert user roles with MFA" ON public.user_roles; +DROP POLICY IF EXISTS "Admins can manage all user roles" ON public.user_roles; +DROP POLICY IF EXISTS "Moderators can manage roles" ON public.user_roles; + +CREATE POLICY "Admins can delete user roles with MFA" +ON public.user_roles +FOR DELETE +TO authenticated +USING (is_moderator((SELECT auth.uid())) AND has_aal2()); + +CREATE POLICY "Admins can insert user roles with MFA" +ON public.user_roles +FOR INSERT +TO authenticated +WITH CHECK (is_moderator((SELECT auth.uid())) AND has_aal2()); + +CREATE POLICY "Admins can manage all user roles" +ON public.user_roles +FOR SELECT +TO authenticated +USING (is_moderator((SELECT auth.uid()))); + +CREATE POLICY "Moderators can manage roles" +ON public.user_roles +FOR UPDATE +TO authenticated +USING (is_moderator((SELECT auth.uid()))); + +-- ============================================================================ +-- ADMIN AUDIT LOG +-- ============================================================================ + +DROP POLICY IF EXISTS "Admins can insert audit log with MFA" ON public.admin_audit_log; +DROP POLICY IF EXISTS "Admins can view audit log" 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((SELECT auth.uid())) AND has_aal2()); + +CREATE POLICY "Admins can view audit log" +ON public.admin_audit_log +FOR SELECT +TO authenticated +USING ( + is_moderator((SELECT auth.uid())) + AND ((NOT EXISTS ( + SELECT 1 FROM auth.mfa_factors + WHERE mfa_factors.user_id = (SELECT auth.uid()) AND mfa_factors.status = 'verified'::auth.factor_status + )) OR has_aal2()) +); + +-- ============================================================================ +-- NOTIFICATION CHANNELS +-- ============================================================================ + +DROP POLICY IF EXISTS "Admins can manage notification channels" ON public.notification_channels; + +CREATE POLICY "Admins can manage notification channels" +ON public.notification_channels +FOR ALL +TO authenticated +USING (is_moderator((SELECT auth.uid()))); + +-- ============================================================================ +-- NOTIFICATION TEMPLATES +-- ============================================================================ + +DROP POLICY IF EXISTS "Admins can manage notification templates" ON public.notification_templates; + +CREATE POLICY "Admins can manage notification templates" +ON public.notification_templates +FOR ALL +TO authenticated +USING (is_moderator((SELECT auth.uid()))); + +-- ============================================================================ +-- ACCOUNT DELETION REQUESTS +-- ============================================================================ + +DROP POLICY IF EXISTS "Admins can view all deletion requests" ON public.account_deletion_requests; + +CREATE POLICY "Admins can view all deletion requests" +ON public.account_deletion_requests +FOR SELECT +TO authenticated +USING (is_moderator((SELECT auth.uid()))); + +-- ============================================================================ +-- COMPANY SUBMISSIONS +-- ============================================================================ + +DROP POLICY IF EXISTS "Moderators can delete company submissions" ON public.company_submissions; +DROP POLICY IF EXISTS "Moderators can update company submissions" ON public.company_submissions; +DROP POLICY IF EXISTS "Moderators can view all 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 EXISTS ( + SELECT 1 FROM auth.mfa_factors + WHERE mfa_factors.user_id = (SELECT auth.uid()) AND mfa_factors.status = 'verified'::auth.factor_status + )) OR has_aal2()) +); + +CREATE POLICY "Moderators can update company submissions" +ON public.company_submissions +FOR UPDATE +TO authenticated +USING ( + is_moderator((SELECT auth.uid())) + AND ((NOT EXISTS ( + SELECT 1 FROM auth.mfa_factors + WHERE mfa_factors.user_id = (SELECT auth.uid()) AND mfa_factors.status = 'verified'::auth.factor_status + )) OR has_aal2()) +); + +CREATE POLICY "Moderators can view all company submissions" +ON public.company_submissions +FOR SELECT +TO authenticated +USING ( + is_moderator((SELECT auth.uid())) + AND ((NOT EXISTS ( + SELECT 1 FROM auth.mfa_factors + WHERE mfa_factors.user_id = (SELECT auth.uid()) AND mfa_factors.status = 'verified'::auth.factor_status + )) OR has_aal2()) +); + +-- ============================================================================ +-- CONTACT SUBMISSIONS +-- ============================================================================ + +DROP POLICY IF EXISTS "Moderators can delete contact submissions" ON public.contact_submissions; +DROP POLICY IF EXISTS "Moderators can update contact submissions" ON public.contact_submissions; +DROP POLICY IF EXISTS "Moderators can view all contact submissions" ON public.contact_submissions; + +CREATE POLICY "Moderators can delete contact submissions" +ON public.contact_submissions +FOR DELETE +TO authenticated +USING (is_moderator((SELECT auth.uid())) AND has_aal2()); + +CREATE POLICY "Moderators can update contact submissions" +ON public.contact_submissions +FOR UPDATE +TO authenticated +USING (is_moderator((SELECT auth.uid())) AND ((NOT has_mfa_enabled((SELECT auth.uid()))) OR has_aal2())) +WITH CHECK (is_moderator((SELECT auth.uid())) AND ((NOT has_mfa_enabled((SELECT auth.uid()))) OR has_aal2())); + +CREATE POLICY "Moderators can view all contact submissions" +ON public.contact_submissions +FOR SELECT +TO authenticated +USING (is_moderator((SELECT auth.uid()))); + +-- ============================================================================ +-- PARK SUBMISSIONS +-- ============================================================================ + +DROP POLICY IF EXISTS "Moderators can delete park submissions" ON public.park_submissions; +DROP POLICY IF EXISTS "Moderators can update park submissions" ON public.park_submissions; +DROP POLICY IF EXISTS "Moderators can view all 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 EXISTS ( + SELECT 1 FROM auth.mfa_factors + WHERE mfa_factors.user_id = (SELECT auth.uid()) AND mfa_factors.status = 'verified'::auth.factor_status + )) OR has_aal2()) +); + +CREATE POLICY "Moderators can update park submissions" +ON public.park_submissions +FOR UPDATE +TO authenticated +USING ( + is_moderator((SELECT auth.uid())) + AND ((NOT EXISTS ( + SELECT 1 FROM auth.mfa_factors + WHERE mfa_factors.user_id = (SELECT auth.uid()) AND mfa_factors.status = 'verified'::auth.factor_status + )) OR has_aal2()) +); + +CREATE POLICY "Moderators can view all park submissions" +ON public.park_submissions +FOR SELECT +TO authenticated +USING ( + is_moderator((SELECT auth.uid())) + AND ((NOT EXISTS ( + SELECT 1 FROM auth.mfa_factors + WHERE mfa_factors.user_id = (SELECT auth.uid()) AND mfa_factors.status = 'verified'::auth.factor_status + )) OR has_aal2()) +); + +-- ============================================================================ +-- ENTITY TIMELINE EVENTS +-- ============================================================================ + +DROP POLICY IF EXISTS "Moderators can delete timeline events" ON public.entity_timeline_events; +DROP POLICY IF EXISTS "Moderators can update timeline events" ON public.entity_timeline_events; +DROP POLICY IF EXISTS "Moderators can view all timeline events" ON public.entity_timeline_events; + +CREATE POLICY "Moderators can delete timeline events" +ON public.entity_timeline_events +FOR DELETE +TO authenticated +USING (is_moderator((SELECT auth.uid())) AND has_aal2()); + +CREATE POLICY "Moderators can update timeline events" +ON public.entity_timeline_events +FOR UPDATE +TO authenticated +USING (is_moderator((SELECT auth.uid())) AND has_aal2()) +WITH CHECK (is_moderator((SELECT auth.uid())) AND has_aal2()); + +CREATE POLICY "Moderators can view all timeline events" +ON public.entity_timeline_events +FOR SELECT +TO authenticated +USING (is_moderator((SELECT auth.uid())) AND has_aal2()); + +-- ============================================================================ +-- PHOTO SUBMISSION ITEMS +-- ============================================================================ + +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((SELECT auth.uid())) + AND ((NOT EXISTS ( + SELECT 1 FROM auth.mfa_factors + WHERE mfa_factors.user_id = (SELECT auth.uid()) AND mfa_factors.status = 'verified'::auth.factor_status + )) OR has_aal2()) +); + +-- ============================================================================ +-- PHOTO SUBMISSIONS +-- ============================================================================ + +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((SELECT auth.uid())) + AND ((NOT EXISTS ( + SELECT 1 FROM auth.mfa_factors + WHERE mfa_factors.user_id = (SELECT auth.uid()) AND mfa_factors.status = 'verified'::auth.factor_status + )) OR has_aal2()) +); + +-- ============================================================================ +-- REPORTS +-- ============================================================================ + +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((SELECT auth.uid())) + AND ((NOT EXISTS ( + SELECT 1 FROM auth.mfa_factors + WHERE mfa_factors.user_id = (SELECT auth.uid()) AND mfa_factors.status = 'verified'::auth.factor_status + )) OR has_aal2()) +); + +-- ============================================================================ +-- RIDE MODEL SUBMISSIONS +-- ============================================================================ + +DROP POLICY IF EXISTS "Moderators can delete ride model submissions" ON public.ride_model_submissions; + +CREATE POLICY "Moderators can delete ride model submissions" +ON public.ride_model_submissions +FOR DELETE +TO authenticated +USING ( + is_moderator((SELECT auth.uid())) + AND ((NOT EXISTS ( + SELECT 1 FROM auth.mfa_factors + WHERE mfa_factors.user_id = (SELECT auth.uid()) AND mfa_factors.status = 'verified'::auth.factor_status + )) OR has_aal2()) +); + +-- ============================================================================ +-- RIDE SUBMISSIONS +-- ============================================================================ + +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((SELECT auth.uid())) + AND ((NOT EXISTS ( + SELECT 1 FROM auth.mfa_factors + WHERE mfa_factors.user_id = (SELECT auth.uid()) AND mfa_factors.status = 'verified'::auth.factor_status + )) OR has_aal2()) +); + +-- ============================================================================ +-- SUBMISSION ITEMS +-- ============================================================================ + +DROP POLICY IF EXISTS "Moderators can delete submission items" ON public.submission_items; +DROP POLICY IF EXISTS "Moderators can insert submission items" ON public.submission_items; + +CREATE POLICY "Moderators can delete submission items" +ON public.submission_items +FOR DELETE +TO authenticated +USING ( + is_moderator((SELECT auth.uid())) + AND ((NOT EXISTS ( + SELECT 1 FROM auth.mfa_factors + WHERE mfa_factors.user_id = (SELECT auth.uid()) AND mfa_factors.status = 'verified'::auth.factor_status + )) OR has_aal2()) +); + +CREATE POLICY "Moderators can insert submission items" +ON public.submission_items +FOR INSERT +TO authenticated +WITH CHECK ( + is_moderator((SELECT auth.uid())) + AND ((NOT EXISTS ( + SELECT 1 FROM auth.mfa_factors + WHERE mfa_factors.user_id = (SELECT auth.uid()) AND mfa_factors.status = 'verified'::auth.factor_status + )) OR has_aal2()) +); + +-- ============================================================================ +-- CONTENT SUBMISSIONS +-- ============================================================================ + +DROP POLICY IF EXISTS "Moderators can delete submissions with MFA" ON public.content_submissions; +DROP POLICY IF EXISTS "Moderators can update submissions" ON public.content_submissions; +DROP POLICY IF EXISTS "Moderators can view all submissions" ON public.content_submissions; + +CREATE POLICY "Moderators can delete submissions with MFA" +ON public.content_submissions +FOR DELETE +TO authenticated +USING (is_moderator((SELECT auth.uid())) AND has_aal2()); + +CREATE POLICY "Moderators can update submissions" +ON public.content_submissions +FOR UPDATE +TO authenticated +USING (is_moderator((SELECT auth.uid())) AND ((NOT has_mfa_enabled((SELECT auth.uid()))) OR has_aal2())) +WITH CHECK (is_moderator((SELECT auth.uid())) AND ((NOT has_mfa_enabled((SELECT auth.uid()))) OR has_aal2())); + +CREATE POLICY "Moderators can view all submissions" +ON public.content_submissions +FOR SELECT +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 delete timeline submissions" ON public.timeline_event_submissions; + +CREATE POLICY "Moderators can delete timeline submissions" +ON public.timeline_event_submissions +FOR DELETE +TO authenticated +USING ( + is_moderator((SELECT auth.uid())) + AND ((NOT EXISTS ( + SELECT 1 FROM auth.mfa_factors + WHERE mfa_factors.user_id = (SELECT auth.uid()) AND mfa_factors.status = 'verified'::auth.factor_status + )) OR has_aal2()) +); + +-- ============================================================================ +-- LOCATIONS +-- ============================================================================ + +DROP POLICY IF EXISTS "Moderators can insert locations" ON public.locations; +DROP POLICY IF EXISTS "Moderators can update locations" ON public.locations; + +CREATE POLICY "Moderators can insert locations" +ON public.locations +FOR INSERT +TO authenticated +WITH CHECK (is_moderator((SELECT auth.uid()))); + +CREATE POLICY "Moderators can update locations" +ON public.locations +FOR UPDATE +TO authenticated +USING (is_moderator((SELECT auth.uid()))); + +-- ============================================================================ +-- REVIEW PHOTOS +-- ============================================================================ + +DROP POLICY IF EXISTS "Moderators can manage all review photos" ON public.review_photos; + +CREATE POLICY "Moderators can manage all review photos" +ON public.review_photos +FOR ALL +TO authenticated +USING ( + is_moderator((SELECT auth.uid())) + AND ((NOT EXISTS ( + SELECT 1 FROM auth.mfa_factors + WHERE mfa_factors.user_id = (SELECT auth.uid()) AND mfa_factors.status = 'verified'::auth.factor_status + )) OR has_aal2()) +); + +-- ============================================================================ +-- RIDE COASTER STATS +-- ============================================================================ + +DROP POLICY IF EXISTS "Moderators can manage ride coaster statistics" ON public.ride_coaster_stats; + +CREATE POLICY "Moderators can manage ride coaster statistics" +ON public.ride_coaster_stats +FOR ALL +TO authenticated +USING ( + is_moderator((SELECT auth.uid())) + AND ((NOT EXISTS ( + SELECT 1 FROM auth.mfa_factors + WHERE mfa_factors.user_id = (SELECT auth.uid()) AND mfa_factors.status = 'verified'::auth.factor_status + )) OR has_aal2()) +); + +-- ============================================================================ +-- RIDE MODEL TECHNICAL SPECIFICATIONS +-- ============================================================================ + +DROP POLICY IF EXISTS "Moderators can manage ride model technical specifications" ON public.ride_model_technical_specifications; + +CREATE POLICY "Moderators can manage ride model technical specifications" +ON public.ride_model_technical_specifications +FOR ALL +TO authenticated +USING ( + is_moderator((SELECT auth.uid())) + AND ((NOT EXISTS ( + SELECT 1 FROM auth.mfa_factors + WHERE mfa_factors.user_id = (SELECT auth.uid()) AND mfa_factors.status = 'verified'::auth.factor_status + )) OR has_aal2()) +); + +-- ============================================================================ +-- RIDE NAME HISTORY +-- ============================================================================ + +DROP POLICY IF EXISTS "Moderators can manage ride name history" ON public.ride_name_history; + +CREATE POLICY "Moderators can manage ride name history" +ON public.ride_name_history +FOR ALL +TO authenticated +USING ( + is_moderator((SELECT auth.uid())) + AND ((NOT EXISTS ( + SELECT 1 FROM auth.mfa_factors + WHERE mfa_factors.user_id = (SELECT auth.uid()) AND mfa_factors.status = 'verified'::auth.factor_status + )) OR has_aal2()) +); + +-- ============================================================================ +-- RIDE SUBMISSION COASTER STATISTICS +-- ============================================================================ + +DROP POLICY IF EXISTS "Moderators can manage ride submission coaster statistics" ON public.ride_submission_coaster_statistics; + +CREATE POLICY "Moderators can manage ride submission coaster statistics" +ON public.ride_submission_coaster_statistics +FOR ALL +TO authenticated +USING ( + is_moderator((SELECT auth.uid())) + AND ((NOT EXISTS ( + SELECT 1 FROM auth.mfa_factors + WHERE mfa_factors.user_id = (SELECT auth.uid()) AND mfa_factors.status = 'verified'::auth.factor_status + )) OR has_aal2()) +); + +-- ============================================================================ +-- RIDE SUBMISSION NAME HISTORY +-- ============================================================================ + +DROP POLICY IF EXISTS "Moderators can manage ride submission name history" ON public.ride_submission_name_history; + +CREATE POLICY "Moderators can manage ride submission name history" +ON public.ride_submission_name_history +FOR ALL +TO authenticated +USING ( + is_moderator((SELECT auth.uid())) + AND ((NOT EXISTS ( + SELECT 1 FROM auth.mfa_factors + WHERE mfa_factors.user_id = (SELECT auth.uid()) AND mfa_factors.status = 'verified'::auth.factor_status + )) OR has_aal2()) +); + +-- ============================================================================ +-- RIDE SUBMISSION TECHNICAL SPECIFICATIONS +-- ============================================================================ + +DROP POLICY IF EXISTS "Moderators can manage ride submission technical specifications" ON public.ride_submission_technical_specifications; + +CREATE POLICY "Moderators can manage ride submission technical specifications" +ON public.ride_submission_technical_specifications +FOR ALL +TO authenticated +USING ( + is_moderator((SELECT auth.uid())) + AND ((NOT EXISTS ( + SELECT 1 FROM auth.mfa_factors + WHERE mfa_factors.user_id = (SELECT auth.uid()) AND mfa_factors.status = 'verified'::auth.factor_status + )) OR has_aal2()) +); + +-- ============================================================================ +-- RIDE TECHNICAL SPECIFICATIONS +-- ============================================================================ + +DROP POLICY IF EXISTS "Moderators can manage ride technical specifications" ON public.ride_technical_specifications; + +CREATE POLICY "Moderators can manage ride technical specifications" +ON public.ride_technical_specifications +FOR ALL +TO authenticated +USING ( + is_moderator((SELECT auth.uid())) + AND ((NOT EXISTS ( + SELECT 1 FROM auth.mfa_factors + WHERE mfa_factors.user_id = (SELECT auth.uid()) AND mfa_factors.status = 'verified'::auth.factor_status + )) OR has_aal2()) +); + +-- ============================================================================ +-- SUBMISSION DEPENDENCIES +-- ============================================================================ + +DROP POLICY IF EXISTS "Moderators can manage submission dependencies" ON public.submission_dependencies; + +CREATE POLICY "Moderators can manage submission dependencies" +ON public.submission_dependencies +FOR ALL +TO authenticated +USING ( + is_moderator((SELECT auth.uid())) + AND ((NOT EXISTS ( + SELECT 1 FROM auth.mfa_factors + WHERE mfa_factors.user_id = (SELECT auth.uid()) AND mfa_factors.status = 'verified'::auth.factor_status + )) OR has_aal2()) +); + +-- ============================================================================ +-- TEST DATA REGISTRY +-- ============================================================================ + +DROP POLICY IF EXISTS "Moderators can manage test data registry" ON public.test_data_registry; + +CREATE POLICY "Moderators can manage test data registry" +ON public.test_data_registry +FOR ALL +TO authenticated +USING ( + is_moderator((SELECT auth.uid())) + AND ((NOT EXISTS ( + SELECT 1 FROM auth.mfa_factors + WHERE mfa_factors.user_id = (SELECT auth.uid()) AND mfa_factors.status = 'verified'::auth.factor_status + )) OR has_aal2()) +); \ No newline at end of file