-- Best-effort revert of 021. NOT a clean roll-back — this migration only -- restores the broken German-bodied versions of can_see_project / -- note_is_visible / projekte_*; if the underlying tables have already been -- renamed to English (i.e. 020 hasn't been rolled back yet), the German -- bodies will still error. Run 020 / 018 down first if you really want to -- get back to a working German state. -- -- We do not recreate the dropped policies under their previous German names; -- migration 018 / 020 down rebuilds the German-named policy set, and the -- English-named policies created by 021.up are the right starting point for -- those rollbacks. -- --------------------------------------------------------------------------- -- Revert trigger functions -- --------------------------------------------------------------------------- DROP TRIGGER IF EXISTS projects_sync_path_before ON paliad.projects; DROP TRIGGER IF EXISTS projects_rewrite_subtree_after ON paliad.projects; DROP FUNCTION IF EXISTS paliad.projects_sync_path() CASCADE; DROP FUNCTION IF EXISTS paliad.projects_rewrite_subtree() CASCADE; CREATE OR REPLACE FUNCTION paliad.projekte_sync_path() RETURNS trigger LANGUAGE plpgsql AS $$ DECLARE parent_path text; BEGIN IF NEW.parent_id IS NULL THEN NEW.path := NEW.id::text; ELSE SELECT path INTO parent_path FROM paliad.projekte WHERE id = NEW.parent_id; IF parent_path IS NULL THEN RAISE EXCEPTION 'parent projekt % not found', NEW.parent_id; END IF; IF parent_path = NEW.id::text OR parent_path LIKE '%.' || NEW.id::text OR parent_path LIKE NEW.id::text || '.%' OR parent_path LIKE '%.' || NEW.id::text || '.%' THEN RAISE EXCEPTION 'cannot set parent to own descendant'; END IF; NEW.path := parent_path || '.' || NEW.id::text; END IF; RETURN NEW; END; $$; CREATE OR REPLACE FUNCTION paliad.projekte_rewrite_subtree() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN IF OLD.path IS DISTINCT FROM NEW.path THEN UPDATE paliad.projekte SET path = NEW.path || substring(path FROM length(OLD.path) + 1) WHERE path LIKE OLD.path || '.%'; END IF; RETURN NEW; END; $$; -- The triggers can only be bound to a table that exists; pick whichever of -- paliad.projekte / paliad.projects is currently around. DO $$ BEGIN EXECUTE 'CREATE TRIGGER projekte_sync_path_before BEFORE INSERT OR UPDATE OF parent_id ON paliad.projekte FOR EACH ROW EXECUTE FUNCTION paliad.projekte_sync_path()'; EXCEPTION WHEN undefined_table THEN EXECUTE 'CREATE TRIGGER projekte_sync_path_before BEFORE INSERT OR UPDATE OF parent_id ON paliad.projects FOR EACH ROW EXECUTE FUNCTION paliad.projekte_sync_path()'; END $$; DO $$ BEGIN EXECUTE 'CREATE TRIGGER projekte_rewrite_subtree_after AFTER UPDATE OF path ON paliad.projekte FOR EACH ROW EXECUTE FUNCTION paliad.projekte_rewrite_subtree()'; EXCEPTION WHEN undefined_table THEN EXECUTE 'CREATE TRIGGER projekte_rewrite_subtree_after AFTER UPDATE OF path ON paliad.projects FOR EACH ROW EXECUTE FUNCTION paliad.projekte_rewrite_subtree()'; END $$; -- --------------------------------------------------------------------------- -- Revert visibility functions to their pre-021 (broken) state -- --------------------------------------------------------------------------- DROP FUNCTION IF EXISTS paliad.note_is_visible(uuid, uuid, uuid, uuid) CASCADE; DROP FUNCTION IF EXISTS paliad.can_see_project(uuid) CASCADE; CREATE FUNCTION paliad.can_see_project(_projekt_id uuid) RETURNS boolean LANGUAGE sql STABLE SECURITY DEFINER SET search_path = paliad, public AS $$ SELECT EXISTS ( SELECT 1 FROM paliad.users u WHERE u.id = auth.uid() AND u.role = 'admin' ) OR EXISTS ( SELECT 1 FROM paliad.projekte target JOIN paliad.projekt_teams pt ON pt.user_id = auth.uid() AND pt.projekt_id = ANY(string_to_array(target.path, '.')::uuid[]) WHERE target.id = _projekt_id ); $$; CREATE FUNCTION paliad.note_is_visible( _projekt_id uuid, _frist_id uuid, _termin_id uuid, _projekt_event_id uuid ) RETURNS boolean LANGUAGE sql STABLE SECURITY DEFINER SET search_path = paliad, public AS $$ SELECT CASE WHEN _projekt_id IS NOT NULL THEN paliad.can_see_projekt(_projekt_id) WHEN _frist_id IS NOT NULL THEN paliad.can_see_projekt( (SELECT projekt_id FROM paliad.fristen WHERE id = _frist_id)) WHEN _termin_id IS NOT NULL THEN CASE WHEN (SELECT projekt_id FROM paliad.termine WHERE id = _termin_id) IS NULL THEN (SELECT created_by FROM paliad.termine WHERE id = _termin_id) = auth.uid() ELSE paliad.can_see_projekt( (SELECT projekt_id FROM paliad.termine WHERE id = _termin_id)) END WHEN _projekt_event_id IS NOT NULL THEN paliad.can_see_projekt( (SELECT projekt_id FROM paliad.projekt_events WHERE id = _projekt_event_id)) ELSE false END; $$;