-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathsupabase-setup.sql
More file actions
140 lines (117 loc) · 4.25 KB
/
supabase-setup.sql
File metadata and controls
140 lines (117 loc) · 4.25 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
-- =============================================
-- Global Notes Workspace — Database Setup
-- Run this in Supabase SQL Editor (supabase.com/dashboard → SQL Editor)
-- =============================================
-- 1. PROFILES TABLE
-- Auto-created when a user signs up (via trigger)
CREATE TABLE IF NOT EXISTS profiles (
id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
username TEXT,
avatar_url TEXT,
created_at TIMESTAMPTZ DEFAULT now()
);
-- 2. NOTES TABLE
CREATE TABLE IF NOT EXISTS notes (
id TEXT PRIMARY KEY,
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
title TEXT DEFAULT '',
content TEXT DEFAULT '',
tags JSONB DEFAULT '[]'::jsonb,
folder_id TEXT,
theme TEXT,
editor_pattern TEXT DEFAULT 'plain',
is_favorite BOOLEAN DEFAULT false,
is_archived BOOLEAN DEFAULT false,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);
-- Index for fast user lookups
CREATE INDEX IF NOT EXISTS idx_notes_user_id ON notes(user_id);
CREATE INDEX IF NOT EXISTS idx_notes_updated_at ON notes(updated_at DESC);
-- 3. FOLDERS TABLE
CREATE TABLE IF NOT EXISTS folders (
id TEXT PRIMARY KEY,
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
name TEXT NOT NULL DEFAULT 'Untitled Folder',
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_folders_user_id ON folders(user_id);
-- 4. SHARED NOTES TABLE (publicly readable)
CREATE TABLE IF NOT EXISTS shared_notes (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES auth.users(id) ON DELETE SET NULL,
title TEXT DEFAULT '',
content TEXT DEFAULT '',
created_at TIMESTAMPTZ DEFAULT now()
);
-- =============================================
-- ROW LEVEL SECURITY (RLS)
-- =============================================
-- Enable RLS on all tables
ALTER TABLE profiles ENABLE ROW LEVEL SECURITY;
ALTER TABLE notes ENABLE ROW LEVEL SECURITY;
ALTER TABLE folders ENABLE ROW LEVEL SECURITY;
ALTER TABLE shared_notes ENABLE ROW LEVEL SECURITY;
-- PROFILES: Users can read/update their own profile
CREATE POLICY "Users can view own profile"
ON profiles FOR SELECT
USING (auth.uid() = id);
CREATE POLICY "Users can update own profile"
ON profiles FOR UPDATE
USING (auth.uid() = id);
CREATE POLICY "Users can insert own profile"
ON profiles FOR INSERT
WITH CHECK (auth.uid() = id);
-- NOTES: Users can CRUD their own notes only
CREATE POLICY "Users can view own notes"
ON notes FOR SELECT
USING (auth.uid() = user_id);
CREATE POLICY "Users can insert own notes"
ON notes FOR INSERT
WITH CHECK (auth.uid() = user_id);
CREATE POLICY "Users can update own notes"
ON notes FOR UPDATE
USING (auth.uid() = user_id);
CREATE POLICY "Users can delete own notes"
ON notes FOR DELETE
USING (auth.uid() = user_id);
-- FOLDERS: Users can CRUD their own folders only
CREATE POLICY "Users can view own folders"
ON folders FOR SELECT
USING (auth.uid() = user_id);
CREATE POLICY "Users can insert own folders"
ON folders FOR INSERT
WITH CHECK (auth.uid() = user_id);
CREATE POLICY "Users can update own folders"
ON folders FOR UPDATE
USING (auth.uid() = user_id);
CREATE POLICY "Users can delete own folders"
ON folders FOR DELETE
USING (auth.uid() = user_id);
-- SHARED NOTES: Anyone can read, only authenticated users can create
CREATE POLICY "Anyone can read shared notes"
ON shared_notes FOR SELECT
USING (true);
CREATE POLICY "Authenticated users can share notes"
ON shared_notes FOR INSERT
WITH CHECK (auth.uid() = user_id);
-- =============================================
-- AUTO-CREATE PROFILE ON SIGNUP (Trigger)
-- =============================================
CREATE OR REPLACE FUNCTION public.handle_new_user()
RETURNS TRIGGER AS $$
BEGIN
INSERT INTO public.profiles (id, username, avatar_url)
VALUES (
NEW.id,
COALESCE(NEW.raw_user_meta_data->>'username', NEW.raw_user_meta_data->>'full_name', split_part(NEW.email, '@', 1)),
COALESCE(NEW.raw_user_meta_data->>'avatar_url', '')
);
RETURN NEW;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
-- Drop existing trigger if any, then create
DROP TRIGGER IF EXISTS on_auth_user_created ON auth.users;
CREATE TRIGGER on_auth_user_created
AFTER INSERT ON auth.users
FOR EACH ROW EXECUTE FUNCTION public.handle_new_user();