This creates the essential tables for quizzes, results, and user data.
1
Open SQL Editor
In your Supabase Dashboard, click SQL Editor in the left sidebar
Click New query
2
Run the core schema
Copy the contents of backend/database-schema.sql and paste into the SQL Editor:
-- Quiz Generation App Database Schema-- Run this in your Supabase SQL Editor-- Enable UUID extensionCREATE EXTENSION IF NOT EXISTS "uuid-ossp";-- Quizzes tableCREATE TABLE IF NOT EXISTS quizzes ( id UUID DEFAULT uuid_generate_v4() PRIMARY KEY, user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE, source_name TEXT NOT NULL, questions JSONB NOT NULL, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW());-- Quiz results tableCREATE TABLE IF NOT EXISTS quiz_results ( id UUID DEFAULT uuid_generate_v4() PRIMARY KEY, user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE NOT NULL, quiz_id UUID REFERENCES quizzes(id) ON DELETE CASCADE, score INTEGER NOT NULL, total_questions INTEGER NOT NULL, percentage INTEGER NOT NULL, answers JSONB NOT NULL, submitted_at TIMESTAMP WITH TIME ZONE DEFAULT NOW());-- Create indexes for better query performanceCREATE INDEX IF NOT EXISTS idx_quizzes_user_id ON quizzes(user_id);CREATE INDEX IF NOT EXISTS idx_quizzes_created_at ON quizzes(created_at DESC);CREATE INDEX IF NOT EXISTS idx_quiz_results_user_id ON quiz_results(user_id);CREATE INDEX IF NOT EXISTS idx_quiz_results_quiz_id ON quiz_results(quiz_id);CREATE INDEX IF NOT EXISTS idx_quiz_results_submitted_at ON quiz_results(submitted_at DESC);-- Enable Row Level SecurityALTER TABLE quizzes ENABLE ROW LEVEL SECURITY;ALTER TABLE quiz_results ENABLE ROW LEVEL SECURITY;-- Policies for quizzes tableCREATE POLICY "Users can view their own quizzes" ON quizzes FOR SELECT USING (auth.uid() = user_id);CREATE POLICY "Users can create quizzes" ON quizzes FOR INSERT WITH CHECK (auth.uid() = user_id);CREATE POLICY "Users can delete their own quizzes" ON quizzes FOR DELETE USING (auth.uid() = user_id);-- Policies for quiz_results tableCREATE POLICY "Users can view their own results" ON quiz_results FOR SELECT USING (auth.uid() = user_id);CREATE POLICY "Users can create results" ON quiz_results FOR INSERT WITH CHECK (auth.uid() = user_id);CREATE POLICY "Users can delete their own results" ON quiz_results FOR DELETE USING (auth.uid() = user_id);
Click Run or press Ctrl+Enter.You should see: ✅ Success. No rows returned
Copy the contents of backend/database-migration-sharing.sql and run it:
-- Quiz Sharing Feature Migration-- Update quizzes table for sharingALTER TABLE quizzes ADD COLUMN IF NOT EXISTS share_token TEXT UNIQUE, ADD COLUMN IF NOT EXISTS is_shared BOOLEAN DEFAULT false, ADD COLUMN IF NOT EXISTS created_by_username TEXT;CREATE INDEX IF NOT EXISTS idx_quizzes_share_token ON quizzes(share_token) WHERE share_token IS NOT NULL;-- Create quiz_attempts tableCREATE TABLE IF NOT EXISTS quiz_attempts ( id UUID DEFAULT uuid_generate_v4() PRIMARY KEY, quiz_id UUID NOT NULL REFERENCES quizzes(id) ON DELETE CASCADE, user_id UUID REFERENCES auth.users(id) ON DELETE SET NULL, attempt_name TEXT NOT NULL, is_guest BOOLEAN DEFAULT false, score INTEGER NOT NULL, total_questions INTEGER NOT NULL, percentage INTEGER NOT NULL, answers JSONB NOT NULL, completed_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), CONSTRAINT valid_attempt_name CHECK (char_length(trim(attempt_name)) > 0 AND char_length(attempt_name) <= 50), CONSTRAINT valid_score CHECK (score >= 0 AND score <= total_questions), CONSTRAINT valid_percentage CHECK (percentage >= 0 AND percentage <= 100));-- Create indexesCREATE INDEX IF NOT EXISTS idx_quiz_attempts_quiz_id ON quiz_attempts(quiz_id);CREATE INDEX IF NOT EXISTS idx_quiz_attempts_user_id ON quiz_attempts(user_id) WHERE user_id IS NOT NULL;CREATE INDEX IF NOT EXISTS idx_quiz_attempts_completed_at ON quiz_attempts(completed_at DESC);CREATE INDEX IF NOT EXISTS idx_quiz_attempts_is_guest ON quiz_attempts(is_guest);-- Enable RLSALTER TABLE quiz_attempts ENABLE ROW LEVEL SECURITY;-- RLS PoliciesCREATE POLICY "Anyone can create quiz attempts" ON quiz_attempts FOR INSERT WITH CHECK (true);CREATE POLICY "Quiz creators can view attempts on their quizzes" ON quiz_attempts FOR SELECT USING ( EXISTS ( SELECT 1 FROM quizzes WHERE quizzes.id = quiz_attempts.quiz_id AND quizzes.user_id = auth.uid() ) );CREATE POLICY "Users can view their own attempts" ON quiz_attempts FOR SELECT USING (auth.uid() = user_id);-- Update quizzes policy for shared quizzesDROP POLICY IF EXISTS "Users can view their own quizzes" ON quizzes;CREATE POLICY "Users can view their own quizzes or shared quizzes" ON quizzes FOR SELECT USING (auth.uid() = user_id OR is_shared = true);
-- Users can only view their own dataCREATE POLICY "Users can view their own X" ON table_name FOR SELECT USING (auth.uid() = user_id);-- Users can only insert their own dataCREATE POLICY "Users can create X" ON table_name FOR INSERT WITH CHECK (auth.uid() = user_id);-- Users can only delete their own dataCREATE POLICY "Users can delete their own X" ON table_name FOR DELETE USING (auth.uid() = user_id);