rbac.grants

This commit is contained in:
Michael Hoennig 2024-09-13 20:31:41 +02:00
parent 8715ae484a
commit 342102e85c
9 changed files with 48 additions and 48 deletions

View File

@ -114,7 +114,7 @@ class RolesGrantsAndPermissionsGenerator {
begin begin
if ${updateConditions} then if ${updateConditions} then
delete from rbacgrants g where g.grantedbytriggerof = OLD.uuid; delete from rbac.grants g where g.grantedbytriggerof = OLD.uuid;
call buildRbacSystemFor${simpleEntityName}(NEW); call buildRbacSystemFor${simpleEntityName}(NEW);
end if; end if;
end; $$; end; $$;

View File

@ -300,7 +300,7 @@ create or replace function deleteRbacGrantsOfRbacRole()
strict as $$ strict as $$
begin begin
if TG_OP = 'DELETE' then if TG_OP = 'DELETE' then
delete from RbacGrants g where old.uuid in (g.grantedbyroleuuid, g.ascendantuuid, g.descendantuuid); delete from rbac.grants g where old.uuid in (g.grantedbyroleuuid, g.ascendantuuid, g.descendantuuid);
else else
raise exception 'invalid usage of TRIGGER BEFORE DELETE'; raise exception 'invalid usage of TRIGGER BEFORE DELETE';
end if; end if;
@ -484,7 +484,7 @@ $$;
/* /*
Table to store grants / role- or permission assignments to subjects or roles. Table to store grants / role- or permission assignments to subjects or roles.
*/ */
create table RbacGrants create table rbac.grants
( (
uuid uuid primary key default uuid_generate_v4(), uuid uuid primary key default uuid_generate_v4(),
grantedByTriggerOf uuid references rbac.object (uuid) on delete cascade initially deferred , grantedByTriggerOf uuid references rbac.object (uuid) on delete cascade initially deferred ,
@ -494,26 +494,26 @@ create table RbacGrants
assumed boolean not null default true, -- auto assumed (true) vs. needs assumeRoles (false) assumed boolean not null default true, -- auto assumed (true) vs. needs assumeRoles (false)
unique (ascendantUuid, descendantUuid), unique (ascendantUuid, descendantUuid),
constraint rbacGrant_createdBy check ( grantedByRoleUuid is null or grantedByTriggerOf is null) ); constraint rbacGrant_createdBy check ( grantedByRoleUuid is null or grantedByTriggerOf is null) );
create index on RbacGrants (ascendantUuid); create index on rbac.grants (ascendantUuid);
create index on RbacGrants (descendantUuid); create index on rbac.grants (descendantUuid);
call base.create_journal('RbacGrants'); call base.create_journal('rbac.grants');
create or replace function findGrantees(grantedId uuid) create or replace function findGrantees(grantedId uuid)
returns setof rbac.reference returns setof rbac.reference
returns null on null input returns null on null input
language sql as $$ language sql as $$
with recursive grants as ( with recursive grants as (
select descendantUuid, ascendantUuid select descendantUuid, ascendantUuid
from RbacGrants from rbac.grants
where descendantUuid = grantedId where descendantUuid = grantedId
union all union all
select g.descendantUuid, g.ascendantUuid select g.descendantUuid, g.ascendantUuid
from RbacGrants g from rbac.grants g
inner join grants on grants.ascendantUuid = g.descendantUuid inner join grants on grants.ascendantUuid = g.descendantUuid
) )
select ref.* select ref.*
from grants from grants
join rbac.reference ref on ref.uuid = grants.ascendantUuid; join rbac.reference ref on ref.uuid = grants.ascendantUuid;
$$; $$;
create or replace function isGranted(granteeIds uuid[], grantedId uuid) create or replace function isGranted(granteeIds uuid[], grantedId uuid)
@ -522,11 +522,11 @@ create or replace function isGranted(granteeIds uuid[], grantedId uuid)
language sql as $$ language sql as $$
with recursive grants as ( with recursive grants as (
select descendantUuid, ascendantUuid select descendantUuid, ascendantUuid
from RbacGrants from rbac.grants
where descendantUuid = grantedId where descendantUuid = grantedId
union all union all
select "grant".descendantUuid, "grant".ascendantUuid select "grant".descendantUuid, "grant".ascendantUuid
from RbacGrants "grant" from rbac.grants "grant"
inner join grants recur on recur.ascendantUuid = "grant".descendantUuid inner join grants recur on recur.ascendantUuid = "grant".descendantUuid
) )
select exists ( select exists (
@ -548,11 +548,11 @@ create or replace function isPermissionGrantedToSubject(permissionId uuid, subje
language sql as $$ language sql as $$
with recursive grants as ( with recursive grants as (
select descendantUuid, ascendantUuid select descendantUuid, ascendantUuid
from RbacGrants from rbac.grants
where descendantUuid = permissionId where descendantUuid = permissionId
union all union all
select g.descendantUuid, g.ascendantUuid select g.descendantUuid, g.ascendantUuid
from RbacGrants g from rbac.grants g
inner join grants on grants.ascendantUuid = g.descendantUuid inner join grants on grants.ascendantUuid = g.descendantUuid
) )
select exists( select exists(
@ -580,7 +580,7 @@ create or replace function hasGlobalRoleGranted(forAscendantUuid uuid)
language sql as $$ language sql as $$
select exists( select exists(
select r.uuid select r.uuid
from RbacGrants as g from rbac.grants as g
join RbacRole as r on r.uuid = g.descendantuuid join RbacRole as r on r.uuid = g.descendantuuid
join rbac.object as o on o.uuid = r.objectuuid join rbac.object as o on o.uuid = r.objectuuid
where g.ascendantuuid = forAscendantUuid where g.ascendantuuid = forAscendantUuid
@ -595,7 +595,7 @@ begin
perform rbac.assertReferenceType('permissionId (descendant)', permissionUuid, 'RbacPermission'); perform rbac.assertReferenceType('permissionId (descendant)', permissionUuid, 'RbacPermission');
insert insert
into RbacGrants (grantedByTriggerOf, ascendantUuid, descendantUuid, assumed) into rbac.grants (grantedByTriggerOf, ascendantUuid, descendantUuid, assumed)
values (rbac.currentTriggerObjectUuid(), roleUuid, permissionUuid, true) values (rbac.currentTriggerObjectUuid(), roleUuid, permissionUuid, true)
on conflict do nothing; -- allow granting multiple times on conflict do nothing; -- allow granting multiple times
end; end;
@ -619,7 +619,7 @@ begin
end if; end if;
insert insert
into RbacGrants (grantedByTriggerOf, ascendantuuid, descendantUuid, assumed) into rbac.grants (grantedByTriggerOf, ascendantuuid, descendantUuid, assumed)
values (rbac.currentTriggerObjectUuid(), superRoleId, subRoleId, doAssume) values (rbac.currentTriggerObjectUuid(), superRoleId, subRoleId, doAssume)
on conflict do nothing; -- allow granting multiple times on conflict do nothing; -- allow granting multiple times
end; $$; end; $$;
@ -647,7 +647,7 @@ begin
end if; end if;
insert insert
into RbacGrants (grantedByTriggerOf, ascendantuuid, descendantUuid, assumed) into rbac.grants (grantedByTriggerOf, ascendantuuid, descendantUuid, assumed)
values (rbac.currentTriggerObjectUuid(), superRoleId, subRoleId, doAssume) values (rbac.currentTriggerObjectUuid(), superRoleId, subRoleId, doAssume)
on conflict do nothing; -- allow granting multiple times on conflict do nothing; -- allow granting multiple times
end; $$; end; $$;
@ -665,7 +665,7 @@ begin
perform rbac.assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole'); perform rbac.assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole');
if (isGranted(superRoleId, subRoleId)) then if (isGranted(superRoleId, subRoleId)) then
delete from RbacGrants where ascendantUuid = superRoleId and descendantUuid = subRoleId; delete from rbac.grants where ascendantUuid = superRoleId and descendantUuid = subRoleId;
else else
raise exception 'cannot revoke role % (%) from % (%) because it is not granted', raise exception 'cannot revoke role % (%) from % (%) because it is not granted',
subRole, subRoleId, superRole, superRoleId; subRole, subRoleId, superRole, superRoleId;
@ -686,10 +686,10 @@ begin
perform rbac.assertReferenceType('permission (descendant)', permissionId, 'RbacPermission'); perform rbac.assertReferenceType('permission (descendant)', permissionId, 'RbacPermission');
if (isGranted(superRoleId, permissionId)) then if (isGranted(superRoleId, permissionId)) then
delete from RbacGrants where ascendantUuid = superRoleId and descendantUuid = permissionId; delete from rbac.grants where ascendantUuid = superRoleId and descendantUuid = permissionId;
else else
select p.op, o.objectTable, o.uuid select p.op, o.objectTable, o.uuid
from rbacGrants g from rbac.grants g
join rbacPermission p on p.uuid=g.descendantUuid join rbacPermission p on p.uuid=g.descendantUuid
join rbac.object o on o.uuid=p.objectUuid join rbac.object o on o.uuid=p.objectUuid
where g.uuid=permissionId where g.uuid=permissionId
@ -720,12 +720,12 @@ begin
return query return query
WITH RECURSIVE grants AS ( WITH RECURSIVE grants AS (
SELECT descendantUuid, ascendantUuid, 1 AS level SELECT descendantUuid, ascendantUuid, 1 AS level
FROM RbacGrants FROM rbac.grants
WHERE assumed WHERE assumed
AND ascendantUuid = any(subjectIds) AND ascendantUuid = any(subjectIds)
UNION ALL UNION ALL
SELECT g.descendantUuid, g.ascendantUuid, grants.level + 1 AS level SELECT g.descendantUuid, g.ascendantUuid, grants.level + 1 AS level
FROM RbacGrants g FROM rbac.grants g
INNER JOIN grants ON grants.descendantUuid = g.ascendantUuid INNER JOIN grants ON grants.descendantUuid = g.ascendantUuid
WHERE g.assumed WHERE g.assumed
), ),
@ -764,11 +764,11 @@ create or replace function queryPermissionsGrantedToSubjectId(subjectId uuid)
language sql as $$ language sql as $$
with recursive grants as ( with recursive grants as (
select descendantUuid, ascendantUuid select descendantUuid, ascendantUuid
from RbacGrants from rbac.grants
where ascendantUuid = subjectId where ascendantUuid = subjectId
union all union all
select g.descendantUuid, g.ascendantUuid select g.descendantUuid, g.ascendantUuid
from RbacGrants g from rbac.grants g
inner join grants on grants.descendantUuid = g.ascendantUuid inner join grants on grants.descendantUuid = g.ascendantUuid
) )
select perm.* select perm.*
@ -798,11 +798,11 @@ select *
-- @formatter:off -- @formatter:off
with recursive grants as ( with recursive grants as (
select descendantUuid, ascendantUuid select descendantUuid, ascendantUuid
from RbacGrants from rbac.grants
where descendantUuid = objectId where descendantUuid = objectId
union all union all
select "grant".descendantUuid, "grant".ascendantUuid select "grant".descendantUuid, "grant".ascendantUuid
from RbacGrants "grant" from rbac.grants "grant"
inner join grants recur on recur.ascendantUuid = "grant".descendantUuid inner join grants recur on recur.ascendantUuid = "grant".descendantUuid
) )
-- @formatter:on -- @formatter:on

View File

@ -28,7 +28,7 @@ begin
perform rbac.assertReferenceType('subjectUuid (ascendant)', subjectUuid, 'rbac.subject'); perform rbac.assertReferenceType('subjectUuid (ascendant)', subjectUuid, 'rbac.subject');
insert insert
into RbacGrants (grantedByRoleUuid, ascendantUuid, descendantUuid, assumed) into rbac.grants (grantedByRoleUuid, ascendantUuid, descendantUuid, assumed)
values (grantedByRoleUuid, subjectUuid, grantedRoleUuid, doAssume) values (grantedByRoleUuid, subjectUuid, grantedRoleUuid, doAssume)
-- TODO: check if grantedByRoleUuid+doAssume are the same, otherwise raise exception? -- TODO: check if grantedByRoleUuid+doAssume are the same, otherwise raise exception?
on conflict do nothing; -- allow granting multiple times on conflict do nothing; -- allow granting multiple times
@ -61,7 +61,7 @@ begin
end if; end if;
insert insert
into RbacGrants (grantedByRoleUuid, ascendantUuid, descendantUuid, assumed) into rbac.grants (grantedByRoleUuid, ascendantUuid, descendantUuid, assumed)
values (grantedByRoleUuid, subjectUuid, grantedRoleUuid, doAssume); values (grantedByRoleUuid, subjectUuid, grantedRoleUuid, doAssume);
-- TODO.impl: What should happen on multiple grants? What if options (doAssume) are not the same? -- TODO.impl: What should happen on multiple grants? What if options (doAssume) are not the same?
-- Most powerful or latest grant wins? What about managed? -- Most powerful or latest grant wins? What about managed?
@ -104,8 +104,8 @@ create or replace procedure rbac.revokeRoleFromSubject(grantedByRoleUuid uuid, g
begin begin
call rbac.checkRevokeRoleFromSubjectPreconditions(grantedByRoleUuid, grantedRoleUuid, subjectUuid); call rbac.checkRevokeRoleFromSubjectPreconditions(grantedByRoleUuid, grantedRoleUuid, subjectUuid);
raise INFO 'delete from RbacGrants where ascendantUuid = % and descendantUuid = %', subjectUuid, grantedRoleUuid; raise INFO 'delete from rbac.grants where ascendantUuid = % and descendantUuid = %', subjectUuid, grantedRoleUuid;
delete from RbacGrants as g delete from rbac.grants as g
where g.ascendantUuid = subjectUuid and g.descendantUuid = grantedRoleUuid where g.ascendantUuid = subjectUuid and g.descendantUuid = grantedRoleUuid
and g.grantedByRoleUuid = revokeRoleFromSubject.grantedByRoleUuid; and g.grantedByRoleUuid = revokeRoleFromSubject.grantedByRoleUuid;
end; $$; end; $$;
@ -118,8 +118,8 @@ end; $$;
create or replace procedure rbac.revokePermissionFromRole(permissionUuid uuid, superRoleUuid uuid) create or replace procedure rbac.revokePermissionFromRole(permissionUuid uuid, superRoleUuid uuid)
language plpgsql as $$ language plpgsql as $$
begin begin
raise INFO 'delete from RbacGrants where ascendantUuid = % and descendantUuid = %', superRoleUuid, permissionUuid; raise INFO 'delete from rbac.grants where ascendantUuid = % and descendantUuid = %', superRoleUuid, permissionUuid;
delete from RbacGrants as g delete from rbac.grants as g
where g.ascendantUuid = superRoleUuid and g.descendantUuid = permissionUuid; where g.ascendantUuid = superRoleUuid and g.descendantUuid = permissionUuid;
end; $$; end; $$;
--// --//

View File

@ -85,7 +85,7 @@ create or replace view rbacgrants_ev as
) as descendingIdName, ) as descendingIdName,
dro.objectTable, dro.uuid, dro.objectTable, dro.uuid,
dp.op, dp.optablename dp.op, dp.optablename
from rbacgrants as g from rbac.grants as g
left outer join rbacrole as ar on ar.uuid = g.ascendantUuid left outer join rbacrole as ar on ar.uuid = g.ascendantUuid
left outer join rbac.object as aro on aro.uuid = ar.objectuuid left outer join rbac.object as aro on aro.uuid = ar.objectuuid
@ -123,7 +123,7 @@ select o.objectTable || '#' || findIdNameByObjectUuid(o.objectTable, o.uuid) ||
select g.grantedbyroleuuid, g.ascendantuuid, g.descendantuuid, g.assumed, select g.grantedbyroleuuid, g.ascendantuuid, g.descendantuuid, g.assumed,
u.name as userName, o.objecttable, r.objectuuid, r.roletype, u.name as userName, o.objecttable, r.objectuuid, r.roletype,
findIdNameByObjectUuid(o.objectTable, o.uuid) as objectIdName findIdNameByObjectUuid(o.objectTable, o.uuid) as objectIdName
from rbacgrants as g from rbac.grants as g
join rbacrole as r on r.uuid = g.descendantUuid join rbacrole as r on r.uuid = g.descendantUuid
join rbac.object o on o.uuid = r.objectuuid join rbac.object o on o.uuid = r.objectuuid
left outer join rbac.subject u on u.uuid = g.ascendantuuid left outer join rbac.subject u on u.uuid = g.ascendantuuid
@ -211,7 +211,7 @@ select distinct *
from ( from (
select usersInRolesOfcurrentSubject.* select usersInRolesOfcurrentSubject.*
from rbac.subject as usersInRolesOfcurrentSubject from rbac.subject as usersInRolesOfcurrentSubject
join RbacGrants as g on g.ascendantuuid = usersInRolesOfcurrentSubject.uuid join rbac.grants as g on g.ascendantuuid = usersInRolesOfcurrentSubject.uuid
join rbacrole_ev as r on r.uuid = g.descendantuuid join rbacrole_ev as r on r.uuid = g.descendantuuid
union union
select users.* select users.*
@ -236,7 +236,7 @@ create or replace view rbac.subject_rv as
from ( from (
select usersInRolesOfcurrentSubject.* select usersInRolesOfcurrentSubject.*
from rbac.subject as usersInRolesOfcurrentSubject from rbac.subject as usersInRolesOfcurrentSubject
join RbacGrants as g on g.ascendantuuid = usersInRolesOfcurrentSubject.uuid join rbac.grants as g on g.ascendantuuid = usersInRolesOfcurrentSubject.uuid
join rbacrole_rv as r on r.uuid = g.descendantuuid join rbacrole_rv as r on r.uuid = g.descendantuuid
union union
select users.* select users.*
@ -330,7 +330,7 @@ select r.uuid as roleuuid, p.uuid as permissionUuid,
(r.objecttable || ':' || r.objectidname || ':' || r.roletype) as roleName, p.op, (r.objecttable || ':' || r.objectidname || ':' || r.roletype) as roleName, p.op,
o.objecttable, r.objectidname, o.uuid as objectuuid o.objecttable, r.objectidname, o.uuid as objectuuid
from rbacrole_rv r from rbacrole_rv r
join rbacgrants g on g.ascendantuuid = r.uuid join rbac.grants g on g.ascendantuuid = r.uuid
join rbacpermission p on p.uuid = g.descendantuuid join rbacpermission p on p.uuid = g.descendantuuid
join rbac.object o on o.uuid = p.objectuuid; join rbac.object o on o.uuid = p.objectuuid;
grant all privileges on rbac.own_granted_permissions_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME}; grant all privileges on rbac.own_granted_permissions_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
@ -370,7 +370,7 @@ begin
findIdNameByObjectUuid(po.objectTable, po.uuid) as permissionObjectIdName, findIdNameByObjectUuid(po.objectTable, po.uuid) as permissionObjectIdName,
po.uuid as permissionObjectUuid po.uuid as permissionObjectUuid
from queryPermissionsGrantedToSubjectId( targetSubjectUuid) as p from queryPermissionsGrantedToSubjectId( targetSubjectUuid) as p
join rbacgrants as g on g.descendantUuid = p.uuid join rbac.grants as g on g.descendantUuid = p.uuid
join rbac.object as po on po.uuid = p.objectUuid join rbac.object as po on po.uuid = p.objectUuid
join rbacrole_rv as r on r.uuid = g.ascendantUuid join rbacrole_rv as r on r.uuid = g.ascendantUuid
join rbac.object as ro on ro.uuid = r.objectUuid join rbac.object as ro on ro.uuid = r.objectUuid

View File

@ -179,19 +179,19 @@ begin
with accessible_%1$s_uuids as ( with accessible_%1$s_uuids as (
with recursive with recursive
recursive_grants as recursive_grants as
(select distinct rbacgrants.descendantuuid, (select distinct rbac.grants.descendantuuid,
rbacgrants.ascendantuuid, rbac.grants.ascendantuuid,
1 as level, 1 as level,
true true
from rbacgrants from rbac.grants
where rbacgrants.assumed where rbac.grants.assumed
and (rbacgrants.ascendantuuid = any (rbac.currentSubjectOrAssumedRolesUuids())) and (rbac.grants.ascendantuuid = any (rbac.currentSubjectOrAssumedRolesUuids()))
union all union all
select distinct g.descendantuuid, select distinct g.descendantuuid,
g.ascendantuuid, g.ascendantuuid,
grants.level + 1 as level, grants.level + 1 as level,
base.assertTrue(grants.level < 22, 'too many grant-levels: ' || grants.level) base.assertTrue(grants.level < 22, 'too many grant-levels: ' || grants.level)
from rbacgrants g from rbac.grants g
join recursive_grants grants on grants.descendantuuid = g.ascendantuuid join recursive_grants grants on grants.descendantuuid = g.ascendantuuid
where g.assumed), where g.assumed),
grant_count AS ( grant_count AS (

View File

@ -20,7 +20,7 @@ select no, to_char("count", '9 999 999 999') as "count", "table"
from rbac.reference from rbac.reference
union union
select 5 as no, count(*) as "count", 'grants' as "table" select 5 as no, count(*) as "count", 'grants' as "table"
from RbacGrants from rbac.grants
union union
select 6 as no, count(*) as "count", 'objects' as "table" select 6 as no, count(*) as "count", 'objects' as "table"
from rbac.object) as totals from rbac.object) as totals

View File

@ -125,7 +125,7 @@ create or replace procedure updateRbacRulesForHsOfficeRelation(
begin begin
if NEW.contactUuid is distinct from OLD.contactUuid then if NEW.contactUuid is distinct from OLD.contactUuid then
delete from rbacgrants g where g.grantedbytriggerof = OLD.uuid; delete from rbac.grants g where g.grantedbytriggerof = OLD.uuid;
call buildRbacSystemForHsOfficeRelation(NEW); call buildRbacSystemForHsOfficeRelation(NEW);
end if; end if;
end; $$; end; $$;

View File

@ -101,7 +101,7 @@ begin
if NEW.debitorRelUuid is distinct from OLD.debitorRelUuid if NEW.debitorRelUuid is distinct from OLD.debitorRelUuid
or NEW.refundBankAccountUuid is distinct from OLD.refundBankAccountUuid then or NEW.refundBankAccountUuid is distinct from OLD.refundBankAccountUuid then
delete from rbacgrants g where g.grantedbytriggerof = OLD.uuid; delete from rbac.grants g where g.grantedbytriggerof = OLD.uuid;
call buildRbacSystemForHsOfficeDebitor(NEW); call buildRbacSystemForHsOfficeDebitor(NEW);
end if; end if;
end; $$; end; $$;

View File

@ -129,7 +129,7 @@ begin
if NEW.assignedToAssetUuid is distinct from OLD.assignedToAssetUuid if NEW.assignedToAssetUuid is distinct from OLD.assignedToAssetUuid
or NEW.alarmContactUuid is distinct from OLD.alarmContactUuid then or NEW.alarmContactUuid is distinct from OLD.alarmContactUuid then
delete from rbacgrants g where g.grantedbytriggerof = OLD.uuid; delete from rbac.grants g where g.grantedbytriggerof = OLD.uuid;
call buildRbacSystemForHsHostingAsset(NEW); call buildRbacSystemForHsHostingAsset(NEW);
end if; end if;
end; $$; end; $$;