-- Phase 4: Security Fixes for New Tables -- ============================================================================ -- Enable RLS on new tables -- ============================================================================ ALTER TABLE orphaned_images ENABLE ROW LEVEL SECURITY; ALTER TABLE system_alerts ENABLE ROW LEVEL SECURITY; -- ============================================================================ -- RLS Policies for orphaned_images (admin/moderator access only) -- ============================================================================ CREATE POLICY "Admins can view orphaned images" ON orphaned_images FOR SELECT TO authenticated USING ( EXISTS ( SELECT 1 FROM user_roles WHERE user_id = auth.uid() AND role IN ('admin', 'superuser', 'moderator') ) ); CREATE POLICY "Admins can manage orphaned images" ON orphaned_images FOR ALL TO authenticated USING ( EXISTS ( SELECT 1 FROM user_roles WHERE user_id = auth.uid() AND role IN ('admin', 'superuser') ) ); -- ============================================================================ -- RLS Policies for system_alerts (admin access only) -- ============================================================================ CREATE POLICY "Admins can view system alerts" ON system_alerts FOR SELECT TO authenticated USING ( EXISTS ( SELECT 1 FROM user_roles WHERE user_id = auth.uid() AND role IN ('admin', 'superuser', 'moderator') ) ); CREATE POLICY "Admins can manage system alerts" ON system_alerts FOR ALL TO authenticated USING ( EXISTS ( SELECT 1 FROM user_roles WHERE user_id = auth.uid() AND role IN ('admin', 'superuser') ) ); -- ============================================================================ -- Fix search_path for security definer view -- ============================================================================ -- Recreate system_health view with proper security DROP VIEW IF EXISTS system_health; -- Create a function instead of a security definer view CREATE OR REPLACE FUNCTION get_system_health() RETURNS TABLE( orphaned_images_count BIGINT, critical_alerts_count BIGINT, alerts_last_24h BIGINT, checked_at TIMESTAMPTZ ) LANGUAGE plpgsql SECURITY DEFINER SET search_path = public AS $$ BEGIN RETURN QUERY SELECT (SELECT COUNT(*) FROM orphaned_images WHERE marked_for_deletion_at IS NOT NULL)::BIGINT as orphaned_images_count, (SELECT COUNT(*) FROM system_alerts WHERE resolved_at IS NULL AND severity IN ('high', 'critical'))::BIGINT as critical_alerts_count, (SELECT COUNT(*) FROM system_alerts WHERE resolved_at IS NULL AND created_at > now() - interval '24 hours')::BIGINT as alerts_last_24h, now() as checked_at; END; $$; GRANT EXECUTE ON FUNCTION get_system_health() TO authenticated;