mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-28 05:27:06 -05:00
Compare commits
3 Commits
8083774991
...
fdcb4e7540
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fdcb4e7540 | ||
|
|
fd92c1c3e2 | ||
|
|
644a0d655c |
@@ -0,0 +1,192 @@
|
|||||||
|
-- Phase 2: Fix Remaining RLS Security Issues (corrected)
|
||||||
|
-- Fix user_roles, reviews, reports, submission_items, and other tables
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
-- 1. FIX user_roles TABLE - Remove public read access
|
||||||
|
-- ============================================================================
|
||||||
|
|
||||||
|
DROP POLICY IF EXISTS "Public read access to user_roles" ON user_roles;
|
||||||
|
DROP POLICY IF EXISTS "Anyone can view user roles" ON user_roles;
|
||||||
|
DROP POLICY IF EXISTS "Users can view their own roles" ON user_roles;
|
||||||
|
DROP POLICY IF EXISTS "Moderators can view all roles with MFA" ON user_roles;
|
||||||
|
DROP POLICY IF EXISTS "Superusers can manage roles with MFA" ON user_roles;
|
||||||
|
|
||||||
|
CREATE POLICY "Users can view their own roles"
|
||||||
|
ON user_roles FOR SELECT TO authenticated
|
||||||
|
USING (user_id = auth.uid());
|
||||||
|
|
||||||
|
CREATE POLICY "Moderators can view all roles with MFA"
|
||||||
|
ON user_roles FOR SELECT TO authenticated
|
||||||
|
USING (is_moderator(auth.uid()) AND ((NOT has_mfa_enabled(auth.uid())) OR has_aal2()));
|
||||||
|
|
||||||
|
CREATE POLICY "Superusers can manage roles with MFA"
|
||||||
|
ON user_roles FOR ALL TO authenticated
|
||||||
|
USING (has_role(auth.uid(), 'superuser') AND has_aal2())
|
||||||
|
WITH CHECK (has_role(auth.uid(), 'superuser') AND has_aal2());
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
-- 2. FIX reviews TABLE - Implement proper access control
|
||||||
|
-- ============================================================================
|
||||||
|
|
||||||
|
DROP POLICY IF EXISTS "Public read access to reviews" ON reviews;
|
||||||
|
DROP POLICY IF EXISTS "Anyone can view reviews" ON reviews;
|
||||||
|
DROP POLICY IF EXISTS "Public can insert reviews" ON reviews;
|
||||||
|
DROP POLICY IF EXISTS "Public can view approved reviews" ON reviews;
|
||||||
|
DROP POLICY IF EXISTS "Users can view their own reviews" ON reviews;
|
||||||
|
DROP POLICY IF EXISTS "Moderators can view all reviews with MFA" ON reviews;
|
||||||
|
DROP POLICY IF EXISTS "Authenticated users can insert reviews" ON reviews;
|
||||||
|
DROP POLICY IF EXISTS "Users can update their own pending reviews" ON reviews;
|
||||||
|
DROP POLICY IF EXISTS "Moderators can update any review with MFA" ON reviews;
|
||||||
|
DROP POLICY IF EXISTS "Moderators can delete reviews with MFA" ON reviews;
|
||||||
|
|
||||||
|
CREATE POLICY "Public can view approved reviews"
|
||||||
|
ON reviews FOR SELECT TO authenticated
|
||||||
|
USING (moderation_status = 'approved');
|
||||||
|
|
||||||
|
CREATE POLICY "Users can view their own reviews"
|
||||||
|
ON reviews FOR SELECT TO authenticated
|
||||||
|
USING (user_id = auth.uid());
|
||||||
|
|
||||||
|
CREATE POLICY "Moderators can view all reviews with MFA"
|
||||||
|
ON reviews FOR SELECT TO authenticated
|
||||||
|
USING (is_moderator(auth.uid()) AND ((NOT has_mfa_enabled(auth.uid())) OR has_aal2()));
|
||||||
|
|
||||||
|
CREATE POLICY "Authenticated users can insert reviews"
|
||||||
|
ON reviews FOR INSERT TO authenticated
|
||||||
|
WITH CHECK (user_id = auth.uid() AND NOT is_user_banned(auth.uid()));
|
||||||
|
|
||||||
|
CREATE POLICY "Users can update their own pending reviews"
|
||||||
|
ON reviews FOR UPDATE TO authenticated
|
||||||
|
USING (user_id = auth.uid() AND moderation_status = 'pending')
|
||||||
|
WITH CHECK (user_id = auth.uid() AND moderation_status = 'pending');
|
||||||
|
|
||||||
|
CREATE POLICY "Moderators can update any review with MFA"
|
||||||
|
ON reviews 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()));
|
||||||
|
|
||||||
|
CREATE POLICY "Moderators can delete reviews with MFA"
|
||||||
|
ON reviews FOR DELETE TO authenticated
|
||||||
|
USING (is_moderator(auth.uid()) AND has_aal2());
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
-- 3. FIX reports TABLE - Implement proper access control
|
||||||
|
-- ============================================================================
|
||||||
|
|
||||||
|
DROP POLICY IF EXISTS "Anyone can view reports" ON reports;
|
||||||
|
DROP POLICY IF EXISTS "Public read access to reports" ON reports;
|
||||||
|
DROP POLICY IF EXISTS "Users can view their own reports" ON reports;
|
||||||
|
DROP POLICY IF EXISTS "Moderators can view all reports with MFA" ON reports;
|
||||||
|
DROP POLICY IF EXISTS "Authenticated users can create reports" ON reports;
|
||||||
|
DROP POLICY IF EXISTS "Moderators can update reports with MFA" ON reports;
|
||||||
|
DROP POLICY IF EXISTS "Moderators can delete reports with MFA" ON reports;
|
||||||
|
|
||||||
|
CREATE POLICY "Users can view their own reports"
|
||||||
|
ON reports FOR SELECT TO authenticated
|
||||||
|
USING (reporter_id = auth.uid());
|
||||||
|
|
||||||
|
CREATE POLICY "Moderators can view all reports with MFA"
|
||||||
|
ON reports FOR SELECT TO authenticated
|
||||||
|
USING (is_moderator(auth.uid()) AND ((NOT has_mfa_enabled(auth.uid())) OR has_aal2()));
|
||||||
|
|
||||||
|
CREATE POLICY "Authenticated users can create reports"
|
||||||
|
ON reports FOR INSERT TO authenticated
|
||||||
|
WITH CHECK (reporter_id = auth.uid() AND NOT is_user_banned(auth.uid()));
|
||||||
|
|
||||||
|
CREATE POLICY "Moderators can update reports with MFA"
|
||||||
|
ON reports 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()));
|
||||||
|
|
||||||
|
CREATE POLICY "Moderators can delete reports with MFA"
|
||||||
|
ON reports FOR DELETE TO authenticated
|
||||||
|
USING (is_moderator(auth.uid()) AND has_aal2());
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
-- 4. FIX submission_items TABLE - Implement proper access control
|
||||||
|
-- ============================================================================
|
||||||
|
|
||||||
|
DROP POLICY IF EXISTS "Anyone can view submission items" ON submission_items;
|
||||||
|
DROP POLICY IF EXISTS "Public read access to submission_items" ON submission_items;
|
||||||
|
DROP POLICY IF EXISTS "Users can view items from their own submissions" ON submission_items;
|
||||||
|
DROP POLICY IF EXISTS "Moderators can view all submission items with MFA" ON submission_items;
|
||||||
|
DROP POLICY IF EXISTS "Moderators can manage submission items with MFA" ON submission_items;
|
||||||
|
|
||||||
|
CREATE POLICY "Users can view items from their own submissions"
|
||||||
|
ON submission_items FOR SELECT TO authenticated
|
||||||
|
USING (EXISTS (
|
||||||
|
SELECT 1 FROM content_submissions cs
|
||||||
|
WHERE cs.id = submission_items.submission_id
|
||||||
|
AND cs.user_id = auth.uid()
|
||||||
|
));
|
||||||
|
|
||||||
|
CREATE POLICY "Moderators can view all submission items with MFA"
|
||||||
|
ON submission_items FOR SELECT TO authenticated
|
||||||
|
USING (is_moderator(auth.uid()) AND ((NOT has_mfa_enabled(auth.uid())) OR has_aal2()));
|
||||||
|
|
||||||
|
CREATE POLICY "Moderators can manage submission items with MFA"
|
||||||
|
ON submission_items FOR ALL 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()));
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
-- 5. FIX user_blocks TABLE - Ensure proper access control
|
||||||
|
-- ============================================================================
|
||||||
|
|
||||||
|
DROP POLICY IF EXISTS "Anyone can view blocks" ON user_blocks;
|
||||||
|
DROP POLICY IF EXISTS "Users can view their own blocks" ON user_blocks;
|
||||||
|
DROP POLICY IF EXISTS "Users can manage their own blocks" ON user_blocks;
|
||||||
|
DROP POLICY IF EXISTS "Moderators can view all blocks with MFA" ON user_blocks;
|
||||||
|
|
||||||
|
CREATE POLICY "Users can view their own blocks"
|
||||||
|
ON user_blocks FOR SELECT TO authenticated
|
||||||
|
USING (blocker_id = auth.uid());
|
||||||
|
|
||||||
|
CREATE POLICY "Users can manage their own blocks"
|
||||||
|
ON user_blocks FOR ALL TO authenticated
|
||||||
|
USING (blocker_id = auth.uid())
|
||||||
|
WITH CHECK (blocker_id = auth.uid());
|
||||||
|
|
||||||
|
CREATE POLICY "Moderators can view all blocks with MFA"
|
||||||
|
ON user_blocks FOR SELECT TO authenticated
|
||||||
|
USING (is_moderator(auth.uid()) AND ((NOT has_mfa_enabled(auth.uid())) OR has_aal2()));
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
-- 6. FIX user_preferences TABLE - Ensure proper access control
|
||||||
|
-- ============================================================================
|
||||||
|
|
||||||
|
DROP POLICY IF EXISTS "Anyone can view preferences" ON user_preferences;
|
||||||
|
DROP POLICY IF EXISTS "Users can view their own preferences" ON user_preferences;
|
||||||
|
DROP POLICY IF EXISTS "Users can manage their own preferences" ON user_preferences;
|
||||||
|
DROP POLICY IF EXISTS "Moderators can view all preferences with MFA" ON user_preferences;
|
||||||
|
|
||||||
|
CREATE POLICY "Users can view their own preferences"
|
||||||
|
ON user_preferences FOR SELECT TO authenticated
|
||||||
|
USING (user_id = auth.uid());
|
||||||
|
|
||||||
|
CREATE POLICY "Users can manage their own preferences"
|
||||||
|
ON user_preferences FOR ALL TO authenticated
|
||||||
|
USING (user_id = auth.uid())
|
||||||
|
WITH CHECK (user_id = auth.uid());
|
||||||
|
|
||||||
|
CREATE POLICY "Moderators can view all preferences with MFA"
|
||||||
|
ON user_preferences FOR SELECT TO authenticated
|
||||||
|
USING (is_moderator(auth.uid()) AND has_aal2());
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
-- 7. AUDIT: Verify all critical tables have RLS enabled
|
||||||
|
-- ============================================================================
|
||||||
|
|
||||||
|
ALTER TABLE user_roles ENABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE reviews ENABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE reports ENABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE submission_items ENABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE user_blocks ENABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE user_preferences ENABLE ROW LEVEL SECURITY;
|
||||||
|
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
RAISE NOTICE '✅ Phase 2 Complete: Secured user_roles, reviews, reports, submission_items, user_blocks, user_preferences';
|
||||||
|
RAISE NOTICE '🔒 All critical tables now have proper access control with MFA enforcement';
|
||||||
|
RAISE NOTICE '🚫 Banned users blocked from creating reviews and reports';
|
||||||
|
END $$;
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
-- Fix search_path for validate_slug_format function
|
||||||
|
-- This resolves the final function search_path security warning
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION public.validate_slug_format()
|
||||||
|
RETURNS trigger
|
||||||
|
LANGUAGE plpgsql
|
||||||
|
SET search_path = public
|
||||||
|
AS $function$
|
||||||
|
BEGIN
|
||||||
|
IF NEW.slug IS NOT NULL THEN
|
||||||
|
-- Check format: lowercase letters, numbers, hyphens only
|
||||||
|
IF NEW.slug !~ '^[a-z0-9]+(-[a-z0-9]+)*$' THEN
|
||||||
|
RAISE EXCEPTION 'Invalid slug format: %. Slugs must be lowercase alphanumeric with hyphens only.', NEW.slug;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- Check length constraints
|
||||||
|
IF length(NEW.slug) < 2 THEN
|
||||||
|
RAISE EXCEPTION 'Slug too short: %. Minimum length is 2 characters.', NEW.slug;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
IF length(NEW.slug) > 100 THEN
|
||||||
|
RAISE EXCEPTION 'Slug too long: %. Maximum length is 100 characters.', NEW.slug;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- Prevent reserved slugs
|
||||||
|
IF NEW.slug IN ('admin', 'api', 'auth', 'new', 'edit', 'delete', 'create', 'update', 'null', 'undefined') THEN
|
||||||
|
RAISE EXCEPTION 'Reserved slug: %. This slug cannot be used.', NEW.slug;
|
||||||
|
END IF;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
RETURN NEW;
|
||||||
|
END;
|
||||||
|
$function$;
|
||||||
|
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
RAISE NOTICE '✅ Fixed search_path for validate_slug_format function';
|
||||||
|
RAISE NOTICE '🔒 All database functions now have secure search_path settings';
|
||||||
|
END $$;
|
||||||
@@ -0,0 +1,226 @@
|
|||||||
|
-- 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 $$;
|
||||||
Reference in New Issue
Block a user