Files
thrilltrack-explorer/supabase/migrations/20251103155059_650b12b2-e3c8-48e7-8d03-3116b05e9fdb.sql
2025-11-03 15:51:12 +00:00

78 lines
2.5 KiB
SQL

-- ============================================================================
-- CRITICAL SECURITY FIXES (P0)
-- ============================================================================
-- Fix #1: Profiles Table PII Exposure - Remove anon access
DROP POLICY IF EXISTS "Public can view non-banned public profiles" ON public.profiles;
CREATE POLICY "Profiles restricted to authenticated users and moderators"
ON public.profiles
FOR SELECT
TO authenticated
USING (
auth.uid() = user_id
OR is_moderator(auth.uid())
);
GRANT SELECT ON public.filtered_profiles TO anon;
COMMENT ON POLICY "Profiles restricted to authenticated users and moderators" ON public.profiles IS
'SECURITY: Restricts direct profile table access to profile owners and moderators only. Anonymous users must use filtered_profiles view.';
-- Fix #2: User_roles Table - Ensure no public access
ALTER TABLE public.user_roles ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS "user_roles are viewable by everyone" ON public.user_roles;
DROP POLICY IF EXISTS "Public can view user roles" ON public.user_roles;
DROP POLICY IF EXISTS "Users can view their own roles" ON public.user_roles;
CREATE POLICY "Users can view their own roles only"
ON public.user_roles
FOR SELECT
TO authenticated
USING (auth.uid() = user_id);
CREATE POLICY "Moderators can view all roles with MFA"
ON public.user_roles
FOR SELECT
TO authenticated
USING (is_moderator(auth.uid()));
-- Fix #3: Error_summary View - Set SECURITY INVOKER
DROP VIEW IF EXISTS error_summary;
CREATE VIEW error_summary
WITH (security_invoker = true)
AS
SELECT
error_type,
endpoint,
COUNT(*) as occurrence_count,
COUNT(DISTINCT user_id) as affected_users,
MAX(created_at) as last_occurred,
MIN(created_at) as first_occurred,
ROUND(AVG(duration_ms)::numeric, 2) as avg_duration_ms,
(ARRAY_AGG(request_id ORDER BY created_at DESC)
FILTER (WHERE created_at > now() - interval '1 day')
)[1:5] as recent_request_ids
FROM request_metadata
WHERE error_type IS NOT NULL
AND created_at > now() - interval '30 days'
GROUP BY error_type, endpoint
ORDER BY occurrence_count DESC;
DROP POLICY IF EXISTS "Moderators can view error metadata" ON request_metadata;
CREATE POLICY "Moderators can view error metadata"
ON request_metadata
FOR SELECT
TO authenticated
USING (
is_moderator(auth.uid())
OR user_id = auth.uid()
);
GRANT SELECT ON error_summary TO authenticated;
COMMENT ON VIEW error_summary IS
'Error aggregation view with SECURITY INVOKER - uses caller permissions.';