00005_movies_update_recursion_fix.sql 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
  1. -- Fix infinite recursion in movies UPDATE policy.
  2. --
  3. -- The original WITH CHECK clause referenced `public.movies` in a subquery
  4. -- (to enforce that added_by cannot change). Selecting from movies while the
  5. -- movies_update policy is being evaluated triggers RLS recursion (42P17).
  6. --
  7. -- Replace the self-referencing check with a BEFORE UPDATE trigger that
  8. -- forbids mutating added_by at the row level. Group-membership check stays
  9. -- in the policy.
  10. DROP POLICY IF EXISTS movies_update ON public.movies;
  11. CREATE POLICY movies_update ON public.movies
  12. FOR UPDATE USING (
  13. EXISTS (
  14. SELECT 1 FROM public.group_members
  15. WHERE group_members.group_id = movies.group_id
  16. AND group_members.user_id = auth.uid()
  17. )
  18. )
  19. WITH CHECK (
  20. EXISTS (
  21. SELECT 1 FROM public.group_members
  22. WHERE group_members.group_id = movies.group_id
  23. AND group_members.user_id = auth.uid()
  24. )
  25. );
  26. CREATE OR REPLACE FUNCTION public.movies_prevent_added_by_change()
  27. RETURNS TRIGGER
  28. LANGUAGE plpgsql
  29. AS $$
  30. BEGIN
  31. IF NEW.added_by IS DISTINCT FROM OLD.added_by THEN
  32. RAISE EXCEPTION 'movies.added_by is immutable';
  33. END IF;
  34. RETURN NEW;
  35. END;
  36. $$;
  37. DROP TRIGGER IF EXISTS movies_added_by_immutable ON public.movies;
  38. CREATE TRIGGER movies_added_by_immutable
  39. BEFORE UPDATE ON public.movies
  40. FOR EACH ROW
  41. EXECUTE FUNCTION public.movies_prevent_added_by_change();