01 - Supabase Configuração
Segue abaixo a configuração incial para um Projeto de Frontend para gerenciar arquivos Markdown online.
SQLs
Tabelas Principais do Projeto
-- Tabela de grupos (ex: Financeiro, Suporte, Dev)
create table if not exists public.app_groups (
id uuid primary key default gen_random_uuid(),
name text not null unique,
slug text not null unique -- ex: 'financeiro', 'suporte'
);
-- Relação usuário ↔ grupo
create table if not exists public.app_group_users (
group_id uuid not null references public.app_groups(id) on delete cascade,
user_id uuid not null references auth.users(id) on delete cascade,
primary key (group_id, user_id)
);
-- Tabela de documentos (metadados do markdown)
create table if not exists public.app_docs (
id uuid primary key default gen_random_uuid(),
slug text not null unique, -- ex: 'financeiro/relatorio-mensal'
title text not null, -- título amigável
bucket text not null default 'docs',
storage_path text not null -- ex: 'financeiro/relatorio-mensal.md'
);
-- Relação grupo ↔ doc (quem pode ver o quê)
create table if not exists public.app_group_docs (
group_id uuid not null references public.app_groups(id) on delete cascade,
doc_id uuid not null references public.app_docs(id) on delete cascade,
primary key (group_id, doc_id)
);
-- Relação grupo x pastas
-- Dica: sempre termine com `/` pra ficar mais claro (`suporte/`).
create table if not exists public.app_group_folders (
id uuid primary key default gen_random_uuid(),
group_id uuid not null references public.app_groups(id) on delete cascade,
folder_prefix text not null -- ex: 'suporte/' ou 'suporte/guias/'
);
Caso precise dropar
-- Relação grupo x pastas
drop table public.app_group_folders;
-- Relação grupo ↔ doc (quem pode ver o quê)
drop table public.app_group_docs;
-- Tabela de documentos (metadados do markdown)
drop table public.app_docs;
-- Relação usuário ↔ grupo
drop table public.app_group_users;
-- Tabela de grupos (ex: Financeiro, Suporte, Dev)
drop table public.app_groups;
RLS
alter table public.app_docs enable row level security;
alter table public.app_group_users enable row level security;
alter table public.app_group_docs enable row level security;
-- para as pastas
alter table public.app_group_folders enable row level security;
create policy "docs_por_grupo" on public.app_docs
for select
using (
-- 1) permissão por doc específico
exists (
select 1
from public.app_group_docs gd
join public.app_group_users gu
on gu.group_id = gd.group_id
where gd.doc_id = app_docs.id
and gu.user_id = auth.uid()
)
OR
-- 2) permissão por pasta (prefixo do slug)
exists (
select 1
from public.app_group_folders gf
join public.app_group_users gu
on gu.group_id = gf.group_id
where gu.user_id = auth.uid()
and app_docs.slug like gf.folder_prefix || '%'
)
);
Cadastrar Alguns grupos, docs e permissões
Ainda no SQL Editor:
insert into public.app_groups (name, slug)
values ('CRMFK', 'crmfk'),
('SESMT', 'sesmt'),
('Desenvolvimento', 'desenvolvimento'),
('Suporte', 'suporte'),
('SESMT-CLIENTE', 'sesmt-cliente'),
('CRMFK-CLIENTE', 'crmfk-cliente')
on conflict (slug) do nothing;
Criar docs (batendo com os arquivos do Storage)
insert into public.app_docs (slug, title, bucket, storage_path)
values
-- sesmt
('sesmt/readme', 'Página Inicial', 'docs', 'SESMT/README.md'),
('sesmt/01-projeto-sesmt', '01 - Projeto SESMT', 'docs', 'SESMT/01 - Projeto SESMT.md'),
('sesmt/02-requisitos-funcionais-e-nao-funcionais', '02 - Requisitos Funcionais e Não Funcionais', 'docs', 'SESMT/02 - Requisitos Funcionais e Não Funcionais.md'),
-- sesmt-cliente
('sesmt-cliente/readme', 'Página Inicial', 'docs', 'SESMT-CLIENTE/README.md'),
('sesmt-cliente/01-projeto-sesmt', '01 - Projeto SESMT', 'docs', 'SESMT-CLIENTE/01 - Projeto SESMT.md'),
('sesmt-cliente/02-requisitos-funcionais-e-nao-funcionais', '02 - Requisitos Funcionais e Não Funcionais', 'docs', 'SESMT-CLIENTE/02 - Requisitos Funcionais e Não Funcionais.md'),
-- crmfk
('crmfk/readme', 'Página Inicial', 'docs', 'CRMFK/README.md'),
('crmfk/checklist-do-projeto', 'Checklist do Projeto', 'docs', 'CRMFK/Checklist do projeto.md'),
-- crmfk-cliente
('crmfk-cliente/readme', 'Página Inicial', 'docs', 'CRMFK-CLIENTE/README.md'),
('crmfk-cliente/checklist-do-projeto', 'Checklist do Projeto', 'docs', 'CRMFK-CLIENTE/Checklist do projeto.md'),
-- desenvolvimento
('desenvolvimento/faq', 'FAQ Desenvolvimento', 'docs', 'Desenvolvimento/faq.md'),
-- suporte
('suporte/faq', 'FAQ Suporte', 'docs', 'Suporte/faq.md')
on conflict (slug) do nothing;
Com isso, qualquer consulta select * from app_docs feita via Supabase Client já vem filtrada para o usuário logado.
💡 Exemplo prático:
app_group_folders.folder_prefix = 'financeiro/'app_docs.slug = 'financeiro/relatorio-mensal'
O like gf.folder_prefix || '%' vira:
app_docs.slug like 'desenvolvimento/' || '%'
-- equivalente a 'financeiro/%'
Como você cadastra a permissão da pasta
Suponha que você já tenha o grupo desenvolvimento em app_groups:
insert into public.app_group_folders (group_id, folder_prefix)
select id, 'desenvolvimento/'
from public.app_groups
where slug = 'desenvolvimento';
Relacionar grupo vs doc
-- SESMT pode ver o README.md
insert into public.app_group_docs (group_id, doc_id)
select g.id, d.id
from app_groups g, app_docs d
where g.slug = 'sesmt'
and d.slug = 'sesmt/readme'
on conflict do nothing;
insert into public.app_group_docs (group_id, doc_id)
select g.id, d.id
from app_groups g, app_docs d
where g.slug = 'sesmt'
and d.slug = 'sesmt/readme'
on conflict do nothing;
-- Dando permissão para o grupo Desenvolvimento ter acesso a tudo
insert into public.app_group_folders (group_id, folder_prefix)
select id, 'Desenvolvimento/'
from public.app_groups
where slug = 'desenvolvimento';
-- Dando permissão para o grupo Suporte ter acesso a tudo
insert into public.app_group_folders (group_id, folder_prefix)
select id, 'Suporte/'
from public.app_groups
where slug = 'suporte';
-- Dando permissão para o grupo SESMT ter acesso a tudo
insert into public.app_group_folders (group_id, folder_prefix)
select id, 'SESMT/'
from public.app_groups
where slug = 'sesmt';
-- Dando permissão para o grupo SESMT-CLIENTE ter acesso a tudo
insert into public.app_group_folders (group_id, folder_prefix)
select id, 'SESMT-CLIENTE/'
from public.app_groups
where slug = 'sesmt-cliente';
-- Dando permissão para o grupo CRMFK ter acesso a tudo
insert into public.app_group_folders (group_id, folder_prefix)
select id, 'CRMFK/'
from public.app_groups
where slug = 'crmfk';
-- Dando permissão para o grupo CRMFK-CLIENTE ter acesso a tudo
insert into public.app_group_folders (group_id, folder_prefix)
select id, 'CRMFK-CLIENTE/'
from public.app_groups
where slug = 'crmfk-cliente';
Dar Privilégios via SQL
Dar acesso à pasta inteira para um grupo
Ex: grupo suporte tem acesso a tudo que comece com suporte/:
insert into public.app_group_folders (group_id, folder_prefix)
select id, 'suporte/'
from public.app_groups
where slug = 'suporte'
on conflict do nothing;
(Opcional) Dar acesso pontual a um doc específico
Ex: doc suporte/faq também pode ser visto pelo grupo financeiro:
insert into public.app_group_docs (group_id, doc_id)
select g.id, d.id
from public.app_groups g, public.app_docs d
where g.slug = 'financeiro'
and d.slug = 'suporte/faq'
on conflict do nothing;
Vincular usuários aos grupos
Aqui você precisa do UUID do usuário em auth.users.
- Vá em Authentication → Users
- Clique no usuário
- Copie o
id(UUID)
-- Exemplo: colocar o usuário no grupo "financeiro"
insert into public.app_group_users (group_id, user_id)
select g.id, '<UUID_DO_USUARIO>'
from public.app_groups g
where g.slug = 'financeiro'
on conflict do nothing;
-- Outro exemplo: mesmo usuário também no grupo "suporte"
insert into public.app_group_users (group_id, user_id)
select g.id, '<UUID_DO_USUARIO>'
from public.app_groups g
where g.slug = 'suporte'
on conflict do nothing;
OBS: Substitua '<UUID_DO_USUARIO>' pelo ID real (por ex: d5d8c1c8-...).