diff --git a/supabase/migrations/20251021155748_fadc15b7-fa3a-48af-afb4-178c4c8e8e4c.sql b/supabase/migrations/20251021155748_fadc15b7-fa3a-48af-afb4-178c4c8e8e4c.sql new file mode 100644 index 00000000..c9885508 --- /dev/null +++ b/supabase/migrations/20251021155748_fadc15b7-fa3a-48af-afb4-178c4c8e8e4c.sql @@ -0,0 +1,82 @@ +-- Fix function search paths to prevent security vulnerabilities +-- This addresses the database linter warnings about mutable search_path + +-- Fix: cleanup_old_request_metadata +CREATE OR REPLACE FUNCTION public.cleanup_old_request_metadata() +RETURNS void +LANGUAGE plpgsql +SECURITY DEFINER +SET search_path = 'public' +AS $function$ +BEGIN + DELETE FROM request_metadata + WHERE created_at < now() - interval '30 days'; +END; +$function$; + +-- Fix: update_content_submissions_updated_at (trigger function) +CREATE OR REPLACE FUNCTION public.update_content_submissions_updated_at() +RETURNS trigger +LANGUAGE plpgsql +SET search_path = 'public' +AS $function$ +BEGIN + -- Only update updated_at if actual content has changed + -- Ignore changes to: updated_at, assigned_to, assigned_at, locked_until, priority, review_count, first_reviewed_at, resolved_at, submitted_at + IF ( + NEW.content IS DISTINCT FROM OLD.content OR + NEW.status IS DISTINCT FROM OLD.status OR + NEW.reviewer_id IS DISTINCT FROM OLD.reviewer_id OR + NEW.reviewer_notes IS DISTINCT FROM OLD.reviewer_notes OR + NEW.escalated IS DISTINCT FROM OLD.escalated OR + NEW.escalation_reason IS DISTINCT FROM OLD.escalation_reason OR + NEW.approval_mode IS DISTINCT FROM OLD.approval_mode OR + NEW.user_id IS DISTINCT FROM OLD.user_id OR + NEW.submission_type IS DISTINCT FROM OLD.submission_type OR + NEW.escalated_by IS DISTINCT FROM OLD.escalated_by OR + NEW.escalated_at IS DISTINCT FROM OLD.escalated_at OR + NEW.original_submission_id IS DISTINCT FROM OLD.original_submission_id + ) THEN + NEW.updated_at = NOW(); + ELSE + -- Keep the old updated_at timestamp if only metadata changed + NEW.updated_at = OLD.updated_at; + END IF; + + RETURN NEW; +END; +$function$; + +-- Fix: notify_discord_via_edge (trigger function) +CREATE OR REPLACE FUNCTION public.notify_discord_via_edge() +RETURNS trigger +LANGUAGE plpgsql +SET search_path = 'public' +AS $function$ +DECLARE + url text := 'https://ydvtmnrszybqnbcqbdcy.supabase.co/functions/v1/discord-webhook-poster'; + payload jsonb; + resp jsonb; +BEGIN + payload := jsonb_build_object( + 'table', TG_TABLE_SCHEMA || '.' || TG_TABLE_NAME, + 'row', to_jsonb(NEW) + ); + + PERFORM public.pg_net.http_post( + url, + payload::text, + 'application/json' + ); + + RETURN NEW; +EXCEPTION WHEN OTHERS THEN + -- Log the error and continue (do not fail the DB operation) + RAISE NOTICE 'Failed to call discord edge function: %', SQLERRM; + RETURN NEW; +END; +$function$; + +COMMENT ON FUNCTION public.cleanup_old_request_metadata() IS 'Deletes request metadata older than 30 days - now with secure search_path'; +COMMENT ON FUNCTION public.update_content_submissions_updated_at() IS 'Trigger to update updated_at only on content changes - now with secure search_path'; +COMMENT ON FUNCTION public.notify_discord_via_edge() IS 'Trigger to notify Discord via edge function - now with secure search_path'; \ No newline at end of file