Michael Hoennig
2022-10-17 63db9395831cc4f8bbd368fea71bbd4bd4857908
commit | author | age
d63e3f 1 --liquibase formatted sql
MH 2
3
4 -- ============================================================================
5 --changeset rbac-generators-RELATED-OBJECT:1 endDelimiter:--//
6 -- ----------------------------------------------------------------------------
7
8 create or replace procedure generateRelatedRbacObject(targetTable varchar)
9     language plpgsql as $$
10 declare
11     createInsertTriggerSQL text;
12     createDeleteTriggerSQL text;
13 begin
14     createInsertTriggerSQL = format($sql$
15         create trigger createRbacObjectFor_%s_Trigger
16             before insert
17             on %s
18             for each row
19                 execute procedure insertRelatedRbacObject();
20         $sql$, targetTable, targetTable);
21     execute createInsertTriggerSQL;
22
23     createDeleteTriggerSQL = format($sql$
24         create trigger deleteRbacRulesFor_%s_Trigger
44eb59 25             after delete
d63e3f 26             on %s
MH 27             for each row
28                 execute procedure deleteRelatedRbacObject();
29         $sql$, targetTable, targetTable);
30     execute createDeleteTriggerSQL;
31 end; $$;
32 --//
33
34
35 -- ============================================================================
36 --changeset rbac-generators-ROLE-DESCRIPTORS:1 endDelimiter:--//
37 -- ----------------------------------------------------------------------------
38
39 create or replace procedure generateRbacRoleDescriptors(prefix text, targetTable text)
40     language plpgsql as $$
41 declare
42     sql text;
43 begin
44     sql = format($sql$
45         create or replace function %1$sOwner(entity %2$s)
46             returns RbacRoleDescriptor
47             language plpgsql
48             strict as $f$
49         begin
50             return roleDescriptor('%2$s', entity.uuid, 'owner');
51         end; $f$;
52
53         create or replace function %1$sAdmin(entity %2$s)
54             returns RbacRoleDescriptor
55             language plpgsql
56             strict as $f$
57         begin
58             return roleDescriptor('%2$s', entity.uuid, 'admin');
59         end; $f$;
60
0b60b9 61         create or replace function %1$sAgent(entity %2$s)
MH 62             returns RbacRoleDescriptor
63             language plpgsql
64             strict as $f$
65         begin
66             return roleDescriptor('%2$s', entity.uuid, 'agent');
67         end; $f$;
68
d63e3f 69         create or replace function %1$sTenant(entity %2$s)
MH 70             returns RbacRoleDescriptor
71             language plpgsql
72             strict as $f$
73         begin
74             return roleDescriptor('%2$s', entity.uuid, 'tenant');
75         end; $f$;
76
0b60b9 77         create or replace function %1$sGuest(entity %2$s)
MH 78             returns RbacRoleDescriptor
79             language plpgsql
80             strict as $f$
81         begin
82             return roleDescriptor('%2$s', entity.uuid, 'guest');
83         end; $f$;
84
d63e3f 85         $sql$, prefix, targetTable);
MH 86     execute sql;
87 end; $$;
88 --//
2cae17 89
MH 90
91 -- ============================================================================
92 --changeset rbac-generators-IDENTITY-VIEW:1 endDelimiter:--//
93 -- ----------------------------------------------------------------------------
94
95 create or replace procedure generateRbacIdentityView(targetTable text, idNameExpression text)
96     language plpgsql as $$
97 declare
98     sql text;
99 begin
100     -- create a view to the target main table which maps an idName to the objectUuid
101     sql = format($sql$
102             create or replace view %1$s_iv as
103             select target.uuid, cleanIdentifier(%2$s) as idName
104                 from %1$s as target;
105             grant all privileges on %1$s_iv to restricted;
106         $sql$, targetTable, idNameExpression);
107     execute sql;
108
109     -- creates a function which maps an idName to the objectUuid
110     sql = format($sql$
111         create or replace function %1$sUuidByIdName(givenIdName varchar)
112             returns uuid
113             language sql
114             strict as $f$
115         select uuid from %1$s_iv iv where iv.idName = givenIdName;
116         $f$;
117         $sql$, targetTable);
118     execute sql;
119
120     -- creates a function which maps an objectUuid to the related idName
121     sql = format($sql$
122         create or replace function %1$sIdNameByUuid(givenUuid uuid)
123             returns varchar
124             language sql
125             strict as $f$
126         select idName from %1$s_iv iv where iv.uuid = givenUuid;
127         $f$;
128     $sql$, targetTable);
129     execute sql;
130 end; $$;
131 --//
44eb59 132
MH 133
134 -- ============================================================================
135 --changeset rbac-generators-RESTRICTED-VIEW:1 endDelimiter:--//
136 -- ----------------------------------------------------------------------------
137
138 create or replace procedure generateRbacRestrictedView(targetTable text, orderBy text, columnUpdates text)
139     language plpgsql as $$
140 declare
141     sql text;
142 begin
143     /*
144         Creates a restricted view based on the 'view' permission of the current subject.
145     */
146     sql := format($sql$
147         set session session authorization default;
148         create view %1$s_rv as
63db93 149             with accessibleObjects as (
MH 150                 select queryAccessibleObjectUuidsOfSubjectIds('view', '%1$s', currentSubjectsUuids())
151             )
152             select target.*
153                 from %1$s as target
154                 where target.uuid in (select * from accessibleObjects)
155                 order by %2$s;
156             grant all privileges on %1$s_rv to restricted;
44eb59 157         $sql$, targetTable, orderBy);
MH 158     execute sql;
159
160     /**
161         Instead of insert trigger function for the restricted view.
162      */
163     sql := format($sql$
164         create or replace function %1$sInsert()
165             returns trigger
166             language plpgsql as $f$
167         declare
168             newTargetRow %1$s;
169         begin
170             insert
171                 into %1$s
172                 values (new.*)
173                 returning * into newTargetRow;
174             return newTargetRow;
175         end; $f$;
176         $sql$, targetTable);
177     execute sql;
178
179     /*
180         Creates an instead of insert trigger for the restricted view.
181      */
182     sql := format($sql$
183         create trigger %1$sInsert_tg
184             instead of insert
185             on %1$s_rv
186             for each row
187         execute function %1$sInsert();
188     $sql$, targetTable);
189     execute sql;
190
191     /**
192         Instead of delete trigger function for the restricted view.
193      */
194     sql := format($sql$
195         create or replace function %1$sDelete()
196             returns trigger
197             language plpgsql as $f$
198         begin
199             if old.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('delete', '%1$s', currentSubjectsUuids())) then
200                 delete from %1$s p where p.uuid = old.uuid;
201                 return old;
202             end if;
203             raise exception '[403] Subject %% is not allowed to delete %1$s uuid %%', currentSubjectsUuids(), old.uuid;
204         end; $f$;
205     $sql$, targetTable);
206     execute sql;
207
208     /*
209         Creates an instead of delete trigger for the restricted view.
210      */
211     sql := format($sql$
212         create trigger %1$sDelete_tg
213             instead of delete
214             on %1$s_rv
215             for each row
216         execute function %1$sDelete();
217     $sql$, targetTable);
218     execute sql;
219
220     /**
221         Instead of update trigger function for the restricted view
222         based on the 'edit' permission of the current subject.
223      */
224     sql := format($sql$
225         create or replace function %1$sUpdate()
226             returns trigger
227             language plpgsql as $f$
228         begin
229             if old.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('edit', '%1$s', currentSubjectsUuids())) then
230                 update %1$s
231                     set %2$s
232                     where uuid = old.uuid;
233                 return old;
234             end if;
235             raise exception '[403] Subject %% is not allowed to update %1$s uuid %%', currentSubjectsUuids(), old.uuid;
236         end; $f$;
237     $sql$, targetTable, columnUpdates);
238     execute sql;
239
240     /*
241         Creates an instead of delete trigger for the restricted view.
242      */
243     sql = format($sql$
244         create trigger %1$sUpdate_tg
245             instead of update
246             on %1$s_rv
247             for each row
248         execute function %1$sUpdate();
249     $sql$, targetTable);
250     execute sql;
251 end; $$;
252 --//