161 lines
7.5 KiB
PL/PgSQL
161 lines
7.5 KiB
PL/PgSQL
-- ============================================================================
|
||
-- 📊 TASK MANAGER - Supabase Database Schema com Row Level Security (RLS)
|
||
-- ============================================================================
|
||
-- Este script cria a tabela 'tasks' e implementa RLS para garantir que
|
||
-- cada usuário acesse apenas suas próprias tarefas.
|
||
--
|
||
-- Executar em: Supabase SQL Editor
|
||
-- Ambiente: Development ou Production (conforme necessário)
|
||
-- ============================================================================
|
||
|
||
-- ============================================================================
|
||
-- 1️⃣ CRIAR TABELA TASKS
|
||
-- ============================================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS public.tasks (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
||
-- 🔗 Referência ao usuário
|
||
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
|
||
|
||
-- 📝 Dados da tarefa
|
||
title VARCHAR(255) NOT NULL,
|
||
description TEXT,
|
||
completed BOOLEAN DEFAULT FALSE,
|
||
|
||
-- 📅 Datas
|
||
due_date TIMESTAMP WITH TIME ZONE,
|
||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||
|
||
-- 🏷️ Categorização e prioridade
|
||
category VARCHAR(50),
|
||
priority VARCHAR(20) DEFAULT 'medium' CHECK (priority IN ('low', 'medium', 'high')),
|
||
|
||
-- 🔍 Índices para performance
|
||
CONSTRAINT title_not_empty CHECK (char_length(title) >= 3)
|
||
);
|
||
|
||
-- Criar índices para melhor performance
|
||
CREATE INDEX IF NOT EXISTS idx_tasks_user_id ON public.tasks(user_id);
|
||
CREATE INDEX IF NOT EXISTS idx_tasks_completed ON public.tasks(completed);
|
||
CREATE INDEX IF NOT EXISTS idx_tasks_created_at ON public.tasks(created_at DESC);
|
||
CREATE INDEX IF NOT EXISTS idx_tasks_due_date ON public.tasks(due_date);
|
||
CREATE INDEX IF NOT EXISTS idx_tasks_user_completed ON public.tasks(user_id, completed);
|
||
|
||
-- ============================================================================
|
||
-- 2️⃣ HABILITAR RLS (Row Level Security)
|
||
-- ============================================================================
|
||
|
||
-- Ativar RLS na tabela
|
||
ALTER TABLE public.tasks ENABLE ROW LEVEL SECURITY;
|
||
|
||
-- ============================================================================
|
||
-- 3️⃣ CRIAR POLÍTICAS DE SEGURANÇA
|
||
-- ============================================================================
|
||
|
||
-- ✅ Política 1: Usuários podem ver apenas suas próprias tarefas (SELECT)
|
||
CREATE POLICY "Users can view their own tasks"
|
||
ON public.tasks
|
||
FOR SELECT
|
||
USING (auth.uid() = user_id);
|
||
|
||
-- ✅ Política 2: Usuários podem inserir tarefas apenas para si mesmos (INSERT)
|
||
CREATE POLICY "Users can create their own tasks"
|
||
ON public.tasks
|
||
FOR INSERT
|
||
WITH CHECK (auth.uid() = user_id);
|
||
|
||
-- ✅ Política 3: Usuários podem atualizar apenas suas próprias tarefas (UPDATE)
|
||
CREATE POLICY "Users can update their own tasks"
|
||
ON public.tasks
|
||
FOR UPDATE
|
||
USING (auth.uid() = user_id)
|
||
WITH CHECK (auth.uid() = user_id);
|
||
|
||
-- ✅ Política 4: Usuários podem deletar apenas suas próprias tarefas (DELETE)
|
||
CREATE POLICY "Users can delete their own tasks"
|
||
ON public.tasks
|
||
FOR DELETE
|
||
USING (auth.uid() = user_id);
|
||
|
||
-- ============================================================================
|
||
-- 4️⃣ CRIAR FUNÇÃO PARA ATUALIZAR updated_at (TRIGGER)
|
||
-- ============================================================================
|
||
|
||
-- Criar função que atualiza o campo updated_at automaticamente
|
||
CREATE OR REPLACE FUNCTION public.update_tasks_updated_at()
|
||
RETURNS TRIGGER AS $$
|
||
BEGIN
|
||
NEW.updated_at = CURRENT_TIMESTAMP;
|
||
RETURN NEW;
|
||
END;
|
||
$$ LANGUAGE plpgsql;
|
||
|
||
-- Criar trigger que dispara a função antes de atualizar
|
||
DROP TRIGGER IF EXISTS trigger_update_tasks_updated_at ON public.tasks;
|
||
CREATE TRIGGER trigger_update_tasks_updated_at
|
||
BEFORE UPDATE ON public.tasks
|
||
FOR EACH ROW
|
||
EXECUTE FUNCTION public.update_tasks_updated_at();
|
||
|
||
-- ============================================================================
|
||
-- 5️⃣ CRIAR TIPOS (TypeScript Integration)
|
||
-- ============================================================================
|
||
|
||
-- Comentários para documentação e integração com TypeScript
|
||
COMMENT ON TABLE public.tasks IS 'Tabela de tarefas com Row Level Security habilitado';
|
||
COMMENT ON COLUMN public.tasks.id IS 'UUID único da tarefa (auto-gerado)';
|
||
COMMENT ON COLUMN public.tasks.user_id IS 'UUID do usuário proprietário da tarefa';
|
||
COMMENT ON COLUMN public.tasks.title IS 'Título da tarefa (obrigatório, 3-255 caracteres)';
|
||
COMMENT ON COLUMN public.tasks.description IS 'Descrição detalhada (opcional, até 2000 caracteres)';
|
||
COMMENT ON COLUMN public.tasks.completed IS 'Flag indicando se tarefa está concluída';
|
||
COMMENT ON COLUMN public.tasks.due_date IS 'Data/hora de vencimento da tarefa';
|
||
COMMENT ON COLUMN public.tasks.category IS 'Categoria para organização (ex: trabalho, pessoal)';
|
||
COMMENT ON COLUMN public.tasks.priority IS 'Prioridade: low, medium, high';
|
||
COMMENT ON COLUMN public.tasks.created_at IS 'Timestamp de criação (auto-preenchido)';
|
||
COMMENT ON COLUMN public.tasks.updated_at IS 'Timestamp da última atualização (auto-preenchido)';
|
||
|
||
-- ============================================================================
|
||
-- 6️⃣ VERIFICAÇÃO - QUERYS PARA TESTAR
|
||
-- ============================================================================
|
||
|
||
-- 🧪 TESTE 1: Verificar se RLS está ativado
|
||
-- SELECT schemaname, tablename, rowsecurity
|
||
-- FROM pg_tables
|
||
-- WHERE tablename = 'tasks';
|
||
-- Esperado: rowsecurity = true
|
||
|
||
-- 🧪 TESTE 2: Listar todas as políticas
|
||
-- SELECT tablename, policyname, qual, with_check
|
||
-- FROM pg_policies
|
||
-- WHERE tablename = 'tasks';
|
||
-- Esperado: 4 políticas
|
||
|
||
-- 🧪 TESTE 3: Testar isolamento (executar como usuário autenticado)
|
||
-- SELECT * FROM tasks; -- Mostra apenas tarefas do usuário atual
|
||
-- INSERT INTO tasks (user_id, title) VALUES (auth.uid(), 'Nova tarefa');
|
||
-- UPDATE tasks SET completed = true WHERE id = '...';
|
||
-- DELETE FROM tasks WHERE id = '...';
|
||
|
||
-- ============================================================================
|
||
-- 🎯 RESUMO DAS POLÍTICAS RLS
|
||
-- ============================================================================
|
||
-- ┌─────────┬────────────────────────────────────────────┐
|
||
-- │ AÇÃO │ PERMISSÃO │
|
||
-- ├─────────┼────────────────────────────────────────────┤
|
||
-- │ SELECT │ ✅ Ver tarefas próprias │
|
||
-- │ INSERT │ ✅ Criar tarefas com user_id próprio │
|
||
-- │ UPDATE │ ✅ Atualizar apenas tarefas próprias │
|
||
-- │ DELETE │ ✅ Deletar apenas tarefas próprias │
|
||
-- │ ADMIN │ ✅ Admin pode sem RLS (role: service_role)│
|
||
-- └─────────┴────────────────────────────────────────────┘
|
||
|
||
-- ============================================================================
|
||
-- 📚 REFERÊNCIAS
|
||
-- ============================================================================
|
||
-- - Supabase RLS: https://supabase.com/docs/guides/auth/row-level-security
|
||
-- - PostgreSQL Triggers: https://www.postgresql.org/docs/current/sql-createtrigger.html
|
||
-- - JWT Claims: https://supabase.com/docs/guides/auth/jwts
|
||
-- - Índices PostgreSQL: https://www.postgresql.org/docs/current/sql-createindex.html
|