| |
|
|
| CREATE EXTENSION IF NOT EXISTS pg_trgm; |
|
|
| CREATE TABLE IF NOT EXISTS public.fipi_tasks ( |
| id BIGSERIAL PRIMARY KEY, |
| title TEXT NOT NULL, |
| content TEXT NOT NULL, |
| source_url TEXT UNIQUE NOT NULL, |
| task_type TEXT DEFAULT 'other', |
| images TEXT[] DEFAULT '{}', |
| variants TEXT[] DEFAULT '{}', |
| rubert_analysis JSONB DEFAULT '{}', |
| scraped_at TIMESTAMPTZ DEFAULT NOW(), |
| created_at TIMESTAMPTZ DEFAULT NOW(), |
| updated_at TIMESTAMPTZ DEFAULT NOW() |
| ); |
|
|
| CREATE INDEX IF NOT EXISTS idx_fipi_tasks_task_type ON public.fipi_tasks(task_type); |
| CREATE INDEX IF NOT EXISTS idx_fipi_tasks_scraped_at ON public.fipi_tasks(scraped_at DESC); |
| CREATE INDEX IF NOT EXISTS idx_fipi_tasks_source_url ON public.fipi_tasks(source_url); |
| CREATE INDEX IF NOT EXISTS idx_fipi_tasks_title ON public.fipi_tasks USING gin(title gin_trgm_ops); |
| CREATE INDEX IF NOT EXISTS idx_fipi_tasks_content ON public.fipi_tasks USING gin(content gin_trgm_ops); |
|
|
| ALTER TABLE public.fipi_tasks ENABLE ROW LEVEL SECURITY; |
|
|
| DROP POLICY IF EXISTS "Public can view all tasks" ON public.fipi_tasks; |
| DROP POLICY IF EXISTS "Service key can insert tasks" ON public.fipi_tasks; |
| DROP POLICY IF EXISTS "Service key can update tasks" ON public.fipi_tasks; |
| DROP POLICY IF EXISTS "Service key can delete tasks" ON public.fipi_tasks; |
|
|
| CREATE POLICY "Public can view all tasks" |
| ON public.fipi_tasks |
| FOR SELECT |
| USING (true); |
|
|
| CREATE POLICY "Service key can insert tasks" |
| ON public.fipi_tasks |
| FOR INSERT |
| WITH CHECK (true); |
|
|
| CREATE POLICY "Service key can update tasks" |
| ON public.fipi_tasks |
| FOR UPDATE |
| USING (true); |
|
|
| CREATE POLICY "Service key can delete tasks" |
| ON public.fipi_tasks |
| FOR DELETE |
| USING (true); |
|
|
| CREATE OR REPLACE FUNCTION public.update_updated_at_column() |
| RETURNS TRIGGER AS $$ |
| BEGIN |
| NEW.updated_at = NOW(); |
| RETURN NEW; |
| END; |
| $$ LANGUAGE plpgsql; |
|
|
| DROP TRIGGER IF EXISTS update_fipi_tasks_updated_at ON public.fipi_tasks; |
| CREATE TRIGGER update_fipi_tasks_updated_at |
| BEFORE UPDATE ON public.fipi_tasks |
| FOR EACH ROW |
| EXECUTE FUNCTION public.update_updated_at_column(); |
|
|
| CREATE OR REPLACE VIEW public.fipi_tasks_stats AS |
| SELECT |
| COUNT(*) AS total_tasks, |
| COUNT(*) FILTER (WHERE task_type = 'writing') AS writing_tasks, |
| COUNT(*) FILTER (WHERE task_type = 'test') AS test_tasks, |
| COUNT(*) FILTER (WHERE task_type = 'listening') AS listening_tasks, |
| COUNT(*) FILTER (WHERE task_type = 'reading') AS reading_tasks, |
| COUNT(*) FILTER (WHERE task_type = 'other') AS other_tasks, |
| MAX(scraped_at) AS last_scrape |
| FROM public.fipi_tasks; |
|
|
| CREATE TABLE IF NOT EXISTS public.task_attempts ( |
| id BIGSERIAL PRIMARY KEY, |
| created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL, |
| user_id UUID REFERENCES auth.users NOT NULL, |
| task_id BIGINT REFERENCES public.fipi_tasks(id) ON DELETE CASCADE NOT NULL, |
| submitted_answer TEXT NOT NULL, |
| is_correct BOOLEAN NOT NULL, |
| check_status TEXT NOT NULL DEFAULT 'not_checked' |
| ); |
|
|
| ALTER TABLE public.task_attempts ENABLE ROW LEVEL SECURITY; |
|
|
| DROP POLICY IF EXISTS "Users can insert their own task attempts" ON public.task_attempts; |
| DROP POLICY IF EXISTS "Users can view their own task attempts" ON public.task_attempts; |
| DROP POLICY IF EXISTS "Users can update their own task attempts" ON public.task_attempts; |
| DROP POLICY IF EXISTS "Users can delete their own task attempts" ON public.task_attempts; |
|
|
| CREATE POLICY "Users can insert their own task attempts" |
| ON public.task_attempts |
| FOR INSERT |
| WITH CHECK (auth.uid() = user_id); |
|
|
| CREATE POLICY "Users can view their own task attempts" |
| ON public.task_attempts |
| FOR SELECT |
| USING (auth.uid() = user_id); |
|
|
| CREATE POLICY "Users can update their own task attempts" |
| ON public.task_attempts |
| FOR UPDATE |
| USING (auth.uid() = user_id) |
| WITH CHECK (auth.uid() = user_id); |
|
|
| CREATE POLICY "Users can delete their own task attempts" |
| ON public.task_attempts |
| FOR DELETE |
| USING (auth.uid() = user_id); |
|
|
| CREATE INDEX IF NOT EXISTS idx_task_attempts_user_created_at ON public.task_attempts(user_id, created_at DESC); |
| CREATE INDEX IF NOT EXISTS idx_task_attempts_task_id ON public.task_attempts(task_id); |
|
|