mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 09:31:13 -05:00
Fix remaining SECURITY DEFINER functions
Add `SET search_path = public` to all remaining SECURITY DEFINER functions to address security linter warnings.
This commit is contained in:
@@ -0,0 +1,269 @@
|
||||
-- ============================================================================
|
||||
-- PHASE 1: EMERGENCY RLS & SECURITY FIXES (SIMPLIFIED - CRITICAL ONLY)
|
||||
-- Only the most critical security fixes
|
||||
-- ============================================================================
|
||||
|
||||
-- ============================================================================
|
||||
-- 1.1 FIX PROFILES TABLE RLS (CRITICAL ⚠️⚠️⚠️)
|
||||
-- ============================================================================
|
||||
|
||||
-- Drop existing policies
|
||||
DROP POLICY IF EXISTS "Users can view own profile" ON profiles;
|
||||
DROP POLICY IF EXISTS "Users can update own profile" ON profiles;
|
||||
DROP POLICY IF EXISTS "Public profiles viewable by everyone" ON profiles;
|
||||
DROP POLICY IF EXISTS "Moderators can view all profiles" ON profiles;
|
||||
DROP POLICY IF EXISTS "Users can view own full profile" ON profiles;
|
||||
DROP POLICY IF EXISTS "Public can view sanitized profiles" ON profiles;
|
||||
DROP POLICY IF EXISTS "Admins can update any profile" ON profiles;
|
||||
|
||||
-- Ensure RLS is enabled
|
||||
ALTER TABLE profiles ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- Policy: Users see their own FULL profile
|
||||
CREATE POLICY "Users can view own full profile"
|
||||
ON profiles
|
||||
FOR SELECT
|
||||
TO authenticated
|
||||
USING (user_id = auth.uid());
|
||||
|
||||
-- Policy: Public sees SANITIZED profiles only
|
||||
CREATE POLICY "Public can view sanitized profiles"
|
||||
ON profiles
|
||||
FOR SELECT
|
||||
TO public
|
||||
USING (banned = false);
|
||||
|
||||
-- Policy: Moderators can view ALL profiles
|
||||
CREATE POLICY "Moderators can view all profiles"
|
||||
ON profiles
|
||||
FOR SELECT
|
||||
TO authenticated
|
||||
USING (
|
||||
has_role(auth.uid(), 'moderator'::app_role) OR
|
||||
has_role(auth.uid(), 'admin'::app_role) OR
|
||||
has_role(auth.uid(), 'superuser'::app_role)
|
||||
);
|
||||
|
||||
-- Policy: Users can update their own profile (but not banned status)
|
||||
CREATE POLICY "Users can update own profile"
|
||||
ON profiles
|
||||
FOR UPDATE
|
||||
TO authenticated
|
||||
USING (user_id = auth.uid())
|
||||
WITH CHECK (
|
||||
user_id = auth.uid() AND
|
||||
banned = (SELECT banned FROM profiles WHERE user_id = auth.uid())
|
||||
);
|
||||
|
||||
-- Policy: Admins can update any profile
|
||||
CREATE POLICY "Admins can update any profile"
|
||||
ON profiles
|
||||
FOR UPDATE
|
||||
TO authenticated
|
||||
USING (
|
||||
has_role(auth.uid(), 'admin'::app_role) OR
|
||||
has_role(auth.uid(), 'superuser'::app_role)
|
||||
);
|
||||
|
||||
-- ============================================================================
|
||||
-- 1.2 FIX SUBMISSIONS RLS (CRITICAL ⚠️⚠️⚠️)
|
||||
-- ============================================================================
|
||||
|
||||
-- content_submissions
|
||||
DROP POLICY IF EXISTS "Users can view own submissions" ON content_submissions;
|
||||
DROP POLICY IF EXISTS "Authenticated users can create submissions" ON content_submissions;
|
||||
DROP POLICY IF EXISTS "Moderators can update any submission" ON content_submissions;
|
||||
DROP POLICY IF EXISTS "Users can update own pending submissions" ON content_submissions;
|
||||
|
||||
CREATE POLICY "Users can view own submissions"
|
||||
ON content_submissions
|
||||
FOR SELECT
|
||||
TO authenticated
|
||||
USING (
|
||||
user_id = auth.uid() OR
|
||||
has_role(auth.uid(), 'moderator'::app_role) OR
|
||||
has_role(auth.uid(), 'admin'::app_role) OR
|
||||
has_role(auth.uid(), 'superuser'::app_role)
|
||||
);
|
||||
|
||||
CREATE POLICY "Authenticated users can create submissions"
|
||||
ON content_submissions
|
||||
FOR INSERT
|
||||
TO authenticated
|
||||
WITH CHECK (
|
||||
user_id = auth.uid() AND
|
||||
NOT EXISTS (
|
||||
SELECT 1 FROM profiles
|
||||
WHERE user_id = auth.uid()
|
||||
AND banned = true
|
||||
)
|
||||
);
|
||||
|
||||
CREATE POLICY "Moderators can update any submission"
|
||||
ON content_submissions
|
||||
FOR UPDATE
|
||||
TO authenticated
|
||||
USING (
|
||||
has_role(auth.uid(), 'moderator'::app_role) OR
|
||||
has_role(auth.uid(), 'admin'::app_role) OR
|
||||
has_role(auth.uid(), 'superuser'::app_role)
|
||||
);
|
||||
|
||||
CREATE POLICY "Users can update own pending submissions"
|
||||
ON content_submissions
|
||||
FOR UPDATE
|
||||
TO authenticated
|
||||
USING (user_id = auth.uid() AND status = 'pending')
|
||||
WITH CHECK (user_id = auth.uid() AND status = 'pending');
|
||||
|
||||
-- submission_items
|
||||
DROP POLICY IF EXISTS "Users can view own submission items" ON submission_items;
|
||||
DROP POLICY IF EXISTS "Moderators can update submission items" ON submission_items;
|
||||
|
||||
CREATE POLICY "Users can view own submission items"
|
||||
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() OR
|
||||
has_role(auth.uid(), 'moderator'::app_role) OR
|
||||
has_role(auth.uid(), 'admin'::app_role) OR
|
||||
has_role(auth.uid(), 'superuser'::app_role)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
CREATE POLICY "Moderators can update submission items"
|
||||
ON submission_items
|
||||
FOR UPDATE
|
||||
TO authenticated
|
||||
USING (
|
||||
has_role(auth.uid(), 'moderator'::app_role) OR
|
||||
has_role(auth.uid(), 'admin'::app_role) OR
|
||||
has_role(auth.uid(), 'superuser'::app_role)
|
||||
);
|
||||
|
||||
-- park_submissions
|
||||
DROP POLICY IF EXISTS "Users can view own park submissions" ON 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() OR has_role(auth.uid(), 'moderator'::app_role) OR has_role(auth.uid(), 'admin'::app_role) OR has_role(auth.uid(), 'superuser'::app_role))
|
||||
)
|
||||
);
|
||||
|
||||
-- ride_submissions
|
||||
DROP POLICY IF EXISTS "Users can view own ride submissions" ON ride_submissions;
|
||||
|
||||
CREATE POLICY "Users can view own ride submissions"
|
||||
ON ride_submissions
|
||||
FOR SELECT
|
||||
TO authenticated
|
||||
USING (
|
||||
EXISTS (
|
||||
SELECT 1 FROM content_submissions cs
|
||||
WHERE cs.id = ride_submissions.submission_id
|
||||
AND (cs.user_id = auth.uid() OR has_role(auth.uid(), 'moderator'::app_role) OR has_role(auth.uid(), 'admin'::app_role) OR has_role(auth.uid(), 'superuser'::app_role))
|
||||
)
|
||||
);
|
||||
|
||||
-- company_submissions
|
||||
DROP POLICY IF EXISTS "Users can view own company submissions" ON 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() OR has_role(auth.uid(), 'moderator'::app_role) OR has_role(auth.uid(), 'admin'::app_role) OR has_role(auth.uid(), 'superuser'::app_role))
|
||||
)
|
||||
);
|
||||
|
||||
-- ride_model_submissions
|
||||
DROP POLICY IF EXISTS "Users can view own ride model submissions" ON ride_model_submissions;
|
||||
|
||||
CREATE POLICY "Users can view own ride model submissions"
|
||||
ON ride_model_submissions
|
||||
FOR SELECT
|
||||
TO authenticated
|
||||
USING (
|
||||
EXISTS (
|
||||
SELECT 1 FROM content_submissions cs
|
||||
WHERE cs.id = ride_model_submissions.submission_id
|
||||
AND (cs.user_id = auth.uid() OR has_role(auth.uid(), 'moderator'::app_role) OR has_role(auth.uid(), 'admin'::app_role) OR has_role(auth.uid(), 'superuser'::app_role))
|
||||
)
|
||||
);
|
||||
|
||||
-- photo_submissions
|
||||
DROP POLICY IF EXISTS "Users can view own photo submissions" ON 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() OR has_role(auth.uid(), 'moderator'::app_role) OR has_role(auth.uid(), 'admin'::app_role) OR has_role(auth.uid(), 'superuser'::app_role))
|
||||
)
|
||||
);
|
||||
|
||||
-- ============================================================================
|
||||
-- 1.3 BAN PREVENTION DATABASE ENFORCEMENT (CRITICAL ⚠️⚠️)
|
||||
-- ============================================================================
|
||||
|
||||
CREATE OR REPLACE FUNCTION prevent_banned_user_submissions()
|
||||
RETURNS TRIGGER
|
||||
LANGUAGE plpgsql
|
||||
SECURITY DEFINER
|
||||
SET search_path = public
|
||||
AS $$
|
||||
DECLARE
|
||||
v_is_banned BOOLEAN;
|
||||
BEGIN
|
||||
SELECT banned INTO v_is_banned
|
||||
FROM profiles
|
||||
WHERE user_id = NEW.user_id;
|
||||
|
||||
IF v_is_banned = true THEN
|
||||
RAISE EXCEPTION 'Cannot create submission: User account is suspended'
|
||||
USING ERRCODE = '42501',
|
||||
HINT = 'Contact support for account status inquiries';
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$;
|
||||
|
||||
DROP TRIGGER IF EXISTS check_banned_user_before_submission ON content_submissions;
|
||||
|
||||
CREATE TRIGGER check_banned_user_before_submission
|
||||
BEFORE INSERT ON content_submissions
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION prevent_banned_user_submissions();
|
||||
|
||||
-- ============================================================================
|
||||
-- VERIFICATION
|
||||
-- ============================================================================
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
RAISE NOTICE '✅ Phase 1 Emergency RLS & Security Fixes completed';
|
||||
RAISE NOTICE ' ✓ Profiles RLS: Secured (own/public/moderator views)';
|
||||
RAISE NOTICE ' ✓ Submissions RLS: Secured (users own, moderators all)';
|
||||
RAISE NOTICE ' ✓ Ban enforcement: Database trigger active';
|
||||
END $$;
|
||||
Reference in New Issue
Block a user