-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsupabase-setup.sql
More file actions
240 lines (206 loc) · 6.84 KB
/
supabase-setup.sql
File metadata and controls
240 lines (206 loc) · 6.84 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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
-- ============================================
-- AniKam Database Setup Script for Supabase
-- ============================================
-- This script creates all necessary tables, policies,
-- functions, and triggers for user authentication
-- ============================================
-- Enable UUID extension
create extension if not exists "uuid-ossp";
-- ============================================
-- PROFILES TABLE
-- ============================================
-- Stores user profile information
create table if not exists public.profiles (
id uuid references auth.users on delete cascade primary key,
username text unique not null,
email text unique not null,
avatar_url text,
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,
constraint username_length check (char_length(username) >= 3),
constraint username_format check (username ~ '^[a-zA-Z0-9_]+$')
);
-- Add comment to table
comment on table public.profiles is 'User profile information linked to auth.users';
-- ============================================
-- ROW LEVEL SECURITY (RLS)
-- ============================================
-- Enable RLS on profiles table
alter table public.profiles enable row level security;
-- Policy: Users can view their own profile
create policy "Users can view their own profile"
on public.profiles for select
using (auth.uid() = id);
-- Policy: Users can update their own profile
create policy "Users can update their own profile"
on public.profiles for update
using (auth.uid() = id);
-- Policy: Users can insert their own profile
create policy "Users can insert their own profile"
on public.profiles for insert
with check (auth.uid() = id);
-- Policy: Users can delete their own profile (optional)
create policy "Users can delete their own profile"
on public.profiles for delete
using (auth.uid() = id);
-- ============================================
-- FUNCTIONS
-- ============================================
-- Function: Automatically create profile on user signup
create or replace function public.handle_new_user()
returns trigger
language plpgsql
security definer
set search_path = public
as $$
begin
insert into public.profiles (id, username, email, avatar_url)
values (
new.id,
coalesce(
new.raw_user_meta_data->>'username',
split_part(new.email, '@', 1)
),
new.email,
new.raw_user_meta_data->>'avatar_url'
);
return new;
exception
when others then
raise log 'Error creating profile for user %: %', new.id, sqlerrm;
return new;
end;
$$;
-- Function: Update updated_at timestamp
create or replace function public.handle_updated_at()
returns trigger
language plpgsql
as $$
begin
new.updated_at = timezone('utc'::text, now());
return new;
end;
$$;
-- Function: Get user profile by ID
create or replace function public.get_profile(user_id uuid)
returns json
language sql
stable
security definer
as $$
select row_to_json(profiles.*)
from public.profiles
where profiles.id = user_id;
$$;
-- ============================================
-- TRIGGERS
-- ============================================
-- Trigger: Automatically create profile when user signs up
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();
-- Trigger: Automatically update updated_at timestamp
drop trigger if exists on_profile_updated on public.profiles;
create trigger on_profile_updated
before update on public.profiles
for each row
execute function public.handle_updated_at();
-- ============================================
-- INDEXES
-- ============================================
-- Indexes for better query performance
-- Index on username for fast lookups
create index if not exists profiles_username_idx
on public.profiles (username);
-- Index on email for fast lookups
create index if not exists profiles_email_idx
on public.profiles (email);
-- Index on created_at for sorting
create index if not exists profiles_created_at_idx
on public.profiles (created_at desc);
-- ============================================
-- GRANTS (Optional - for additional security)
-- ============================================
-- Grant appropriate permissions
-- Grant usage on schema
grant usage on schema public to authenticated;
grant usage on schema public to anon;
-- Grant permissions on profiles table
grant select, insert, update, delete on public.profiles to authenticated;
grant select on public.profiles to anon;
-- ============================================
-- TEST DATA (Optional - Remove in production)
-- ============================================
-- Uncomment the following to add test data
/*
-- Note: You need to create auth users first in Supabase dashboard
-- Then you can manually insert profiles or let the trigger handle it
-- Example test profile (only if user exists in auth.users)
insert into public.profiles (id, username, email, avatar_url)
values (
'your-test-user-uuid-here',
'testuser',
'test@anikam.com',
null
)
on conflict (id) do nothing;
*/
-- ============================================
-- VERIFICATION QUERIES
-- ============================================
-- Run these after setup to verify everything works
-- Check if profiles table exists and is configured correctly
select
schemaname,
tablename,
tableowner,
rowsecurity as "RLS Enabled"
from pg_tables
where tablename = 'profiles';
-- Check policies
select
schemaname,
tablename,
policyname,
permissive,
roles,
cmd
from pg_policies
where tablename = 'profiles';
-- Check triggers
select
trigger_name,
event_manipulation,
event_object_table,
action_statement
from information_schema.triggers
where event_object_table in ('profiles', 'users')
order by event_object_table, trigger_name;
-- ============================================
-- CLEANUP (Use with caution!)
-- ============================================
-- Uncomment to remove everything and start fresh
/*
-- Drop triggers
drop trigger if exists on_auth_user_created on auth.users;
drop trigger if exists on_profile_updated on public.profiles;
-- Drop functions
drop function if exists public.handle_new_user();
drop function if exists public.handle_updated_at();
drop function if exists public.get_profile(uuid);
-- Drop table (this will also drop all policies)
drop table if exists public.profiles cascade;
*/
-- ============================================
-- SETUP COMPLETE
-- ============================================
-- Your database is now ready for AniKam!
--
-- Next steps:
-- 1. Configure email templates in Authentication > Email Templates
-- 2. Set up redirect URLs in Authentication > URL Configuration
-- 3. Test user registration and login
-- 4. Monitor logs in Logs > Auth Logs
-- ============================================