story-generator/supabase/migrations/20240326000001_create_essay_system.sql
Lucas Santana 63498e92c6 feat: adiciona política RLS para deleção de redações
- Permite que alunos deletem apenas suas próprias redações
- Mantém consistência com outras políticas RLS existentes
- Adiciona rollback apropriado para a nova política
2025-02-06 21:34:17 -03:00

175 lines
6.9 KiB
PL/PgSQL

-- Criação do sistema de redações (Essays)
-- Tipos de texto (Narrativo, Dissertativo, etc)
CREATE TABLE public.essay_types (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
slug TEXT NOT NULL UNIQUE,
title TEXT NOT NULL,
description TEXT NOT NULL,
icon TEXT NOT NULL,
active BOOLEAN DEFAULT true,
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
);
-- Gêneros textuais (Artigo de opinião, Carta argumentativa, etc)
CREATE TABLE public.essay_genres (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
type_id UUID NOT NULL REFERENCES public.essay_types(id),
slug TEXT NOT NULL UNIQUE,
title TEXT NOT NULL,
description TEXT NOT NULL,
icon TEXT NOT NULL,
requirements JSONB NOT NULL DEFAULT '{}',
active BOOLEAN DEFAULT true,
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
);
-- Redações dos alunos
CREATE TABLE public.student_essays (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
student_id UUID NOT NULL REFERENCES public.students(id),
type_id UUID NOT NULL REFERENCES public.essay_types(id),
genre_id UUID NOT NULL REFERENCES public.essay_genres(id),
title TEXT NOT NULL,
content TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'draft',
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL,
CONSTRAINT status_check CHECK (status IN ('draft', 'submitted', 'analyzed'))
);
-- Análises das redações
CREATE TABLE public.essay_analyses (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
essay_id UUID NOT NULL REFERENCES public.student_essays(id),
overall_score INTEGER NOT NULL CHECK (overall_score >= 0 AND overall_score <= 100),
feedback JSONB NOT NULL DEFAULT '{}',
strengths TEXT[] DEFAULT ARRAY[]::TEXT[],
improvements TEXT[] DEFAULT ARRAY[]::TEXT[],
suggestions TEXT,
criteria_scores JSONB NOT NULL DEFAULT '{}',
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
);
-- Índices para melhor performance
CREATE INDEX idx_student_essays_student_id ON public.student_essays(student_id);
CREATE INDEX idx_student_essays_status ON public.student_essays(status);
CREATE INDEX idx_essay_genres_type_id ON public.essay_genres(type_id);
CREATE INDEX idx_essay_analyses_essay_id ON public.essay_analyses(essay_id);
-- Triggers para updated_at
CREATE OR REPLACE FUNCTION public.handle_updated_at()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = now();
RETURN NEW;
END;
$$ language 'plpgsql';
CREATE TRIGGER essay_types_updated_at
BEFORE UPDATE ON public.essay_types
FOR EACH ROW
EXECUTE PROCEDURE public.handle_updated_at();
CREATE TRIGGER essay_genres_updated_at
BEFORE UPDATE ON public.essay_genres
FOR EACH ROW
EXECUTE PROCEDURE public.handle_updated_at();
CREATE TRIGGER student_essays_updated_at
BEFORE UPDATE ON public.student_essays
FOR EACH ROW
EXECUTE PROCEDURE public.handle_updated_at();
-- Políticas RLS
ALTER TABLE public.essay_types ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.essay_genres ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.student_essays ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.essay_analyses ENABLE ROW LEVEL SECURITY;
-- Políticas para essay_types (visível para todos)
CREATE POLICY "Tipos de redação visíveis para todos"
ON public.essay_types FOR SELECT
USING (active = true);
-- Políticas para essay_genres (visível para todos)
CREATE POLICY "Gêneros textuais visíveis para todos"
ON public.essay_genres FOR SELECT
USING (active = true);
-- Políticas para student_essays
CREATE POLICY "Alunos podem ver suas próprias redações"
ON public.student_essays FOR SELECT
USING (student_id = auth.uid());
CREATE POLICY "Alunos podem criar suas próprias redações"
ON public.student_essays FOR INSERT
WITH CHECK (student_id = auth.uid());
CREATE POLICY "Alunos podem atualizar suas próprias redações"
ON public.student_essays FOR UPDATE
USING (student_id = auth.uid())
WITH CHECK (student_id = auth.uid());
CREATE POLICY "Alunos podem deletar suas próprias redações"
ON public.student_essays FOR DELETE
USING (student_id = auth.uid());
-- Políticas para essay_analyses
CREATE POLICY "Alunos podem ver análises de suas próprias redações"
ON public.essay_analyses FOR SELECT
USING (
essay_id IN (
SELECT id FROM public.student_essays
WHERE student_id = auth.uid()
)
);
-- Função para verificar se uma redação pertence ao aluno
CREATE OR REPLACE FUNCTION public.check_essay_ownership(essay_id UUID)
RETURNS BOOLEAN AS $$
BEGIN
RETURN EXISTS (
SELECT 1
FROM public.student_essays
WHERE id = essay_id
AND student_id = auth.uid()
);
END;
$$ language plpgsql security definer;
-- Comentários nas tabelas
COMMENT ON TABLE public.essay_types IS 'Tipos de texto (Narrativo, Dissertativo, etc)';
COMMENT ON TABLE public.essay_genres IS 'Gêneros textuais relacionados a cada tipo de texto';
COMMENT ON TABLE public.student_essays IS 'Redações escritas pelos alunos';
COMMENT ON TABLE public.essay_analyses IS 'Análises e feedbacks das redações dos alunos';
-- Dados iniciais
INSERT INTO public.essay_types (slug, title, description, icon) VALUES
('narrative', 'Narrativo', 'Textos que contam uma história com personagens, tempo e espaço definidos', '📖'),
('dissertation', 'Dissertativo', 'Textos que apresentam uma análise e discussão de um tema', '📝'),
('descriptive', 'Descritivo', 'Textos que descrevem detalhadamente um objeto, pessoa, lugar ou situação', '🎨');
INSERT INTO public.essay_genres (type_id, slug, title, description, icon, requirements) VALUES
((SELECT id FROM public.essay_types WHERE slug = 'dissertation'),
'opinion-article',
'Artigo de Opinião',
'Texto que apresenta um ponto de vista sobre um tema atual',
'📰',
'{"min_words": 300, "max_words": 600, "required_sections": ["introduction", "development", "conclusion"]}'
),
((SELECT id FROM public.essay_types WHERE slug = 'narrative'),
'short-story',
'Conto',
'História curta com poucos personagens e um único conflito',
'📚',
'{"min_words": 200, "max_words": 1000, "required_elements": ["characters", "setting", "conflict", "resolution"]}'
),
((SELECT id FROM public.essay_types WHERE slug = 'descriptive'),
'character-description',
'Descrição de Personagem',
'Texto que descreve características físicas e psicológicas de um personagem',
'👤',
'{"min_words": 150, "max_words": 400, "required_aspects": ["physical", "psychological", "habits"]}'
);