-- Migration: Secure User Roles from Self-Escalation -- Purpose: Prevent users from updating their own roles to 'admin' using RLS / Triggers. -- Ensure RLS is enabled on users ALTER TABLE public.users ENABLE ROW LEVEL SECURITY; -- Policy to allow users to view their own records CREATE POLICY select_own_user ON public.users FOR SELECT TO authenticated USING (auth.uid() = id); -- Policy to allow admins to view all users CREATE POLICY select_all_users_for_admin ON public.users FOR SELECT TO authenticated USING ( (SELECT role FROM public.users WHERE id = auth.uid()) = 'admin' ); -- Trigger to prevent any role updates to 'admin' from unauthorized users CREATE OR REPLACE FUNCTION check_user_role_escalation() RETURNS TRIGGER AS $$ BEGIN -- Only allow changes to the role column if executed by the service_role IF (TG_OP = 'UPDATE' AND OLD.role IS DISTINCT FROM NEW.role) OR (TG_OP = 'INSERT') THEN IF current_setting('role', true) <> 'service_role' THEN -- Partners cannot upgrade themselves or others to admin IF NEW.role = 'admin' THEN RAISE EXCEPTION 'Unberechtigtes Rollen-Upgrade verweigert.'; END IF; END IF; END IF; RETURN NEW; END; $$ LANGUAGE plpgsql SECURITY DEFINER; DROP TRIGGER IF EXISTS enforce_role_protection ON public.users; CREATE TRIGGER enforce_role_protection BEFORE INSERT OR UPDATE ON public.users FOR EACH ROW EXECUTE FUNCTION check_user_role_escalation();