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