Initial commit of akmon project
This commit is contained in:
123
doc_chat/alter_policies.sql
Normal file
123
doc_chat/alter_policies.sql
Normal file
@@ -0,0 +1,123 @@
|
||||
begin;
|
||||
|
||||
-- Allow chat messages to store new audio payloads.
|
||||
alter table chat_messages
|
||||
drop constraint if exists chat_messages_content_type_check;
|
||||
|
||||
alter table chat_messages
|
||||
add constraint chat_messages_content_type_check
|
||||
check (content_type in ('text', 'markdown', 'json', 'image', 'file', 'audio'));
|
||||
|
||||
-- Track the ingress source for every message.
|
||||
alter table chat_messages
|
||||
add column if not exists ingress_type text not null default 'manual'
|
||||
check (ingress_type in ('manual', 'bluetooth', 'school_gateway', 'system'));
|
||||
|
||||
comment on column chat_messages.ingress_type is
|
||||
'Source of message ingestion: manual app entry, bluetooth wearable sync, school gateway, or system automation.';
|
||||
|
||||
-- Refresh insert policies so authenticated users and gateways follow the new ingress contract.
|
||||
drop policy if exists chat_messages_insert on chat_messages;
|
||||
drop policy if exists chat_messages_insert_self on chat_messages;
|
||||
drop policy if exists chat_messages_insert_gateway on chat_messages;
|
||||
|
||||
create policy chat_messages_insert_self on chat_messages
|
||||
for insert
|
||||
to authenticated
|
||||
with check (
|
||||
chat_messages.sender_id = auth.uid()
|
||||
and chat_messages.ingress_type in ('manual', 'bluetooth')
|
||||
and exists (
|
||||
select 1
|
||||
from chat_participants p
|
||||
where p.conversation_id = chat_messages.conversation_id
|
||||
and p.user_id = auth.uid()
|
||||
)
|
||||
);
|
||||
|
||||
create policy chat_messages_insert_gateway on chat_messages
|
||||
for insert
|
||||
to authenticated
|
||||
with check (
|
||||
coalesce((current_setting('request.jwt.claims', true)::jsonb ->> 'app_role'), '') in ('gateway_ingress', 'system_bot')
|
||||
and chat_messages.ingress_type in ('school_gateway', 'system')
|
||||
);
|
||||
|
||||
-- Fix chat participant policies to avoid recursive RLS evaluation.
|
||||
create or replace function public.chat_user_is_manager(p_conversation_id uuid, p_user_id uuid)
|
||||
returns boolean
|
||||
language sql
|
||||
security definer
|
||||
set search_path = public
|
||||
as $$
|
||||
select exists (
|
||||
select 1
|
||||
from chat_participants
|
||||
where conversation_id = p_conversation_id
|
||||
and user_id = p_user_id
|
||||
and role in ('owner', 'admin')
|
||||
);
|
||||
$$;
|
||||
|
||||
revoke all on function public.chat_user_is_manager(uuid, uuid) from public;
|
||||
grant execute on function public.chat_user_is_manager(uuid, uuid) to authenticated;
|
||||
|
||||
drop policy if exists chat_conversations_update on chat_conversations;
|
||||
create policy chat_conversations_update on chat_conversations for update to authenticated using (
|
||||
public.chat_user_is_manager(chat_conversations.id, auth.uid())
|
||||
) with check (
|
||||
public.chat_user_is_manager(chat_conversations.id, auth.uid())
|
||||
);
|
||||
|
||||
drop policy if exists chat_participants_select on chat_participants;
|
||||
drop policy if exists chat_participants_update on chat_participants;
|
||||
drop policy if exists chat_participants_delete on chat_participants;
|
||||
drop policy if exists chat_participants_insert on chat_participants;
|
||||
|
||||
create policy chat_participants_select on chat_participants for select to authenticated using (
|
||||
user_id = auth.uid() or public.chat_user_is_manager(chat_participants.conversation_id, auth.uid())
|
||||
);
|
||||
|
||||
create policy chat_participants_update on chat_participants for update to authenticated using (
|
||||
user_id = auth.uid() or public.chat_user_is_manager(chat_participants.conversation_id, auth.uid())
|
||||
) with check (
|
||||
user_id = auth.uid() or public.chat_user_is_manager(chat_participants.conversation_id, auth.uid())
|
||||
);
|
||||
|
||||
create policy chat_participants_delete on chat_participants for delete to authenticated using (
|
||||
user_id = auth.uid() or public.chat_user_is_manager(chat_participants.conversation_id, auth.uid())
|
||||
);
|
||||
|
||||
create policy chat_participants_insert on chat_participants for insert to authenticated with check (
|
||||
user_id = auth.uid() or public.chat_user_is_manager(chat_participants.conversation_id, auth.uid())
|
||||
);
|
||||
|
||||
-- Ensure downlink queue has optional metadata payload for automation hints.
|
||||
alter table chat_mqtt_downlinks
|
||||
add column if not exists metadata jsonb;
|
||||
|
||||
commit;
|
||||
drop policy if exists chat_participants_all on chat_participants;
|
||||
|
||||
drop policy if exists chat_participants_select on chat_participants;
|
||||
drop policy if exists chat_participants_update on chat_participants;
|
||||
drop policy if exists chat_participants_delete on chat_participants;
|
||||
drop policy if exists chat_participants_insert on chat_participants;
|
||||
|
||||
create policy chat_participants_select on chat_participants for select to authenticated using (
|
||||
user_id = auth.uid() or public.chat_user_is_manager(chat_participants.conversation_id, auth.uid())
|
||||
);
|
||||
|
||||
create policy chat_participants_update on chat_participants for update to authenticated using (
|
||||
user_id = auth.uid() or public.chat_user_is_manager(chat_participants.conversation_id, auth.uid())
|
||||
) with check (
|
||||
user_id = auth.uid() or public.chat_user_is_manager(chat_participants.conversation_id, auth.uid())
|
||||
);
|
||||
|
||||
create policy chat_participants_delete on chat_participants for delete to authenticated using (
|
||||
user_id = auth.uid() or public.chat_user_is_manager(chat_participants.conversation_id, auth.uid())
|
||||
);
|
||||
|
||||
create policy chat_participants_insert on chat_participants for insert to authenticated with check (
|
||||
user_id = auth.uid() or public.chat_user_is_manager(chat_participants.conversation_id, auth.uid())
|
||||
);
|
||||
Reference in New Issue
Block a user