rbac.role

This commit is contained in:
Michael Hoennig 2024-09-13 20:46:54 +02:00
parent bcef4e794d
commit b490f2c191
8 changed files with 63 additions and 63 deletions

View File

@ -8,7 +8,7 @@ import jakarta.persistence.*;
import java.util.UUID;
@Entity
@Table(name = "rbacrole_rv")
@Table(schema = "rbac", name = "role_rv")
@Getter
@Setter
@ToString

View File

@ -6,7 +6,7 @@
/*
*/
create type rbac.referenceType as enum ('rbac.subject', 'RbacRole', 'rbac.permission');
create type rbac.referenceType as enum ('rbac.subject', 'rbac.role', 'rbac.permission');
create table rbac.reference
(
@ -166,7 +166,7 @@ end; $$;
create type RbacRoleType as enum ('OWNER', 'ADMIN', 'AGENT', 'TENANT', 'GUEST', 'REFERRER');
create table RbacRole
create table rbac.role
(
uuid uuid primary key references rbac.reference (uuid) on delete cascade initially deferred, -- initially deferred
objectUuid uuid not null references rbac.object (uuid) initially deferred,
@ -174,7 +174,7 @@ create table RbacRole
unique (objectUuid, roleType)
);
call base.create_journal('RbacRole');
call base.create_journal('rbac.role');
create type RbacRoleDescriptor as
(
@ -218,10 +218,10 @@ declare
begin
insert
into rbac.reference (type)
values ('RbacRole')
values ('rbac.role')
returning uuid into referenceId;
insert
into RbacRole (uuid, objectUuid, roleType)
into rbac.role (uuid, objectUuid, roleType)
values (referenceId, roleDescriptor.objectUuid, roleDescriptor.roleType);
return referenceId;
end;
@ -232,7 +232,7 @@ create or replace procedure deleteRole(roleUUid uuid)
language plpgsql as $$
begin
--raise exception '% deleting role uuid %', rbac.currentSubjectOrAssumedRolesUuids(), roleUUid;
delete from RbacRole where uuid = roleUUid;
delete from rbac.role where uuid = roleUUid;
end;
$$;
@ -256,7 +256,7 @@ begin
objectUuidOfRole = findObjectUuidByIdName(objectTableFromRoleIdName, objectNameFromRoleIdName);
select uuid
from RbacRole
from rbac.role
where objectUuid = objectUuidOfRole
and roleType = roleTypeFromRoleIdName
into roleUuid;
@ -267,7 +267,7 @@ create or replace function findRoleId(roleDescriptor RbacRoleDescriptor)
returns uuid
returns null on null input
language sql as $$
select uuid from RbacRole where objectUuid = roleDescriptor.objectUuid and roleType = roleDescriptor.roleType;
select uuid from rbac.role where objectUuid = roleDescriptor.objectUuid and roleType = roleDescriptor.roleType;
$$;
create or replace function getRoleId(roleDescriptor RbacRoleDescriptor)
@ -280,7 +280,7 @@ begin
roleUuid := findRoleId(roleDescriptor);
if (roleUuid is null) then
raise exception 'RbacRole "%#%.%" not found', roleDescriptor.objectTable, roleDescriptor.objectUuid, roleDescriptor.roleType;
raise exception 'rbac.role "%#%.%" not found', roleDescriptor.objectTable, roleDescriptor.objectUuid, roleDescriptor.roleType;
end if;
return roleUuid;
end;
@ -292,9 +292,9 @@ $$;
-- ----------------------------------------------------------------------------
/*
RbacRole BEFORE DELETE TRIGGER function which deletes all related roles.
rbac.role BEFORE DELETE TRIGGER function which deletes all related roles.
*/
create or replace function deleteRbacGrantsOfRbacRole()
create or replace function rbac.delete_grants_of_role_tf()
returns trigger
language plpgsql
strict as $$
@ -308,13 +308,13 @@ begin
end; $$;
/*
Installs the RbacRole BEFORE DELETE TRIGGER.
Installs the rbac.role BEFORE DELETE TRIGGER.
*/
create trigger deleteRbacGrantsOfRbacRole_Trigger
create trigger delete_grants_of_role_tg
before delete
on RbacRole
on rbac.role
for each row
execute procedure deleteRbacGrantsOfRbacRole();
execute procedure rbac.delete_grants_of_role_tf();
--//
@ -325,14 +325,14 @@ execute procedure deleteRbacGrantsOfRbacRole();
/*
rbac.object BEFORE DELETE TRIGGER function which deletes all related roles.
*/
create or replace function deleteRbacRolesOfRbacObject()
create or replace function rbac.delete_roles_of_object_tf()
returns trigger
language plpgsql
strict as $$
begin
if TG_OP = 'DELETE' then
delete from rbac.permission p where p.objectuuid = old.uuid;
delete from RbacRole r where r.objectUuid = old.uuid;
delete from rbac.role r where r.objectUuid = old.uuid;
else
raise exception 'invalid usage of TRIGGER BEFORE DELETE';
end if;
@ -340,13 +340,13 @@ begin
end; $$;
/*
Installs the RbacRole BEFORE DELETE TRIGGER.
Installs the rbac.role BEFORE DELETE TRIGGER.
*/
create trigger deleteRbacRolesOfRbacObject_Trigger
create trigger delete_roles_of_object_tg
before delete
on rbac.object
for each row
execute procedure deleteRbacRolesOfRbacObject();
execute procedure rbac.delete_roles_of_object_tf();
--//
@ -470,8 +470,8 @@ declare
subRoleIdName text;
superRoleIdName text;
begin
select roleIdName from rbacRole_ev where uuid=subRoleId into subRoleIdName;
select roleIdName from rbacRole_ev where uuid=superRoleId into superRoleIdName;
select roleIdName from rbac.role_ev where uuid=subRoleId into subRoleIdName;
select roleIdName from rbac.role_ev where uuid=superRoleId into superRoleIdName;
raise exception '[400] Duplicate role grant detected: role % (%) already granted to % (%)', subRoleId, subRoleIdName, superRoleId, superRoleIdName;
end;
$$;
@ -488,7 +488,7 @@ create table rbac.grants
(
uuid uuid primary key default uuid_generate_v4(),
grantedByTriggerOf uuid references rbac.object (uuid) on delete cascade initially deferred ,
grantedByRoleUuid uuid references RbacRole (uuid),
grantedByRoleUuid uuid references rbac.role (uuid),
ascendantUuid uuid references rbac.reference (uuid),
descendantUuid uuid references rbac.reference (uuid),
assumed boolean not null default true, -- auto assumed (true) vs. needs assumeRoles (false)
@ -581,7 +581,7 @@ create or replace function hasGlobalRoleGranted(forAscendantUuid uuid)
select exists(
select r.uuid
from rbac.grants as g
join RbacRole as r on r.uuid = g.descendantuuid
join rbac.role as r on r.uuid = g.descendantuuid
join rbac.object as o on o.uuid = r.objectuuid
where g.ascendantuuid = forAscendantUuid
and o.objecttable = 'rbac.global'
@ -591,7 +591,7 @@ $$;
create or replace procedure grantPermissionToRole(permissionUuid uuid, roleUuid uuid)
language plpgsql as $$
begin
perform rbac.assertReferenceType('roleId (ascendant)', roleUuid, 'RbacRole');
perform rbac.assertReferenceType('roleId (ascendant)', roleUuid, 'rbac.role');
perform rbac.assertReferenceType('permissionId (descendant)', permissionUuid, 'rbac.permission');
insert
@ -611,8 +611,8 @@ $$;
create or replace procedure grantRoleToRole(subRoleId uuid, superRoleId uuid, doAssume bool = true)
language plpgsql as $$
begin
perform rbac.assertReferenceType('superRoleId (ascendant)', superRoleId, 'RbacRole');
perform rbac.assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole');
perform rbac.assertReferenceType('superRoleId (ascendant)', superRoleId, 'rbac.role');
perform rbac.assertReferenceType('subRoleId (descendant)', subRoleId, 'rbac.role');
if isGranted(subRoleId, superRoleId) then
call raiseDuplicateRoleGrantException(subRoleId, superRoleId);
@ -639,8 +639,8 @@ begin
superRoleId := findRoleId(superRole);
subRoleId := findRoleId(subRole);
perform rbac.assertReferenceType('superRoleId (ascendant)', superRoleId, 'RbacRole');
perform rbac.assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole');
perform rbac.assertReferenceType('superRoleId (ascendant)', superRoleId, 'rbac.role');
perform rbac.assertReferenceType('subRoleId (descendant)', subRoleId, 'rbac.role');
if isGranted(subRoleId, superRoleId) then
call raiseDuplicateRoleGrantException(subRoleId, superRoleId);
@ -661,8 +661,8 @@ begin
superRoleId := findRoleId(superRole);
subRoleId := findRoleId(subRole);
perform rbac.assertReferenceType('superRoleId (ascendant)', superRoleId, 'RbacRole');
perform rbac.assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole');
perform rbac.assertReferenceType('superRoleId (ascendant)', superRoleId, 'rbac.role');
perform rbac.assertReferenceType('subRoleId (descendant)', subRoleId, 'rbac.role');
if (isGranted(superRoleId, subRoleId)) then
delete from rbac.grants where ascendantUuid = superRoleId and descendantUuid = subRoleId;
@ -682,7 +682,7 @@ declare
begin
superRoleId := findRoleId(superRole);
perform rbac.assertReferenceType('superRoleId (ascendant)', superRoleId, 'RbacRole');
perform rbac.assertReferenceType('superRoleId (ascendant)', superRoleId, 'rbac.role');
perform rbac.assertReferenceType('permission (descendant)', permissionId, 'rbac.permission');
if (isGranted(superRoleId, permissionId)) then

View File

@ -23,8 +23,8 @@ end; $$;
create or replace procedure rbac.grantRoleToUserUnchecked(grantedByRoleUuid uuid, grantedRoleUuid uuid, subjectUuid uuid, doAssume boolean = true)
language plpgsql as $$
begin
perform rbac.assertReferenceType('grantingRoleUuid', grantedByRoleUuid, 'RbacRole');
perform rbac.assertReferenceType('roleId (descendant)', grantedRoleUuid, 'RbacRole');
perform rbac.assertReferenceType('grantingRoleUuid', grantedByRoleUuid, 'rbac.role');
perform rbac.assertReferenceType('roleId (descendant)', grantedRoleUuid, 'rbac.role');
perform rbac.assertReferenceType('subjectUuid (ascendant)', subjectUuid, 'rbac.subject');
insert
@ -40,8 +40,8 @@ declare
grantedByRoleIdName text;
grantedRoleIdName text;
begin
perform rbac.assertReferenceType('grantingRoleUuid', grantedByRoleUuid, 'RbacRole');
perform rbac.assertReferenceType('grantedRoleUuid (descendant)', grantedRoleUuid, 'RbacRole');
perform rbac.assertReferenceType('grantingRoleUuid', grantedByRoleUuid, 'rbac.role');
perform rbac.assertReferenceType('grantedRoleUuid (descendant)', grantedRoleUuid, 'rbac.role');
perform rbac.assertReferenceType('subjectUuid (ascendant)', subjectUuid, 'rbac.subject');
assert grantedByRoleUuid is not null, 'grantedByRoleUuid must not be null';
@ -49,13 +49,13 @@ begin
assert subjectUuid is not null, 'subjectUuid must not be null';
if NOT isGranted(rbac.currentSubjectOrAssumedRolesUuids(), grantedByRoleUuid) then
select roleIdName from rbacRole_ev where uuid=grantedByRoleUuid into grantedByRoleIdName;
select roleIdName from rbac.role_ev where uuid=grantedByRoleUuid into grantedByRoleIdName;
raise exception '[403] Access to granted-by-role % (%) forbidden for % (%)',
grantedByRoleIdName, grantedByRoleUuid, currentSubjects(), rbac.currentSubjectOrAssumedRolesUuids();
end if;
if NOT isGranted(grantedByRoleUuid, grantedRoleUuid) then
select roleIdName from rbacRole_ev where uuid=grantedByRoleUuid into grantedByRoleIdName;
select roleIdName from rbacRole_ev where uuid=grantedRoleUuid into grantedRoleIdName;
select roleIdName from rbac.role_ev where uuid=grantedByRoleUuid into grantedByRoleIdName;
select roleIdName from rbac.role_ev where uuid=grantedRoleUuid into grantedRoleIdName;
raise exception '[403] Access to granted role % (%) forbidden for % (%)',
grantedRoleIdName, grantedRoleUuid, grantedByRoleIdName, grantedByRoleUuid;
end if;
@ -77,8 +77,8 @@ end; $$;
create or replace procedure rbac.checkRevokeRoleFromSubjectPreconditions(grantedByRoleUuid uuid, grantedRoleUuid uuid, subjectUuid uuid)
language plpgsql as $$
begin
perform rbac.assertReferenceType('grantedByRoleUuid', grantedByRoleUuid, 'RbacRole');
perform rbac.assertReferenceType('grantedRoleUuid (descendant)', grantedRoleUuid, 'RbacRole');
perform rbac.assertReferenceType('grantedByRoleUuid', grantedByRoleUuid, 'rbac.role');
perform rbac.assertReferenceType('grantedRoleUuid (descendant)', grantedRoleUuid, 'rbac.role');
perform rbac.assertReferenceType('subjectUuid (ascendant)', subjectUuid, 'rbac.subject');
if NOT isGranted(rbac.currentSubjectOrAssumedRolesUuids(), grantedByRoleUuid) then

View File

@ -61,7 +61,7 @@ begin
end if;
select uuid
from RbacRole r
from rbac.role r
where r.objectUuid = objectUuidToAssume
and r.roleType = roleTypeToAssume
into roleUuidToAssume;

View File

@ -7,14 +7,14 @@
Creates a view to the role table with additional columns
for easier human readability.
*/
drop view if exists rbacrole_ev;
create or replace view rbacrole_ev as
drop view if exists rbac.role_ev;
create or replace view rbac.role_ev as
select (objectTable || '#' || objectIdName || ':' || roleType) as roleIdName, *
-- @formatter:off
from (
select r.*,
o.objectTable, findIdNameByObjectUuid(o.objectTable, o.uuid) as objectIdName
from rbacrole as r
from rbac.role as r
join rbac.object as o on o.uuid = r.objectuuid
) as unordered
-- @formatter:on
@ -28,20 +28,20 @@ select (objectTable || '#' || objectIdName || ':' || roleType) as roleIdName, *
Creates a view to the role table with row-level limitation
based on the grants of the current user or assumed roles.
*/
drop view if exists rbacrole_rv;
create or replace view rbacrole_rv as
drop view if exists rbac.role_rv;
create or replace view rbac.role_rv as
select *
-- @formatter:off
from (
select r.*, o.objectTable,
findIdNameByObjectUuid(o.objectTable, o.uuid) as objectIdName
from rbacrole as r
from rbac.role as r
join rbac.object as o on o.uuid = r.objectuuid
where isGranted(rbac.currentSubjectOrAssumedRolesUuids(), r.uuid)
) as unordered
-- @formatter:on
order by objectTable || '#' || objectIdName || ':' || roleType;
grant all privileges on rbacrole_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
grant all privileges on rbac.role_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
--//
@ -87,16 +87,16 @@ create or replace view rbacgrants_ev as
dp.op, dp.optablename
from rbac.grants as g
left outer join rbacrole as ar on ar.uuid = g.ascendantUuid
left outer join rbac.role as ar on ar.uuid = g.ascendantUuid
left outer join rbac.object as aro on aro.uuid = ar.objectuuid
left outer join rbac.subject as au on au.uuid = g.ascendantUuid
left outer join rbacrole as dr on dr.uuid = g.descendantUuid
left outer join rbac.role as dr on dr.uuid = g.descendantUuid
left outer join rbac.object as dro on dro.uuid = dr.objectuuid
left outer join rbac.permission dp on dp.uuid = g.descendantUuid
left outer join rbac.object as dpo on dpo.uuid = dp.objectUuid
) as x
left outer join rbacrole as r on r.uuid = grantedByRoleUuid
left outer join rbac.role as r on r.uuid = grantedByRoleUuid
left outer join rbac.subject u on u.uuid = x.ascendantuuid
left outer join rbac.object go on go.uuid = r.objectuuid
@ -124,16 +124,16 @@ select o.objectTable || '#' || findIdNameByObjectUuid(o.objectTable, o.uuid) ||
u.name as userName, o.objecttable, r.objectuuid, r.roletype,
findIdNameByObjectUuid(o.objectTable, o.uuid) as objectIdName
from rbac.grants as g
join rbacrole as r on r.uuid = g.descendantUuid
join rbac.role as r on r.uuid = g.descendantUuid
join rbac.object o on o.uuid = r.objectuuid
left outer join rbac.subject u on u.uuid = g.ascendantuuid
where isGranted(rbac.currentSubjectOrAssumedRolesUuids(), r.uuid)
) as g
join RbacRole as r on r.uuid = grantedByRoleUuid
join rbac.role as r on r.uuid = grantedByRoleUuid
join rbac.object as o on o.uuid = r.objectUuid
order by grantedRoleIdName;
-- @formatter:on
grant all privileges on rbacrole_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
grant all privileges on rbac.role_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
--//
@ -212,7 +212,7 @@ select distinct *
select usersInRolesOfcurrentSubject.*
from rbac.subject as usersInRolesOfcurrentSubject
join rbac.grants as g on g.ascendantuuid = usersInRolesOfcurrentSubject.uuid
join rbacrole_ev as r on r.uuid = g.descendantuuid
join rbac.role_ev as r on r.uuid = g.descendantuuid
union
select users.*
from rbac.subject as users
@ -237,7 +237,7 @@ create or replace view rbac.subject_rv as
select usersInRolesOfcurrentSubject.*
from rbac.subject as usersInRolesOfcurrentSubject
join rbac.grants as g on g.ascendantuuid = usersInRolesOfcurrentSubject.uuid
join rbacrole_rv as r on r.uuid = g.descendantuuid
join rbac.role_rv as r on r.uuid = g.descendantuuid
union
select users.*
from rbac.subject as users
@ -329,7 +329,7 @@ create or replace view rbac.own_granted_permissions_rv as
select r.uuid as roleuuid, p.uuid as permissionUuid,
(r.objecttable || ':' || r.objectidname || ':' || r.roletype) as roleName, p.op,
o.objecttable, r.objectidname, o.uuid as objectuuid
from rbacrole_rv r
from rbac.role_rv r
join rbac.grants g on g.ascendantuuid = r.uuid
join rbac.permission p on p.uuid = g.descendantuuid
join rbac.object o on o.uuid = p.objectuuid;
@ -372,7 +372,7 @@ begin
from queryPermissionsGrantedToSubjectId( targetSubjectUuid) as p
join rbac.grants as g on g.descendantUuid = p.uuid
join rbac.object as po on po.uuid = p.objectUuid
join rbacrole_rv as r on r.uuid = g.ascendantUuid
join rbac.role_rv as r on r.uuid = g.ascendantUuid
join rbac.object as ro on ro.uuid = r.objectUuid
where isGranted(targetSubjectUuid, r.uuid)
) xp;

View File

@ -11,7 +11,7 @@ select no, to_char("count", '9 999 999 999') as "count", "table"
from rbac.subject
union
select 2 as no, count(*) as "count", 'roles' as "table"
from RbacRole
from rbac.role
union
select 3 as no, count(*) as "count", 'permissions' as "table"
from rbac.permission

View File

@ -10,7 +10,7 @@ import java.util.List;
import java.util.UUID;
@Entity
@Table(name = "rbacrole_ev")
@Table(schema = "rbac", name = "role_ev")
@Getter
@Setter
@ToString

View File

@ -305,7 +305,7 @@ public abstract class ContextBasedTestWithCleanup extends ContextBasedTest {
protected String[] roleNames(final String sqlLikeExpression) {
final var pattern = Pattern.compile(sqlLikeExpression);
//noinspection unchecked
final List<Object[]> rows = (List<Object[]>) em.createNativeQuery("select * from rbacrole_ev where roleidname like 'hs_booking_project#%'")
final List<Object[]> rows = (List<Object[]>) em.createNativeQuery("select * from rbac.role_ev where roleidname like 'hs_booking_project#%'")
.getResultList();
return rows.stream()
.map(row -> (row[0]).toString())