-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathsupabase_schema.sql
More file actions
146 lines (131 loc) · 5.88 KB
/
supabase_schema.sql
File metadata and controls
146 lines (131 loc) · 5.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
-- Run this script in your Supabase SQL Editor
-- 1. Create Tables
CREATE TABLE public.boards (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
title TEXT NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
);
CREATE TABLE public.profiles (
id UUID REFERENCES auth.users(id) ON DELETE CASCADE PRIMARY KEY,
name TEXT NOT NULL,
email TEXT NOT NULL,
role TEXT CHECK (role IN ('admin', 'member')) DEFAULT 'member',
avatar_url TEXT
);
CREATE TABLE public.tasks (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
title TEXT NOT NULL,
description TEXT,
status TEXT CHECK (status IN ('todo', 'in_progress', 'review', 'done')) DEFAULT 'todo',
priority TEXT CHECK (priority IN ('low', 'medium', 'high', 'blocker')) DEFAULT 'medium',
due_date TIMESTAMP WITH TIME ZONE,
assignee_id UUID REFERENCES public.profiles(id) ON DELETE SET NULL,
created_by UUID REFERENCES public.profiles(id) ON DELETE SET NULL,
board_id UUID REFERENCES public.boards(id) ON DELETE CASCADE NOT NULL,
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
);
CREATE TABLE public.subtasks (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
task_id UUID REFERENCES public.tasks(id) ON DELETE CASCADE NOT NULL,
title TEXT NOT NULL,
completed BOOLEAN DEFAULT false,
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
);
CREATE TABLE public.task_comments (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
task_id UUID REFERENCES public.tasks(id) ON DELETE CASCADE NOT NULL,
author_id UUID REFERENCES public.profiles(id) ON DELETE SET NULL, -- Can be null for AI
is_ai BOOLEAN DEFAULT false,
content TEXT NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
);
CREATE TABLE public.task_history (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
task_id UUID REFERENCES public.tasks(id) ON DELETE CASCADE NOT NULL,
actor_id UUID REFERENCES public.profiles(id) ON DELETE SET NULL, -- Null if AI
action TEXT NOT NULL,
changes JSONB,
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
);
-- 2. Automatically update tasks updated_at
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = now();
RETURN NEW;
END;
$$ language 'plpgsql';
CREATE TRIGGER update_tasks_updated_at
BEFORE UPDATE ON public.tasks
FOR EACH ROW
EXECUTE PROCEDURE update_updated_at_column();
-- 3. Row Level Security Setup
ALTER TABLE public.boards ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.profiles ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.tasks ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.subtasks ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.task_comments ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.task_history ENABLE ROW LEVEL SECURITY;
-- Disable RLS constraints for simplicity in prototype, but keep it on
-- To ensure all authenticated users can do anything
CREATE POLICY "Allow authenticated full access on boards" ON public.boards FOR ALL USING (auth.role() = 'authenticated');
CREATE POLICY "Allow authenticated full access on profiles" ON public.profiles FOR ALL USING (auth.role() = 'authenticated');
CREATE POLICY "Allow authenticated full access on tasks" ON public.tasks FOR ALL USING (auth.role() = 'authenticated');
CREATE POLICY "Allow authenticated full access on subtasks" ON public.subtasks FOR ALL USING (auth.role() = 'authenticated');
CREATE POLICY "Allow authenticated full access on task_comments" ON public.task_comments FOR ALL USING (auth.role() = 'authenticated');
CREATE POLICY "Allow authenticated full access on task_history" ON public.task_history FOR ALL USING (auth.role() = 'authenticated');
-- 4. Auto-create profile on signup
CREATE OR REPLACE FUNCTION public.handle_new_user()
RETURNS trigger AS $$
BEGIN
INSERT INTO public.profiles (id, name, email, role, avatar_url)
VALUES (
new.id,
coalesce(new.raw_user_meta_data->>'name', split_part(new.email, '@', 1)),
new.email,
coalesce(new.raw_user_meta_data->>'role', 'member'),
coalesce(new.raw_user_meta_data->>'avatar_url', '')
);
RETURN new;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
CREATE OR REPLACE TRIGGER on_auth_user_created
AFTER INSERT ON auth.users
FOR EACH ROW EXECUTE PROCEDURE public.handle_new_user();
-- 5. History Tracker Trigger
CREATE OR REPLACE FUNCTION public.log_task_history()
RETURNS trigger AS $$
DECLARE
v_action TEXT;
v_changes JSONB;
BEGIN
IF TG_OP = 'INSERT' THEN
v_action := 'Task created';
v_changes := json_build_object('title', NEW.title, 'status', NEW.status);
INSERT INTO task_history(task_id, actor_id, action, changes)
VALUES (NEW.id, auth.uid(), v_action, v_changes);
RETURN NEW;
ELSIF TG_OP = 'UPDATE' THEN
IF OLD.status IS DISTINCT FROM NEW.status THEN
v_action := 'Status updated';
v_changes := json_build_object('old', OLD.status, 'new', NEW.status);
INSERT INTO task_history(task_id, actor_id, action, changes)
VALUES (NEW.id, auth.uid(), v_action, v_changes);
END IF;
IF OLD.assignee_id IS DISTINCT FROM NEW.assignee_id THEN
v_action := 'Reassigned';
v_changes := json_build_object('old', OLD.assignee_id, 'new', NEW.assignee_id);
INSERT INTO task_history(task_id, actor_id, action, changes)
VALUES (NEW.id, auth.uid(), v_action, v_changes);
END IF;
RETURN NEW;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
CREATE TRIGGER task_history_trigger
AFTER INSERT OR UPDATE ON public.tasks
FOR EACH ROW EXECUTE PROCEDURE public.log_task_history();
-- 6. Add Default dummy Board
INSERT INTO public.boards (id, title) VALUES ('11111111-1111-1111-1111-111111111111', 'Project Alpha - Hackathon') ON CONFLICT DO NOTHING;