diff --git a/README.md b/README.md index 4301d8fe..23209dd2 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 3cf58e25..9e562148 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 542f1cd7..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,7 +1,11 @@ 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.persistence.HasUuid; @@ -10,7 +14,16 @@ 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; @@ -109,7 +125,7 @@ public class HsOfficeCoopAssetsTransactionEntity implements Stringifyable, HasUu .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 f45b52d4..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,6 +1,10 @@ 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.persistence.HasUuid; @@ -9,7 +13,16 @@ 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; @@ -105,7 +120,7 @@ public class HsOfficeCoopSharesTransactionEntity implements Stringifyable, HasUu .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 f21f5013..71a8b1d0 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 @@ -27,7 +27,7 @@ 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.SQL.fetchedBySql; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor; @@ -145,14 +145,14 @@ public class HsOfficeMembershipEntity implements HasUuid, 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/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 c0def119..f3601449 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 64ef6803..1659c929 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);