194 lines
6 KiB
PL/PgSQL
194 lines
6 KiB
PL/PgSQL
-- Extend the owner-scoped channel_active_memberships generation to every
|
|
-- durable predicate used by ListActiveChannelIDsForUser. Ordinary memberships
|
|
-- are covered by user_channel_member_index; these triggers cover monoforum
|
|
-- subscriber message visibility, manager rights, and parent/mono enablement.
|
|
|
|
CREATE OR REPLACE FUNCTION public.telesrv_bump_channel_active_membership_owner(p_user_id bigint)
|
|
RETURNS void
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
BEGIN
|
|
IF COALESCE(p_user_id, 0) <= 0 THEN
|
|
RETURN;
|
|
END IF;
|
|
PERFORM public.telesrv_bump_read_model_version(
|
|
'channel_active_memberships', p_user_id, 'user', p_user_id
|
|
);
|
|
END;
|
|
$$;
|
|
|
|
CREATE OR REPLACE FUNCTION public.telesrv_notify_monoforum_message_visibility_read_model()
|
|
RETURNS trigger
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
DECLARE
|
|
old_owner bigint := 0;
|
|
new_owner bigint := 0;
|
|
BEGIN
|
|
IF TG_OP <> 'INSERT'
|
|
AND OLD.saved_peer_type = 'user'
|
|
AND OLD.saved_peer_id > 0
|
|
AND NOT OLD.deleted
|
|
THEN
|
|
old_owner := OLD.saved_peer_id;
|
|
END IF;
|
|
IF TG_OP <> 'DELETE'
|
|
AND NEW.saved_peer_type = 'user'
|
|
AND NEW.saved_peer_id > 0
|
|
AND NOT NEW.deleted
|
|
THEN
|
|
new_owner := NEW.saved_peer_id;
|
|
END IF;
|
|
|
|
IF old_owner > 0 THEN
|
|
PERFORM public.telesrv_bump_channel_active_membership_owner(old_owner);
|
|
END IF;
|
|
IF new_owner > 0 AND new_owner IS DISTINCT FROM old_owner THEN
|
|
PERFORM public.telesrv_bump_channel_active_membership_owner(new_owner);
|
|
END IF;
|
|
RETURN NULL;
|
|
END;
|
|
$$;
|
|
|
|
CREATE TRIGGER channel_messages_monoforum_active_membership_changed
|
|
AFTER INSERT OR DELETE OR UPDATE OF channel_id, saved_peer_type, saved_peer_id, deleted
|
|
ON public.channel_messages
|
|
FOR EACH ROW EXECUTE FUNCTION public.telesrv_notify_monoforum_message_visibility_read_model();
|
|
|
|
CREATE OR REPLACE FUNCTION public.telesrv_notify_monoforum_manager_visibility_read_model()
|
|
RETURNS trigger
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
BEGIN
|
|
IF OLD.role IS NOT DISTINCT FROM NEW.role
|
|
AND OLD.admin_rights IS NOT DISTINCT FROM NEW.admin_rights
|
|
THEN
|
|
RETURN NULL;
|
|
END IF;
|
|
IF EXISTS (
|
|
SELECT 1
|
|
FROM public.channels AS parent
|
|
WHERE parent.id = NEW.channel_id
|
|
AND parent.linked_monoforum_id <> 0
|
|
AND parent.broadcast_messages_allowed
|
|
AND NOT parent.deleted
|
|
) THEN
|
|
PERFORM public.telesrv_bump_channel_active_membership_owner(NEW.user_id);
|
|
END IF;
|
|
RETURN NULL;
|
|
END;
|
|
$$;
|
|
|
|
CREATE TRIGGER channel_members_monoforum_manager_visibility_changed
|
|
AFTER UPDATE OF role, admin_rights ON public.channel_members
|
|
FOR EACH ROW EXECUTE FUNCTION public.telesrv_notify_monoforum_manager_visibility_read_model();
|
|
|
|
CREATE OR REPLACE FUNCTION public.telesrv_bump_monoforum_visibility_owners(
|
|
p_parent_id bigint,
|
|
p_monoforum_id bigint
|
|
)
|
|
RETURNS void
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
DECLARE
|
|
affected record;
|
|
BEGIN
|
|
IF COALESCE(p_parent_id, 0) <= 0 OR COALESCE(p_monoforum_id, 0) <= 0 THEN
|
|
RETURN;
|
|
END IF;
|
|
FOR affected IN
|
|
SELECT DISTINCT owner_id
|
|
FROM (
|
|
SELECT member.user_id AS owner_id
|
|
FROM public.user_channel_member_index AS member
|
|
WHERE member.channel_id = p_parent_id
|
|
AND member.status = 'active'
|
|
AND NOT member.deleted
|
|
AND member.role IN ('creator', 'admin')
|
|
UNION
|
|
SELECT message.saved_peer_id AS owner_id
|
|
FROM public.channel_messages AS message
|
|
WHERE message.channel_id = p_monoforum_id
|
|
AND message.saved_peer_type = 'user'
|
|
AND message.saved_peer_id > 0
|
|
AND NOT message.deleted
|
|
) AS owners
|
|
WHERE owner_id > 0
|
|
ORDER BY owner_id
|
|
LOOP
|
|
PERFORM public.telesrv_bump_channel_active_membership_owner(affected.owner_id);
|
|
END LOOP;
|
|
END;
|
|
$$;
|
|
|
|
CREATE OR REPLACE FUNCTION public.telesrv_notify_monoforum_channel_visibility_read_model()
|
|
RETURNS trigger
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
DECLARE
|
|
old_parent_id bigint := 0;
|
|
old_monoforum_id bigint := 0;
|
|
new_parent_id bigint := 0;
|
|
new_monoforum_id bigint := 0;
|
|
BEGIN
|
|
IF (OLD.broadcast_messages_allowed, OLD.linked_monoforum_id, OLD.deleted, OLD.monoforum)
|
|
IS NOT DISTINCT FROM
|
|
(NEW.broadcast_messages_allowed, NEW.linked_monoforum_id, NEW.deleted, NEW.monoforum)
|
|
THEN
|
|
RETURN NULL;
|
|
END IF;
|
|
|
|
IF OLD.linked_monoforum_id > 0 THEN
|
|
IF OLD.monoforum THEN
|
|
old_parent_id := OLD.linked_monoforum_id;
|
|
old_monoforum_id := OLD.id;
|
|
ELSE
|
|
old_parent_id := OLD.id;
|
|
old_monoforum_id := OLD.linked_monoforum_id;
|
|
END IF;
|
|
END IF;
|
|
IF NEW.linked_monoforum_id > 0 THEN
|
|
IF NEW.monoforum THEN
|
|
new_parent_id := NEW.linked_monoforum_id;
|
|
new_monoforum_id := NEW.id;
|
|
ELSE
|
|
new_parent_id := NEW.id;
|
|
new_monoforum_id := NEW.linked_monoforum_id;
|
|
END IF;
|
|
END IF;
|
|
|
|
IF old_parent_id > 0 THEN
|
|
PERFORM public.telesrv_bump_monoforum_visibility_owners(old_parent_id, old_monoforum_id);
|
|
END IF;
|
|
IF new_parent_id > 0
|
|
AND (new_parent_id, new_monoforum_id)
|
|
IS DISTINCT FROM (old_parent_id, old_monoforum_id)
|
|
THEN
|
|
PERFORM public.telesrv_bump_monoforum_visibility_owners(new_parent_id, new_monoforum_id);
|
|
END IF;
|
|
RETURN NULL;
|
|
END;
|
|
$$;
|
|
|
|
CREATE TRIGGER channels_monoforum_active_membership_changed
|
|
AFTER UPDATE OF broadcast_messages_allowed, linked_monoforum_id, deleted, monoforum
|
|
ON public.channels
|
|
FOR EACH ROW EXECUTE FUNCTION public.telesrv_notify_monoforum_channel_visibility_read_model();
|
|
|
|
-- Existing monoforum owners need a fresh generation before any shared page can
|
|
-- be populated under the expanded dependency contract.
|
|
DO $$
|
|
DECLARE
|
|
linked record;
|
|
BEGIN
|
|
FOR linked IN
|
|
SELECT parent.id AS parent_id, parent.linked_monoforum_id AS monoforum_id
|
|
FROM public.channels AS parent
|
|
WHERE parent.linked_monoforum_id > 0
|
|
LOOP
|
|
PERFORM public.telesrv_bump_monoforum_visibility_owners(
|
|
linked.parent_id, linked.monoforum_id
|
|
);
|
|
END LOOP;
|
|
END;
|
|
$$;
|