From b490f2c191f1f4c9b1507a713af039da23cd9f4d Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Fri, 13 Sep 2024 20:46:54 +0200 Subject: [PATCH] rbac.role --- .../rbac/rbacrole/RbacRoleEntity.java | 2 +- .../db/changelog/1-rbac/1050-rbac-base.sql | 64 +++++++++---------- .../1-rbac/1051-rbac-subject-grant.sql | 18 +++--- .../db/changelog/1-rbac/1054-rbac-context.sql | 2 +- .../db/changelog/1-rbac/1055-rbac-views.sql | 34 +++++----- .../changelog/1-rbac/1059-rbac-statistics.sql | 2 +- .../rbac/rbacrole/RawRbacRoleEntity.java | 2 +- .../test/ContextBasedTestWithCleanup.java | 2 +- 8 files changed, 63 insertions(+), 63 deletions(-) diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleEntity.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleEntity.java index fa21785a..25fe16de 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleEntity.java @@ -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 diff --git a/src/main/resources/db/changelog/1-rbac/1050-rbac-base.sql b/src/main/resources/db/changelog/1-rbac/1050-rbac-base.sql index 6ddd9d8e..c4ca5906 100644 --- a/src/main/resources/db/changelog/1-rbac/1050-rbac-base.sql +++ b/src/main/resources/db/changelog/1-rbac/1050-rbac-base.sql @@ -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 diff --git a/src/main/resources/db/changelog/1-rbac/1051-rbac-subject-grant.sql b/src/main/resources/db/changelog/1-rbac/1051-rbac-subject-grant.sql index c44d21e4..10442bef 100644 --- a/src/main/resources/db/changelog/1-rbac/1051-rbac-subject-grant.sql +++ b/src/main/resources/db/changelog/1-rbac/1051-rbac-subject-grant.sql @@ -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 diff --git a/src/main/resources/db/changelog/1-rbac/1054-rbac-context.sql b/src/main/resources/db/changelog/1-rbac/1054-rbac-context.sql index 10db7e0f..32399b3c 100644 --- a/src/main/resources/db/changelog/1-rbac/1054-rbac-context.sql +++ b/src/main/resources/db/changelog/1-rbac/1054-rbac-context.sql @@ -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; diff --git a/src/main/resources/db/changelog/1-rbac/1055-rbac-views.sql b/src/main/resources/db/changelog/1-rbac/1055-rbac-views.sql index 94e1616c..130bf547 100644 --- a/src/main/resources/db/changelog/1-rbac/1055-rbac-views.sql +++ b/src/main/resources/db/changelog/1-rbac/1055-rbac-views.sql @@ -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; diff --git a/src/main/resources/db/changelog/1-rbac/1059-rbac-statistics.sql b/src/main/resources/db/changelog/1-rbac/1059-rbac-statistics.sql index 7367e1f0..19670fb9 100644 --- a/src/main/resources/db/changelog/1-rbac/1059-rbac-statistics.sql +++ b/src/main/resources/db/changelog/1-rbac/1059-rbac-statistics.sql @@ -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 diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/rbacrole/RawRbacRoleEntity.java b/src/test/java/net/hostsharing/hsadminng/rbac/rbacrole/RawRbacRoleEntity.java index e80f8ce6..8b800146 100644 --- a/src/test/java/net/hostsharing/hsadminng/rbac/rbacrole/RawRbacRoleEntity.java +++ b/src/test/java/net/hostsharing/hsadminng/rbac/rbacrole/RawRbacRoleEntity.java @@ -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 diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/test/ContextBasedTestWithCleanup.java b/src/test/java/net/hostsharing/hsadminng/rbac/test/ContextBasedTestWithCleanup.java index e386bd4a..5ace3a33 100644 --- a/src/test/java/net/hostsharing/hsadminng/rbac/test/ContextBasedTestWithCleanup.java +++ b/src/test/java/net/hostsharing/hsadminng/rbac/test/ContextBasedTestWithCleanup.java @@ -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 rows = (List) em.createNativeQuery("select * from rbacrole_ev where roleidname like 'hs_booking_project#%'") + final List rows = (List) em.createNativeQuery("select * from rbac.role_ev where roleidname like 'hs_booking_project#%'") .getResultList(); return rows.stream() .map(row -> (row[0]).toString())