124 lines
3.9 KiB
SQL
124 lines
3.9 KiB
SQL
-- ============================================================
|
|
-- saas_docs — Documentação dinâmica do sistema
|
|
-- Exibida nas páginas do frontend via botão "Ajuda"
|
|
-- ============================================================
|
|
|
|
-- ------------------------------------------------------------
|
|
-- 1. TABELA
|
|
-- ------------------------------------------------------------
|
|
CREATE TABLE IF NOT EXISTS public.saas_docs (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
titulo text NOT NULL,
|
|
conteudo text NOT NULL DEFAULT '',
|
|
medias jsonb NOT NULL DEFAULT '[]'::jsonb,
|
|
-- formato: [{ "tipo": "imagem"|"video", "url": "..." }, ...]
|
|
|
|
tipo_acesso text NOT NULL DEFAULT 'usuario'
|
|
CHECK (tipo_acesso IN ('usuario', 'admin')),
|
|
-- 'usuario' → todos os autenticados
|
|
-- 'admin' → clinic_admin, tenant_admin, saas_admin
|
|
|
|
pagina_path text NOT NULL,
|
|
-- path da rota do frontend, ex: '/therapist/agenda'
|
|
|
|
pagina_label text,
|
|
-- label amigável (informativo, não usado no match)
|
|
|
|
docs_relacionados uuid[] NOT NULL DEFAULT '{}',
|
|
-- IDs de outros saas_docs exibidos como "Veja também"
|
|
|
|
ativo boolean NOT NULL DEFAULT true,
|
|
ordem int NOT NULL DEFAULT 0,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
-- ------------------------------------------------------------
|
|
-- 2. ÍNDICE
|
|
-- ------------------------------------------------------------
|
|
-- Query principal do frontend: filtra por path + ativo
|
|
CREATE INDEX IF NOT EXISTS saas_docs_path_ativo_idx
|
|
ON public.saas_docs (pagina_path, ativo);
|
|
|
|
-- ------------------------------------------------------------
|
|
-- 3. RLS
|
|
-- ------------------------------------------------------------
|
|
ALTER TABLE public.saas_docs ENABLE ROW LEVEL SECURITY;
|
|
|
|
-- SaaS admin: acesso total (SELECT, INSERT, UPDATE, DELETE)
|
|
-- Verificado via tabela saas_admins
|
|
CREATE POLICY "saas_admin_full_access" ON public.saas_docs
|
|
FOR ALL
|
|
TO authenticated
|
|
USING (
|
|
EXISTS (
|
|
SELECT 1 FROM public.saas_admins
|
|
WHERE saas_admins.user_id = auth.uid()
|
|
)
|
|
)
|
|
WITH CHECK (
|
|
EXISTS (
|
|
SELECT 1 FROM public.saas_admins
|
|
WHERE saas_admins.user_id = auth.uid()
|
|
)
|
|
);
|
|
|
|
-- Admins de clínica: leem todos os docs ativos (usuario + admin)
|
|
CREATE POLICY "clinic_admin_read_all_docs" ON public.saas_docs
|
|
FOR SELECT
|
|
TO authenticated
|
|
USING (
|
|
ativo = true
|
|
AND EXISTS (
|
|
SELECT 1 FROM public.profiles
|
|
WHERE profiles.id = auth.uid()
|
|
AND profiles.role IN ('clinic_admin', 'tenant_admin')
|
|
)
|
|
);
|
|
|
|
-- Demais usuários autenticados: leem apenas docs do tipo 'usuario'
|
|
CREATE POLICY "users_read_usuario_docs" ON public.saas_docs
|
|
FOR SELECT
|
|
TO authenticated
|
|
USING (
|
|
ativo = true
|
|
AND tipo_acesso = 'usuario'
|
|
);
|
|
|
|
-- ------------------------------------------------------------
|
|
-- 4. STORAGE — bucket saas-docs (imagens dos documentos)
|
|
-- ------------------------------------------------------------
|
|
INSERT INTO storage.buckets (id, name, public)
|
|
VALUES ('saas-docs', 'saas-docs', true)
|
|
ON CONFLICT (id) DO NOTHING;
|
|
|
|
-- SaaS admin: pode fazer upload
|
|
CREATE POLICY "saas_admin_storage_upload" ON storage.objects
|
|
FOR INSERT
|
|
TO authenticated
|
|
WITH CHECK (
|
|
bucket_id = 'saas-docs'
|
|
AND EXISTS (
|
|
SELECT 1 FROM public.saas_admins
|
|
WHERE saas_admins.user_id = auth.uid()
|
|
)
|
|
);
|
|
|
|
-- SaaS admin: pode deletar
|
|
CREATE POLICY "saas_admin_storage_delete" ON storage.objects
|
|
FOR DELETE
|
|
TO authenticated
|
|
USING (
|
|
bucket_id = 'saas-docs'
|
|
AND EXISTS (
|
|
SELECT 1 FROM public.saas_admins
|
|
WHERE saas_admins.user_id = auth.uid()
|
|
)
|
|
);
|
|
|
|
-- Leitura pública (bucket é público, mas policy explícita para clareza)
|
|
CREATE POLICY "saas_docs_public_read" ON storage.objects
|
|
FOR SELECT
|
|
TO public
|
|
USING (bucket_id = 'saas-docs');
|