-
Notifications
You must be signed in to change notification settings - Fork 8
/
schema.sql
287 lines (233 loc) · 8.57 KB
/
schema.sql
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
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
create extension if not exists "moddatetime" with schema "extensions" version '1.0';
create type "public"."language" as enum ('typescript');
create table "public"."profiles" (
"id" uuid not null,
"created_at" timestamp with time zone not null,
"updated_at" timestamp with time zone,
"username" text not null,
"avatar_url" text not null,
"full_name" text not null default '"default"'::text
);
alter table "public"."profiles" enable row level security;
create table "public"."quizzes" (
"id" bigint generated by default as identity not null,
"created_at" timestamp with time zone not null default now(),
"updated_at" timestamp with time zone not null default now(),
"description" character varying,
"start_code" character varying not null,
"target_output" character varying not null,
"language" language not null,
"created_by" uuid,
"friendly_id" character varying
);
alter table "public"."quizzes" add column "views" bigint default '0'::bigint;
CREATE OR REPLACE FUNCTION public.increment(x integer, row_id integer)
RETURNS integer
LANGUAGE sql
SECURITY DEFINER
AS $function$
update quizzes
set views = views + x
where id = row_id;
select views from quizzes where id = row_id ;
$function$
;
alter table "public"."quizzes" enable row level security;
CREATE UNIQUE INDEX profiles_pkey ON public.profiles USING btree (id);
CREATE UNIQUE INDEX profiles_username_key ON public.profiles USING btree (username);
CREATE UNIQUE INDEX quizzes_pkey ON public.quizzes USING btree (id);
alter table "public"."profiles" add constraint "profiles_pkey" PRIMARY KEY using index "profiles_pkey";
alter table "public"."quizzes" add constraint "quizzes_pkey" PRIMARY KEY using index "quizzes_pkey";
alter table "public"."profiles" add constraint "profiles_id_fkey" FOREIGN KEY (id) REFERENCES auth.users(id);
alter table "public"."profiles" add constraint "profiles_username_key" UNIQUE using index "profiles_username_key";
alter table "public"."quizzes" add constraint "quizzes_created_by_fkey" FOREIGN KEY (created_by) REFERENCES auth.users(id);
set check_function_bodies = off;
CREATE OR REPLACE FUNCTION public.create_profile_for_new_user()
RETURNS trigger
LANGUAGE plpgsql
SECURITY DEFINER
AS $function$
BEGIN
INSERT INTO public.profiles (id, created_at, updated_at, username, avatar_url, full_name)
VALUES (
NEW.id,
NEW.created_at,
NEW.updated_at,
NEW.raw_user_meta_data ->> 'user_name',
NEW.raw_user_meta_data ->> 'avatar_url',
NEW.raw_user_meta_data ->> 'full_name'
);
RETURN NEW;
END;
$function$
;
CREATE OR REPLACE FUNCTION extensions.grant_pg_net_access()
RETURNS event_trigger
LANGUAGE plpgsql
AS $function$
BEGIN
IF EXISTS (
SELECT 1
FROM pg_event_trigger_ddl_commands() AS ev
JOIN pg_extension AS ext
ON ev.objid = ext.oid
WHERE ext.extname = 'pg_net'
)
THEN
IF NOT EXISTS (
SELECT 1
FROM pg_roles
WHERE rolname = 'supabase_functions_admin'
)
THEN
CREATE USER supabase_functions_admin NOINHERIT CREATEROLE LOGIN NOREPLICATION;
END IF;
GRANT USAGE ON SCHEMA net TO supabase_functions_admin, postgres, anon, authenticated, service_role;
ALTER function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) SECURITY DEFINER;
ALTER function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) SECURITY DEFINER;
ALTER function net.http_collect_response(request_id bigint, async boolean) SECURITY DEFINER;
ALTER function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) SET search_path = net;
ALTER function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) SET search_path = net;
ALTER function net.http_collect_response(request_id bigint, async boolean) SET search_path = net;
REVOKE ALL ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC;
REVOKE ALL ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC;
REVOKE ALL ON FUNCTION net.http_collect_response(request_id bigint, async boolean) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) TO supabase_functions_admin, postgres, anon, authenticated, service_role;
GRANT EXECUTE ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) TO supabase_functions_admin, postgres, anon, authenticated, service_role;
GRANT EXECUTE ON FUNCTION net.http_collect_response(request_id bigint, async boolean) TO supabase_functions_admin, postgres, anon, authenticated, service_role;
END IF;
END;
$function$
;
CREATE OR REPLACE FUNCTION storage.extension(name text)
RETURNS text
LANGUAGE plpgsql
AS $function$
DECLARE
_parts text[];
_filename text;
BEGIN
select string_to_array(name, '/') into _parts;
select _parts[array_length(_parts,1)] into _filename;
-- @todo return the last part instead of 2
return split_part(_filename, '.', 2);
END
$function$
;
CREATE OR REPLACE FUNCTION storage.filename(name text)
RETURNS text
LANGUAGE plpgsql
AS $function$
DECLARE
_parts text[];
BEGIN
select string_to_array(name, '/') into _parts;
return _parts[array_length(_parts,1)];
END
$function$
;
CREATE OR REPLACE FUNCTION storage.foldername(name text)
RETURNS text[]
LANGUAGE plpgsql
AS $function$
DECLARE
_parts text[];
BEGIN
select string_to_array(name, '/') into _parts;
return _parts[1:array_length(_parts,1)-1];
END
$function$
;
CREATE OR REPLACE FUNCTION storage.get_size_by_bucket()
RETURNS TABLE(size bigint, bucket_id text)
LANGUAGE plpgsql
AS $function$
BEGIN
return query
select sum((metadata->>'size')::int) as size, obj.bucket_id
from "storage".objects as obj
group by obj.bucket_id;
END
$function$
;
CREATE OR REPLACE FUNCTION storage.search(prefix text, bucketname text, limits integer DEFAULT 100, levels integer DEFAULT 1, offsets integer DEFAULT 0)
RETURNS TABLE(name text, id uuid, updated_at timestamp with time zone, created_at timestamp with time zone, last_accessed_at timestamp with time zone, metadata jsonb)
LANGUAGE plpgsql
AS $function$
BEGIN
return query
with files_folders as (
select path_tokens[levels] as folder
from storage.objects
where objects.name ilike prefix || '%'
and bucket_id = bucketname
GROUP by folder
limit limits
offset offsets
)
select files_folders.folder as name, objects.id, objects.updated_at, objects.created_at, objects.last_accessed_at, objects.metadata from files_folders
left join storage.objects
on prefix || files_folders.folder = objects.name
where objects.id is null or objects.bucket_id=bucketname;
END
$function$
;
create policy "Public profiles are viewable by everyone."
on "public"."profiles"
as permissive
for select
to public
using (true);
create policy "Users can insert their own profile."
on "public"."profiles"
as permissive
for insert
to public
with check (auth.uid() = id);
create policy "Users can update own profile."
on "public"."profiles"
as permissive
for update
to public
using ((auth.uid() = id));
create policy "Quizzes are viewable by everyone"
on "public"."quizzes"
as permissive
for select
to public
using (true);
create policy "Users can insert quizzes created by themself"
on "public"."quizzes"
as permissive
for insert
to public
with check (auth.uid() = created_by);
create policy "Users can update their own quizzes"
on "public"."quizzes"
as permissive
for update
to public
using ((auth.uid() = created_by))
with check (auth.uid() = created_by);
create policy "Anyone can update an avatar."
on "storage"."objects"
as permissive
for update
to public
with check (bucket_id = 'avatars'::text);
create policy "Anyone can upload an avatar."
on "storage"."objects"
as permissive
for insert
to public
with check (bucket_id = 'avatars'::text);
create policy "Avatar images are publicly accessible."
on "storage"."objects"
as permissive
for select
to public
using ((bucket_id = 'avatars'::text));
CREATE TRIGGER create_profile_on_signup AFTER INSERT ON auth.users FOR EACH ROW EXECUTE FUNCTION create_profile_for_new_user();
CREATE TRIGGER handle_updated_at BEFORE UPDATE ON public.quizzes FOR EACH ROW EXECUTE FUNCTION moddatetime('updated_at');
alter table "public"."quizzes" add column "solution" character varying;
alter table "public"."quizzes" add column "explanation" jsonb;