62 lines
2.3 KiB
PL/PgSQL
62 lines
2.3 KiB
PL/PgSQL
-- 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;
|