feat(db): pinned_messages table (≤5 per conv via trigger)
This commit is contained in:
@@ -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;
|
||||
Reference in New Issue
Block a user