-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsupabase-schema.sql
More file actions
166 lines (144 loc) · 6.67 KB
/
supabase-schema.sql
File metadata and controls
166 lines (144 loc) · 6.67 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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
-- Wavelength Database Schema for Supabase
-- Run this in your Supabase SQL Editor
-- Enable UUID extension
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
-- Users table (extends Supabase auth.users)
CREATE TABLE public.users (
id UUID REFERENCES auth.users(id) ON DELETE CASCADE PRIMARY KEY,
display_name TEXT NOT NULL,
email TEXT NOT NULL,
bio TEXT DEFAULT '',
photo_url TEXT DEFAULT '',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
posts_count INTEGER DEFAULT 0
);
-- Feedback table
CREATE TABLE public.feedback (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
text TEXT NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Posts table
CREATE TABLE public.posts (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
user_id UUID REFERENCES public.users(id) ON DELETE CASCADE NOT NULL,
username TEXT NOT NULL,
user_avatar TEXT DEFAULT '',
caption TEXT NOT NULL,
location TEXT,
coordinates JSONB, -- {latitude: number, longitude: number}
rating INTEGER NOT NULL CHECK (rating >= 1 AND rating <= 10),
category TEXT NOT NULL,
photos TEXT[] NOT NULL, -- Array of photo URLs
is_public BOOLEAN DEFAULT true,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
agreed_by UUID[] DEFAULT '{}', -- Array of user IDs
disagreed_by UUID[] DEFAULT '{}' -- Array of user IDs
);
-- Comments table
CREATE TABLE public.comments (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
post_id UUID REFERENCES public.posts(id) ON DELETE CASCADE NOT NULL,
user_id UUID REFERENCES public.users(id) ON DELETE CASCADE NOT NULL,
username TEXT NOT NULL,
user_avatar TEXT DEFAULT '',
text TEXT NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Follow relationships table
CREATE TABLE public.follows (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
follower_id UUID REFERENCES public.users(id) ON DELETE CASCADE NOT NULL,
following_id UUID REFERENCES public.users(id) ON DELETE CASCADE NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
UNIQUE(follower_id, following_id),
CHECK (follower_id != following_id)
);
-- Follow requests table
CREATE TABLE public.follow_requests (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
from_user_id UUID REFERENCES public.users(id) ON DELETE CASCADE NOT NULL,
to_user_id UUID REFERENCES public.users(id) ON DELETE CASCADE NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
UNIQUE(from_user_id, to_user_id),
CHECK (from_user_id != to_user_id)
);
-- Indexes for performance
CREATE INDEX idx_posts_user_id ON public.posts(user_id);
CREATE INDEX idx_posts_created_at ON public.posts(created_at DESC);
CREATE INDEX idx_posts_is_public ON public.posts(is_public);
CREATE INDEX idx_posts_coordinates ON public.posts USING GIN(coordinates);
CREATE INDEX idx_comments_post_id ON public.comments(post_id);
CREATE INDEX idx_comments_created_at ON public.comments(created_at);
CREATE INDEX idx_follows_follower ON public.follows(follower_id);
CREATE INDEX idx_follows_following ON public.follows(following_id);
CREATE INDEX idx_follow_requests_from ON public.follow_requests(from_user_id);
CREATE INDEX idx_follow_requests_to ON public.follow_requests(to_user_id);
-- Row Level Security (RLS) Policies
-- Enable RLS
ALTER TABLE public.users ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.posts ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.comments ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.follows ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.follow_requests ENABLE ROW LEVEL SECURITY;
-- Users policies
CREATE POLICY "Users can view all profiles" ON public.users FOR SELECT USING (true);
CREATE POLICY "Users can update own profile" ON public.users FOR UPDATE USING (auth.uid() = id);
CREATE POLICY "Users can insert own profile" ON public.users FOR INSERT WITH CHECK (auth.uid() = id);
-- Posts policies
CREATE POLICY "Anyone can view public posts" ON public.posts FOR SELECT USING (is_public = true OR user_id = auth.uid());
CREATE POLICY "Users can view posts from people they follow" ON public.posts FOR SELECT USING (
user_id = auth.uid() OR
EXISTS (SELECT 1 FROM public.follows WHERE follower_id = auth.uid() AND following_id = user_id)
);
CREATE POLICY "Users can create own posts" ON public.posts FOR INSERT WITH CHECK (auth.uid() = user_id);
CREATE POLICY "Users can update own posts" ON public.posts FOR UPDATE USING (auth.uid() = user_id);
CREATE POLICY "Users can delete own posts" ON public.posts FOR DELETE USING (auth.uid() = user_id);
-- Comments policies
CREATE POLICY "Anyone can view comments" ON public.comments FOR SELECT USING (true);
CREATE POLICY "Authenticated users can create comments" ON public.comments FOR INSERT WITH CHECK (auth.uid() = user_id);
CREATE POLICY "Users can delete own comments" ON public.comments FOR DELETE USING (auth.uid() = user_id);
-- Follows policies
CREATE POLICY "Anyone can view follows" ON public.follows FOR SELECT USING (true);
CREATE POLICY "Users can create own follows" ON public.follows FOR INSERT WITH CHECK (auth.uid() = follower_id);
CREATE POLICY "Users can delete own follows" ON public.follows FOR DELETE USING (auth.uid() = follower_id);
-- Follow requests policies
CREATE POLICY "Users can view their own requests" ON public.follow_requests FOR SELECT USING (
auth.uid() = from_user_id OR auth.uid() = to_user_id
);
CREATE POLICY "Users can create follow requests" ON public.follow_requests FOR INSERT WITH CHECK (auth.uid() = from_user_id);
CREATE POLICY "Users can delete their own requests" ON public.follow_requests FOR DELETE USING (
auth.uid() = from_user_id OR auth.uid() = to_user_id
);
-- Function to handle new user creation
CREATE OR REPLACE FUNCTION public.handle_new_user()
RETURNS TRIGGER AS $$
BEGIN
INSERT INTO public.users (id, display_name, email, photo_url)
VALUES (
NEW.id,
COALESCE(NEW.raw_user_meta_data->>'display_name', split_part(NEW.email, '@', 1)),
NEW.email,
COALESCE(NEW.raw_user_meta_data->>'photo_url', '')
);
RETURN NEW;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
-- Trigger to create user profile on signup
CREATE TRIGGER on_auth_user_created
AFTER INSERT ON auth.users
FOR EACH ROW EXECUTE FUNCTION public.handle_new_user();
-- RLS Policies for feedback table
ALTER TABLE public.feedback ENABLE ROW LEVEL SECURITY;
-- Anyone can insert feedback (anonymous or authenticated)
CREATE POLICY "Anyone can insert feedback"
ON public.feedback
FOR INSERT
TO authenticated
WITH CHECK (true);
-- Storage buckets (run these in SQL editor or create via Supabase UI)
-- You'll need to create these buckets in the Supabase Storage UI:
-- 1. "avatars" - for profile photos
-- 2. "posts" - for post images
-- Storage policies will be set up via the Supabase UI or with additional SQL