forked from moofoo/nestjs-prisma-postgres-tenancy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path1_schema.sql
161 lines (126 loc) · 3.96 KB
/
1_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
-- PG_DUMP BOILERPLATE ---------------------------------
SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET xmloption = content;
SET client_min_messages = warning;
SET row_security = off;
-- DROP AND CREATE DATABASE ---------------------------------
DROP DATABASE IF EXISTS app_db;
CREATE DATABASE app_db WITH TEMPLATE = template0 ENCODING = 'UTF8' LOCALE = 'C.UTF-8';
ALTER DATABASE app_db OWNER TO postgres;
\connect app_db
-- CREATE FN SCHEMA ---------------------------------
CREATE SCHEMA IF NOT EXISTS fn;
ALTER SCHEMA fn OWNER TO postgres;
-- CREATE TENANT ROLE ---------------------------------
CREATE ROLE tenant WITH
LOGIN
NOSUPERUSER
INHERIT
NOCREATEDB
NOCREATEROLE
NOREPLICATION
ENCRYPTED PASSWORD 'SCRAM-SHA-256$4096:E0Wq8zef+fUG5k++CVd7lg==$TpHflYTTvCNNIvHW2dkOe4UTb5V0yPw9su/kpoNxLy0=:BgselHsx/GYWjgaVxFQPE/NyUBzMM5O5WB168qFwYH8=';
-- c7b38884e5c959ac151e4f24320c7a34
GRANT USAGE ON SCHEMA public TO tenant;
GRANT USAGE ON SCHEMA fn TO tenant;
-- TABLES: TENANTS, USERS, PATIENTS ---------------------------------
create table if not exists public.tenants
(
id bigserial primary key,
display_name varchar,
is_admin boolean default false
);
create table if not exists public.users
(
id bigserial primary key,
tenant_id bigint
constraint users_tenants_id_fk
references public.tenants
on delete cascade,
user_name varchar,
password varchar
);
create table if not exists public.patients
(
id bigserial primary key,
tenant_id bigint
constraint patients_tenants_id_fk
references public.tenants
on delete cascade,
first_name varchar,
last_name varchar,
dob date
);
-- GRANTS FOR TENANT ROLE ---------------------------------
grant delete, insert, select, update on public.tenants to tenant;
grant delete, insert, select, update on public.users to tenant;
grant delete, insert, select, update on public.patients to tenant;
-- ROW LEVEL SECURITY CHECK FUNCTION ---------------------------------
create or replace function fn.tenant_data_rls_check(row_tenant_id bigint) returns boolean
language plpgsql
as
$$
BEGIN
IF current_setting('tenancy.bypass')::text = '1' THEN
return true;
end if;
IF current_setting('tenancy.tenant_id')::integer = row_tenant_id THEN
return true;
end if;
return false;
END;
$$;
alter function fn.tenant_data_rls_check(bigint) owner to postgres;
-- ENABLE / DISABLE RLS ---------------------------------
create or replace procedure fn.enable_rls()
language plpgsql
as
$$
DECLARE
r record;
BEGIN
FOR r in select * from pg_catalog.pg_policies
LOOP
EXECUTE format('ALTER TABLE public.%I ENABLE ROW LEVEL SECURITY', r.tablename);
END LOOP;
END;
$$;
alter procedure fn.enable_rls() owner to postgres;
create or replace procedure fn.disable_rls()
language plpgsql
as
$$
DECLARE
r record;
BEGIN
FOR r in select * from pg_catalog.pg_policies
LOOP
EXECUTE format('ALTER TABLE public.%I DISABLE ROW LEVEL SECURITY', r.tablename);
END LOOP;
END;
$$;
alter procedure fn.enable_rls() owner to postgres;
-- POLICIES ---------------------------------
create policy tenancy_policy on public.tenants
as permissive
for all
using (fn.tenant_data_rls_check(id) = true)
with check (fn.tenant_data_rls_check(id) = true);
create policy tenancy_policy on public.users
as permissive
for all
using (fn.tenant_data_rls_check(tenant_id) = true)
with check (fn.tenant_data_rls_check(tenant_id) = true);
create policy tenancy_policy on public.patients
as permissive
for all
using (fn.tenant_data_rls_check(tenant_id) = true)
with check (fn.tenant_data_rls_check(tenant_id) = true);
-- ENABLE ROW LEVEL SECURITY ---------------------------------
CALL fn.enable_rls();