feat(db): pinned_messages table (≤5 per conv via trigger)

This commit is contained in:
byGalax
2026-05-16 17:39:42 +02:00
parent 5ace6735d8
commit 745b8cd69d
@@ -0,0 +1,61 @@
-- Pinned messages: each conversation gets up to 5 anchored references to its
-- own messages. Any accepted member can pin/unpin. RLS mirrors conversation
-- membership; the cap is enforced by a BEFORE INSERT trigger because partial
-- unique indexes can't express "at most N rows per group".
create table if not exists public.pinned_messages (
conversation_id uuid not null references public.conversations(id) on delete cascade,
message_id uuid not null references public.messages(id) on delete cascade,
pinned_by uuid not null references auth.users(id) on delete set null,
pinned_at timestamptz not null default now(),
primary key (conversation_id, message_id)
);
create index if not exists pinned_messages_conv_idx
on public.pinned_messages(conversation_id, pinned_at desc);
alter table public.pinned_messages enable row level security;
drop policy if exists pinned_messages_select_member on public.pinned_messages;
create policy pinned_messages_select_member
on public.pinned_messages
for select
to authenticated
using (public.is_conversation_member(conversation_id));
drop policy if exists pinned_messages_insert_member on public.pinned_messages;
create policy pinned_messages_insert_member
on public.pinned_messages
for insert
to authenticated
with check (
public.is_conversation_member(conversation_id)
and pinned_by = auth.uid()
);
drop policy if exists pinned_messages_delete_member on public.pinned_messages;
create policy pinned_messages_delete_member
on public.pinned_messages
for delete
to authenticated
using (public.is_conversation_member(conversation_id));
-- Enforce the per-conversation cap. Trigger-based so cross-row counts work.
create or replace function public.pinned_messages_enforce_cap()
returns trigger
language plpgsql
as $$
begin
if (select count(*) from public.pinned_messages where conversation_id = new.conversation_id) >= 5 then
raise exception 'pinned_messages_cap_reached: at most 5 pins per conversation';
end if;
return new;
end;
$$;
drop trigger if exists pinned_messages_cap on public.pinned_messages;
create trigger pinned_messages_cap
before insert on public.pinned_messages
for each row execute function public.pinned_messages_enforce_cap();
alter publication supabase_realtime add table public.pinned_messages;