diff --git a/README.md b/README.md index 8bdd9461..4d03a6d3 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ If you have at least Docker and the Java JDK installed in appropriate versions a # the following command should return a JSON array with just all packages visible for the admin of the customer yyy: curl \ - -H 'current-user: superuser-alex@hostsharing.net' -H 'assumed-roles: test_customer#yyy:admin' \ + -H 'current-user: superuser-alex@hostsharing.net' -H 'assumed-roles: test_customer#yyy:ADMIN' \ http://localhost:8080/api/test/packages # add a new customer diff --git a/doc/rbac.md b/doc/rbac.md index 3213d740..662bed29 100644 --- a/doc/rbac.md +++ b/doc/rbac.md @@ -206,7 +206,7 @@ and the *role-stereotype* describes a role relative to a referenced business-obj #### owner The owner-role is granted to the subject which created the business object. -E.g. for a new *customer* it would be granted to 'administrators' and for a new *package* to the 'customer#...:admin'. +E.g. for a new *customer* it would be granted to 'administrators' and for a new *package* to the 'customer#...:ADMIN'. Whoever has the owner-role assigned can do everything with the related business-object, including deleting (or deactivating) it. @@ -470,14 +470,14 @@ together { permCustomerXyzSELECT--> boCustXyz } -entity "Role customer#xyz:tenant" as roleCustXyzTenant +entity "Role customer#xyz:TENANT" as roleCustXyzTenant roleCustXyzTenant --> permCustomerXyzSELECT -entity "Role customer#xyz:admin" as roleCustXyzAdmin +entity "Role customer#xyz:ADMIN" as roleCustXyzAdmin roleCustXyzAdmin --> roleCustXyzTenant roleCustXyzAdmin --> permCustomerXyzINSERT:package -entity "Role customer#xyz:owner" as roleCustXyzOwner +entity "Role customer#xyz:OWNER" as roleCustXyzOwner roleCustXyzOwner ..> roleCustXyzAdmin roleCustXyzOwner --> permCustomerXyzDELETE @@ -493,7 +493,7 @@ actorHostmaster --> roleAdmins ``` As you can see, there something special: -From the 'Role customer#xyz:owner' to the 'Role customer#xyz:admin' there is a dashed line, whereas all other lines are solid lines. +From the 'Role customer#xyz:OWNER' to the 'Role customer#xyz:admin' there is a dashed line, whereas all other lines are solid lines. Solid lines means, that one role is granted to another and automatically assumed in all queries to the restricted views. The dashed line means that one role is granted to another but not automatically assumed in queries to the restricted views. @@ -541,15 +541,15 @@ together { } package { - entity "Role customer#xyz:tenant" as roleCustXyzTenant - entity "Role customer#xyz:admin" as roleCustXyzAdmin - entity "Role customer#xyz:owner" as roleCustXyzOwner + entity "Role customer#xyz:TENANT" as roleCustXyzTenant + entity "Role customer#xyz:ADMIN" as roleCustXyzAdmin + entity "Role customer#xyz:OWNER" as roleCustXyzOwner } package { - entity "Role package#xyz00:owner" as rolePacXyz00Owner - entity "Role package#xyz00:admin" as rolePacXyz00Admin - entity "Role package#xyz00:tenant" as rolePacXyz00Tenant + entity "Role package#xyz00:OWNER" as rolePacXyz00Owner + entity "Role package#xyz00:ADMIN" as rolePacXyz00Admin + entity "Role package#xyz00:TENANT" as rolePacXyz00Tenant } rolePacXyz00Tenant --> permPacXyz00SELECT diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionEntity.java index 32bf8bee..af2ea582 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionEntity.java @@ -1,16 +1,29 @@ package net.hostsharing.hsadminng.hs.office.coopassets; -import lombok.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; import net.hostsharing.hsadminng.errors.DisplayName; import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity; -import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject; +import net.hostsharing.hsadminng.persistence.HasUuid; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.stringify.Stringify; import net.hostsharing.hsadminng.stringify.Stringifyable; import org.hibernate.annotations.GenericGenerator; -import jakarta.persistence.*; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import java.io.IOException; import java.io.IOException; import java.math.BigDecimal; import java.time.LocalDate; @@ -20,8 +33,11 @@ import java.util.UUID; import static java.util.Optional.ofNullable; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Column.dependsOnColumn; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NOT_NULL; -import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.*; +import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.INSERT; +import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.SELECT; +import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.UPDATE; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.ADMIN; +import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.AGENT; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL.directlyFetchedByDependsOnColumn; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor; import static net.hostsharing.hsadminng.stringify.Stringify.stringify; @@ -34,7 +50,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify; @NoArgsConstructor @AllArgsConstructor @DisplayName("CoopAssetsTransaction") -public class HsOfficeCoopAssetsTransactionEntity implements Stringifyable, RbacObject { +public class HsOfficeCoopAssetsTransactionEntity implements Stringifyable, HasUuid { private static Stringify stringify = stringify(HsOfficeCoopAssetsTransactionEntity.class) .withIdProp(HsOfficeCoopAssetsTransactionEntity::getTaggedMemberNumber) @@ -109,7 +125,7 @@ public class HsOfficeCoopAssetsTransactionEntity implements Stringifyable, RbacO .toRole("membership", ADMIN).grantPermission(INSERT) .toRole("membership", ADMIN).grantPermission(UPDATE) - .toRole("membership", ADMIN).grantPermission(SELECT); + .toRole("membership", AGENT).grantPermission(SELECT); } public static void main(String[] args) throws IOException { diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionEntity.java index 57318afb..c62c1605 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionEntity.java @@ -1,15 +1,28 @@ package net.hostsharing.hsadminng.hs.office.coopshares; -import lombok.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; import net.hostsharing.hsadminng.errors.DisplayName; import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity; -import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject; +import net.hostsharing.hsadminng.persistence.HasUuid; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL; import net.hostsharing.hsadminng.stringify.Stringify; import net.hostsharing.hsadminng.stringify.Stringifyable; -import jakarta.persistence.*; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import java.io.IOException; import java.io.IOException; import java.time.LocalDate; import java.util.UUID; @@ -17,9 +30,11 @@ import java.util.UUID; import static java.util.Optional.ofNullable; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Column.dependsOnColumn; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NOT_NULL; -import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.*; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.INSERT; -import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.*; +import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.SELECT; +import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.UPDATE; +import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.ADMIN; +import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.AGENT; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL.directlyFetchedByDependsOnColumn; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor; import static net.hostsharing.hsadminng.stringify.Stringify.stringify; @@ -32,7 +47,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify; @NoArgsConstructor @AllArgsConstructor @DisplayName("CoopShareTransaction") -public class HsOfficeCoopSharesTransactionEntity implements Stringifyable, RbacObject { +public class HsOfficeCoopSharesTransactionEntity implements Stringifyable, HasUuid { private static Stringify stringify = stringify(HsOfficeCoopSharesTransactionEntity.class) .withProp(HsOfficeCoopSharesTransactionEntity::getMemberNumberTagged) @@ -105,7 +120,7 @@ public class HsOfficeCoopSharesTransactionEntity implements Stringifyable, RbacO .toRole("membership", ADMIN).grantPermission(INSERT) .toRole("membership", ADMIN).grantPermission(UPDATE) - .toRole("membership", ADMIN).grantPermission(SELECT); + .toRole("membership", AGENT).grantPermission(SELECT); } public static void main(String[] args) throws IOException { diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntity.java index 6259b50d..c486dc92 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntity.java @@ -28,7 +28,8 @@ import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacUserReference. import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.ADMIN; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.AGENT; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.OWNER; -import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.REFERRER; +import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.TENANT; +import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.TENANT; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.TENANT; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL.fetchedBySql; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor; @@ -148,14 +149,14 @@ public class HsOfficeMembershipEntity implements RbacObject, Stringifyable { .createRole(OWNER, (with) -> { with.owningUser(CREATOR); - with.incomingSuperRole("partnerRel", ADMIN); - with.permission(DELETE); }) .createSubRole(ADMIN, (with) -> { - with.incomingSuperRole("partnerRel", AGENT); + with.incomingSuperRole("partnerRel", ADMIN); + with.permission(DELETE); with.permission(UPDATE); }) - .createSubRole(REFERRER, (with) -> { + .createSubRole(AGENT, (with) -> { + with.incomingSuperRole("partnerRel", AGENT); with.outgoingSubRole("partnerRel", TENANT); with.permission(SELECT); }); 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 bfe897a4..6a3387fb 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 @@ -248,7 +248,7 @@ declare objectUuidOfRole uuid; roleUuid uuid; begin - -- TODO.refa: extract function toRbacRoleDescriptor(roleIdName varchar) + find other occurrences + -- TODO.refact: extract function toRbacRoleDescriptor(roleIdName varchar) + find other occurrences roleParts = overlay(roleIdName placing '#' from length(roleIdName) + 1 - strpos(reverse(roleIdName), ':')); objectTableFromRoleIdName = split_part(roleParts, '#', 1); objectNameFromRoleIdName = split_part(roleParts, '#', 2); @@ -356,13 +356,16 @@ create trigger deleteRbacRolesOfRbacObject_Trigger /* */ -create domain RbacOp as varchar(6) +create domain RbacOp as varchar(67) -- TODO: shorten to 8, once the deprecated values are gone check ( VALUE = 'DELETE' or VALUE = 'UPDATE' or VALUE = 'SELECT' or VALUE = 'INSERT' or VALUE = 'ASSUME' + -- TODO: all values below are deprecated, use insert with table + or VALUE ~ '^add-[a-z]+$' + or VALUE ~ '^new-[a-z-]+$' ); create table RbacPermission @@ -414,6 +417,37 @@ begin return permissionUuid; end; $$; +-- TODO: deprecated, remove and amend all usages to createPermission +create or replace function createPermissions(forObjectUuid uuid, permitOps RbacOp[]) + returns uuid[] + language plpgsql as $$ +declare + refId uuid; + permissionIds uuid[] = array []::uuid[]; +begin + if (forObjectUuid is null) then + raise exception 'forObjectUuid must not be null'; + end if; + + for i in array_lower(permitOps, 1)..array_upper(permitOps, 1) + loop + refId = (select uuid from RbacPermission where objectUuid = forObjectUuid and op = permitOps[i]); + if (refId is null) then + insert + into RbacReference ("type") + values ('RbacPermission') + returning uuid into refId; + insert + into RbacPermission (uuid, objectUuid, op) + values (refId, forObjectUuid, permitOps[i]); + end if; + permissionIds = permissionIds || refId; + end loop; + + return permissionIds; +end; +$$; + create or replace function findEffectivePermissionId(forObjectUuid uuid, forOp RbacOp, forOpTableName text = null) returns uuid returns null on null input @@ -615,6 +649,25 @@ begin end; $$; +-- TODO: deprecated, remove and use grantPermissionToRole(...) +create or replace procedure grantPermissionsToRole(roleUuid uuid, permissionIds uuid[]) + language plpgsql as $$ +begin + if cardinality(permissionIds) = 0 then return; end if; + + for i in array_lower(permissionIds, 1)..array_upper(permissionIds, 1) + loop + perform assertReferenceType('roleId (ascendant)', roleUuid, 'RbacRole'); + perform assertReferenceType('permissionId (descendant)', permissionIds[i], 'RbacPermission'); + + insert + into RbacGrants (grantedByTriggerOf, ascendantUuid, descendantUuid, assumed) + values (currentTriggerObjectUuid(), roleUuid, permissionIds[i], true) + on conflict do nothing; -- allow granting multiple times + end loop; +end; +$$; + create or replace procedure grantRoleToRole(subRoleId uuid, superRoleId uuid, doAssume bool = true) language plpgsql as $$ begin @@ -638,7 +691,7 @@ declare superRoleId uuid; subRoleId uuid; begin - -- TODO.refa: maybe separate method grantRoleToRoleIfNotNull(...) for NULLABLE references + -- TODO: maybe separate method grantRoleToRoleIfNotNull(...) for NULLABLE references if superRole.objectUuid is null or subRole.objectuuid is null then return; end if; diff --git a/src/main/resources/db/changelog/1-rbac/1058-rbac-generators.sql b/src/main/resources/db/changelog/1-rbac/1058-rbac-generators.sql index cf0804a0..958d3afe 100644 --- a/src/main/resources/db/changelog/1-rbac/1058-rbac-generators.sql +++ b/src/main/resources/db/changelog/1-rbac/1058-rbac-generators.sql @@ -73,6 +73,15 @@ begin return roleDescriptor('%2$s', entity.uuid, 'TENANT', assumed); end; $f$; + -- TODO: remove guest role + create or replace function %1$sGuest(entity %2$s, assumed boolean = true) + returns RbacRoleDescriptor + language plpgsql + strict as $f$ + begin + return roleDescriptor('%2$s', entity.uuid, 'GUEST', assumed); + end; $f$; + create or replace function %1$sReferrer(entity %2$s) returns RbacRoleDescriptor language plpgsql diff --git a/src/main/resources/db/changelog/1-rbac/1080-rbac-global.sql b/src/main/resources/db/changelog/1-rbac/1080-rbac-global.sql index 7577e88c..c28a464d 100644 --- a/src/main/resources/db/changelog/1-rbac/1080-rbac-global.sql +++ b/src/main/resources/db/changelog/1-rbac/1080-rbac-global.sql @@ -139,7 +139,7 @@ select 'global', (select uuid from RbacObject where objectTable = 'global'), 'GU $$; begin transaction; - call defineContext('creating role:global#loba:guest', null, null, null); + call defineContext('creating role:global#global:guest', null, null, null); select createRole(globalGuest()); commit; --// diff --git a/src/main/resources/db/changelog/5-hs-office/510-membership/5103-hs-office-membership-rbac.md b/src/main/resources/db/changelog/5-hs-office/510-membership/5103-hs-office-membership-rbac.md index d458212c..3681b8e6 100644 --- a/src/main/resources/db/changelog/5-hs-office/510-membership/5103-hs-office-membership-rbac.md +++ b/src/main/resources/db/changelog/5-hs-office/510-membership/5103-hs-office-membership-rbac.md @@ -42,7 +42,7 @@ subgraph membership["`**membership**`"] role:membership:OWNER[[membership:OWNER]] role:membership:ADMIN[[membership:ADMIN]] - role:membership:REFERRER[[membership:REFERRER]] + role:membership:AGENT[[membership:AGENT]] end subgraph membership:permissions[ ] @@ -105,16 +105,16 @@ role:partnerRel.contact:ADMIN -.-> role:partnerRel:TENANT role:partnerRel:TENANT -.-> role:partnerRel.anchorPerson:REFERRER role:partnerRel:TENANT -.-> role:partnerRel.holderPerson:REFERRER role:partnerRel:TENANT -.-> role:partnerRel.contact:REFERRER -role:partnerRel:ADMIN ==> role:membership:OWNER role:membership:OWNER ==> role:membership:ADMIN -role:partnerRel:AGENT ==> role:membership:ADMIN -role:membership:ADMIN ==> role:membership:REFERRER -role:membership:REFERRER ==> role:partnerRel:TENANT +role:partnerRel:ADMIN ==> role:membership:ADMIN +role:membership:ADMIN ==> role:membership:AGENT +role:partnerRel:AGENT ==> role:membership:AGENT +role:membership:AGENT ==> role:partnerRel:TENANT %% granting permissions to roles role:global:ADMIN ==> perm:membership:INSERT -role:membership:OWNER ==> perm:membership:DELETE +role:membership:ADMIN ==> perm:membership:DELETE role:membership:ADMIN ==> perm:membership:UPDATE -role:membership:REFERRER ==> perm:membership:SELECT +role:membership:AGENT ==> perm:membership:SELECT ``` diff --git a/src/main/resources/db/changelog/5-hs-office/510-membership/5103-hs-office-membership-rbac.sql b/src/main/resources/db/changelog/5-hs-office/510-membership/5103-hs-office-membership-rbac.sql index 9c423ba4..7f8de66b 100644 --- a/src/main/resources/db/changelog/5-hs-office/510-membership/5103-hs-office-membership-rbac.sql +++ b/src/main/resources/db/changelog/5-hs-office/510-membership/5103-hs-office-membership-rbac.sql @@ -45,23 +45,23 @@ begin perform createRoleWithGrants( hsOfficeMembershipOWNER(NEW), - permissions => array['DELETE'], - incomingSuperRoles => array[hsOfficeRelationADMIN(newPartnerRel)], userUuids => array[currentUserUuid()] ); perform createRoleWithGrants( hsOfficeMembershipADMIN(NEW), - permissions => array['UPDATE'], + permissions => array['DELETE', 'UPDATE'], incomingSuperRoles => array[ hsOfficeMembershipOWNER(NEW), - hsOfficeRelationAGENT(newPartnerRel)] + hsOfficeRelationADMIN(newPartnerRel)] ); perform createRoleWithGrants( - hsOfficeMembershipREFERRER(NEW), + hsOfficeMembershipAGENT(NEW), permissions => array['SELECT'], - incomingSuperRoles => array[hsOfficeMembershipADMIN(NEW)], + incomingSuperRoles => array[ + hsOfficeMembershipADMIN(NEW), + hsOfficeRelationAGENT(newPartnerRel)], outgoingSubRoles => array[hsOfficeRelationTENANT(newPartnerRel)] ); diff --git a/src/main/resources/db/changelog/5-hs-office/511-coopshares/5113-hs-office-coopshares-rbac.md b/src/main/resources/db/changelog/5-hs-office/511-coopshares/5113-hs-office-coopshares-rbac.md index 129de47c..26ff3d5c 100644 --- a/src/main/resources/db/changelog/5-hs-office/511-coopshares/5113-hs-office-coopshares-rbac.md +++ b/src/main/resources/db/changelog/5-hs-office/511-coopshares/5113-hs-office-coopshares-rbac.md @@ -54,7 +54,7 @@ subgraph membership["`**membership**`"] role:membership:OWNER[[membership:OWNER]] role:membership:ADMIN[[membership:ADMIN]] - role:membership:REFERRER[[membership:REFERRER]] + role:membership:AGENT[[membership:AGENT]] end end @@ -106,15 +106,15 @@ role:membership.partnerRel.contact:ADMIN -.-> role:membership.partnerRel:TENANT role:membership.partnerRel:TENANT -.-> role:membership.partnerRel.anchorPerson:REFERRER role:membership.partnerRel:TENANT -.-> role:membership.partnerRel.holderPerson:REFERRER role:membership.partnerRel:TENANT -.-> role:membership.partnerRel.contact:REFERRER -role:membership.partnerRel:ADMIN -.-> role:membership:OWNER role:membership:OWNER -.-> role:membership:ADMIN -role:membership.partnerRel:AGENT -.-> role:membership:ADMIN -role:membership:ADMIN -.-> role:membership:REFERRER -role:membership:REFERRER -.-> role:membership.partnerRel:TENANT +role:membership.partnerRel:ADMIN -.-> role:membership:ADMIN +role:membership:ADMIN -.-> role:membership:AGENT +role:membership.partnerRel:AGENT -.-> role:membership:AGENT +role:membership:AGENT -.-> role:membership.partnerRel:TENANT %% granting permissions to roles role:membership:ADMIN ==> perm:coopSharesTransaction:INSERT role:membership:ADMIN ==> perm:coopSharesTransaction:UPDATE -role:membership:ADMIN ==> perm:coopSharesTransaction:SELECT +role:membership:AGENT ==> perm:coopSharesTransaction:SELECT ``` diff --git a/src/main/resources/db/changelog/5-hs-office/511-coopshares/5113-hs-office-coopshares-rbac.sql b/src/main/resources/db/changelog/5-hs-office/511-coopshares/5113-hs-office-coopshares-rbac.sql index 1e894300..f4856f0a 100644 --- a/src/main/resources/db/changelog/5-hs-office/511-coopshares/5113-hs-office-coopshares-rbac.sql +++ b/src/main/resources/db/changelog/5-hs-office/511-coopshares/5113-hs-office-coopshares-rbac.sql @@ -38,7 +38,7 @@ begin SELECT * FROM hs_office_membership WHERE uuid = NEW.membershipUuid INTO newMembership; assert newMembership.uuid is not null, format('newMembership must not be null for NEW.membershipUuid = %s', NEW.membershipUuid); - call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeMembershipADMIN(newMembership)); + call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeMembershipAGENT(newMembership)); call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeMembershipADMIN(newMembership)); call leaveTriggerForObjectUuid(NEW.uuid); diff --git a/src/main/resources/db/changelog/5-hs-office/512-coopassets/5123-hs-office-coopassets-rbac.md b/src/main/resources/db/changelog/5-hs-office/512-coopassets/5123-hs-office-coopassets-rbac.md index 2b96a199..d220a38c 100644 --- a/src/main/resources/db/changelog/5-hs-office/512-coopassets/5123-hs-office-coopassets-rbac.md +++ b/src/main/resources/db/changelog/5-hs-office/512-coopassets/5123-hs-office-coopassets-rbac.md @@ -54,7 +54,7 @@ subgraph membership["`**membership**`"] role:membership:OWNER[[membership:OWNER]] role:membership:ADMIN[[membership:ADMIN]] - role:membership:REFERRER[[membership:REFERRER]] + role:membership:AGENT[[membership:AGENT]] end end @@ -106,15 +106,15 @@ role:membership.partnerRel.contact:ADMIN -.-> role:membership.partnerRel:TENANT role:membership.partnerRel:TENANT -.-> role:membership.partnerRel.anchorPerson:REFERRER role:membership.partnerRel:TENANT -.-> role:membership.partnerRel.holderPerson:REFERRER role:membership.partnerRel:TENANT -.-> role:membership.partnerRel.contact:REFERRER -role:membership.partnerRel:ADMIN -.-> role:membership:OWNER role:membership:OWNER -.-> role:membership:ADMIN -role:membership.partnerRel:AGENT -.-> role:membership:ADMIN -role:membership:ADMIN -.-> role:membership:REFERRER -role:membership:REFERRER -.-> role:membership.partnerRel:TENANT +role:membership.partnerRel:ADMIN -.-> role:membership:ADMIN +role:membership:ADMIN -.-> role:membership:AGENT +role:membership.partnerRel:AGENT -.-> role:membership:AGENT +role:membership:AGENT -.-> role:membership.partnerRel:TENANT %% granting permissions to roles role:membership:ADMIN ==> perm:coopAssetsTransaction:INSERT role:membership:ADMIN ==> perm:coopAssetsTransaction:UPDATE -role:membership:ADMIN ==> perm:coopAssetsTransaction:SELECT +role:membership:AGENT ==> perm:coopAssetsTransaction:SELECT ``` diff --git a/src/main/resources/db/changelog/5-hs-office/512-coopassets/5123-hs-office-coopassets-rbac.sql b/src/main/resources/db/changelog/5-hs-office/512-coopassets/5123-hs-office-coopassets-rbac.sql index 2c292436..df1fdd3b 100644 --- a/src/main/resources/db/changelog/5-hs-office/512-coopassets/5123-hs-office-coopassets-rbac.sql +++ b/src/main/resources/db/changelog/5-hs-office/512-coopassets/5123-hs-office-coopassets-rbac.sql @@ -38,7 +38,7 @@ begin SELECT * FROM hs_office_membership WHERE uuid = NEW.membershipUuid INTO newMembership; assert newMembership.uuid is not null, format('newMembership must not be null for NEW.membershipUuid = %s', NEW.membershipUuid); - call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeMembershipADMIN(newMembership)); + call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeMembershipAGENT(newMembership)); call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeMembershipADMIN(newMembership)); call leaveTriggerForObjectUuid(NEW.uuid); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionRepositoryIntegrationTest.java index 40163eab..978e2081 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionRepositoryIntegrationTest.java @@ -112,7 +112,7 @@ class HsOfficeCoopAssetsTransactionRepositoryIntegrationTest extends ContextBase .map(s -> s.replace("hs_office_", "")) .containsExactlyInAnyOrder(Array.fromFormatted( initialGrantNames, - "{ grant perm:coopassetstransaction#temprefB:SELECT to role:membership#M-1000101:ADMIN by system and assume }", + "{ grant perm:coopassetstransaction#temprefB:SELECT to role:membership#M-1000101:AGENT by system and assume }", "{ grant perm:coopassetstransaction#temprefB:UPDATE to role:membership#M-1000101:ADMIN by system and assume }", null)); } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionRepositoryIntegrationTest.java index b0b01d65..eff83079 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionRepositoryIntegrationTest.java @@ -111,7 +111,7 @@ class HsOfficeCoopSharesTransactionRepositoryIntegrationTest extends ContextBase .map(s -> s.replace("hs_office_", "")) .containsExactlyInAnyOrder(Array.fromFormatted( initialGrantNames, - "{ grant perm:coopsharestransaction#temprefB:SELECT to role:membership#M-1000101:ADMIN by system and assume }", + "{ grant perm:coopsharestransaction#temprefB:SELECT to role:membership#M-1000101:AGENT by system and assume }", "{ grant perm:coopsharestransaction#temprefB:UPDATE to role:membership#M-1000101:ADMIN by system and assume }", null)); } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipControllerAcceptanceTest.java index 5b59c9cb..5ff5c032 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipControllerAcceptanceTest.java @@ -335,18 +335,18 @@ class HsOfficeMembershipControllerAcceptanceTest extends ContextBasedTestWithCle } @Test - void partnerRelAgent_canPatchValidityOfRelatedMembership() { + void partnerRelAdmin_canPatchValidityOfRelatedMembership() { // given - final var givenPartnerAgent = "hs_office_relation#HostsharingeG-with-PARTNER-FirstGmbH:AGENT"; - context.define("superuser-alex@hostsharing.net", givenPartnerAgent); + final var givenPartnerAdmin = "hs_office_relation#HostsharingeG-with-PARTNER-FirstGmbH:ADMIN"; + context.define("superuser-alex@hostsharing.net", givenPartnerAdmin); final var givenMembership = givenSomeTemporaryMembershipBessler("First"); // when RestAssured // @formatter:off .given() .header("current-user", "superuser-alex@hostsharing.net") - .header("assumed-roles", givenPartnerAgent) + .header("assumed-roles", givenPartnerAdmin) .contentType(ContentType.JSON) .body(""" { diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipRepositoryIntegrationTest.java index 8ffc9e1b..633278a0 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipRepositoryIntegrationTest.java @@ -110,9 +110,9 @@ class HsOfficeMembershipRepositoryIntegrationTest extends ContextBasedTestWithCl final var all = rawRoleRepo.findAll(); assertThat(distinctRoleNamesOf(all)).containsExactlyInAnyOrder(Array.from( initialRoleNames, - "hs_office_membership#M-1000117:ADMIN", "hs_office_membership#M-1000117:OWNER", - "hs_office_membership#M-1000117:REFERRER")); + "hs_office_membership#M-1000117:ADMIN", + "hs_office_membership#M-1000117:AGENT")); assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll())) .map(s -> s.replace("hs_office_", "")) .containsExactlyInAnyOrder(Array.fromFormatted( @@ -122,21 +122,20 @@ class HsOfficeMembershipRepositoryIntegrationTest extends ContextBasedTestWithCl "{ grant perm:membership#M-1000117:INSERT>coopsharestransaction to role:membership#M-1000117:ADMIN by system and assume }", // owner - "{ grant perm:membership#M-1000117:DELETE to role:membership#M-1000117:OWNER by system and assume }", + "{ grant perm:membership#M-1000117:DELETE to role:membership#M-1000117:ADMIN by system and assume }", + "{ grant role:membership#M-1000117:OWNER to user:superuser-alex@hostsharing.net by membership#M-1000117:OWNER and assume }", // admin - "{ grant perm:membership#M-1000117:UPDATE to role:membership#M-1000117:ADMIN by system and assume }", - "{ grant role:membership#M-1000117:ADMIN to role:membership#M-1000117:OWNER by system and assume }", - "{ grant role:membership#M-1000117:OWNER to role:relation#HostsharingeG-with-PARTNER-FirstGmbH:ADMIN by system and assume }", - "{ grant role:membership#M-1000117:OWNER to user:superuser-alex@hostsharing.net by membership#M-1000117:OWNER and assume }", + "{ grant perm:membership#M-1000117:UPDATE to role:membership#M-1000117:ADMIN by system and assume }", + "{ grant role:membership#M-1000117:ADMIN to role:membership#M-1000117:OWNER by system and assume }", + "{ grant role:membership#M-1000117:ADMIN to role:relation#HostsharingeG-with-PARTNER-FirstGmbH:ADMIN by system and assume }", // agent - "{ grant role:membership#M-1000117:ADMIN to role:relation#HostsharingeG-with-PARTNER-FirstGmbH:AGENT by system and assume }", + "{ grant perm:membership#M-1000117:SELECT to role:membership#M-1000117:AGENT by system and assume }", + "{ grant role:membership#M-1000117:AGENT to role:membership#M-1000117:ADMIN by system and assume }", - // referrer - "{ grant perm:membership#M-1000117:SELECT to role:membership#M-1000117:REFERRER by system and assume }", - "{ grant role:membership#M-1000117:REFERRER to role:membership#M-1000117:ADMIN by system and assume }", - "{ grant role:relation#HostsharingeG-with-PARTNER-FirstGmbH:TENANT to role:membership#M-1000117:REFERRER by system and assume }", + "{ grant role:membership#M-1000117:AGENT to role:relation#HostsharingeG-with-PARTNER-FirstGmbH:AGENT by system and assume }", + "{ grant role:relation#HostsharingeG-with-PARTNER-FirstGmbH:TENANT to role:membership#M-1000117:AGENT by system and assume }", null)); } @@ -224,20 +223,20 @@ class HsOfficeMembershipRepositoryIntegrationTest extends ContextBasedTestWithCl } @Test - public void membershipReferrer_canViewButNotUpdateRelatedMembership() { + public void membershipAgent_canViewButNotUpdateRelatedMembership() { // given context("superuser-alex@hostsharing.net"); final var givenMembership = givenSomeTemporaryMembership("First", "13"); assertThatMembershipExistsAndIsAccessibleToCurrentContext(givenMembership); assertThatMembershipIsVisibleForRole( givenMembership, - "hs_office_membership#M-1000113:REFERRER"); + "hs_office_membership#M-1000113:AGENT"); final var newValidityEnd = LocalDate.now(); // when final var result = jpaAttempt.transacted(() -> { // TODO: we should test with debitor- and partner-admin as well - context("superuser-alex@hostsharing.net", "hs_office_membership#M-1000113:REFERRER"); + context("superuser-alex@hostsharing.net", "hs_office_membership#M-1000113:AGENT"); givenMembership.setValidity( Range.closedOpen(givenMembership.getValidity().lower(), newValidityEnd)); return membershipRepo.save(givenMembership); diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantControllerAcceptanceTest.java index 8bcfd28e..9b6bb3a9 100644 --- a/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantControllerAcceptanceTest.java @@ -507,7 +507,7 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest { }).assertNotNull().returnedValue(); } - RbacRoleRvEntity getRbacRoleByName(final String roleName) { + RbacRoleEntity getRbacRoleByName(final String roleName) { return jpaAttempt.transacted(() -> { context("superuser-alex@hostsharing.net", null); return rbacRoleRepository.findByRoleName(roleName); diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/rbacrole/TestRbacRole.java b/src/test/java/net/hostsharing/hsadminng/rbac/rbacrole/TestRbacRole.java index 9eb0f3c7..73e30a1b 100644 --- a/src/test/java/net/hostsharing/hsadminng/rbac/rbacrole/TestRbacRole.java +++ b/src/test/java/net/hostsharing/hsadminng/rbac/rbacrole/TestRbacRole.java @@ -4,11 +4,11 @@ import static java.util.UUID.randomUUID; public class TestRbacRole { - public static final RbacRoleRvEntity hostmasterRole = rbacRole("global", "global", RbacRoleType.ADMIN); - static final RbacRoleRvEntity customerXxxOwner = rbacRole("test_customer", "xxx", RbacRoleType.OWNER); - static final RbacRoleRvEntity customerXxxAdmin = rbacRole("test_customer", "xxx", RbacRoleType.ADMIN); + public static final RbacRoleEntity hostmasterRole = rbacRole("global", "global", RbacRoleType.ADMIN); + static final RbacRoleEntity customerXxxOwner = rbacRole("test_customer", "xxx", RbacRoleType.OWNER); + static final RbacRoleEntity customerXxxAdmin = rbacRole("test_customer", "xxx", RbacRoleType.ADMIN); - static public RbacRoleRvEntity rbacRole(final String objectTable, final String objectIdName, final RbacRoleType roleType) { - return new RbacRoleRvEntity(randomUUID(), randomUUID(), objectTable, objectIdName, roleType, objectTable+'#'+objectIdName+':'+roleType); + static public RbacRoleEntity rbacRole(final String objectTable, final String objectIdName, final RbacRoleType roleType) { + return new RbacRoleEntity(randomUUID(), randomUUID(), objectTable, objectIdName, roleType, objectTable+'#'+objectIdName+':'+roleType); } }