-- LightRAG namespace → workspace/user 访问控制函数
create or replace function public.lightrag_namespace_is_accessible(namespace text)
returns boolean
language plpgsql
security definer
set search_path = public
as $$
declare
  target_workspace uuid;
  target_user uuid;
begin
  target_user := auth.uid();
  if namespace is null or target_user is null then
    return false;
  end if;

  if left(namespace, 5) = 'user_' then
    begin
      return target_user = substring(namespace from 6 for 36)::uuid;
    exception
      when others then
        return false;
    end;
  elsif left(namespace, 10) = 'workspace_' then
    begin
      target_workspace := substring(namespace from 11 for 36)::uuid;
    exception
      when others then
        return false;
    end;

    return exists (
      select 1
      from public.workspace_members wm
      where wm.workspace_id = target_workspace
        and wm.user_id = target_user
    );
  end if;

  return false;
end;
$$;

comment on function public.lightrag_namespace_is_accessible(text)
is '返回 true 表示当前登录用户对指定 LightRAG namespace 有访问权';

grant execute on function public.lightrag_namespace_is_accessible(text)
to authenticated, anon, service_role;

-- LightRAG 相关表启用 RLS 并添加策略
alter table public.lightrag_doc_full enable row level security;
alter table public.lightrag_doc_full force row level security;

create policy lightrag_doc_full_service_role_all
on public.lightrag_doc_full
using (auth.role() = 'service_role')
with check (auth.role() = 'service_role');

create policy lightrag_doc_full_workspace_read
on public.lightrag_doc_full
for select using (public.lightrag_namespace_is_accessible(workspace));

alter table public.lightrag_doc_chunks enable row level security;
alter table public.lightrag_doc_chunks force row level security;

create policy lightrag_doc_chunks_service_role_all
on public.lightrag_doc_chunks
using (auth.role() = 'service_role')
with check (auth.role() = 'service_role');

create policy lightrag_doc_chunks_workspace_read
on public.lightrag_doc_chunks
for select using (public.lightrag_namespace_is_accessible(workspace));

alter table public.lightrag_doc_status enable row level security;
alter table public.lightrag_doc_status force row level security;

create policy lightrag_doc_status_service_role_all
on public.lightrag_doc_status
using (auth.role() = 'service_role')
with check (auth.role() = 'service_role');

create policy lightrag_doc_status_workspace_read
on public.lightrag_doc_status
for select using (public.lightrag_namespace_is_accessible(workspace));

alter table public.lightrag_entity_chunks enable row level security;
alter table public.lightrag_entity_chunks force row level security;

create policy lightrag_entity_chunks_service_role_all
on public.lightrag_entity_chunks
using (auth.role() = 'service_role')
with check (auth.role() = 'service_role');

create policy lightrag_entity_chunks_workspace_read
on public.lightrag_entity_chunks
for select using (public.lightrag_namespace_is_accessible(workspace));

alter table public.lightrag_full_entities enable row level security;
alter table public.lightrag_full_entities force row level security;

create policy lightrag_full_entities_service_role_all
on public.lightrag_full_entities
using (auth.role() = 'service_role')
with check (auth.role() = 'service_role');

create policy lightrag_full_entities_workspace_read
on public.lightrag_full_entities
for select using (public.lightrag_namespace_is_accessible(workspace));

alter table public.lightrag_full_relations enable row level security;
alter table public.lightrag_full_relations force row level security;

create policy lightrag_full_relations_service_role_all
on public.lightrag_full_relations
using (auth.role() = 'service_role')
with check (auth.role() = 'service_role');

create policy lightrag_full_relations_workspace_read
on public.lightrag_full_relations
for select using (public.lightrag_namespace_is_accessible(workspace));

alter table public.lightrag_llm_cache enable row level security;
alter table public.lightrag_llm_cache force row level security;

create policy lightrag_llm_cache_service_role_all
on public.lightrag_llm_cache
using (auth.role() = 'service_role')
with check (auth.role() = 'service_role');

create policy lightrag_llm_cache_workspace_read
on public.lightrag_llm_cache
for select using (public.lightrag_namespace_is_accessible(workspace));

alter table public.lightrag_relation_chunks enable row level security;
alter table public.lightrag_relation_chunks force row level security;

create policy lightrag_relation_chunks_service_role_all
on public.lightrag_relation_chunks
using (auth.role() = 'service_role')
with check (auth.role() = 'service_role');

create policy lightrag_relation_chunks_workspace_read
on public.lightrag_relation_chunks
for select using (public.lightrag_namespace_is_accessible(workspace));

alter table public.lightrag_vdb_chunks enable row level security;
alter table public.lightrag_vdb_chunks force row level security;

create policy lightrag_vdb_chunks_service_role_all
on public.lightrag_vdb_chunks
using (auth.role() = 'service_role')
with check (auth.role() = 'service_role');

create policy lightrag_vdb_chunks_workspace_read
on public.lightrag_vdb_chunks
for select using (public.lightrag_namespace_is_accessible(workspace));

alter table public.lightrag_vdb_entity enable row level security;
alter table public.lightrag_vdb_entity force row level security;

create policy lightrag_vdb_entity_service_role_all
on public.lightrag_vdb_entity
using (auth.role() = 'service_role')
with check (auth.role() = 'service_role');

create policy lightrag_vdb_entity_workspace_read
on public.lightrag_vdb_entity
for select using (public.lightrag_namespace_is_accessible(workspace));

alter table public.lightrag_vdb_relation enable row level security;
alter table public.lightrag_vdb_relation force row level security;

create policy lightrag_vdb_relation_service_role_all
on public.lightrag_vdb_relation
using (auth.role() = 'service_role')
with check (auth.role() = 'service_role');

create policy lightrag_vdb_relation_workspace_read
on public.lightrag_vdb_relation
for select using (public.lightrag_namespace_is_accessible(workspace));
