-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathschema.sql
More file actions
251 lines (200 loc) · 8.33 KB
/
schema.sql
File metadata and controls
251 lines (200 loc) · 8.33 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
241
242
243
244
245
246
247
248
249
-- Echo – Main Database Schema
-- Run this in your Supabase SQL Editor to create all required tables, policies, and helpers.
-- Existing data will be respected where possible (most statements are CREATE IF NOT EXISTS / ALTER / DROP POLICY IF EXISTS).
-- ========================================================
-- 1. Notifications: push_subscriptions table + RLS
-- ========================================================
-- Create table to store push subscriptions
create table if not exists public.push_subscriptions (
id uuid default gen_random_uuid() primary key,
user_id uuid references auth.users(id) on delete cascade not null,
endpoint text not null unique,
p256dh text not null,
auth text not null,
user_agent 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
);
-- Enable RLS
alter table public.push_subscriptions enable row level security;
-- Policies
create policy "Users can view their own subscriptions"
on public.push_subscriptions for select
using (auth.uid() = user_id);
create policy "Users can insert their own subscriptions"
on public.push_subscriptions for insert
with check (auth.uid() = user_id);
create policy "Users can update their own subscriptions"
on public.push_subscriptions for update
using (auth.uid() = user_id);
create policy "Users can delete their own subscriptions"
on public.push_subscriptions for delete
using (auth.uid() = user_id);
-- Indexes
create index if not exists push_subscriptions_user_id_idx on public.push_subscriptions(user_id);
-- ========================================================
-- 2. Weekly Check-ins: config, checkins, responses + RLS
-- ========================================================
-- Check-in Configuration
create table if not exists checkin_config (
family_id uuid references families(id) not null primary key,
day_of_week int not null check (day_of_week between 0 and 6), -- 0 = Sunday
time_utc time not null,
created_at timestamp with time zone default timezone('utc'::text, now()) not null
);
alter table checkin_config enable row level security;
create policy "Users can view checkin config for their family"
on checkin_config for select
using ( family_id in (select family_id from profiles where id = auth.uid()) );
create policy "Users can update checkin config for their family"
on checkin_config for update
using ( family_id in (select family_id from profiles where id = auth.uid()) );
create policy "Users can insert checkin config for their family"
on checkin_config for insert
with check ( family_id in (select family_id from profiles where id = auth.uid()) );
-- Check-ins (The weekly instances)
create table if not exists checkins (
id uuid default gen_random_uuid() primary key,
family_id uuid references families(id) not null,
week_start_date date not null, -- The Monday (or Sunday) of the week this check-in belongs to
status text check (status in ('pending', 'completed')) default 'pending',
ai_topic jsonb, -- { "title": "...", "description": "..." }
created_at timestamp with time zone default timezone('utc'::text, now()) not null,
unique(family_id, week_start_date)
);
alter table checkins enable row level security;
create policy "Users can view checkins for their family"
on checkins for select
using ( family_id in (select family_id from profiles where id = auth.uid()) );
create policy "Service role can manage checkins"
on checkins
using ( true );
create policy "Users can insert checkins for their family"
on checkins for insert
with check ( family_id in (select family_id from profiles where id = auth.uid()) );
create policy "Users can update checkins for their family"
on checkins for update
using ( family_id in (select family_id from profiles where id = auth.uid()) );
-- Check-in Responses
create table if not exists checkin_responses (
id uuid default gen_random_uuid() primary key,
checkin_id uuid references checkins(id) not null,
user_id uuid references auth.users(id) not null,
temperature int not null check (temperature between 1 and 10),
notes text,
created_at timestamp with time zone default timezone('utc'::text, now()) not null,
unique(checkin_id, user_id)
);
alter table checkin_responses enable row level security;
create policy "Users can view responses for their family"
on checkin_responses for select
using (
exists (
select 1 from checkins
where checkins.id = checkin_responses.checkin_id
and checkins.family_id in (select family_id from profiles where id = auth.uid())
)
);
create policy "Users can insert their own response"
on checkin_responses for insert
with check ( user_id = auth.uid() );
create policy "Users can update their own response"
on checkin_responses for update
using ( user_id = auth.uid() );
-- ========================================================
-- 3. RPC Helpers
-- ========================================================
-- Function to safely reset a check-in week by deleting responses and the check-in itself.
-- Runs with SECURITY DEFINER to bypass RLS restrictions (needed to delete partner's responses).
create or replace function reset_checkin_week(target_checkin_id uuid)
returns void
language plpgsql
security definer
as $$
begin
-- 1. Delete all responses for this check-in
delete from checkin_responses
where checkin_id = target_checkin_id;
-- 2. Delete the check-in itself
delete from checkins
where id = target_checkin_id;
end;
$$;
-- ========================================================
-- 4. Final RLS for families & profiles
-- ========================================================
-- Helper Function (Prevention of Infinite Recursion)
CREATE OR REPLACE FUNCTION get_my_family_id()
RETURNS uuid
LANGUAGE sql
SECURITY DEFINER
SET search_path = public
STABLE
AS $$
SELECT family_id FROM profiles WHERE id = auth.uid();
$$;
-- FAMILIES Table Policies
ALTER TABLE public.families ENABLE ROW LEVEL SECURITY;
-- Allow INSERT (This was missing/failing)
DROP POLICY IF EXISTS "Users can create families" ON public.families;
CREATE POLICY "Users can create families"
ON public.families
FOR INSERT
TO authenticated
WITH CHECK (true);
-- Allow SELECT (View your own family)
DROP POLICY IF EXISTS "Users can view their family" ON public.families;
CREATE POLICY "Users can view their family"
ON public.families
FOR SELECT
TO authenticated
USING (
id = get_my_family_id()
);
-- Allow UPDATE (Update your own family)
DROP POLICY IF EXISTS "Users can update their family" ON public.families;
CREATE POLICY "Users can update their family"
ON public.families
FOR UPDATE
TO authenticated
USING (
id = get_my_family_id()
);
-- PROFILES Table Policies
ALTER TABLE public.profiles ENABLE ROW LEVEL SECURITY;
-- Allow INSERT (Create your own profile)
DROP POLICY IF EXISTS "Users can insert their own profile" ON public.profiles;
CREATE POLICY "Users can insert their own profile"
ON public.profiles
FOR INSERT
TO authenticated
WITH CHECK (id = auth.uid());
-- Allow UPDATE (Edit your own profile)
DROP POLICY IF EXISTS "Users can update their own profile" ON public.profiles;
CREATE POLICY "Users can update their own profile"
ON public.profiles
FOR UPDATE
TO authenticated
USING (id = auth.uid());
-- Allow SELECT (View yourself AND family members)
DROP POLICY IF EXISTS "Users can view family members" ON public.profiles;
CREATE POLICY "Users can view family members"
ON public.profiles
FOR SELECT
TO authenticated
USING (
id = auth.uid()
OR
family_id = get_my_family_id()
);
-- Cleanup old/conflicting policies if they exist (Optional but good hygiene)
DROP POLICY IF EXISTS "Users can view their own subscriptions" ON public.families;
-- ========================================================
-- 5. Realtime publication configuration
-- ========================================================
-- Enable Realtime for the 'glows' table (so new messages appear instantly)
alter publication supabase_realtime add table glows;
-- Enable Realtime for the 'profiles' table (so vibes update instantly)
alter publication supabase_realtime add table profiles;
-- Verify it worked (Optional)
-- select * from pg_publication_tables where pubname = 'supabase_realtime';