From 0a033c28f1291c9389872ec4eab0b9e0030541df Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Thu, 28 Mar 2024 13:40:28 +0100 Subject: [PATCH 01/29] allow currentTask up to 127 characters in length --- src/main/resources/db/changelog/010-context.sql | 10 +++++----- src/main/resources/db/changelog/020-audit-log.sql | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/resources/db/changelog/010-context.sql b/src/main/resources/db/changelog/010-context.sql index 66ebacc3..ba655e93 100644 --- a/src/main/resources/db/changelog/010-context.sql +++ b/src/main/resources/db/changelog/010-context.sql @@ -23,7 +23,7 @@ end; $$; Defines the transaction context. */ create or replace procedure defineContext( - currentTask varchar(96), + currentTask varchar(127), currentRequest text = null, currentUser varchar(63) = null, assumedRoles varchar(1023) = null @@ -31,8 +31,8 @@ create or replace procedure defineContext( language plpgsql as $$ begin currentTask := coalesce(currentTask, ''); - assert length(currentTask) <= 96, FORMAT('currentTask must not be longer than 96 characters: "%s"', currentTask); - assert length(currentTask) > 8, FORMAT('currentTask must be at least 8 characters long: "%s""', currentTask); + assert length(currentTask) <= 127, FORMAT('currentTask must not be longer than 127 characters: "%s"', currentTask); + assert length(currentTask) >= 12, FORMAT('currentTask must be at least 12 characters long: "%s""', currentTask); execute format('set local hsadminng.currentTask to %L', currentTask); currentRequest := coalesce(currentRequest, ''); @@ -59,11 +59,11 @@ end; $$; Raises exception if not set. */ create or replace function currentTask() - returns varchar(96) + returns varchar(127) stable -- leakproof language plpgsql as $$ declare - currentTask varchar(96); + currentTask varchar(127); begin begin currentTask := current_setting('hsadminng.currentTask'); diff --git a/src/main/resources/db/changelog/020-audit-log.sql b/src/main/resources/db/changelog/020-audit-log.sql index 2491218d..4c2826e3 100644 --- a/src/main/resources/db/changelog/020-audit-log.sql +++ b/src/main/resources/db/changelog/020-audit-log.sql @@ -28,7 +28,7 @@ create table tx_context txTimestamp timestamp not null, currentUser varchar(63) not null, -- not the uuid, because users can be deleted assumedRoles varchar(1023) not null, -- not the uuids, because roles can be deleted - currentTask varchar(96) not null, + currentTask varchar(127) not null, currentRequest text not null ); -- 2.39.5 From 59c41a176ec18e1cf367a22751b1ea7d3684691a Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Thu, 28 Mar 2024 15:42:38 +0100 Subject: [PATCH 02/29] generated RBAC for CoopShares --- .../HsOfficeCoopSharesTransactionEntity.java | 28 ++ .../313-hs-office-coopshares-rbac.md | 257 ++++++++++++++++-- .../313-hs-office-coopshares-rbac.sql | 174 +++++++----- ...sTransactionRepositoryIntegrationTest.java | 3 +- 4 files changed, 369 insertions(+), 93 deletions(-) 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 807af25f..4a36f63d 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 @@ -4,14 +4,24 @@ import lombok.*; import net.hostsharing.hsadminng.errors.DisplayName; import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity; 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 java.io.IOException; import java.time.LocalDate; 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.SQL.directlyFetchedByDependsOnColumn; +import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor; import static net.hostsharing.hsadminng.stringify.Stringify.stringify; @Entity @@ -83,4 +93,22 @@ public class HsOfficeCoopSharesTransactionEntity implements Stringifyable, HasUu public String toShortString() { return "%s%+d".formatted(getMemberNumberTagged(), shareCount); } + + public static RbacView rbac() { + return rbacViewFor("coopSharesTransaction", HsOfficeCoopSharesTransactionEntity.class) + .withIdentityView(SQL.projection("reference")) + .withUpdatableColumns("comment") + .importEntityAlias("membership", HsOfficeMembershipEntity.class, + dependsOnColumn("membershipUuid"), + directlyFetchedByDependsOnColumn(), + NOT_NULL) + + .toRole("membership", ADMIN).grantPermission(INSERT) + .toRole("membership", ADMIN).grantPermission(UPDATE) + .toRole("membership", ADMIN).grantPermission(SELECT); + } + + public static void main(String[] args) throws IOException { + rbac().generateWithBaseFileName("313-hs-office-coopshares-rbac"); + } } diff --git a/src/main/resources/db/changelog/313-hs-office-coopshares-rbac.md b/src/main/resources/db/changelog/313-hs-office-coopshares-rbac.md index 4093eb2d..cdc18b6f 100644 --- a/src/main/resources/db/changelog/313-hs-office-coopshares-rbac.md +++ b/src/main/resources/db/changelog/313-hs-office-coopshares-rbac.md @@ -1,29 +1,250 @@ -### hs_office_coopSharesTransaction RBAC +### rbac coopSharesTransaction + +This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually. ```mermaid +%%{init:{'flowchart':{'htmlLabels':false}}}%% flowchart TB -subgraph hsOfficeMembership +subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"] direction TB - style hsOfficeMembership fill:#eee - - role:hsOfficeMembership.owner[membership.admin] - --> role:hsOfficeMembership.admin[membership.admin] - --> role:hsOfficeMembership.agent[membership.agent] - --> role:hsOfficeMembership.tenant[membership.tenant] - --> role:hsOfficeMembership.guest[membership.guest] - - role:hsOfficePartner.agent --> role:hsOfficeMembership.agent + style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.holderPerson:roles[ ] + style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.holderPerson:owner[[membership.partnerRel.holderPerson:owner]] + role:membership.partnerRel.holderPerson:admin[[membership.partnerRel.holderPerson:admin]] + role:membership.partnerRel.holderPerson:referrer[[membership.partnerRel.holderPerson:referrer]] + end end -subgraph hsOfficeCoopSharesTransaction - - role:hsOfficeMembership.admin - --> perm:hsOfficeCoopSharesTransaction.create{{coopSharesTx.create}} - - role:hsOfficeMembership.agent - --> perm:hsOfficeCoopSharesTransaction.view{{coopSharesTx.view}} +subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"] + direction TB + style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.anchorPerson:roles[ ] + style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.anchorPerson:owner[[membership.partnerRel.anchorPerson:owner]] + role:membership.partnerRel.anchorPerson:admin[[membership.partnerRel.anchorPerson:admin]] + role:membership.partnerRel.anchorPerson:referrer[[membership.partnerRel.anchorPerson:referrer]] + end end +subgraph coopSharesTransaction["`**coopSharesTransaction**`"] + direction TB + style coopSharesTransaction fill:#dd4901,stroke:#274d6e,stroke-width:8px + + subgraph coopSharesTransaction:permissions[ ] + style coopSharesTransaction:permissions fill:#dd4901,stroke:white + + perm:coopSharesTransaction:INSERT{{coopSharesTransaction:INSERT}} + perm:coopSharesTransaction:UPDATE{{coopSharesTransaction:UPDATE}} + perm:coopSharesTransaction:SELECT{{coopSharesTransaction:SELECT}} + end +end + +subgraph membership["`**membership**`"] + direction TB + style membership fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"] + direction TB + style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.holderPerson:roles[ ] + style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.holderPerson:owner[[membership.partnerRel.holderPerson:owner]] + role:membership.partnerRel.holderPerson:admin[[membership.partnerRel.holderPerson:admin]] + role:membership.partnerRel.holderPerson:referrer[[membership.partnerRel.holderPerson:referrer]] + end + end + + subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"] + direction TB + style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.anchorPerson:roles[ ] + style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.anchorPerson:owner[[membership.partnerRel.anchorPerson:owner]] + role:membership.partnerRel.anchorPerson:admin[[membership.partnerRel.anchorPerson:admin]] + role:membership.partnerRel.anchorPerson:referrer[[membership.partnerRel.anchorPerson:referrer]] + end + end + + subgraph membership.partnerRel["`**membership.partnerRel**`"] + direction TB + style membership.partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"] + direction TB + style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.holderPerson:roles[ ] + style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.holderPerson:owner[[membership.partnerRel.holderPerson:owner]] + role:membership.partnerRel.holderPerson:admin[[membership.partnerRel.holderPerson:admin]] + role:membership.partnerRel.holderPerson:referrer[[membership.partnerRel.holderPerson:referrer]] + end + end + + subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"] + direction TB + style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.anchorPerson:roles[ ] + style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.anchorPerson:owner[[membership.partnerRel.anchorPerson:owner]] + role:membership.partnerRel.anchorPerson:admin[[membership.partnerRel.anchorPerson:admin]] + role:membership.partnerRel.anchorPerson:referrer[[membership.partnerRel.anchorPerson:referrer]] + end + end + + subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"] + direction TB + style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.contact:roles[ ] + style membership.partnerRel.contact:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.contact:owner[[membership.partnerRel.contact:owner]] + role:membership.partnerRel.contact:admin[[membership.partnerRel.contact:admin]] + role:membership.partnerRel.contact:referrer[[membership.partnerRel.contact:referrer]] + end + end + + subgraph membership.partnerRel:roles[ ] + style membership.partnerRel:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel:owner[[membership.partnerRel:owner]] + role:membership.partnerRel:admin[[membership.partnerRel:admin]] + role:membership.partnerRel:agent[[membership.partnerRel:agent]] + role:membership.partnerRel:tenant[[membership.partnerRel:tenant]] + end + end + + subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"] + direction TB + style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.contact:roles[ ] + style membership.partnerRel.contact:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.contact:owner[[membership.partnerRel.contact:owner]] + role:membership.partnerRel.contact:admin[[membership.partnerRel.contact:admin]] + role:membership.partnerRel.contact:referrer[[membership.partnerRel.contact:referrer]] + end + end + + subgraph membership:roles[ ] + style membership:roles fill:#99bcdb,stroke:white + + role:membership:owner[[membership:owner]] + role:membership:admin[[membership:admin]] + role:membership:referrer[[membership:referrer]] + end +end + +subgraph membership.partnerRel["`**membership.partnerRel**`"] + direction TB + style membership.partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"] + direction TB + style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.holderPerson:roles[ ] + style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.holderPerson:owner[[membership.partnerRel.holderPerson:owner]] + role:membership.partnerRel.holderPerson:admin[[membership.partnerRel.holderPerson:admin]] + role:membership.partnerRel.holderPerson:referrer[[membership.partnerRel.holderPerson:referrer]] + end + end + + subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"] + direction TB + style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.anchorPerson:roles[ ] + style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.anchorPerson:owner[[membership.partnerRel.anchorPerson:owner]] + role:membership.partnerRel.anchorPerson:admin[[membership.partnerRel.anchorPerson:admin]] + role:membership.partnerRel.anchorPerson:referrer[[membership.partnerRel.anchorPerson:referrer]] + end + end + + subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"] + direction TB + style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.contact:roles[ ] + style membership.partnerRel.contact:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.contact:owner[[membership.partnerRel.contact:owner]] + role:membership.partnerRel.contact:admin[[membership.partnerRel.contact:admin]] + role:membership.partnerRel.contact:referrer[[membership.partnerRel.contact:referrer]] + end + end + + subgraph membership.partnerRel:roles[ ] + style membership.partnerRel:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel:owner[[membership.partnerRel:owner]] + role:membership.partnerRel:admin[[membership.partnerRel:admin]] + role:membership.partnerRel:agent[[membership.partnerRel:agent]] + role:membership.partnerRel:tenant[[membership.partnerRel:tenant]] + end +end + +subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"] + direction TB + style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.contact:roles[ ] + style membership.partnerRel.contact:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.contact:owner[[membership.partnerRel.contact:owner]] + role:membership.partnerRel.contact:admin[[membership.partnerRel.contact:admin]] + role:membership.partnerRel.contact:referrer[[membership.partnerRel.contact:referrer]] + end +end + +%% granting roles to roles +role:global:admin -.-> role:membership.partnerRel.anchorPerson:owner +role:membership.partnerRel.anchorPerson:owner -.-> role:membership.partnerRel.anchorPerson:admin +role:membership.partnerRel.anchorPerson:admin -.-> role:membership.partnerRel.anchorPerson:referrer +role:global:admin -.-> role:membership.partnerRel.holderPerson:owner +role:membership.partnerRel.holderPerson:owner -.-> role:membership.partnerRel.holderPerson:admin +role:membership.partnerRel.holderPerson:admin -.-> role:membership.partnerRel.holderPerson:referrer +role:global:admin -.-> role:membership.partnerRel.contact:owner +role:membership.partnerRel.contact:owner -.-> role:membership.partnerRel.contact:admin +role:membership.partnerRel.contact:admin -.-> role:membership.partnerRel.contact:referrer +role:global:admin -.-> role:membership.partnerRel:owner +role:membership.partnerRel:owner -.-> role:membership.partnerRel:admin +role:membership.partnerRel.anchorPerson:admin -.-> role:membership.partnerRel:admin +role:membership.partnerRel:admin -.-> role:membership.partnerRel:agent +role:membership.partnerRel.holderPerson:admin -.-> role:membership.partnerRel:agent +role:membership.partnerRel:agent -.-> role:membership.partnerRel:tenant +role:membership.partnerRel.holderPerson:admin -.-> role:membership.partnerRel:tenant +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 + +%% granting permissions to roles +role:membership:admin ==> perm:coopSharesTransaction:INSERT +role:membership:admin ==> perm:coopSharesTransaction:UPDATE +role:membership:admin ==> perm:coopSharesTransaction:SELECT ``` diff --git a/src/main/resources/db/changelog/313-hs-office-coopshares-rbac.sql b/src/main/resources/db/changelog/313-hs-office-coopshares-rbac.sql index a4cac136..0f063309 100644 --- a/src/main/resources/db/changelog/313-hs-office-coopshares-rbac.sql +++ b/src/main/resources/db/changelog/313-hs-office-coopshares-rbac.sql @@ -1,125 +1,151 @@ --liquibase formatted sql +-- This code generated was by RbacViewPostgresGenerator, do not amend manually. + -- ============================================================================ ---changeset hs-office-coopSharesTransaction-rbac-OBJECT:1 endDelimiter:--// +--changeset hs-office-coopsharestransaction-rbac-OBJECT:1 endDelimiter:--// -- ---------------------------------------------------------------------------- -call generateRelatedRbacObject('hs_office_coopSharesTransaction'); +call generateRelatedRbacObject('hs_office_coopsharestransaction'); --// -- ============================================================================ ---changeset hs-office-coopSharesTransaction-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--// +--changeset hs-office-coopsharestransaction-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--// -- ---------------------------------------------------------------------------- -call generateRbacRoleDescriptors('hsOfficeCoopSharesTransaction', 'hs_office_coopSharesTransaction'); +call generateRbacRoleDescriptors('hsOfficeCoopSharesTransaction', 'hs_office_coopsharestransaction'); --// -- ============================================================================ ---changeset hs-office-coopSharesTransaction-rbac-ROLES-CREATION:1 endDelimiter:--// +--changeset hs-office-coopsharestransaction-rbac-insert-trigger:1 endDelimiter:--// -- ---------------------------------------------------------------------------- /* - Creates and updates the permissions for coopSharesTransaction entities. + Creates the roles, grants and permission for the AFTER INSERT TRIGGER. */ -create or replace function hsOfficeCoopSharesTransactionRbacRolesTrigger() - returns trigger - language plpgsql - strict as $$ +create or replace procedure buildRbacSystemForHsOfficeCoopSharesTransaction( + NEW hs_office_coopsharestransaction +) + language plpgsql as $$ + declare - newHsOfficeMembership hs_office_membership; + newMembership hs_office_membership; + begin call enterTriggerForObjectUuid(NEW.uuid); - select * from hs_office_membership as p where p.uuid = NEW.membershipUuid into newHsOfficeMembership; + 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); - if TG_OP = 'INSERT' then - - -- Each coopSharesTransaction entity belong exactly to one membership entity - -- and it makes little sense just to delegate coopSharesTransaction roles. - -- Therefore, we do not create coopSharesTransaction roles at all, - -- but instead just assign extra permissions to existing membership-roles. - - -- coopsharestransactions cannot be edited nor deleted, just created+viewed - call grantPermissionsToRole( - getRoleId(hsOfficeMembershipReferrer(newHsOfficeMembership)), - createPermissions(NEW.uuid, array ['SELECT']) - ); - - else - raise exception 'invalid usage of TRIGGER'; - end if; + call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeMembershipAdmin(newMembership)); + call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeMembershipAdmin(newMembership)); call leaveTriggerForObjectUuid(NEW.uuid); +end; $$; + +/* + AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_coopsharestransaction row. + */ + +create or replace function insertTriggerForHsOfficeCoopSharesTransaction_tf() + returns trigger + language plpgsql + strict as $$ +begin + call buildRbacSystemForHsOfficeCoopSharesTransaction(NEW); return NEW; end; $$; -/* - An AFTER INSERT TRIGGER which creates the role structure for a new customer. - */ -create trigger createRbacRolesForHsOfficeCoopSharesTransaction_Trigger - after insert - on hs_office_coopSharesTransaction +create trigger insertTriggerForHsOfficeCoopSharesTransaction_tg + after insert on hs_office_coopsharestransaction for each row -execute procedure hsOfficeCoopSharesTransactionRbacRolesTrigger(); +execute procedure insertTriggerForHsOfficeCoopSharesTransaction_tf(); --// -- ============================================================================ ---changeset hs-office-coopSharesTransaction-rbac-IDENTITY-VIEW:1 endDelimiter:--// +--changeset hs-office-coopsharestransaction-rbac-INSERT:1 endDelimiter:--// -- ---------------------------------------------------------------------------- -call generateRbacIdentityViewFromProjection('hs_office_coopSharesTransaction', 'target.reference'); ---// - --- ============================================================================ ---changeset hs-office-coopSharesTransaction-rbac-RESTRICTED-VIEW:1 endDelimiter:--// --- ---------------------------------------------------------------------------- -call generateRbacRestrictedView('hs_office_coopSharesTransaction', orderby => 'target.reference'); ---// - - --- ============================================================================ ---changeset hs-office-coopSharesTransaction-rbac-NEW-CoopSharesTransaction:1 endDelimiter:--// --- ---------------------------------------------------------------------------- /* - Creates a global permission for new-coopSharesTransaction and assigns it to the hostsharing admins role. + Creates INSERT INTO hs_office_coopsharestransaction permissions for the related hs_office_membership rows. */ do language plpgsql $$ declare - addCustomerPermissions uuid[]; - globalObjectUuid uuid; - globalAdminRoleUuid uuid ; + row hs_office_membership; begin - call defineContext('granting global new-coopSharesTransaction permission to global admin role', null, null, null); + call defineContext('create INSERT INTO hs_office_coopsharestransaction permissions for the related hs_office_membership rows'); - globalAdminRoleUuid := findRoleId(globalAdmin()); - globalObjectUuid := (select uuid from global); - addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-coopsharestransaction']); - call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions); - end; + FOR row IN SELECT * FROM hs_office_membership + LOOP + call grantPermissionToRole( + createPermission(row.uuid, 'INSERT', 'hs_office_coopsharestransaction'), + hsOfficeMembershipAdmin(row)); + END LOOP; + END; $$; /** - Used by the trigger to prevent the add-customer to current user respectively assumed roles. - */ -create or replace function addHsOfficeCoopSharesTransactionNotAllowedForCurrentSubjects() + Adds hs_office_coopsharestransaction INSERT permission to specified role of new hs_office_membership rows. +*/ +create or replace function hs_office_coopsharestransaction_hs_office_membership_insert_tf() returns trigger - language PLPGSQL -as $$ + language plpgsql + strict as $$ begin - raise exception '[403] new-coopsharestransaction not permitted for %', - array_to_string(currentSubjects(), ';', 'null'); + call grantPermissionToRole( + createPermission(NEW.uuid, 'INSERT', 'hs_office_coopsharestransaction'), + hsOfficeMembershipAdmin(NEW)); + return NEW; end; $$; -/** - Checks if the user or assumed roles are allowed to create a new customer. - */ -create trigger hs_office_coopSharesTransaction_insert_trigger - before insert - on hs_office_coopSharesTransaction +-- z_... is to put it at the end of after insert triggers, to make sure the roles exist +create trigger z_hs_office_coopsharestransaction_hs_office_membership_insert_tg + after insert on hs_office_membership for each row - when ( not hasAssumedRole() ) -execute procedure addHsOfficeCoopSharesTransactionNotAllowedForCurrentSubjects(); +execute procedure hs_office_coopsharestransaction_hs_office_membership_insert_tf(); + +/** + Checks if the user or assumed roles are allowed to insert a row to hs_office_coopsharestransaction, + where the check is performed by a direct role. + + A direct role is a role depending on a foreign key directly available in the NEW row. +*/ +create or replace function hs_office_coopsharestransaction_insert_permission_missing_tf() + returns trigger + language plpgsql as $$ +begin + raise exception '[403] insert into hs_office_coopsharestransaction not allowed for current subjects % (%)', + currentSubjects(), currentSubjectsUuids(); +end; $$; + +create trigger hs_office_coopsharestransaction_insert_permission_check_tg + before insert on hs_office_coopsharestransaction + for each row + when ( not hasInsertPermission(NEW.membershipUuid, 'INSERT', 'hs_office_coopsharestransaction') ) + execute procedure hs_office_coopsharestransaction_insert_permission_missing_tf(); +--// + +-- ============================================================================ +--changeset hs-office-coopsharestransaction-rbac-IDENTITY-VIEW:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- + +call generateRbacIdentityViewFromProjection('hs_office_coopsharestransaction', + $idName$ + reference + $idName$); +--// + +-- ============================================================================ +--changeset hs-office-coopsharestransaction-rbac-RESTRICTED-VIEW:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- +call generateRbacRestrictedView('hs_office_coopsharestransaction', + $orderBy$ + reference + $orderBy$, + $updates$ + comment = new.comment + $updates$); --// 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 837e02fd..16880741 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,8 @@ class HsOfficeCoopSharesTransactionRepositoryIntegrationTest extends ContextBase .map(s -> s.replace("hs_office_", "")) .containsExactlyInAnyOrder(Array.fromFormatted( initialGrantNames, - "{ grant perm SELECT on coopsharestransaction#temprefB to role membership#M-1000101.referrer by system and assume }", + "{ grant perm SELECT on coopsharestransaction#temprefB to role membership#M-1000101.admin by system and assume }", + "{ grant perm UPDATE on coopsharestransaction#temprefB to role membership#M-1000101.admin by system and assume }", null)); } -- 2.39.5 From 844ea380a0ad7d0437a4f456b17c9261bffe0511 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Thu, 28 Mar 2024 15:43:03 +0100 Subject: [PATCH 03/29] generated RBAC for CoopAssets --- .../HsOfficeCoopAssetsTransactionEntity.java | 26 ++ .../323-hs-office-coopassets-rbac.md | 257 ++++++++++++++++-- .../323-hs-office-coopassets-rbac.sql | 174 +++++++----- ...sTransactionRepositoryIntegrationTest.java | 5 +- 4 files changed, 367 insertions(+), 95 deletions(-) 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 0b579a85..2fd6c430 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 @@ -5,17 +5,25 @@ import lombok.*; import net.hostsharing.hsadminng.errors.DisplayName; import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity; 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 java.io.IOException; import java.math.BigDecimal; import java.time.LocalDate; import java.util.Optional; 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.Role.ADMIN; +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; @Entity @@ -89,4 +97,22 @@ public class HsOfficeCoopAssetsTransactionEntity implements Stringifyable, HasUu public String toShortString() { return "%s:%+1.2f".formatted(getTaggedMemberNumber(), Optional.ofNullable(assetValue).orElse(BigDecimal.ZERO)); } + + public static RbacView rbac() { + return rbacViewFor("coopAssetsTransaction", HsOfficeCoopAssetsTransactionEntity.class) + .withIdentityView(RbacView.SQL.projection("reference")) + .withUpdatableColumns("comment") + .importEntityAlias("membership", HsOfficeMembershipEntity.class, + dependsOnColumn("membershipUuid"), + directlyFetchedByDependsOnColumn(), + NOT_NULL) + + .toRole("membership", ADMIN).grantPermission(INSERT) + .toRole("membership", ADMIN).grantPermission(UPDATE) + .toRole("membership", ADMIN).grantPermission(SELECT); + } + + public static void main(String[] args) throws IOException { + rbac().generateWithBaseFileName("323-hs-office-coopassets-rbac"); + } } diff --git a/src/main/resources/db/changelog/323-hs-office-coopassets-rbac.md b/src/main/resources/db/changelog/323-hs-office-coopassets-rbac.md index 94ce746a..cbbe3fad 100644 --- a/src/main/resources/db/changelog/323-hs-office-coopassets-rbac.md +++ b/src/main/resources/db/changelog/323-hs-office-coopassets-rbac.md @@ -1,29 +1,250 @@ -### hs_office_coopAssetsTransaction RBAC +### rbac coopAssetsTransaction + +This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually. ```mermaid +%%{init:{'flowchart':{'htmlLabels':false}}}%% flowchart TB -subgraph hsOfficeMembership +subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"] direction TB - style hsOfficeMembership fill:#eee - - role:hsOfficeMembership.owner[membership.admin] - --> role:hsOfficeMembership.admin[membership.admin] - --> role:hsOfficeMembership.agent[membership.agent] - --> role:hsOfficeMembership.tenant[membership.tenant] - --> role:hsOfficeMembership.guest[membership.guest] - - role:hsOfficePartner.agent --> role:hsOfficeMembership.agent + style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.holderPerson:roles[ ] + style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.holderPerson:owner[[membership.partnerRel.holderPerson:owner]] + role:membership.partnerRel.holderPerson:admin[[membership.partnerRel.holderPerson:admin]] + role:membership.partnerRel.holderPerson:referrer[[membership.partnerRel.holderPerson:referrer]] + end end -subgraph hsOfficeCoopAssetsTransaction - - role:hsOfficeMembership.admin - --> perm:hsOfficeCoopAssetsTransaction.create{{coopAssetsTx.create}} - - role:hsOfficeMembership.agent - --> perm:hsOfficeCoopAssetsTransaction.view{{coopAssetsTx.view}} +subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"] + direction TB + style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.anchorPerson:roles[ ] + style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.anchorPerson:owner[[membership.partnerRel.anchorPerson:owner]] + role:membership.partnerRel.anchorPerson:admin[[membership.partnerRel.anchorPerson:admin]] + role:membership.partnerRel.anchorPerson:referrer[[membership.partnerRel.anchorPerson:referrer]] + end end +subgraph coopAssetsTransaction["`**coopAssetsTransaction**`"] + direction TB + style coopAssetsTransaction fill:#dd4901,stroke:#274d6e,stroke-width:8px + + subgraph coopAssetsTransaction:permissions[ ] + style coopAssetsTransaction:permissions fill:#dd4901,stroke:white + + perm:coopAssetsTransaction:INSERT{{coopAssetsTransaction:INSERT}} + perm:coopAssetsTransaction:UPDATE{{coopAssetsTransaction:UPDATE}} + perm:coopAssetsTransaction:SELECT{{coopAssetsTransaction:SELECT}} + end +end + +subgraph membership["`**membership**`"] + direction TB + style membership fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"] + direction TB + style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.holderPerson:roles[ ] + style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.holderPerson:owner[[membership.partnerRel.holderPerson:owner]] + role:membership.partnerRel.holderPerson:admin[[membership.partnerRel.holderPerson:admin]] + role:membership.partnerRel.holderPerson:referrer[[membership.partnerRel.holderPerson:referrer]] + end + end + + subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"] + direction TB + style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.anchorPerson:roles[ ] + style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.anchorPerson:owner[[membership.partnerRel.anchorPerson:owner]] + role:membership.partnerRel.anchorPerson:admin[[membership.partnerRel.anchorPerson:admin]] + role:membership.partnerRel.anchorPerson:referrer[[membership.partnerRel.anchorPerson:referrer]] + end + end + + subgraph membership.partnerRel["`**membership.partnerRel**`"] + direction TB + style membership.partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"] + direction TB + style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.holderPerson:roles[ ] + style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.holderPerson:owner[[membership.partnerRel.holderPerson:owner]] + role:membership.partnerRel.holderPerson:admin[[membership.partnerRel.holderPerson:admin]] + role:membership.partnerRel.holderPerson:referrer[[membership.partnerRel.holderPerson:referrer]] + end + end + + subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"] + direction TB + style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.anchorPerson:roles[ ] + style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.anchorPerson:owner[[membership.partnerRel.anchorPerson:owner]] + role:membership.partnerRel.anchorPerson:admin[[membership.partnerRel.anchorPerson:admin]] + role:membership.partnerRel.anchorPerson:referrer[[membership.partnerRel.anchorPerson:referrer]] + end + end + + subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"] + direction TB + style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.contact:roles[ ] + style membership.partnerRel.contact:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.contact:owner[[membership.partnerRel.contact:owner]] + role:membership.partnerRel.contact:admin[[membership.partnerRel.contact:admin]] + role:membership.partnerRel.contact:referrer[[membership.partnerRel.contact:referrer]] + end + end + + subgraph membership.partnerRel:roles[ ] + style membership.partnerRel:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel:owner[[membership.partnerRel:owner]] + role:membership.partnerRel:admin[[membership.partnerRel:admin]] + role:membership.partnerRel:agent[[membership.partnerRel:agent]] + role:membership.partnerRel:tenant[[membership.partnerRel:tenant]] + end + end + + subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"] + direction TB + style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.contact:roles[ ] + style membership.partnerRel.contact:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.contact:owner[[membership.partnerRel.contact:owner]] + role:membership.partnerRel.contact:admin[[membership.partnerRel.contact:admin]] + role:membership.partnerRel.contact:referrer[[membership.partnerRel.contact:referrer]] + end + end + + subgraph membership:roles[ ] + style membership:roles fill:#99bcdb,stroke:white + + role:membership:owner[[membership:owner]] + role:membership:admin[[membership:admin]] + role:membership:referrer[[membership:referrer]] + end +end + +subgraph membership.partnerRel["`**membership.partnerRel**`"] + direction TB + style membership.partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"] + direction TB + style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.holderPerson:roles[ ] + style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.holderPerson:owner[[membership.partnerRel.holderPerson:owner]] + role:membership.partnerRel.holderPerson:admin[[membership.partnerRel.holderPerson:admin]] + role:membership.partnerRel.holderPerson:referrer[[membership.partnerRel.holderPerson:referrer]] + end + end + + subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"] + direction TB + style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.anchorPerson:roles[ ] + style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.anchorPerson:owner[[membership.partnerRel.anchorPerson:owner]] + role:membership.partnerRel.anchorPerson:admin[[membership.partnerRel.anchorPerson:admin]] + role:membership.partnerRel.anchorPerson:referrer[[membership.partnerRel.anchorPerson:referrer]] + end + end + + subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"] + direction TB + style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.contact:roles[ ] + style membership.partnerRel.contact:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.contact:owner[[membership.partnerRel.contact:owner]] + role:membership.partnerRel.contact:admin[[membership.partnerRel.contact:admin]] + role:membership.partnerRel.contact:referrer[[membership.partnerRel.contact:referrer]] + end + end + + subgraph membership.partnerRel:roles[ ] + style membership.partnerRel:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel:owner[[membership.partnerRel:owner]] + role:membership.partnerRel:admin[[membership.partnerRel:admin]] + role:membership.partnerRel:agent[[membership.partnerRel:agent]] + role:membership.partnerRel:tenant[[membership.partnerRel:tenant]] + end +end + +subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"] + direction TB + style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.contact:roles[ ] + style membership.partnerRel.contact:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.contact:owner[[membership.partnerRel.contact:owner]] + role:membership.partnerRel.contact:admin[[membership.partnerRel.contact:admin]] + role:membership.partnerRel.contact:referrer[[membership.partnerRel.contact:referrer]] + end +end + +%% granting roles to roles +role:global:admin -.-> role:membership.partnerRel.anchorPerson:owner +role:membership.partnerRel.anchorPerson:owner -.-> role:membership.partnerRel.anchorPerson:admin +role:membership.partnerRel.anchorPerson:admin -.-> role:membership.partnerRel.anchorPerson:referrer +role:global:admin -.-> role:membership.partnerRel.holderPerson:owner +role:membership.partnerRel.holderPerson:owner -.-> role:membership.partnerRel.holderPerson:admin +role:membership.partnerRel.holderPerson:admin -.-> role:membership.partnerRel.holderPerson:referrer +role:global:admin -.-> role:membership.partnerRel.contact:owner +role:membership.partnerRel.contact:owner -.-> role:membership.partnerRel.contact:admin +role:membership.partnerRel.contact:admin -.-> role:membership.partnerRel.contact:referrer +role:global:admin -.-> role:membership.partnerRel:owner +role:membership.partnerRel:owner -.-> role:membership.partnerRel:admin +role:membership.partnerRel.anchorPerson:admin -.-> role:membership.partnerRel:admin +role:membership.partnerRel:admin -.-> role:membership.partnerRel:agent +role:membership.partnerRel.holderPerson:admin -.-> role:membership.partnerRel:agent +role:membership.partnerRel:agent -.-> role:membership.partnerRel:tenant +role:membership.partnerRel.holderPerson:admin -.-> role:membership.partnerRel:tenant +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 + +%% granting permissions to roles +role:membership:admin ==> perm:coopAssetsTransaction:INSERT +role:membership:admin ==> perm:coopAssetsTransaction:UPDATE +role:membership:admin ==> perm:coopAssetsTransaction:SELECT ``` diff --git a/src/main/resources/db/changelog/323-hs-office-coopassets-rbac.sql b/src/main/resources/db/changelog/323-hs-office-coopassets-rbac.sql index 035da07b..d1218873 100644 --- a/src/main/resources/db/changelog/323-hs-office-coopassets-rbac.sql +++ b/src/main/resources/db/changelog/323-hs-office-coopassets-rbac.sql @@ -1,125 +1,151 @@ --liquibase formatted sql +-- This code generated was by RbacViewPostgresGenerator, do not amend manually. + -- ============================================================================ ---changeset hs-office-coopAssetsTransaction-rbac-OBJECT:1 endDelimiter:--// +--changeset hs-office-coopassetstransaction-rbac-OBJECT:1 endDelimiter:--// -- ---------------------------------------------------------------------------- -call generateRelatedRbacObject('hs_office_coopAssetsTransaction'); +call generateRelatedRbacObject('hs_office_coopassetstransaction'); --// -- ============================================================================ ---changeset hs-office-coopAssetsTransaction-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--// +--changeset hs-office-coopassetstransaction-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--// -- ---------------------------------------------------------------------------- -call generateRbacRoleDescriptors('hsOfficeCoopAssetsTransaction', 'hs_office_coopAssetsTransaction'); +call generateRbacRoleDescriptors('hsOfficeCoopAssetsTransaction', 'hs_office_coopassetstransaction'); --// -- ============================================================================ ---changeset hs-office-coopAssetsTransaction-rbac-ROLES-CREATION:1 endDelimiter:--// +--changeset hs-office-coopassetstransaction-rbac-insert-trigger:1 endDelimiter:--// -- ---------------------------------------------------------------------------- /* - Creates and updates the permissions for coopAssetsTransaction entities. + Creates the roles, grants and permission for the AFTER INSERT TRIGGER. */ -create or replace function hsOfficeCoopAssetsTransactionRbacRolesTrigger() - returns trigger - language plpgsql - strict as $$ +create or replace procedure buildRbacSystemForHsOfficeCoopAssetsTransaction( + NEW hs_office_coopassetstransaction +) + language plpgsql as $$ + declare - newHsOfficeMembership hs_office_membership; + newMembership hs_office_membership; + begin call enterTriggerForObjectUuid(NEW.uuid); - select * from hs_office_membership as p where p.uuid = NEW.membershipUuid into newHsOfficeMembership; + 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); - if TG_OP = 'INSERT' then - - -- Each coopAssetsTransaction entity belong exactly to one membership entity - -- and it makes little sense just to delegate coopAssetsTransaction roles. - -- Therefore, we do not create coopAssetsTransaction roles at all, - -- but instead just assign extra permissions to existing membership-roles. - - -- coopassetstransactions cannot be edited nor deleted, just created+viewed - call grantPermissionsToRole( - getRoleId(hsOfficeMembershipReferrer(newHsOfficeMembership)), - createPermissions(NEW.uuid, array ['SELECT']) - ); - - else - raise exception 'invalid usage of TRIGGER'; - end if; + call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeMembershipAdmin(newMembership)); + call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeMembershipAdmin(newMembership)); call leaveTriggerForObjectUuid(NEW.uuid); +end; $$; + +/* + AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_coopassetstransaction row. + */ + +create or replace function insertTriggerForHsOfficeCoopAssetsTransaction_tf() + returns trigger + language plpgsql + strict as $$ +begin + call buildRbacSystemForHsOfficeCoopAssetsTransaction(NEW); return NEW; end; $$; -/* - An AFTER INSERT TRIGGER which creates the role structure for a new customer. - */ -create trigger createRbacRolesForHsOfficeCoopAssetsTransaction_Trigger - after insert - on hs_office_coopAssetsTransaction +create trigger insertTriggerForHsOfficeCoopAssetsTransaction_tg + after insert on hs_office_coopassetstransaction for each row -execute procedure hsOfficeCoopAssetsTransactionRbacRolesTrigger(); +execute procedure insertTriggerForHsOfficeCoopAssetsTransaction_tf(); --// -- ============================================================================ ---changeset hs-office-coopAssetsTransaction-rbac-IDENTITY-VIEW:1 endDelimiter:--// +--changeset hs-office-coopassetstransaction-rbac-INSERT:1 endDelimiter:--// -- ---------------------------------------------------------------------------- -call generateRbacIdentityViewFromProjection('hs_office_coopAssetsTransaction', 'target.reference'); ---// - --- ============================================================================ ---changeset hs-office-coopAssetsTransaction-rbac-RESTRICTED-VIEW:1 endDelimiter:--// --- ---------------------------------------------------------------------------- -call generateRbacRestrictedView('hs_office_coopAssetsTransaction', orderby => 'target.reference'); ---// - - --- ============================================================================ ---changeset hs-office-coopAssetsTransaction-rbac-NEW-CoopAssetsTransaction:1 endDelimiter:--// --- ---------------------------------------------------------------------------- /* - Creates a global permission for new-coopAssetsTransaction and assigns it to the hostsharing admins role. + Creates INSERT INTO hs_office_coopassetstransaction permissions for the related hs_office_membership rows. */ do language plpgsql $$ declare - addCustomerPermissions uuid[]; - globalObjectUuid uuid; - globalAdminRoleUuid uuid ; + row hs_office_membership; begin - call defineContext('granting global new-coopAssetsTransaction permission to global admin role', null, null, null); + call defineContext('create INSERT INTO hs_office_coopassetstransaction permissions for the related hs_office_membership rows'); - globalAdminRoleUuid := findRoleId(globalAdmin()); - globalObjectUuid := (select uuid from global); - addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-coopassetstransaction']); - call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions); - end; + FOR row IN SELECT * FROM hs_office_membership + LOOP + call grantPermissionToRole( + createPermission(row.uuid, 'INSERT', 'hs_office_coopassetstransaction'), + hsOfficeMembershipAdmin(row)); + END LOOP; + END; $$; /** - Used by the trigger to prevent the add-customer to current user respectively assumed roles. - */ -create or replace function addHsOfficeCoopAssetsTransactionNotAllowedForCurrentSubjects() + Adds hs_office_coopassetstransaction INSERT permission to specified role of new hs_office_membership rows. +*/ +create or replace function hs_office_coopassetstransaction_hs_office_membership_insert_tf() returns trigger - language PLPGSQL -as $$ + language plpgsql + strict as $$ begin - raise exception '[403] new-coopassetstransaction not permitted for %', - array_to_string(currentSubjects(), ';', 'null'); + call grantPermissionToRole( + createPermission(NEW.uuid, 'INSERT', 'hs_office_coopassetstransaction'), + hsOfficeMembershipAdmin(NEW)); + return NEW; end; $$; -/** - Checks if the user or assumed roles are allowed to create a new customer. - */ -create trigger hs_office_coopAssetsTransaction_insert_trigger - before insert - on hs_office_coopAssetsTransaction +-- z_... is to put it at the end of after insert triggers, to make sure the roles exist +create trigger z_hs_office_coopassetstransaction_hs_office_membership_insert_tg + after insert on hs_office_membership for each row - when ( not hasAssumedRole() ) -execute procedure addHsOfficeCoopAssetsTransactionNotAllowedForCurrentSubjects(); +execute procedure hs_office_coopassetstransaction_hs_office_membership_insert_tf(); + +/** + Checks if the user or assumed roles are allowed to insert a row to hs_office_coopassetstransaction, + where the check is performed by a direct role. + + A direct role is a role depending on a foreign key directly available in the NEW row. +*/ +create or replace function hs_office_coopassetstransaction_insert_permission_missing_tf() + returns trigger + language plpgsql as $$ +begin + raise exception '[403] insert into hs_office_coopassetstransaction not allowed for current subjects % (%)', + currentSubjects(), currentSubjectsUuids(); +end; $$; + +create trigger hs_office_coopassetstransaction_insert_permission_check_tg + before insert on hs_office_coopassetstransaction + for each row + when ( not hasInsertPermission(NEW.membershipUuid, 'INSERT', 'hs_office_coopassetstransaction') ) + execute procedure hs_office_coopassetstransaction_insert_permission_missing_tf(); +--// + +-- ============================================================================ +--changeset hs-office-coopassetstransaction-rbac-IDENTITY-VIEW:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- + +call generateRbacIdentityViewFromProjection('hs_office_coopassetstransaction', + $idName$ + reference + $idName$); +--// + +-- ============================================================================ +--changeset hs-office-coopassetstransaction-rbac-RESTRICTED-VIEW:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- +call generateRbacRestrictedView('hs_office_coopassetstransaction', + $orderBy$ + reference + $orderBy$, + $updates$ + comment = new.comment + $updates$); --// 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 90ab1f00..7031476e 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 @@ -89,7 +89,6 @@ class HsOfficeCoopAssetsTransactionRepositoryIntegrationTest extends ContextBase context("superuser-alex@hostsharing.net"); final var initialRoleNames = distinctRoleNamesOf(rawRoleRepo.findAll()); final var initialGrantNames = distinctGrantDisplaysOf(rawGrantRepo.findAll()).stream() - .map(s -> s.replace("FirstGmbH-firstcontact", "...")) .map(s -> s.replace("hs_office_", "")) .toList(); @@ -110,11 +109,11 @@ class HsOfficeCoopAssetsTransactionRepositoryIntegrationTest extends ContextBase final var all = rawRoleRepo.findAll(); assertThat(distinctRoleNamesOf(all)).containsExactlyInAnyOrder(Array.from(initialRoleNames)); // no new roles created assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll())) - .map(s -> s.replace("FirstGmbH-firstcontact", "...")) .map(s -> s.replace("hs_office_", "")) .containsExactlyInAnyOrder(Array.fromFormatted( initialGrantNames, - "{ grant perm SELECT on coopassetstransaction#temprefB to role membership#M-1000101.referrer by system and assume }", + "{ grant perm SELECT on coopassetstransaction#temprefB to role membership#M-1000101.admin by system and assume }", + "{ grant perm UPDATE on coopassetstransaction#temprefB to role membership#M-1000101.admin by system and assume }", null)); } -- 2.39.5 From da5eea80004c2cfb0179000c36945d7c1a4d561f Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Fri, 29 Mar 2024 19:18:27 +0100 Subject: [PATCH 04/29] uniform idnames --- README.md | 2 +- doc/ideas/rbac-schema-f.md | 4 +- doc/ideas/simplified-grant-structure.md | 4 +- doc/rbac.md | 48 ++-- sql/rbac-tests.sql | 8 +- sql/rbac-view-option-experiments.sql | 2 +- .../membership/HsOfficeMembershipEntity.java | 5 +- .../partner/HsOfficePartnerDetailsEntity.java | 2 +- .../rbac/rbacdef/InsertTriggerGenerator.java | 4 +- .../hsadminng/rbac/rbacdef/RbacView.java | 9 +- .../RbacViewMermaidFlowchartGenerator.java | 2 +- .../RolesGrantsAndPermissionsGenerator.java | 6 +- .../rbac/rbacgrant/RbacGrantEntity.java | 6 +- .../rbacgrant/RbacGrantsDiagramService.java | 20 +- .../rbac/rbacrole/RbacRoleController.java | 2 +- .../rbac/rbacrole/RbacRoleRepository.java | 6 +- ...cRoleEntity.java => RbacRoleRvEntity.java} | 4 +- .../hsadminng/rbac/rbacrole/RbacRoleType.java | 2 +- .../rbac/rbac-role-schemas.yaml | 10 +- .../resources/db/changelog/010-context.sql | 3 +- .../resources/db/changelog/050-rbac-base.sql | 4 +- .../db/changelog/054-rbac-context.sql | 2 +- .../resources/db/changelog/055-rbac-views.sql | 24 +- .../db/changelog/058-rbac-generators.sql | 12 +- .../db/changelog/080-rbac-global.sql | 8 +- .../db/changelog/113-test-customer-rbac.md | 22 +- .../db/changelog/113-test-customer-rbac.sql | 16 +- .../changelog/118-test-customer-test-data.sql | 2 +- .../db/changelog/123-test-package-rbac.md | 34 +-- .../db/changelog/123-test-package-rbac.sql | 26 +- .../changelog/128-test-package-test-data.sql | 2 +- .../db/changelog/133-test-domain-rbac.md | 59 ++--- .../db/changelog/133-test-domain-rbac.sql | 28 +- .../changelog/203-hs-office-contact-rbac.md | 22 +- .../changelog/203-hs-office-contact-rbac.sql | 16 +- .../db/changelog/213-hs-office-person-rbac.md | 22 +- .../changelog/213-hs-office-person-rbac.sql | 16 +- .../changelog/223-hs-office-relation-rbac.md | 76 +++--- .../changelog/223-hs-office-relation-rbac.sql | 42 +-- .../228-hs-office-relation-test-data.sql | 2 +- .../changelog/233-hs-office-partner-rbac.md | 118 +++------ .../changelog/233-hs-office-partner-rbac.sql | 40 +-- .../234-hs-office-partner-details-rbac.md | 2 +- .../234-hs-office-partner-details-rbac.sql | 10 +- .../238-hs-office-partner-test-data.sql | 2 +- .../243-hs-office-bankaccount-rbac.md | 22 +- .../243-hs-office-bankaccount-rbac.sql | 16 +- .../253-hs-office-sepamandate-rbac.md | 153 +++++------ .../253-hs-office-sepamandate-rbac.sql | 30 +-- .../258-hs-office-sepamandate-test-data.sql | 2 +- .../changelog/273-hs-office-debitor-rbac.md | 239 ++++++------------ .../changelog/273-hs-office-debitor-rbac.sql | 20 +- .../278-hs-office-debitor-test-data.sql | 2 +- .../303-hs-office-membership-rbac.md | 131 ++++------ .../303-hs-office-membership-rbac.sql | 20 +- .../308-hs-office-membership-test-data.sql | 2 +- .../context/ContextIntegrationTests.java | 12 +- ...eBankAccountRepositoryIntegrationTest.java | 20 +- ...fficeContactRepositoryIntegrationTest.java | 20 +- ...sTransactionRepositoryIntegrationTest.java | 6 +- ...sTransactionRepositoryIntegrationTest.java | 6 +- ...OfficeDebitorControllerAcceptanceTest.java | 2 +- ...fficeDebitorRepositoryIntegrationTest.java | 96 +++---- ...iceMembershipControllerAcceptanceTest.java | 6 +- ...ceMembershipRepositoryIntegrationTest.java | 32 ++- .../hs/office/migration/ImportOfficeData.java | 2 +- ...fficePartnerRepositoryIntegrationTest.java | 70 ++--- ...OfficePersonRepositoryIntegrationTest.java | 24 +- ...ficeRelationRepositoryIntegrationTest.java | 56 ++-- ...eSepaMandateRepositoryIntegrationTest.java | 40 +-- .../test/ContextBasedTestWithCleanup.java | 4 +- .../RbacGrantControllerAcceptanceTest.java | 108 ++++---- .../rbacgrant/RbacGrantEntityUnitTest.java | 8 +- .../RbacGrantRepositoryIntegrationTest.java | 56 ++-- ...acGrantsDiagramServiceIntegrationTest.java | 32 +-- .../rbac/rbacrole/RawRbacRoleEntity.java | 2 +- .../RbacRoleControllerAcceptanceTest.java | 54 ++-- .../rbacrole/RbacRoleControllerRestTest.java | 6 +- .../RbacRoleRepositoryIntegrationTest.java | 96 +++---- .../hsadminng/rbac/rbacrole/TestRbacRole.java | 10 +- .../RbacUserControllerAcceptanceTest.java | 18 +- .../RbacUserRepositoryIntegrationTest.java | 176 ++++++------- .../TestCustomerControllerAcceptanceTest.java | 8 +- .../test/cust/TestCustomerEntityUnitTest.java | 22 +- ...TestCustomerRepositoryIntegrationTest.java | 8 +- .../TestPackageControllerAcceptanceTest.java | 14 +- .../test/pac/TestPackageEntityUnitTest.java | 34 +-- .../TestPackageRepositoryIntegrationTest.java | 10 +- .../java/net/hostsharing/test/JpaAttempt.java | 5 + 89 files changed, 1129 insertions(+), 1327 deletions(-) rename src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/{RbacRoleEntity.java => RbacRoleRvEntity.java} (88%) diff --git a/README.md b/README.md index 04827ba3..4301d8fe 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/ideas/rbac-schema-f.md b/doc/ideas/rbac-schema-f.md index 7047d066..f1731d4f 100644 --- a/doc/ideas/rbac-schema-f.md +++ b/doc/ideas/rbac-schema-f.md @@ -27,8 +27,8 @@ Objektorientiert gedacht, enthalten solche Objekte die Zusatzdaten einer Subklas - Für die Rollenzuordnung zwischen referenzierten Objekten gilt: - Für Objekte vom Typ Root werden die Rollen des zugehörigen Aggregator-Objektes verwendet. - Gibt es Referenzen auf hierarchisch verbundene Objekte (z.B. Debitor.refundBankAccount) gilt folgende Faustregel: - ***Nach oben absteigen, nach unten halten oder aufsteigen.*** An einem fachlich übergeordneten Objekt wird also eine niedrigere Rolle (z.B. Debitor-admin -> Partner.agent), einem fachlich untergeordneten Objekt eine gleichwertige Rolle (z.B. Partner.admin -> Debitor.admin) zugewiesen oder sogar aufgestiegen (Debitor.admin -> Package.tenant). - - Für Referenzen zwischen Objekten, die nicht hierarchisch zueinander stehen (z.B. Debitor und Bankverbindung), wird auf beiden seiten abgestiegen (also Debitor.admin -> BankAccount.referrer und BankAccount.admin -> Debitor.tenant). + ***Nach oben absteigen, nach unten halten oder aufsteigen.*** An einem fachlich übergeordneten Objekt wird also eine niedrigere Rolle (z.B. Debitor.ADMIN -> Partner.AGENT), einem fachlich untergeordneten Objekt eine gleichwertige Rolle (z.B. Partner.ADMIN -> Debitor.ADMIN) zugewiesen oder sogar aufgestiegen (Debitor.ADMIN -> Package.TENANT). + - Für Referenzen zwischen Objekten, die nicht hierarchisch zueinander stehen (z.B. Debitor und Bankverbindung), wird auf beiden seiten abgestiegen (also Debitor.ADMIN -> BankAccount.REFERRER und BankAccount.ADMIN -> Debitor.TENANT). Anmerkung: Der Typ-Begriff *Root* bezieht sich auf die Rolle im fachlichen Datenmodell. Im Bezug auf den Teilgraphen eines fachlichen Kontexts ist dies auch eine Wurzel im Sinne der Graphentheorie. Aber in anderen fachlichen Kontexten können auch diese Objekte von anderen Teilgraphen referenziert werden und werden dann zum inneren Knoten. diff --git a/doc/ideas/simplified-grant-structure.md b/doc/ideas/simplified-grant-structure.md index 6d89897a..d9b3cf44 100644 --- a/doc/ideas/simplified-grant-structure.md +++ b/doc/ideas/simplified-grant-structure.md @@ -16,11 +16,11 @@ Beim Debitor ist das nämlich selbst mit Generator die Hölle, zumal eben auch Q Mit anderen Worten, um als Repräsentant eines Geschäftspartners auf den Bank-Account der Sepa-Mandate sehen zu dürfen, wird derzeut folgende Grant-Kette durchlaufen (bzw. eben noch nicht, weil es noch nicht funktioniert): -User -> Partner-Holder-Person:Admin -> Partner-Relation:Agent -> Debitor-Relation:Agent -> Sepa-Mandat:Admin -> BankAccount:Admin -> BankAccount:SELECT +User -> Partner-Holder-Person:ADMIN -> Partner-Relation:AGENT -> Debitor-Relation:AGENT -> Sepa-Mandat:ADMIN -> BankAccount:ADMIN -> BankAccount:SELECT Daraus würde: -User -> Partner-Relation:Agent -> Debitor-Relation:Agent -> Sepa-Mandat:Admin -> Sepa-Mandat:SELECT* +User -> Partner-Relation:AGENT -> Debitor-Relation:AGENT -> Sepa-Mandat:ADMIN -> Sepa-Mandat:SELECT* (*mit JOIN auf RawBankAccount, also implizitem Leserecht) diff --git a/doc/rbac.md b/doc/rbac.md index 2de4d4bb..3cf58e25 100644 --- a/doc/rbac.md +++ b/doc/rbac.md @@ -196,24 +196,24 @@ E.g. if a new package is added, the admin-role of the related customer has to be There can be global roles like 'administrators'. Most roles, though, are specific for certain business-objects and automatically generated as such: - business-object-table#business-object-name.relative-role + business-object-table#business-object-name.role-stereotype Where *business-object-table* is the name of the SQL table of the business object (e.g *customer* or 'package'), *business-object-name* is generated from an immutable business key(e.g. a prefix like 'xyz' or 'xyz00') -and the *relative-role*' describes the role relative to the referenced business-object as follows: +and the *role-stereotype* describes a role relative to a referenced business-object as follows: #### 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. In most cases, the permissions to other operations than 'DELETE' are granted through the 'admin' role. By this, all roles ob sub-objects, which are assigned to the 'admin' role, are also granted to the 'owner'. -#### admin +#### ADMIN The admin-role is granted to a role of those subjects who manage the business object. E.g. a 'package' is manged by the admin of the customer. @@ -222,7 +222,7 @@ Whoever has the admin-role assigned, can usually update the related business-obj The admin-role also comprises lesser roles, through which the SELECT-permission is granted. -#### agent +#### AGENT The agent-role is not used in the examples of this document, because it's for more complex cases. It's usually granted to those roles and users who represent the related business-object, but are not allowed to update it. @@ -231,21 +231,25 @@ Other than the tenant-role, it usually offers broader visibility of sub-business E.g. a package-admin is allowed to see the related debitor-business-object, but not its banking data. -#### tenant +#### TENANT The tenant-role is granted to everybody who needs to be able to select the business-object and (probably some) related business-objects. Usually all owners, admins and tenants of sub-objects get this role granted. Some business-objects only have very limited data directly in the main business-object and store more sensitive data in special sub-objects (e.g. 'customer-details') to which tenants of sub-objects of the main-object (e.g. package admins) do not get SELECT permission. -#### guest +#### GUEST + +(Deprecated) + +#### REFERRER Like the agent-role, the guest-role too is not used in the examples of this document, because it's for more complex cases. -If the guest-role exists, the SELECT-permission is granted to it, instead of to the tenant-role. -Other than the tenant-role, the guest-roles does never grant any roles of related objects. +If the referrer-role exists, the SELECT-permission is granted to it, instead of to the tenant-role. +Other than the tenant-role, the referrer-roles does never grant any roles of related objects. -Also, if the guest-role exists, the tenant-role receives the SELECT-permission through the guest-role. +Also, if the referrer-role exists, the tenant-role receives the SELECT-permission through the referrer-role. ### Referenced Business Objects and Role-Depreciation @@ -372,7 +376,7 @@ That user is also used for historicization and audit log, but which is a differe If the session variable `hsadminng.assumedRoles` is set to a non-empty value, its content is interpreted as a list of semicolon-separated role names. Example: - SET LOCAL hsadminng.assumedRoles = 'customer#aab.admin;customer#aac.admin'; + SET LOCAL hsadminng.assumedRoles = 'customer#aab:admin;customer#aac:admin'; In this case, not the current user but the assumed roles are used as a starting point for any further queries. Roles which are not granted to the current user, directly or indirectly, cannot be assumed. @@ -385,7 +389,7 @@ A full example is shown here: BEGIN TRANSACTION; SET SESSION SESSION AUTHORIZATION restricted; SET LOCAL hsadminng.currentUser = 'mike@hostsharing.net'; - SET LOCAL hsadminng.assumedRoles = 'customer#aab.admin;customer#aac.admin'; + SET LOCAL hsadminng.assumedRoles = 'customer#aab:admin;customer#aac:admin'; SELECT c.prefix, p.name as "package", ema.localPart || '@' || dom.name as "email-address" FROM emailaddress_rv ema @@ -466,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 @@ -489,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. @@ -537,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/sql/rbac-tests.sql b/sql/rbac-tests.sql index e30ac926..351d1509 100644 --- a/sql/rbac-tests.sql +++ b/sql/rbac-tests.sql @@ -3,10 +3,10 @@ -- -------------------------------------------------------- -select isGranted(findRoleId('administrators'), findRoleId('test_package#aaa00.owner')); -select isGranted(findRoleId('test_package#aaa00.owner'), findRoleId('administrators')); --- call grantRoleToRole(findRoleId('test_package#aaa00.owner'), findRoleId('administrators')); --- call grantRoleToRole(findRoleId('administrators'), findRoleId('test_package#aaa00.owner')); +select isGranted(findRoleId('administrators'), findRoleId('test_package#aaa00:OWNER')); +select isGranted(findRoleId('test_package#aaa00:OWNER'), findRoleId('administrators')); +-- call grantRoleToRole(findRoleId('test_package#aaa00:OWNER'), findRoleId('administrators')); +-- call grantRoleToRole(findRoleId('administrators'), findRoleId('test_package#aaa00:OWNER')); select count(*) FROM queryAllPermissionsOfSubjectIdForObjectUuids(findRbacUser('superuser-fran@hostsharing.net'), diff --git a/sql/rbac-view-option-experiments.sql b/sql/rbac-view-option-experiments.sql index f6e80e10..c5c04487 100644 --- a/sql/rbac-view-option-experiments.sql +++ b/sql/rbac-view-option-experiments.sql @@ -83,7 +83,7 @@ select rr.uuid, rr.type from RbacGrants g select uuid from queryAllPermissionsOfSubjectId(findRbacUser('alex@example.com')) where objectTable='test_customer'); -call grantRoleToUser(findRoleId('test_customer#aaa.admin'), findRbacUser('aaaaouq@example.com')); +call grantRoleToUser(findRoleId('test_customer#aaa:ADMIN'), findRbacUser('aaaaouq@example.com')); select queryAllPermissionsOfSubjectId(findRbacUser('aaaaouq@example.com')); 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 c4a4c8b9..ac1e5053 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 @@ -24,8 +24,11 @@ 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.SELECT; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacUserReference.UserRole.CREATOR; -import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.*; +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.SQL.fetchedBySql; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor; import static net.hostsharing.hsadminng.stringify.Stringify.stringify; diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerDetailsEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerDetailsEntity.java index 7bb4aea3..9a120ea3 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerDetailsEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerDetailsEntity.java @@ -68,7 +68,7 @@ public class HsOfficePartnerDetailsEntity implements HasUuid, Stringifyable { public static RbacView rbac() { return rbacViewFor("partnerDetails", HsOfficePartnerDetailsEntity.class) .withIdentityView(SQL.query(""" - SELECT partnerDetails.uuid as uuid, partner_iv.idName || '-details' as idName + SELECT partnerDetails.uuid as uuid, partner_iv.idName as idName FROM hs_office_partner_details AS partnerDetails JOIN hs_office_partner partner ON partner.detailsUuid = partnerDetails.uuid JOIN hs_office_partner_iv partner_iv ON partner_iv.uuid = partner.uuid diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/InsertTriggerGenerator.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/InsertTriggerGenerator.java index a9a72160..7ef34252 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/InsertTriggerGenerator.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/InsertTriggerGenerator.java @@ -120,7 +120,7 @@ public class InsertTriggerGenerator { } }, () -> { - System.err.println("WARNING: no explicit INSERT grant for " + rbacDef.getRootEntityAlias().simpleName() + " => implicitly grant INSERT to global.admin"); + System.err.println("WARNING: no explicit INSERT grant for " + rbacDef.getRootEntityAlias().simpleName() + " => implicitly grant INSERT to global:ADMIN"); generateInsertPermissionTriggerAllowOnlyGlobalAdmin(plPgSql); }); } @@ -246,7 +246,7 @@ public class InsertTriggerGenerator { } private static String toVar(final RbacView.RbacRoleDefinition roleDef) { - return uncapitalize(roleDef.getEntityAlias().simpleName()) + capitalize(roleDef.getRole().roleName()); + return uncapitalize(roleDef.getEntityAlias().simpleName()) + capitalize(roleDef.getRole().name()); } diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java index d6fe2ab3..6bba2b12 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java @@ -113,7 +113,7 @@ public class RbacView { *

An identity view is a view which maps an objectUuid to an idName. * The idName should be a human-readable representation of the row, but as short as possible. * The idName must only consist of letters (A-Z, a-z), digits (0-9), dash (-), dot (.) and unserscore '_'. - * It's used to create the object-specific-role-names like test_customer#abc.admin - here 'abc' is the idName. + * It's used to create the object-specific-role-names like test_customer#abc:ADMIN - here 'abc' is the idName. * The idName not necessarily unique in a table, but it should be avoided. *

* @@ -882,15 +882,12 @@ public class RbacView { TENANT, REFERRER, + @Deprecated GUEST; @Override public String toString() { - return ":" + roleName(); - } - - String roleName() { - return name().toLowerCase(); + return ":" + name(); } } diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java index d6a9bc28..c6e775c9 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java @@ -48,7 +48,7 @@ public class RbacViewMermaidFlowchartGenerator { flowchart.indented( () -> { rbacDef.getEntityAliases().values().stream() - .filter(e -> e.aliasName().startsWith(entity.aliasName() + ".")) + .filter(e -> e.aliasName().startsWith(entity.aliasName() + ":")) .forEach(this::renderEntitySubgraph); wrapOutputInSubgraph(entity.aliasName() + ":roles", color, diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java index 719c8ab4..484415f2 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java @@ -333,7 +333,7 @@ class RolesGrantsAndPermissionsGenerator { return "globalAdmin()"; } final String entityRefVar = entityRefVar(rootRefVar, roleDef.getEntityAlias()); - return roleDef.getEntityAlias().simpleName() + capitalize(roleDef.getRole().roleName()) + return roleDef.getEntityAlias().simpleName() + capitalize(roleDef.getRole().name()) + "(" + entityRefVar + ")"; } @@ -359,7 +359,7 @@ class RolesGrantsAndPermissionsGenerator { plPgSql.indented(() -> { plPgSql.writeLn("${simpleVarName)${roleSuffix}(NEW)," .replace("${simpleVarName)", simpleEntityVarName) - .replace("${roleSuffix}", capitalize(role.roleName()))); + .replace("${roleSuffix}", capitalize(role.name()))); generatePermissionsForRole(plPgSql, role); @@ -562,7 +562,7 @@ class RolesGrantsAndPermissionsGenerator { } private static String toRoleRef(final RbacView.RbacRoleDefinition roleDef) { - return uncapitalize(roleDef.getEntityAlias().simpleName()) + capitalize(roleDef.getRole().roleName()); + return uncapitalize(roleDef.getEntityAlias().simpleName()) + capitalize(roleDef.getRole().name()); } private static String toTriggerReference( diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantEntity.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantEntity.java index a3abf528..c2f2d524 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantEntity.java @@ -59,9 +59,9 @@ public class RbacGrantEntity { } public String toDisplay() { - return "{ grant role " + grantedRoleIdName + - " to user " + granteeUserName + - " by role " + grantedByRoleIdName + + return "{ grant role:" + grantedRoleIdName + + " to user:" + granteeUserName + + " by role:" + grantedByRoleIdName + (assumed ? " and assume" : "") + " }"; } diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantsDiagramService.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantsDiagramService.java index cf05496a..f8746eb5 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantsDiagramService.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantsDiagramService.java @@ -71,14 +71,14 @@ public class RbacGrantsDiagramService { private void traverseGrantsTo(final Set graph, final UUID refUuid, final EnumSet includes) { final var grants = rawGrantRepo.findByAscendingUuid(refUuid); grants.forEach(g -> { - if (!includes.contains(PERMISSIONS) && g.getDescendantIdName().startsWith("perm ")) { + if (!includes.contains(PERMISSIONS) && g.getDescendantIdName().startsWith("perm:")) { return; } - if ( !g.getDescendantIdName().startsWith("role global")) { - if (!includes.contains(TEST_ENTITIES) && g.getDescendantIdName().contains(" test_")) { + if ( !g.getDescendantIdName().startsWith("role:global")) { + if (!includes.contains(TEST_ENTITIES) && g.getDescendantIdName().contains(":test_")) { return; } - if (!includes.contains(NON_TEST_ENTITIES) && !g.getDescendantIdName().contains(" test_")) { + if (!includes.contains(NON_TEST_ENTITIES) && !g.getDescendantIdName().contains(":test_")) { return; } } @@ -102,7 +102,7 @@ public class RbacGrantsDiagramService { private void traverseGrantsFrom(final Set graph, final UUID refUuid, final EnumSet option) { final var grants = rawGrantRepo.findByDescendantUuid(refUuid); grants.forEach(g -> { - if (!option.contains(USERS) && g.getAscendantIdName().startsWith("user ")) { + if (!option.contains(USERS) && g.getAscendantIdName().startsWith("user:")) { return; } graph.add(g); @@ -171,7 +171,7 @@ public class RbacGrantsDiagramService { } if (refType.equals("role")) { final var withoutRolePrefix = node.idName().substring("role:".length()); - return withoutRolePrefix.substring(0, withoutRolePrefix.lastIndexOf('.')); + return withoutRolePrefix.substring(0, withoutRolePrefix.lastIndexOf(':')); } throw new IllegalArgumentException("unknown refType '" + refType + "' in '" + node.idName() + "'"); } @@ -188,23 +188,23 @@ public class RbacGrantsDiagramService { return "(" + displayName + "\nref:" + uuid + ")"; } if (refType.equals("role")) { - final var roleType = idName.substring(idName.lastIndexOf('.') + 1); + final var roleType = idName.substring(idName.lastIndexOf(':') + 1); return "[" + roleType + "\nref:" + uuid + "]"; } if (refType.equals("perm")) { - final var roleType = idName.split(" ")[1]; + final var roleType = idName.split(":")[1]; return "{{" + roleType + "\nref:" + uuid + "}}"; } return ""; } private static String refType(final String idName) { - return idName.split(" ", 2)[0]; + return idName.split(":", 2)[0]; } @NotNull private static String cleanId(final String idName) { - return idName.replace(" ", ":").replaceAll("@.*", "") + return idName.replaceAll("@.*", "") .replace("[", "").replace("]", "").replace("(", "").replace(")", "").replace(",", ""); } diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleController.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleController.java index 0405fee2..cf528361 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleController.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleController.java @@ -31,7 +31,7 @@ public class RbacRoleController implements RbacRolesApi { context.define(currentUser, assumedRoles); - final List result = rbacRoleRepository.findAll(); + final List result = rbacRoleRepository.findAll(); return ResponseEntity.ok(mapper.mapList(result, RbacRoleResource.class)); } diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleRepository.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleRepository.java index 94633d7c..2d9d005b 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleRepository.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleRepository.java @@ -5,7 +5,7 @@ import org.springframework.data.repository.Repository; import java.util.List; import java.util.UUID; -public interface RbacRoleRepository extends Repository { +public interface RbacRoleRepository extends Repository { /** * @return the number of persistent RbacRoleEntity instances, mostly for testing purposes. @@ -15,7 +15,7 @@ public interface RbacRoleRepository extends Repository { /** * @return all persistent RbacRoleEntity instances, assigned to the current subject (user or assumed roles) */ - List findAll(); + List findAll(); - RbacRoleEntity findByRoleName(String roleName); + RbacRoleRvEntity findByRoleName(String roleName); } diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleEntity.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleRvEntity.java similarity index 88% rename from src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleEntity.java rename to src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleRvEntity.java index 26528c8a..d174182a 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleRvEntity.java @@ -15,7 +15,7 @@ import java.util.UUID; @Immutable @NoArgsConstructor @AllArgsConstructor -public class RbacRoleEntity { +public class RbacRoleRvEntity { @Id @GeneratedValue @@ -34,6 +34,6 @@ public class RbacRoleEntity { @Enumerated(EnumType.STRING) private RbacRoleType roleType; - @Formula("objectTable||'#'||objectIdName||'.'||roleType") + @Formula("objectTable||'#'||objectIdName||':'||roleType") private String roleName; } diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleType.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleType.java index fa5b16aa..e78e8836 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleType.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleType.java @@ -1,5 +1,5 @@ package net.hostsharing.hsadminng.rbac.rbacrole; public enum RbacRoleType { - owner, admin, agent, tenant, guest, referrer + OWNER, ADMIN, AGENT, TENANT, GUEST, REFERRER } diff --git a/src/main/resources/api-definition/rbac/rbac-role-schemas.yaml b/src/main/resources/api-definition/rbac/rbac-role-schemas.yaml index ff0e18e4..45736dc3 100644 --- a/src/main/resources/api-definition/rbac/rbac-role-schemas.yaml +++ b/src/main/resources/api-definition/rbac/rbac-role-schemas.yaml @@ -19,9 +19,11 @@ components: roleType: type: string enum: - - owner - - admin - - tenant - - referrer + - OWNER + - ADMIN + - AGENT + - TENANT + - GUEST + - REFERRER roleName: type: string diff --git a/src/main/resources/db/changelog/010-context.sql b/src/main/resources/db/changelog/010-context.sql index ba655e93..3bb37037 100644 --- a/src/main/resources/db/changelog/010-context.sql +++ b/src/main/resources/db/changelog/010-context.sql @@ -149,8 +149,7 @@ create or replace function cleanIdentifier(rawIdentifier varchar) declare cleanIdentifier varchar; begin - -- TODO: remove the ':' from the list of allowed characters as soon as it's not used anymore - cleanIdentifier := regexp_replace(rawIdentifier, '[^A-Za-z0-9\-._:]+', '', 'g'); + cleanIdentifier := regexp_replace(rawIdentifier, '[^A-Za-z0-9\-._]+', '', 'g'); return cleanIdentifier; end; $$; diff --git a/src/main/resources/db/changelog/050-rbac-base.sql b/src/main/resources/db/changelog/050-rbac-base.sql index ca560bf9..6a3387fb 100644 --- a/src/main/resources/db/changelog/050-rbac-base.sql +++ b/src/main/resources/db/changelog/050-rbac-base.sql @@ -164,7 +164,7 @@ end; $$; */ -create type RbacRoleType as enum ('owner', 'admin', 'agent', 'tenant', 'guest', 'referrer'); +create type RbacRoleType as enum ('OWNER', 'ADMIN', 'AGENT', 'TENANT', 'GUEST', 'REFERRER'); create table RbacRole ( @@ -249,7 +249,7 @@ declare roleUuid uuid; begin -- TODO.refact: extract function toRbacRoleDescriptor(roleIdName varchar) + find other occurrences - roleParts = overlay(roleIdName placing '#' from length(roleIdName) + 1 - strpos(reverse(roleIdName), '.')); + roleParts = overlay(roleIdName placing '#' from length(roleIdName) + 1 - strpos(reverse(roleIdName), ':')); objectTableFromRoleIdName = split_part(roleParts, '#', 1); objectNameFromRoleIdName = split_part(roleParts, '#', 2); roleTypeFromRoleIdName = split_part(roleParts, '#', 3); diff --git a/src/main/resources/db/changelog/054-rbac-context.sql b/src/main/resources/db/changelog/054-rbac-context.sql index 5437131f..faae1782 100644 --- a/src/main/resources/db/changelog/054-rbac-context.sql +++ b/src/main/resources/db/changelog/054-rbac-context.sql @@ -50,7 +50,7 @@ begin foreach roleName in array string_to_array(assumedRoles, ';') loop - roleNameParts = overlay(roleName placing '#' from length(roleName) + 1 - strpos(reverse(roleName), '.')); + roleNameParts = overlay(roleName placing '#' from length(roleName) + 1 - strpos(reverse(roleName), ':')); objectTableToAssume = split_part(roleNameParts, '#', 1); objectNameToAssume = split_part(roleNameParts, '#', 2); roleTypeToAssume = split_part(roleNameParts, '#', 3); diff --git a/src/main/resources/db/changelog/055-rbac-views.sql b/src/main/resources/db/changelog/055-rbac-views.sql index 408c3594..a8570f6c 100644 --- a/src/main/resources/db/changelog/055-rbac-views.sql +++ b/src/main/resources/db/changelog/055-rbac-views.sql @@ -9,7 +9,7 @@ */ drop view if exists rbacrole_ev; create or replace view rbacrole_ev as -select (objectTable || '#' || objectIdName || '.' || roleType) as roleIdName, * +select (objectTable || '#' || objectIdName || ':' || roleType) as roleIdName, * -- @formatter:off from ( select r.*, @@ -40,7 +40,7 @@ select * where isGranted(currentSubjectsUuids(), r.uuid) ) as unordered -- @formatter:on - order by objectTable || '#' || objectIdName || '.' || roleType; + order by objectTable || '#' || objectIdName || ':' || roleType; grant all privileges on rbacrole_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME}; --// @@ -57,7 +57,7 @@ create or replace view rbacgrants_ev as -- @formatter:off select x.grantUuid as uuid, x.grantedByTriggerOf as grantedByTriggerOf, - go.objectTable || '#' || findIdNameByObjectUuid(go.objectTable, go.uuid) || '.' || r.roletype as grantedByRoleIdName, + go.objectTable || '#' || findIdNameByObjectUuid(go.objectTable, go.uuid) || ':' || r.roletype as grantedByRoleIdName, x.ascendingIdName as ascendantIdName, x.descendingIdName as descendantIdName, x.grantedByRoleUuid, @@ -71,16 +71,16 @@ create or replace view rbacgrants_ev as g.grantedbyroleuuid, g.ascendantuuid, g.descendantuuid, g.assumed, coalesce( - 'user ' || au.name, - 'role ' || aro.objectTable || '#' || findIdNameByObjectUuid(aro.objectTable, aro.uuid) || '.' || ar.roletype + 'user:' || au.name, + 'role:' || aro.objectTable || '#' || findIdNameByObjectUuid(aro.objectTable, aro.uuid) || ':' || ar.roletype ) as ascendingIdName, aro.objectTable, aro.uuid, ( case when dro is not null - then ('role ' || dro.objectTable || '#' || findIdNameByObjectUuid(dro.objectTable, dro.uuid) || '.' || dr.roletype) + then ('role:' || dro.objectTable || '#' || findIdNameByObjectUuid(dro.objectTable, dro.uuid) || ':' || dr.roletype) when dp.op = 'INSERT' - then 'perm ' || dp.op || ' into ' || dp.opTableName || ' with ' || dpo.objecttable || '#' || findIdNameByObjectUuid(dpo.objectTable, dpo.uuid) - else 'perm ' || dp.op || ' on ' || dpo.objecttable || '#' || findIdNameByObjectUuid(dpo.objectTable, dpo.uuid) + then 'perm:' || dpo.objecttable || '#' || findIdNameByObjectUuid(dpo.objectTable, dpo.uuid) || ':' || dp.op || '>' || dp.opTableName + else 'perm:' || dpo.objecttable || '#' || findIdNameByObjectUuid(dpo.objectTable, dpo.uuid) || ':' || dp.op end ) as descendingIdName, dro.objectTable, dro.uuid, @@ -115,8 +115,8 @@ create or replace view rbacgrants_ev as drop view if exists rbacgrants_rv; create or replace view rbacgrants_rv as -- @formatter:off -select o.objectTable || '#' || findIdNameByObjectUuid(o.objectTable, o.uuid) || '.' || r.roletype as grantedByRoleIdName, - g.objectTable || '#' || g.objectIdName || '.' || g.roletype as grantedRoleIdName, g.userName, g.assumed, +select o.objectTable || '#' || findIdNameByObjectUuid(o.objectTable, o.uuid) || ':' || r.roletype as grantedByRoleIdName, + g.objectTable || '#' || g.objectIdName || ':' || g.roletype as grantedRoleIdName, g.userName, g.assumed, g.grantedByRoleUuid, g.descendantUuid as grantedRoleUuid, g.ascendantUuid as userUuid, g.objectTable, g.objectUuid, g.objectIdName, g.roleType as grantedRoleType from ( @@ -327,7 +327,7 @@ execute function deleteRbacUser(); drop view if exists RbacOwnGrantedPermissions_rv; create or replace view RbacOwnGrantedPermissions_rv as select r.uuid as roleuuid, p.uuid as permissionUuid, - (r.objecttable || '#' || r.objectidname || '.' || r.roletype) as roleName, p.op, + (r.objecttable || ':' || r.objectidname || ':' || r.roletype) as roleName, p.op, o.objecttable, r.objectidname, o.uuid as objectuuid from rbacrole_rv r join rbacgrants g on g.ascendantuuid = r.uuid @@ -359,7 +359,7 @@ begin return query select xp.roleUuid, - (xp.roleObjectTable || '#' || xp.roleObjectIdName || '.' || xp.roleType) as roleName, + (xp.roleObjectTable || '#' || xp.roleObjectIdName || ':' || xp.roleType) as roleName, xp.permissionUuid, xp.op, xp.opTableName, xp.permissionObjectTable, xp.permissionObjectIdName, xp.permissionObjectUuid from (select diff --git a/src/main/resources/db/changelog/058-rbac-generators.sql b/src/main/resources/db/changelog/058-rbac-generators.sql index efe71b1b..958d3afe 100644 --- a/src/main/resources/db/changelog/058-rbac-generators.sql +++ b/src/main/resources/db/changelog/058-rbac-generators.sql @@ -46,7 +46,7 @@ begin language plpgsql strict as $f$ begin - return roleDescriptor('%2$s', entity.uuid, 'owner', assumed); + return roleDescriptor('%2$s', entity.uuid, 'OWNER', assumed); end; $f$; create or replace function %1$sAdmin(entity %2$s, assumed boolean = true) @@ -54,7 +54,7 @@ begin language plpgsql strict as $f$ begin - return roleDescriptor('%2$s', entity.uuid, 'admin', assumed); + return roleDescriptor('%2$s', entity.uuid, 'ADMIN', assumed); end; $f$; create or replace function %1$sAgent(entity %2$s, assumed boolean = true) @@ -62,7 +62,7 @@ begin language plpgsql strict as $f$ begin - return roleDescriptor('%2$s', entity.uuid, 'agent', assumed); + return roleDescriptor('%2$s', entity.uuid, 'AGENT', assumed); end; $f$; create or replace function %1$sTenant(entity %2$s, assumed boolean = true) @@ -70,7 +70,7 @@ begin language plpgsql strict as $f$ begin - return roleDescriptor('%2$s', entity.uuid, 'tenant', assumed); + return roleDescriptor('%2$s', entity.uuid, 'TENANT', assumed); end; $f$; -- TODO: remove guest role @@ -79,7 +79,7 @@ begin language plpgsql strict as $f$ begin - return roleDescriptor('%2$s', entity.uuid, 'guest', assumed); + return roleDescriptor('%2$s', entity.uuid, 'GUEST', assumed); end; $f$; create or replace function %1$sReferrer(entity %2$s) @@ -87,7 +87,7 @@ begin language plpgsql strict as $f$ begin - return roleDescriptor('%2$s', entity.uuid, 'referrer'); + return roleDescriptor('%2$s', entity.uuid, 'REFERRER'); end; $f$; $sql$, prefix, targetTable); diff --git a/src/main/resources/db/changelog/080-rbac-global.sql b/src/main/resources/db/changelog/080-rbac-global.sql index f8058113..7577e88c 100644 --- a/src/main/resources/db/changelog/080-rbac-global.sql +++ b/src/main/resources/db/changelog/080-rbac-global.sql @@ -114,11 +114,11 @@ create or replace function globalAdmin(assumed boolean = true) returns null on null input stable -- leakproof language sql as $$ -select 'global', (select uuid from RbacObject where objectTable = 'global'), 'admin'::RbacRoleType, assumed; +select 'global', (select uuid from RbacObject where objectTable = 'global'), 'ADMIN'::RbacRoleType, assumed; $$; begin transaction; - call defineContext('creating global admin role', null, null, null); + call defineContext('creating role:global#global:ADMIN', null, null, null); select createRole(globalAdmin()); commit; --// @@ -135,11 +135,11 @@ create or replace function globalGuest(assumed boolean = true) returns null on null input stable -- leakproof language sql as $$ -select 'global', (select uuid from RbacObject where objectTable = 'global'), 'guest'::RbacRoleType, assumed; +select 'global', (select uuid from RbacObject where objectTable = 'global'), 'GUEST'::RbacRoleType, assumed; $$; begin transaction; - call defineContext('creating global guest role', null, null, null); + call defineContext('creating role:global#loba:guest', null, null, null); select createRole(globalGuest()); commit; --// diff --git a/src/main/resources/db/changelog/113-test-customer-rbac.md b/src/main/resources/db/changelog/113-test-customer-rbac.md index 4d63eeac..19e67a38 100644 --- a/src/main/resources/db/changelog/113-test-customer-rbac.md +++ b/src/main/resources/db/changelog/113-test-customer-rbac.md @@ -13,9 +13,9 @@ subgraph customer["`**customer**`"] subgraph customer:roles[ ] style customer:roles fill:#dd4901,stroke:white - role:customer:owner[[customer:owner]] - role:customer:admin[[customer:admin]] - role:customer:tenant[[customer:tenant]] + role:customer:OWNER[[customer:OWNER]] + role:customer:ADMIN[[customer:ADMIN]] + role:customer:TENANT[[customer:TENANT]] end subgraph customer:permissions[ ] @@ -29,17 +29,17 @@ subgraph customer["`**customer**`"] end %% granting roles to users -user:creator ==>|XX| role:customer:owner +user:creator ==>|XX| role:customer:OWNER %% granting roles to roles -role:global:admin ==>|XX| role:customer:owner -role:customer:owner ==> role:customer:admin -role:customer:admin ==> role:customer:tenant +role:global:ADMIN ==>|XX| role:customer:OWNER +role:customer:OWNER ==> role:customer:ADMIN +role:customer:ADMIN ==> role:customer:TENANT %% granting permissions to roles -role:global:admin ==> perm:customer:INSERT -role:customer:owner ==> perm:customer:DELETE -role:customer:admin ==> perm:customer:UPDATE -role:customer:tenant ==> perm:customer:SELECT +role:global:ADMIN ==> perm:customer:INSERT +role:customer:OWNER ==> perm:customer:DELETE +role:customer:ADMIN ==> perm:customer:UPDATE +role:customer:TENANT ==> perm:customer:SELECT ``` diff --git a/src/main/resources/db/changelog/113-test-customer-rbac.sql b/src/main/resources/db/changelog/113-test-customer-rbac.sql index fd460049..2f9ea4de 100644 --- a/src/main/resources/db/changelog/113-test-customer-rbac.sql +++ b/src/main/resources/db/changelog/113-test-customer-rbac.sql @@ -35,22 +35,22 @@ begin call enterTriggerForObjectUuid(NEW.uuid); perform createRoleWithGrants( - testCustomerOwner(NEW), + testCustomerOWNER(NEW), permissions => array['DELETE'], - incomingSuperRoles => array[globalAdmin(unassumed())], + incomingSuperRoles => array[globalADMIN(unassumed())], userUuids => array[currentUserUuid()] ); perform createRoleWithGrants( - testCustomerAdmin(NEW), + testCustomerADMIN(NEW), permissions => array['UPDATE'], - incomingSuperRoles => array[testCustomerOwner(NEW)] + incomingSuperRoles => array[testCustomerOWNER(NEW)] ); perform createRoleWithGrants( - testCustomerTenant(NEW), + testCustomerTENANT(NEW), permissions => array['SELECT'], - incomingSuperRoles => array[testCustomerAdmin(NEW)] + incomingSuperRoles => array[testCustomerADMIN(NEW)] ); call leaveTriggerForObjectUuid(NEW.uuid); @@ -93,7 +93,7 @@ do language plpgsql $$ LOOP call grantPermissionToRole( createPermission(row.uuid, 'INSERT', 'test_customer'), - globalAdmin()); + globalADMIN()); END LOOP; END; $$; @@ -108,7 +108,7 @@ create or replace function test_customer_global_insert_tf() begin call grantPermissionToRole( createPermission(NEW.uuid, 'INSERT', 'test_customer'), - globalAdmin()); + globalADMIN()); return NEW; end; $$; diff --git a/src/main/resources/db/changelog/118-test-customer-test-data.sql b/src/main/resources/db/changelog/118-test-customer-test-data.sql index 85c34ac6..73c8e535 100644 --- a/src/main/resources/db/changelog/118-test-customer-test-data.sql +++ b/src/main/resources/db/changelog/118-test-customer-test-data.sql @@ -32,7 +32,7 @@ declare newCust test_customer; begin currentTask = 'creating RBAC test customer #' || custReference || '/' || custPrefix; - call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global.admin'); + call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN'); execute format('set local hsadminng.currentTask to %L', currentTask); custRowId = uuid_generate_v4(); diff --git a/src/main/resources/db/changelog/123-test-package-rbac.md b/src/main/resources/db/changelog/123-test-package-rbac.md index 34b8c7c7..368cfe2f 100644 --- a/src/main/resources/db/changelog/123-test-package-rbac.md +++ b/src/main/resources/db/changelog/123-test-package-rbac.md @@ -13,9 +13,9 @@ subgraph package["`**package**`"] subgraph package:roles[ ] style package:roles fill:#dd4901,stroke:white - role:package:owner[[package:owner]] - role:package:admin[[package:admin]] - role:package:tenant[[package:tenant]] + role:package:OWNER[[package:OWNER]] + role:package:ADMIN[[package:ADMIN]] + role:package:TENANT[[package:TENANT]] end subgraph package:permissions[ ] @@ -35,25 +35,25 @@ subgraph customer["`**customer**`"] subgraph customer:roles[ ] style customer:roles fill:#99bcdb,stroke:white - role:customer:owner[[customer:owner]] - role:customer:admin[[customer:admin]] - role:customer:tenant[[customer:tenant]] + role:customer:OWNER[[customer:OWNER]] + role:customer:ADMIN[[customer:ADMIN]] + role:customer:TENANT[[customer:TENANT]] end end %% granting roles to roles -role:global:admin -.->|XX| role:customer:owner -role:customer:owner -.-> role:customer:admin -role:customer:admin -.-> role:customer:tenant -role:customer:admin ==> role:package:owner -role:package:owner ==> role:package:admin -role:package:admin ==> role:package:tenant -role:package:tenant ==> role:customer:tenant +role:global:ADMIN -.->|XX| role:customer:OWNER +role:customer:OWNER -.-> role:customer:ADMIN +role:customer:ADMIN -.-> role:customer:TENANT +role:customer:ADMIN ==> role:package:OWNER +role:package:OWNER ==> role:package:ADMIN +role:package:ADMIN ==> role:package:TENANT +role:package:TENANT ==> role:customer:TENANT %% granting permissions to roles -role:customer:admin ==> perm:package:INSERT -role:package:owner ==> perm:package:DELETE -role:package:owner ==> perm:package:UPDATE -role:package:tenant ==> perm:package:SELECT +role:customer:ADMIN ==> perm:package:INSERT +role:package:OWNER ==> perm:package:DELETE +role:package:OWNER ==> perm:package:UPDATE +role:package:TENANT ==> perm:package:SELECT ``` diff --git a/src/main/resources/db/changelog/123-test-package-rbac.sql b/src/main/resources/db/changelog/123-test-package-rbac.sql index 972b174d..3a4d5d8b 100644 --- a/src/main/resources/db/changelog/123-test-package-rbac.sql +++ b/src/main/resources/db/changelog/123-test-package-rbac.sql @@ -40,21 +40,21 @@ begin perform createRoleWithGrants( - testPackageOwner(NEW), + testPackageOWNER(NEW), permissions => array['DELETE', 'UPDATE'], - incomingSuperRoles => array[testCustomerAdmin(newCustomer)] + incomingSuperRoles => array[testCustomerADMIN(newCustomer)] ); perform createRoleWithGrants( - testPackageAdmin(NEW), - incomingSuperRoles => array[testPackageOwner(NEW)] + testPackageADMIN(NEW), + incomingSuperRoles => array[testPackageOWNER(NEW)] ); perform createRoleWithGrants( - testPackageTenant(NEW), + testPackageTENANT(NEW), permissions => array['SELECT'], - incomingSuperRoles => array[testPackageAdmin(NEW)], - outgoingSubRoles => array[testCustomerTenant(newCustomer)] + incomingSuperRoles => array[testPackageADMIN(NEW)], + outgoingSubRoles => array[testCustomerTENANT(newCustomer)] ); call leaveTriggerForObjectUuid(NEW.uuid); @@ -110,11 +110,11 @@ begin if NEW.customerUuid <> OLD.customerUuid then - call revokeRoleFromRole(testPackageOwner(OLD), testCustomerAdmin(oldCustomer)); - call grantRoleToRole(testPackageOwner(NEW), testCustomerAdmin(newCustomer)); + call revokeRoleFromRole(testPackageOWNER(OLD), testCustomerADMIN(oldCustomer)); + call grantRoleToRole(testPackageOWNER(NEW), testCustomerADMIN(newCustomer)); - call revokeRoleFromRole(testCustomerTenant(oldCustomer), testPackageTenant(OLD)); - call grantRoleToRole(testCustomerTenant(newCustomer), testPackageTenant(NEW)); + call revokeRoleFromRole(testCustomerTENANT(oldCustomer), testPackageTENANT(OLD)); + call grantRoleToRole(testCustomerTENANT(newCustomer), testPackageTENANT(NEW)); end if; @@ -158,7 +158,7 @@ do language plpgsql $$ LOOP call grantPermissionToRole( createPermission(row.uuid, 'INSERT', 'test_package'), - testCustomerAdmin(row)); + testCustomerADMIN(row)); END LOOP; END; $$; @@ -173,7 +173,7 @@ create or replace function test_package_test_customer_insert_tf() begin call grantPermissionToRole( createPermission(NEW.uuid, 'INSERT', 'test_package'), - testCustomerAdmin(NEW)); + testCustomerADMIN(NEW)); return NEW; end; $$; diff --git a/src/main/resources/db/changelog/128-test-package-test-data.sql b/src/main/resources/db/changelog/128-test-package-test-data.sql index 9abba772..f50ad480 100644 --- a/src/main/resources/db/changelog/128-test-package-test-data.sql +++ b/src/main/resources/db/changelog/128-test-package-test-data.sql @@ -25,7 +25,7 @@ begin cust.uuid; custAdminUser = 'customer-admin@' || cust.prefix || '.example.com'; - custAdminRole = 'test_customer#' || cust.prefix || '.admin'; + custAdminRole = 'test_customer#' || cust.prefix || ':ADMIN'; call defineContext(currentTask, null, 'superuser-fran@hostsharing.net', custAdminRole); raise notice 'task: % by % as %', currentTask, custAdminUser, custAdminRole; diff --git a/src/main/resources/db/changelog/133-test-domain-rbac.md b/src/main/resources/db/changelog/133-test-domain-rbac.md index 6954e9b8..d9b3748c 100644 --- a/src/main/resources/db/changelog/133-test-domain-rbac.md +++ b/src/main/resources/db/changelog/133-test-domain-rbac.md @@ -13,9 +13,9 @@ subgraph package.customer["`**package.customer**`"] subgraph package.customer:roles[ ] style package.customer:roles fill:#99bcdb,stroke:white - role:package.customer:owner[[package.customer:owner]] - role:package.customer:admin[[package.customer:admin]] - role:package.customer:tenant[[package.customer:tenant]] + role:package.customer:OWNER[[package.customer:OWNER]] + role:package.customer:ADMIN[[package.customer:ADMIN]] + role:package.customer:TENANT[[package.customer:TENANT]] end end @@ -23,25 +23,12 @@ subgraph package["`**package**`"] direction TB style package fill:#99bcdb,stroke:#274d6e,stroke-width:8px - subgraph package.customer["`**package.customer**`"] - direction TB - style package.customer fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph package.customer:roles[ ] - style package.customer:roles fill:#99bcdb,stroke:white - - role:package.customer:owner[[package.customer:owner]] - role:package.customer:admin[[package.customer:admin]] - role:package.customer:tenant[[package.customer:tenant]] - end - end - subgraph package:roles[ ] style package:roles fill:#99bcdb,stroke:white - role:package:owner[[package:owner]] - role:package:admin[[package:admin]] - role:package:tenant[[package:tenant]] + role:package:OWNER[[package:OWNER]] + role:package:ADMIN[[package:ADMIN]] + role:package:TENANT[[package:TENANT]] end end @@ -52,8 +39,8 @@ subgraph domain["`**domain**`"] subgraph domain:roles[ ] style domain:roles fill:#dd4901,stroke:white - role:domain:owner[[domain:owner]] - role:domain:admin[[domain:admin]] + role:domain:OWNER[[domain:OWNER]] + role:domain:ADMIN[[domain:ADMIN]] end subgraph domain:permissions[ ] @@ -67,22 +54,22 @@ subgraph domain["`**domain**`"] end %% granting roles to roles -role:global:admin -.->|XX| role:package.customer:owner -role:package.customer:owner -.-> role:package.customer:admin -role:package.customer:admin -.-> role:package.customer:tenant -role:package.customer:admin -.-> role:package:owner -role:package:owner -.-> role:package:admin -role:package:admin -.-> role:package:tenant -role:package:tenant -.-> role:package.customer:tenant -role:package:admin ==> role:domain:owner -role:domain:owner ==> role:package:tenant -role:domain:owner ==> role:domain:admin -role:domain:admin ==> role:package:tenant +role:global:ADMIN -.->|XX| role:package.customer:OWNER +role:package.customer:OWNER -.-> role:package.customer:ADMIN +role:package.customer:ADMIN -.-> role:package.customer:TENANT +role:package.customer:ADMIN -.-> role:package:OWNER +role:package:OWNER -.-> role:package:ADMIN +role:package:ADMIN -.-> role:package:TENANT +role:package:TENANT -.-> role:package.customer:TENANT +role:package:ADMIN ==> role:domain:OWNER +role:domain:OWNER ==> role:package:TENANT +role:domain:OWNER ==> role:domain:ADMIN +role:domain:ADMIN ==> role:package:TENANT %% granting permissions to roles -role:package:admin ==> perm:domain:INSERT -role:domain:owner ==> perm:domain:DELETE -role:domain:owner ==> perm:domain:UPDATE -role:domain:admin ==> perm:domain:SELECT +role:package:ADMIN ==> perm:domain:INSERT +role:domain:OWNER ==> perm:domain:DELETE +role:domain:OWNER ==> perm:domain:UPDATE +role:domain:ADMIN ==> perm:domain:SELECT ``` diff --git a/src/main/resources/db/changelog/133-test-domain-rbac.sql b/src/main/resources/db/changelog/133-test-domain-rbac.sql index 7a891841..de5faa78 100644 --- a/src/main/resources/db/changelog/133-test-domain-rbac.sql +++ b/src/main/resources/db/changelog/133-test-domain-rbac.sql @@ -40,17 +40,17 @@ begin perform createRoleWithGrants( - testDomainOwner(NEW), + testDomainOWNER(NEW), permissions => array['DELETE', 'UPDATE'], - incomingSuperRoles => array[testPackageAdmin(newPackage)], - outgoingSubRoles => array[testPackageTenant(newPackage)] + incomingSuperRoles => array[testPackageADMIN(newPackage)], + outgoingSubRoles => array[testPackageTENANT(newPackage)] ); perform createRoleWithGrants( - testDomainAdmin(NEW), + testDomainADMIN(NEW), permissions => array['SELECT'], - incomingSuperRoles => array[testDomainOwner(NEW)], - outgoingSubRoles => array[testPackageTenant(newPackage)] + incomingSuperRoles => array[testDomainOWNER(NEW)], + outgoingSubRoles => array[testPackageTENANT(newPackage)] ); call leaveTriggerForObjectUuid(NEW.uuid); @@ -106,14 +106,14 @@ begin if NEW.packageUuid <> OLD.packageUuid then - call revokeRoleFromRole(testDomainOwner(OLD), testPackageAdmin(oldPackage)); - call grantRoleToRole(testDomainOwner(NEW), testPackageAdmin(newPackage)); + call revokeRoleFromRole(testDomainOWNER(OLD), testPackageADMIN(oldPackage)); + call grantRoleToRole(testDomainOWNER(NEW), testPackageADMIN(newPackage)); - call revokeRoleFromRole(testPackageTenant(oldPackage), testDomainOwner(OLD)); - call grantRoleToRole(testPackageTenant(newPackage), testDomainOwner(NEW)); + call revokeRoleFromRole(testPackageTENANT(oldPackage), testDomainOWNER(OLD)); + call grantRoleToRole(testPackageTENANT(newPackage), testDomainOWNER(NEW)); - call revokeRoleFromRole(testPackageTenant(oldPackage), testDomainAdmin(OLD)); - call grantRoleToRole(testPackageTenant(newPackage), testDomainAdmin(NEW)); + call revokeRoleFromRole(testPackageTENANT(oldPackage), testDomainADMIN(OLD)); + call grantRoleToRole(testPackageTENANT(newPackage), testDomainADMIN(NEW)); end if; @@ -157,7 +157,7 @@ do language plpgsql $$ LOOP call grantPermissionToRole( createPermission(row.uuid, 'INSERT', 'test_domain'), - testPackageAdmin(row)); + testPackageADMIN(row)); END LOOP; END; $$; @@ -172,7 +172,7 @@ create or replace function test_domain_test_package_insert_tf() begin call grantPermissionToRole( createPermission(NEW.uuid, 'INSERT', 'test_domain'), - testPackageAdmin(NEW)); + testPackageADMIN(NEW)); return NEW; end; $$; diff --git a/src/main/resources/db/changelog/203-hs-office-contact-rbac.md b/src/main/resources/db/changelog/203-hs-office-contact-rbac.md index 52584907..fe736072 100644 --- a/src/main/resources/db/changelog/203-hs-office-contact-rbac.md +++ b/src/main/resources/db/changelog/203-hs-office-contact-rbac.md @@ -13,9 +13,9 @@ subgraph contact["`**contact**`"] subgraph contact:roles[ ] style contact:roles fill:#dd4901,stroke:white - role:contact:owner[[contact:owner]] - role:contact:admin[[contact:admin]] - role:contact:referrer[[contact:referrer]] + role:contact:OWNER[[contact:OWNER]] + role:contact:ADMIN[[contact:ADMIN]] + role:contact:REFERRER[[contact:REFERRER]] end subgraph contact:permissions[ ] @@ -29,17 +29,17 @@ subgraph contact["`**contact**`"] end %% granting roles to users -user:creator ==> role:contact:owner +user:creator ==> role:contact:OWNER %% granting roles to roles -role:global:admin ==> role:contact:owner -role:contact:owner ==> role:contact:admin -role:contact:admin ==> role:contact:referrer +role:global:ADMIN ==> role:contact:OWNER +role:contact:OWNER ==> role:contact:ADMIN +role:contact:ADMIN ==> role:contact:REFERRER %% granting permissions to roles -role:contact:owner ==> perm:contact:DELETE -role:contact:admin ==> perm:contact:UPDATE -role:contact:referrer ==> perm:contact:SELECT -role:global:guest ==> perm:contact:INSERT +role:contact:OWNER ==> perm:contact:DELETE +role:contact:ADMIN ==> perm:contact:UPDATE +role:contact:REFERRER ==> perm:contact:SELECT +role:global:GUEST ==> perm:contact:INSERT ``` diff --git a/src/main/resources/db/changelog/203-hs-office-contact-rbac.sql b/src/main/resources/db/changelog/203-hs-office-contact-rbac.sql index 0e08e15f..0f53b167 100644 --- a/src/main/resources/db/changelog/203-hs-office-contact-rbac.sql +++ b/src/main/resources/db/changelog/203-hs-office-contact-rbac.sql @@ -35,22 +35,22 @@ begin call enterTriggerForObjectUuid(NEW.uuid); perform createRoleWithGrants( - hsOfficeContactOwner(NEW), + hsOfficeContactOWNER(NEW), permissions => array['DELETE'], - incomingSuperRoles => array[globalAdmin()], + incomingSuperRoles => array[globalADMIN()], userUuids => array[currentUserUuid()] ); perform createRoleWithGrants( - hsOfficeContactAdmin(NEW), + hsOfficeContactADMIN(NEW), permissions => array['UPDATE'], - incomingSuperRoles => array[hsOfficeContactOwner(NEW)] + incomingSuperRoles => array[hsOfficeContactOWNER(NEW)] ); perform createRoleWithGrants( - hsOfficeContactReferrer(NEW), + hsOfficeContactREFERRER(NEW), permissions => array['SELECT'], - incomingSuperRoles => array[hsOfficeContactAdmin(NEW)] + incomingSuperRoles => array[hsOfficeContactADMIN(NEW)] ); call leaveTriggerForObjectUuid(NEW.uuid); @@ -93,7 +93,7 @@ do language plpgsql $$ LOOP call grantPermissionToRole( createPermission(row.uuid, 'INSERT', 'hs_office_contact'), - globalGuest()); + globalGUEST()); END LOOP; END; $$; @@ -108,7 +108,7 @@ create or replace function hs_office_contact_global_insert_tf() begin call grantPermissionToRole( createPermission(NEW.uuid, 'INSERT', 'hs_office_contact'), - globalGuest()); + globalGUEST()); return NEW; end; $$; diff --git a/src/main/resources/db/changelog/213-hs-office-person-rbac.md b/src/main/resources/db/changelog/213-hs-office-person-rbac.md index 70e0f33a..d0eebfdd 100644 --- a/src/main/resources/db/changelog/213-hs-office-person-rbac.md +++ b/src/main/resources/db/changelog/213-hs-office-person-rbac.md @@ -13,9 +13,9 @@ subgraph person["`**person**`"] subgraph person:roles[ ] style person:roles fill:#dd4901,stroke:white - role:person:owner[[person:owner]] - role:person:admin[[person:admin]] - role:person:referrer[[person:referrer]] + role:person:OWNER[[person:OWNER]] + role:person:ADMIN[[person:ADMIN]] + role:person:REFERRER[[person:REFERRER]] end subgraph person:permissions[ ] @@ -29,17 +29,17 @@ subgraph person["`**person**`"] end %% granting roles to users -user:creator ==> role:person:owner +user:creator ==> role:person:OWNER %% granting roles to roles -role:global:admin ==> role:person:owner -role:person:owner ==> role:person:admin -role:person:admin ==> role:person:referrer +role:global:ADMIN ==> role:person:OWNER +role:person:OWNER ==> role:person:ADMIN +role:person:ADMIN ==> role:person:REFERRER %% granting permissions to roles -role:global:guest ==> perm:person:INSERT -role:person:owner ==> perm:person:DELETE -role:person:admin ==> perm:person:UPDATE -role:person:referrer ==> perm:person:SELECT +role:global:GUEST ==> perm:person:INSERT +role:person:OWNER ==> perm:person:DELETE +role:person:ADMIN ==> perm:person:UPDATE +role:person:REFERRER ==> perm:person:SELECT ``` diff --git a/src/main/resources/db/changelog/213-hs-office-person-rbac.sql b/src/main/resources/db/changelog/213-hs-office-person-rbac.sql index adbdae33..6dbbf21b 100644 --- a/src/main/resources/db/changelog/213-hs-office-person-rbac.sql +++ b/src/main/resources/db/changelog/213-hs-office-person-rbac.sql @@ -35,22 +35,22 @@ begin call enterTriggerForObjectUuid(NEW.uuid); perform createRoleWithGrants( - hsOfficePersonOwner(NEW), + hsOfficePersonOWNER(NEW), permissions => array['DELETE'], - incomingSuperRoles => array[globalAdmin()], + incomingSuperRoles => array[globalADMIN()], userUuids => array[currentUserUuid()] ); perform createRoleWithGrants( - hsOfficePersonAdmin(NEW), + hsOfficePersonADMIN(NEW), permissions => array['UPDATE'], - incomingSuperRoles => array[hsOfficePersonOwner(NEW)] + incomingSuperRoles => array[hsOfficePersonOWNER(NEW)] ); perform createRoleWithGrants( - hsOfficePersonReferrer(NEW), + hsOfficePersonREFERRER(NEW), permissions => array['SELECT'], - incomingSuperRoles => array[hsOfficePersonAdmin(NEW)] + incomingSuperRoles => array[hsOfficePersonADMIN(NEW)] ); call leaveTriggerForObjectUuid(NEW.uuid); @@ -93,7 +93,7 @@ do language plpgsql $$ LOOP call grantPermissionToRole( createPermission(row.uuid, 'INSERT', 'hs_office_person'), - globalGuest()); + globalGUEST()); END LOOP; END; $$; @@ -108,7 +108,7 @@ create or replace function hs_office_person_global_insert_tf() begin call grantPermissionToRole( createPermission(NEW.uuid, 'INSERT', 'hs_office_person'), - globalGuest()); + globalGUEST()); return NEW; end; $$; diff --git a/src/main/resources/db/changelog/223-hs-office-relation-rbac.md b/src/main/resources/db/changelog/223-hs-office-relation-rbac.md index 8e5524ec..8014cdaf 100644 --- a/src/main/resources/db/changelog/223-hs-office-relation-rbac.md +++ b/src/main/resources/db/changelog/223-hs-office-relation-rbac.md @@ -13,9 +13,9 @@ subgraph holderPerson["`**holderPerson**`"] subgraph holderPerson:roles[ ] style holderPerson:roles fill:#99bcdb,stroke:white - role:holderPerson:owner[[holderPerson:owner]] - role:holderPerson:admin[[holderPerson:admin]] - role:holderPerson:referrer[[holderPerson:referrer]] + role:holderPerson:OWNER[[holderPerson:OWNER]] + role:holderPerson:ADMIN[[holderPerson:ADMIN]] + role:holderPerson:REFERRER[[holderPerson:REFERRER]] end end @@ -26,9 +26,9 @@ subgraph anchorPerson["`**anchorPerson**`"] subgraph anchorPerson:roles[ ] style anchorPerson:roles fill:#99bcdb,stroke:white - role:anchorPerson:owner[[anchorPerson:owner]] - role:anchorPerson:admin[[anchorPerson:admin]] - role:anchorPerson:referrer[[anchorPerson:referrer]] + role:anchorPerson:OWNER[[anchorPerson:OWNER]] + role:anchorPerson:ADMIN[[anchorPerson:ADMIN]] + role:anchorPerson:REFERRER[[anchorPerson:REFERRER]] end end @@ -39,9 +39,9 @@ subgraph contact["`**contact**`"] subgraph contact:roles[ ] style contact:roles fill:#99bcdb,stroke:white - role:contact:owner[[contact:owner]] - role:contact:admin[[contact:admin]] - role:contact:referrer[[contact:referrer]] + role:contact:OWNER[[contact:OWNER]] + role:contact:ADMIN[[contact:ADMIN]] + role:contact:REFERRER[[contact:REFERRER]] end end @@ -52,10 +52,10 @@ subgraph relation["`**relation**`"] subgraph relation:roles[ ] style relation:roles fill:#dd4901,stroke:white - role:relation:owner[[relation:owner]] - role:relation:admin[[relation:admin]] - role:relation:agent[[relation:agent]] - role:relation:tenant[[relation:tenant]] + role:relation:OWNER[[relation:OWNER]] + role:relation:ADMIN[[relation:ADMIN]] + role:relation:AGENT[[relation:AGENT]] + role:relation:TENANT[[relation:TENANT]] end subgraph relation:permissions[ ] @@ -69,34 +69,34 @@ subgraph relation["`**relation**`"] end %% granting roles to users -user:creator ==> role:relation:owner +user:creator ==> role:relation:OWNER %% granting roles to roles -role:global:admin -.-> role:anchorPerson:owner -role:anchorPerson:owner -.-> role:anchorPerson:admin -role:anchorPerson:admin -.-> role:anchorPerson:referrer -role:global:admin -.-> role:holderPerson:owner -role:holderPerson:owner -.-> role:holderPerson:admin -role:holderPerson:admin -.-> role:holderPerson:referrer -role:global:admin -.-> role:contact:owner -role:contact:owner -.-> role:contact:admin -role:contact:admin -.-> role:contact:referrer -role:global:admin ==> role:relation:owner -role:relation:owner ==> role:relation:admin -role:anchorPerson:admin ==> role:relation:admin -role:relation:admin ==> role:relation:agent -role:holderPerson:admin ==> role:relation:agent -role:relation:agent ==> role:relation:tenant -role:holderPerson:admin ==> role:relation:tenant -role:contact:admin ==> role:relation:tenant -role:relation:tenant ==> role:anchorPerson:referrer -role:relation:tenant ==> role:holderPerson:referrer -role:relation:tenant ==> role:contact:referrer +role:global:ADMIN -.-> role:anchorPerson:OWNER +role:anchorPerson:OWNER -.-> role:anchorPerson:ADMIN +role:anchorPerson:ADMIN -.-> role:anchorPerson:REFERRER +role:global:ADMIN -.-> role:holderPerson:OWNER +role:holderPerson:OWNER -.-> role:holderPerson:ADMIN +role:holderPerson:ADMIN -.-> role:holderPerson:REFERRER +role:global:ADMIN -.-> role:contact:OWNER +role:contact:OWNER -.-> role:contact:ADMIN +role:contact:ADMIN -.-> role:contact:REFERRER +role:global:ADMIN ==> role:relation:OWNER +role:relation:OWNER ==> role:relation:ADMIN +role:anchorPerson:ADMIN ==> role:relation:ADMIN +role:relation:ADMIN ==> role:relation:AGENT +role:holderPerson:ADMIN ==> role:relation:AGENT +role:relation:AGENT ==> role:relation:TENANT +role:holderPerson:ADMIN ==> role:relation:TENANT +role:contact:ADMIN ==> role:relation:TENANT +role:relation:TENANT ==> role:anchorPerson:REFERRER +role:relation:TENANT ==> role:holderPerson:REFERRER +role:relation:TENANT ==> role:contact:REFERRER %% granting permissions to roles -role:relation:owner ==> perm:relation:DELETE -role:relation:admin ==> perm:relation:UPDATE -role:relation:tenant ==> perm:relation:SELECT -role:anchorPerson:admin ==> perm:relation:INSERT +role:relation:OWNER ==> perm:relation:DELETE +role:relation:ADMIN ==> perm:relation:UPDATE +role:relation:TENANT ==> perm:relation:SELECT +role:anchorPerson:ADMIN ==> perm:relation:INSERT ``` diff --git a/src/main/resources/db/changelog/223-hs-office-relation-rbac.sql b/src/main/resources/db/changelog/223-hs-office-relation-rbac.sql index 6c9ae616..ff890a59 100644 --- a/src/main/resources/db/changelog/223-hs-office-relation-rbac.sql +++ b/src/main/resources/db/changelog/223-hs-office-relation-rbac.sql @@ -48,38 +48,38 @@ begin perform createRoleWithGrants( - hsOfficeRelationOwner(NEW), + hsOfficeRelationOWNER(NEW), permissions => array['DELETE'], - incomingSuperRoles => array[globalAdmin()], + incomingSuperRoles => array[globalADMIN()], userUuids => array[currentUserUuid()] ); perform createRoleWithGrants( - hsOfficeRelationAdmin(NEW), + hsOfficeRelationADMIN(NEW), permissions => array['UPDATE'], incomingSuperRoles => array[ - hsOfficePersonAdmin(newAnchorPerson), - hsOfficeRelationOwner(NEW)] + hsOfficePersonADMIN(newAnchorPerson), + hsOfficeRelationOWNER(NEW)] ); perform createRoleWithGrants( - hsOfficeRelationAgent(NEW), + hsOfficeRelationAGENT(NEW), incomingSuperRoles => array[ - hsOfficePersonAdmin(newHolderPerson), - hsOfficeRelationAdmin(NEW)] + hsOfficePersonADMIN(newHolderPerson), + hsOfficeRelationADMIN(NEW)] ); perform createRoleWithGrants( - hsOfficeRelationTenant(NEW), + hsOfficeRelationTENANT(NEW), permissions => array['SELECT'], incomingSuperRoles => array[ - hsOfficeContactAdmin(newContact), - hsOfficePersonAdmin(newHolderPerson), - hsOfficeRelationAgent(NEW)], + hsOfficeContactADMIN(newContact), + hsOfficePersonADMIN(newHolderPerson), + hsOfficeRelationAGENT(NEW)], outgoingSubRoles => array[ - hsOfficeContactReferrer(newContact), - hsOfficePersonReferrer(newAnchorPerson), - hsOfficePersonReferrer(newHolderPerson)] + hsOfficeContactREFERRER(newContact), + hsOfficePersonREFERRER(newAnchorPerson), + hsOfficePersonREFERRER(newHolderPerson)] ); call leaveTriggerForObjectUuid(NEW.uuid); @@ -151,11 +151,11 @@ begin if NEW.contactUuid <> OLD.contactUuid then - call revokeRoleFromRole(hsOfficeRelationTenant(OLD), hsOfficeContactAdmin(oldContact)); - call grantRoleToRole(hsOfficeRelationTenant(NEW), hsOfficeContactAdmin(newContact)); + call revokeRoleFromRole(hsOfficeRelationTENANT(OLD), hsOfficeContactADMIN(oldContact)); + call grantRoleToRole(hsOfficeRelationTENANT(NEW), hsOfficeContactADMIN(newContact)); - call revokeRoleFromRole(hsOfficeContactReferrer(oldContact), hsOfficeRelationTenant(OLD)); - call grantRoleToRole(hsOfficeContactReferrer(newContact), hsOfficeRelationTenant(NEW)); + call revokeRoleFromRole(hsOfficeContactREFERRER(oldContact), hsOfficeRelationTENANT(OLD)); + call grantRoleToRole(hsOfficeContactREFERRER(newContact), hsOfficeRelationTENANT(NEW)); end if; @@ -199,7 +199,7 @@ do language plpgsql $$ LOOP call grantPermissionToRole( createPermission(row.uuid, 'INSERT', 'hs_office_relation'), - hsOfficePersonAdmin(row)); + hsOfficePersonADMIN(row)); END LOOP; END; $$; @@ -214,7 +214,7 @@ create or replace function hs_office_relation_hs_office_person_insert_tf() begin call grantPermissionToRole( createPermission(NEW.uuid, 'INSERT', 'hs_office_relation'), - hsOfficePersonAdmin(NEW)); + hsOfficePersonADMIN(NEW)); return NEW; end; $$; diff --git a/src/main/resources/db/changelog/228-hs-office-relation-test-data.sql b/src/main/resources/db/changelog/228-hs-office-relation-test-data.sql index 9bdcab18..61691d6f 100644 --- a/src/main/resources/db/changelog/228-hs-office-relation-test-data.sql +++ b/src/main/resources/db/changelog/228-hs-office-relation-test-data.sql @@ -25,7 +25,7 @@ declare begin idName := cleanIdentifier( anchorPersonName || '-' || holderPersonName); currentTask := 'creating relation test-data ' || idName; - call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global.admin'); + call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN'); execute format('set local hsadminng.currentTask to %L', currentTask); select p.* diff --git a/src/main/resources/db/changelog/233-hs-office-partner-rbac.md b/src/main/resources/db/changelog/233-hs-office-partner-rbac.md index 98bd276d..a0caa074 100644 --- a/src/main/resources/db/changelog/233-hs-office-partner-rbac.md +++ b/src/main/resources/db/changelog/233-hs-office-partner-rbac.md @@ -13,9 +13,9 @@ subgraph partnerRel.contact["`**partnerRel.contact**`"] subgraph partnerRel.contact:roles[ ] style partnerRel.contact:roles fill:#99bcdb,stroke:white - role:partnerRel.contact:owner[[partnerRel.contact:owner]] - role:partnerRel.contact:admin[[partnerRel.contact:admin]] - role:partnerRel.contact:referrer[[partnerRel.contact:referrer]] + role:partnerRel.contact:OWNER[[partnerRel.contact:OWNER]] + role:partnerRel.contact:ADMIN[[partnerRel.contact:ADMIN]] + role:partnerRel.contact:REFERRER[[partnerRel.contact:REFERRER]] end end @@ -35,52 +35,14 @@ subgraph partner["`**partner**`"] subgraph partnerRel["`**partnerRel**`"] direction TB style partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px - subgraph partnerRel.contact["`**partnerRel.contact**`"] - direction TB - style partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph partnerRel.contact:roles[ ] - style partnerRel.contact:roles fill:#99bcdb,stroke:white - - role:partnerRel.contact:owner[[partnerRel.contact:owner]] - role:partnerRel.contact:admin[[partnerRel.contact:admin]] - role:partnerRel.contact:referrer[[partnerRel.contact:referrer]] - end - end - - subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"] - direction TB - style partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph partnerRel.anchorPerson:roles[ ] - style partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white - - role:partnerRel.anchorPerson:owner[[partnerRel.anchorPerson:owner]] - role:partnerRel.anchorPerson:admin[[partnerRel.anchorPerson:admin]] - role:partnerRel.anchorPerson:referrer[[partnerRel.anchorPerson:referrer]] - end - end - - subgraph partnerRel.holderPerson["`**partnerRel.holderPerson**`"] - direction TB - style partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph partnerRel.holderPerson:roles[ ] - style partnerRel.holderPerson:roles fill:#99bcdb,stroke:white - - role:partnerRel.holderPerson:owner[[partnerRel.holderPerson:owner]] - role:partnerRel.holderPerson:admin[[partnerRel.holderPerson:admin]] - role:partnerRel.holderPerson:referrer[[partnerRel.holderPerson:referrer]] - end - end subgraph partnerRel:roles[ ] style partnerRel:roles fill:#99bcdb,stroke:white - role:partnerRel:owner[[partnerRel:owner]] - role:partnerRel:admin[[partnerRel:admin]] - role:partnerRel:agent[[partnerRel:agent]] - role:partnerRel:tenant[[partnerRel:tenant]] + role:partnerRel:OWNER[[partnerRel:OWNER]] + role:partnerRel:ADMIN[[partnerRel:ADMIN]] + role:partnerRel:AGENT[[partnerRel:AGENT]] + role:partnerRel:TENANT[[partnerRel:TENANT]] end end end @@ -105,9 +67,9 @@ subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"] subgraph partnerRel.anchorPerson:roles[ ] style partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white - role:partnerRel.anchorPerson:owner[[partnerRel.anchorPerson:owner]] - role:partnerRel.anchorPerson:admin[[partnerRel.anchorPerson:admin]] - role:partnerRel.anchorPerson:referrer[[partnerRel.anchorPerson:referrer]] + role:partnerRel.anchorPerson:OWNER[[partnerRel.anchorPerson:OWNER]] + role:partnerRel.anchorPerson:ADMIN[[partnerRel.anchorPerson:ADMIN]] + role:partnerRel.anchorPerson:REFERRER[[partnerRel.anchorPerson:REFERRER]] end end @@ -118,41 +80,41 @@ subgraph partnerRel.holderPerson["`**partnerRel.holderPerson**`"] subgraph partnerRel.holderPerson:roles[ ] style partnerRel.holderPerson:roles fill:#99bcdb,stroke:white - role:partnerRel.holderPerson:owner[[partnerRel.holderPerson:owner]] - role:partnerRel.holderPerson:admin[[partnerRel.holderPerson:admin]] - role:partnerRel.holderPerson:referrer[[partnerRel.holderPerson:referrer]] + role:partnerRel.holderPerson:OWNER[[partnerRel.holderPerson:OWNER]] + role:partnerRel.holderPerson:ADMIN[[partnerRel.holderPerson:ADMIN]] + role:partnerRel.holderPerson:REFERRER[[partnerRel.holderPerson:REFERRER]] end end %% granting roles to roles -role:global:admin -.-> role:partnerRel.anchorPerson:owner -role:partnerRel.anchorPerson:owner -.-> role:partnerRel.anchorPerson:admin -role:partnerRel.anchorPerson:admin -.-> role:partnerRel.anchorPerson:referrer -role:global:admin -.-> role:partnerRel.holderPerson:owner -role:partnerRel.holderPerson:owner -.-> role:partnerRel.holderPerson:admin -role:partnerRel.holderPerson:admin -.-> role:partnerRel.holderPerson:referrer -role:global:admin -.-> role:partnerRel.contact:owner -role:partnerRel.contact:owner -.-> role:partnerRel.contact:admin -role:partnerRel.contact:admin -.-> role:partnerRel.contact:referrer -role:global:admin -.-> role:partnerRel:owner -role:partnerRel:owner -.-> role:partnerRel:admin -role:partnerRel.anchorPerson:admin -.-> role:partnerRel:admin -role:partnerRel:admin -.-> role:partnerRel:agent -role:partnerRel.holderPerson:admin -.-> role:partnerRel:agent -role:partnerRel:agent -.-> role:partnerRel:tenant -role:partnerRel.holderPerson:admin -.-> role:partnerRel:tenant -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:global:ADMIN -.-> role:partnerRel.anchorPerson:OWNER +role:partnerRel.anchorPerson:OWNER -.-> role:partnerRel.anchorPerson:ADMIN +role:partnerRel.anchorPerson:ADMIN -.-> role:partnerRel.anchorPerson:REFERRER +role:global:ADMIN -.-> role:partnerRel.holderPerson:OWNER +role:partnerRel.holderPerson:OWNER -.-> role:partnerRel.holderPerson:ADMIN +role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel.holderPerson:REFERRER +role:global:ADMIN -.-> role:partnerRel.contact:OWNER +role:partnerRel.contact:OWNER -.-> role:partnerRel.contact:ADMIN +role:partnerRel.contact:ADMIN -.-> role:partnerRel.contact:REFERRER +role:global:ADMIN -.-> role:partnerRel:OWNER +role:partnerRel:OWNER -.-> role:partnerRel:ADMIN +role:partnerRel.anchorPerson:ADMIN -.-> role:partnerRel:ADMIN +role:partnerRel:ADMIN -.-> role:partnerRel:AGENT +role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:AGENT +role:partnerRel:AGENT -.-> role:partnerRel:TENANT +role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:TENANT +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 %% granting permissions to roles -role:global:admin ==> perm:partner:INSERT -role:partnerRel:admin ==> perm:partner:DELETE -role:partnerRel:agent ==> perm:partner:UPDATE -role:partnerRel:tenant ==> perm:partner:SELECT -role:partnerRel:admin ==> perm:partnerDetails:DELETE -role:partnerRel:agent ==> perm:partnerDetails:UPDATE -role:partnerRel:agent ==> perm:partnerDetails:SELECT +role:global:ADMIN ==> perm:partner:INSERT +role:partnerRel:ADMIN ==> perm:partner:DELETE +role:partnerRel:AGENT ==> perm:partner:UPDATE +role:partnerRel:TENANT ==> perm:partner:SELECT +role:partnerRel:ADMIN ==> perm:partnerDetails:DELETE +role:partnerRel:AGENT ==> perm:partnerDetails:UPDATE +role:partnerRel:AGENT ==> perm:partnerDetails:SELECT ``` diff --git a/src/main/resources/db/changelog/233-hs-office-partner-rbac.sql b/src/main/resources/db/changelog/233-hs-office-partner-rbac.sql index 9cdd92fc..b5510d8c 100644 --- a/src/main/resources/db/changelog/233-hs-office-partner-rbac.sql +++ b/src/main/resources/db/changelog/233-hs-office-partner-rbac.sql @@ -42,12 +42,12 @@ begin SELECT * FROM hs_office_partner_details WHERE uuid = NEW.detailsUuid INTO newPartnerDetails; assert newPartnerDetails.uuid is not null, format('newPartnerDetails must not be null for NEW.detailsUuid = %s', NEW.detailsUuid); - call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationAdmin(newPartnerRel)); - call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationTenant(newPartnerRel)); - call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationAgent(newPartnerRel)); - call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'DELETE'), hsOfficeRelationAdmin(newPartnerRel)); - call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'SELECT'), hsOfficeRelationAgent(newPartnerRel)); - call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationAgent(newPartnerRel)); + call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationADMIN(newPartnerRel)); + call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationTENANT(newPartnerRel)); + call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationAGENT(newPartnerRel)); + call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'DELETE'), hsOfficeRelationADMIN(newPartnerRel)); + call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'SELECT'), hsOfficeRelationAGENT(newPartnerRel)); + call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationAGENT(newPartnerRel)); call leaveTriggerForObjectUuid(NEW.uuid); end; $$; @@ -110,23 +110,23 @@ begin if NEW.partnerRelUuid <> OLD.partnerRelUuid then - call revokePermissionFromRole(getPermissionId(OLD.uuid, 'DELETE'), hsOfficeRelationAdmin(oldPartnerRel)); - call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationAdmin(newPartnerRel)); + call revokePermissionFromRole(getPermissionId(OLD.uuid, 'DELETE'), hsOfficeRelationADMIN(oldPartnerRel)); + call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationADMIN(newPartnerRel)); - call revokePermissionFromRole(getPermissionId(OLD.uuid, 'UPDATE'), hsOfficeRelationAgent(oldPartnerRel)); - call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationAgent(newPartnerRel)); + call revokePermissionFromRole(getPermissionId(OLD.uuid, 'UPDATE'), hsOfficeRelationAGENT(oldPartnerRel)); + call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationAGENT(newPartnerRel)); - call revokePermissionFromRole(getPermissionId(OLD.uuid, 'SELECT'), hsOfficeRelationTenant(oldPartnerRel)); - call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationTenant(newPartnerRel)); + call revokePermissionFromRole(getPermissionId(OLD.uuid, 'SELECT'), hsOfficeRelationTENANT(oldPartnerRel)); + call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationTENANT(newPartnerRel)); - call revokePermissionFromRole(getPermissionId(oldPartnerDetails.uuid, 'DELETE'), hsOfficeRelationAdmin(oldPartnerRel)); - call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'DELETE'), hsOfficeRelationAdmin(newPartnerRel)); + call revokePermissionFromRole(getPermissionId(oldPartnerDetails.uuid, 'DELETE'), hsOfficeRelationADMIN(oldPartnerRel)); + call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'DELETE'), hsOfficeRelationADMIN(newPartnerRel)); - call revokePermissionFromRole(getPermissionId(oldPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationAgent(oldPartnerRel)); - call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationAgent(newPartnerRel)); + call revokePermissionFromRole(getPermissionId(oldPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationAGENT(oldPartnerRel)); + call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationAGENT(newPartnerRel)); - call revokePermissionFromRole(getPermissionId(oldPartnerDetails.uuid, 'SELECT'), hsOfficeRelationAgent(oldPartnerRel)); - call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'SELECT'), hsOfficeRelationAgent(newPartnerRel)); + call revokePermissionFromRole(getPermissionId(oldPartnerDetails.uuid, 'SELECT'), hsOfficeRelationAGENT(oldPartnerRel)); + call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'SELECT'), hsOfficeRelationAGENT(newPartnerRel)); end if; @@ -170,7 +170,7 @@ do language plpgsql $$ LOOP call grantPermissionToRole( createPermission(row.uuid, 'INSERT', 'hs_office_partner'), - globalAdmin()); + globalADMIN()); END LOOP; END; $$; @@ -185,7 +185,7 @@ create or replace function hs_office_partner_global_insert_tf() begin call grantPermissionToRole( createPermission(NEW.uuid, 'INSERT', 'hs_office_partner'), - globalAdmin()); + globalADMIN()); return NEW; end; $$; diff --git a/src/main/resources/db/changelog/234-hs-office-partner-details-rbac.md b/src/main/resources/db/changelog/234-hs-office-partner-details-rbac.md index d27a1064..347896bb 100644 --- a/src/main/resources/db/changelog/234-hs-office-partner-details-rbac.md +++ b/src/main/resources/db/changelog/234-hs-office-partner-details-rbac.md @@ -18,6 +18,6 @@ subgraph partnerDetails["`**partnerDetails**`"] end %% granting permissions to roles -role:global:admin ==> perm:partnerDetails:INSERT +role:global:ADMIN ==> perm:partnerDetails:INSERT ``` diff --git a/src/main/resources/db/changelog/234-hs-office-partner-details-rbac.sql b/src/main/resources/db/changelog/234-hs-office-partner-details-rbac.sql index a594823b..c99639bb 100644 --- a/src/main/resources/db/changelog/234-hs-office-partner-details-rbac.sql +++ b/src/main/resources/db/changelog/234-hs-office-partner-details-rbac.sql @@ -74,7 +74,7 @@ do language plpgsql $$ LOOP call grantPermissionToRole( createPermission(row.uuid, 'INSERT', 'hs_office_partner_details'), - globalAdmin()); + globalADMIN()); END LOOP; END; $$; @@ -89,7 +89,7 @@ create or replace function hs_office_partner_details_global_insert_tf() begin call grantPermissionToRole( createPermission(NEW.uuid, 'INSERT', 'hs_office_partner_details'), - globalAdmin()); + globalADMIN()); return NEW; end; $$; @@ -107,8 +107,8 @@ create or replace function hs_office_partner_details_insert_permission_missing_t returns trigger language plpgsql as $$ begin - raise exception '[403] insert into hs_office_partner_details not allowed for current subjects % (%) assumed by user % (%)', - currentSubjects(), currentSubjectsUuids(), currentUser(), currentUserUuid(); + raise exception '[403] insert into hs_office_partner_details not allowed for current subjects % (%)', + currentSubjects(), currentSubjectsUuids(); end; $$; create trigger hs_office_partner_details_insert_permission_check_tg @@ -124,7 +124,7 @@ create trigger hs_office_partner_details_insert_permission_check_tg call generateRbacIdentityViewFromQuery('hs_office_partner_details', $idName$ - SELECT partnerDetails.uuid as uuid, partner_iv.idName || '-details' as idName + SELECT partnerDetails.uuid as uuid, partner_iv.idName as idName FROM hs_office_partner_details AS partnerDetails JOIN hs_office_partner partner ON partner.detailsUuid = partnerDetails.uuid JOIN hs_office_partner_iv partner_iv ON partner_iv.uuid = partner.uuid diff --git a/src/main/resources/db/changelog/238-hs-office-partner-test-data.sql b/src/main/resources/db/changelog/238-hs-office-partner-test-data.sql index ae3ed66e..65017b18 100644 --- a/src/main/resources/db/changelog/238-hs-office-partner-test-data.sql +++ b/src/main/resources/db/changelog/238-hs-office-partner-test-data.sql @@ -24,7 +24,7 @@ declare begin idName := cleanIdentifier( partnerPersonName|| '-' || contactLabel); currentTask := 'creating partner test-data ' || idName; - call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global.admin'); + call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN'); execute format('set local hsadminng.currentTask to %L', currentTask); select p.* from hs_office_person p diff --git a/src/main/resources/db/changelog/243-hs-office-bankaccount-rbac.md b/src/main/resources/db/changelog/243-hs-office-bankaccount-rbac.md index c33e3374..4558815c 100644 --- a/src/main/resources/db/changelog/243-hs-office-bankaccount-rbac.md +++ b/src/main/resources/db/changelog/243-hs-office-bankaccount-rbac.md @@ -13,9 +13,9 @@ subgraph bankAccount["`**bankAccount**`"] subgraph bankAccount:roles[ ] style bankAccount:roles fill:#dd4901,stroke:white - role:bankAccount:owner[[bankAccount:owner]] - role:bankAccount:admin[[bankAccount:admin]] - role:bankAccount:referrer[[bankAccount:referrer]] + role:bankAccount:OWNER[[bankAccount:OWNER]] + role:bankAccount:ADMIN[[bankAccount:ADMIN]] + role:bankAccount:REFERRER[[bankAccount:REFERRER]] end subgraph bankAccount:permissions[ ] @@ -29,17 +29,17 @@ subgraph bankAccount["`**bankAccount**`"] end %% granting roles to users -user:creator ==> role:bankAccount:owner +user:creator ==> role:bankAccount:OWNER %% granting roles to roles -role:global:admin ==> role:bankAccount:owner -role:bankAccount:owner ==> role:bankAccount:admin -role:bankAccount:admin ==> role:bankAccount:referrer +role:global:ADMIN ==> role:bankAccount:OWNER +role:bankAccount:OWNER ==> role:bankAccount:ADMIN +role:bankAccount:ADMIN ==> role:bankAccount:REFERRER %% granting permissions to roles -role:global:guest ==> perm:bankAccount:INSERT -role:bankAccount:owner ==> perm:bankAccount:DELETE -role:bankAccount:admin ==> perm:bankAccount:UPDATE -role:bankAccount:referrer ==> perm:bankAccount:SELECT +role:global:GUEST ==> perm:bankAccount:INSERT +role:bankAccount:OWNER ==> perm:bankAccount:DELETE +role:bankAccount:ADMIN ==> perm:bankAccount:UPDATE +role:bankAccount:REFERRER ==> perm:bankAccount:SELECT ``` diff --git a/src/main/resources/db/changelog/243-hs-office-bankaccount-rbac.sql b/src/main/resources/db/changelog/243-hs-office-bankaccount-rbac.sql index c4628183..c12c4c88 100644 --- a/src/main/resources/db/changelog/243-hs-office-bankaccount-rbac.sql +++ b/src/main/resources/db/changelog/243-hs-office-bankaccount-rbac.sql @@ -35,22 +35,22 @@ begin call enterTriggerForObjectUuid(NEW.uuid); perform createRoleWithGrants( - hsOfficeBankAccountOwner(NEW), + hsOfficeBankAccountOWNER(NEW), permissions => array['DELETE'], - incomingSuperRoles => array[globalAdmin()], + incomingSuperRoles => array[globalADMIN()], userUuids => array[currentUserUuid()] ); perform createRoleWithGrants( - hsOfficeBankAccountAdmin(NEW), + hsOfficeBankAccountADMIN(NEW), permissions => array['UPDATE'], - incomingSuperRoles => array[hsOfficeBankAccountOwner(NEW)] + incomingSuperRoles => array[hsOfficeBankAccountOWNER(NEW)] ); perform createRoleWithGrants( - hsOfficeBankAccountReferrer(NEW), + hsOfficeBankAccountREFERRER(NEW), permissions => array['SELECT'], - incomingSuperRoles => array[hsOfficeBankAccountAdmin(NEW)] + incomingSuperRoles => array[hsOfficeBankAccountADMIN(NEW)] ); call leaveTriggerForObjectUuid(NEW.uuid); @@ -93,7 +93,7 @@ do language plpgsql $$ LOOP call grantPermissionToRole( createPermission(row.uuid, 'INSERT', 'hs_office_bankaccount'), - globalGuest()); + globalGUEST()); END LOOP; END; $$; @@ -108,7 +108,7 @@ create or replace function hs_office_bankaccount_global_insert_tf() begin call grantPermissionToRole( createPermission(NEW.uuid, 'INSERT', 'hs_office_bankaccount'), - globalGuest()); + globalGUEST()); return NEW; end; $$; diff --git a/src/main/resources/db/changelog/253-hs-office-sepamandate-rbac.md b/src/main/resources/db/changelog/253-hs-office-sepamandate-rbac.md index 43fb6ef3..aa3059f9 100644 --- a/src/main/resources/db/changelog/253-hs-office-sepamandate-rbac.md +++ b/src/main/resources/db/changelog/253-hs-office-sepamandate-rbac.md @@ -13,9 +13,9 @@ subgraph bankAccount["`**bankAccount**`"] subgraph bankAccount:roles[ ] style bankAccount:roles fill:#99bcdb,stroke:white - role:bankAccount:owner[[bankAccount:owner]] - role:bankAccount:admin[[bankAccount:admin]] - role:bankAccount:referrer[[bankAccount:referrer]] + role:bankAccount:OWNER[[bankAccount:OWNER]] + role:bankAccount:ADMIN[[bankAccount:ADMIN]] + role:bankAccount:REFERRER[[bankAccount:REFERRER]] end end @@ -26,9 +26,9 @@ subgraph debitorRel.contact["`**debitorRel.contact**`"] subgraph debitorRel.contact:roles[ ] style debitorRel.contact:roles fill:#99bcdb,stroke:white - role:debitorRel.contact:owner[[debitorRel.contact:owner]] - role:debitorRel.contact:admin[[debitorRel.contact:admin]] - role:debitorRel.contact:referrer[[debitorRel.contact:referrer]] + role:debitorRel.contact:OWNER[[debitorRel.contact:OWNER]] + role:debitorRel.contact:ADMIN[[debitorRel.contact:ADMIN]] + role:debitorRel.contact:REFERRER[[debitorRel.contact:REFERRER]] end end @@ -39,9 +39,9 @@ subgraph debitorRel.anchorPerson["`**debitorRel.anchorPerson**`"] subgraph debitorRel.anchorPerson:roles[ ] style debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white - role:debitorRel.anchorPerson:owner[[debitorRel.anchorPerson:owner]] - role:debitorRel.anchorPerson:admin[[debitorRel.anchorPerson:admin]] - role:debitorRel.anchorPerson:referrer[[debitorRel.anchorPerson:referrer]] + role:debitorRel.anchorPerson:OWNER[[debitorRel.anchorPerson:OWNER]] + role:debitorRel.anchorPerson:ADMIN[[debitorRel.anchorPerson:ADMIN]] + role:debitorRel.anchorPerson:REFERRER[[debitorRel.anchorPerson:REFERRER]] end end @@ -52,9 +52,9 @@ subgraph debitorRel.holderPerson["`**debitorRel.holderPerson**`"] subgraph debitorRel.holderPerson:roles[ ] style debitorRel.holderPerson:roles fill:#99bcdb,stroke:white - role:debitorRel.holderPerson:owner[[debitorRel.holderPerson:owner]] - role:debitorRel.holderPerson:admin[[debitorRel.holderPerson:admin]] - role:debitorRel.holderPerson:referrer[[debitorRel.holderPerson:referrer]] + role:debitorRel.holderPerson:OWNER[[debitorRel.holderPerson:OWNER]] + role:debitorRel.holderPerson:ADMIN[[debitorRel.holderPerson:ADMIN]] + role:debitorRel.holderPerson:REFERRER[[debitorRel.holderPerson:REFERRER]] end end @@ -65,10 +65,10 @@ subgraph sepaMandate["`**sepaMandate**`"] subgraph sepaMandate:roles[ ] style sepaMandate:roles fill:#dd4901,stroke:white - role:sepaMandate:owner[[sepaMandate:owner]] - role:sepaMandate:admin[[sepaMandate:admin]] - role:sepaMandate:agent[[sepaMandate:agent]] - role:sepaMandate:referrer[[sepaMandate:referrer]] + role:sepaMandate:OWNER[[sepaMandate:OWNER]] + role:sepaMandate:ADMIN[[sepaMandate:ADMIN]] + role:sepaMandate:AGENT[[sepaMandate:AGENT]] + role:sepaMandate:REFERRER[[sepaMandate:REFERRER]] end subgraph sepaMandate:permissions[ ] @@ -85,96 +85,57 @@ subgraph debitorRel["`**debitorRel**`"] direction TB style debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px - subgraph debitorRel.contact["`**debitorRel.contact**`"] - direction TB - style debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph debitorRel.contact:roles[ ] - style debitorRel.contact:roles fill:#99bcdb,stroke:white - - role:debitorRel.contact:owner[[debitorRel.contact:owner]] - role:debitorRel.contact:admin[[debitorRel.contact:admin]] - role:debitorRel.contact:referrer[[debitorRel.contact:referrer]] - end - end - - subgraph debitorRel.anchorPerson["`**debitorRel.anchorPerson**`"] - direction TB - style debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph debitorRel.anchorPerson:roles[ ] - style debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white - - role:debitorRel.anchorPerson:owner[[debitorRel.anchorPerson:owner]] - role:debitorRel.anchorPerson:admin[[debitorRel.anchorPerson:admin]] - role:debitorRel.anchorPerson:referrer[[debitorRel.anchorPerson:referrer]] - end - end - - subgraph debitorRel.holderPerson["`**debitorRel.holderPerson**`"] - direction TB - style debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph debitorRel.holderPerson:roles[ ] - style debitorRel.holderPerson:roles fill:#99bcdb,stroke:white - - role:debitorRel.holderPerson:owner[[debitorRel.holderPerson:owner]] - role:debitorRel.holderPerson:admin[[debitorRel.holderPerson:admin]] - role:debitorRel.holderPerson:referrer[[debitorRel.holderPerson:referrer]] - end - end - subgraph debitorRel:roles[ ] style debitorRel:roles fill:#99bcdb,stroke:white - role:debitorRel:owner[[debitorRel:owner]] - role:debitorRel:admin[[debitorRel:admin]] - role:debitorRel:agent[[debitorRel:agent]] - role:debitorRel:tenant[[debitorRel:tenant]] + role:debitorRel:OWNER[[debitorRel:OWNER]] + role:debitorRel:ADMIN[[debitorRel:ADMIN]] + role:debitorRel:AGENT[[debitorRel:AGENT]] + role:debitorRel:TENANT[[debitorRel:TENANT]] end end %% granting roles to users -user:creator ==> role:sepaMandate:owner +user:creator ==> role:sepaMandate:OWNER %% granting roles to roles -role:global:admin -.-> role:debitorRel.anchorPerson:owner -role:debitorRel.anchorPerson:owner -.-> role:debitorRel.anchorPerson:admin -role:debitorRel.anchorPerson:admin -.-> role:debitorRel.anchorPerson:referrer -role:global:admin -.-> role:debitorRel.holderPerson:owner -role:debitorRel.holderPerson:owner -.-> role:debitorRel.holderPerson:admin -role:debitorRel.holderPerson:admin -.-> role:debitorRel.holderPerson:referrer -role:global:admin -.-> role:debitorRel.contact:owner -role:debitorRel.contact:owner -.-> role:debitorRel.contact:admin -role:debitorRel.contact:admin -.-> role:debitorRel.contact:referrer -role:global:admin -.-> role:debitorRel:owner -role:debitorRel:owner -.-> role:debitorRel:admin -role:debitorRel.anchorPerson:admin -.-> role:debitorRel:admin -role:debitorRel:admin -.-> role:debitorRel:agent -role:debitorRel.holderPerson:admin -.-> role:debitorRel:agent -role:debitorRel:agent -.-> role:debitorRel:tenant -role:debitorRel.holderPerson:admin -.-> role:debitorRel:tenant -role:debitorRel.contact:admin -.-> role:debitorRel:tenant -role:debitorRel:tenant -.-> role:debitorRel.anchorPerson:referrer -role:debitorRel:tenant -.-> role:debitorRel.holderPerson:referrer -role:debitorRel:tenant -.-> role:debitorRel.contact:referrer -role:global:admin -.-> role:bankAccount:owner -role:bankAccount:owner -.-> role:bankAccount:admin -role:bankAccount:admin -.-> role:bankAccount:referrer -role:global:admin ==> role:sepaMandate:owner -role:sepaMandate:owner ==> role:sepaMandate:admin -role:sepaMandate:admin ==> role:sepaMandate:agent -role:sepaMandate:agent ==> role:bankAccount:referrer -role:sepaMandate:agent ==> role:debitorRel:agent -role:sepaMandate:agent ==> role:sepaMandate:referrer -role:bankAccount:admin ==> role:sepaMandate:referrer -role:debitorRel:agent ==> role:sepaMandate:referrer -role:sepaMandate:referrer ==> role:debitorRel:tenant +role:global:ADMIN -.-> role:debitorRel.anchorPerson:OWNER +role:debitorRel.anchorPerson:OWNER -.-> role:debitorRel.anchorPerson:ADMIN +role:debitorRel.anchorPerson:ADMIN -.-> role:debitorRel.anchorPerson:REFERRER +role:global:ADMIN -.-> role:debitorRel.holderPerson:OWNER +role:debitorRel.holderPerson:OWNER -.-> role:debitorRel.holderPerson:ADMIN +role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel.holderPerson:REFERRER +role:global:ADMIN -.-> role:debitorRel.contact:OWNER +role:debitorRel.contact:OWNER -.-> role:debitorRel.contact:ADMIN +role:debitorRel.contact:ADMIN -.-> role:debitorRel.contact:REFERRER +role:global:ADMIN -.-> role:debitorRel:OWNER +role:debitorRel:OWNER -.-> role:debitorRel:ADMIN +role:debitorRel.anchorPerson:ADMIN -.-> role:debitorRel:ADMIN +role:debitorRel:ADMIN -.-> role:debitorRel:AGENT +role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:AGENT +role:debitorRel:AGENT -.-> role:debitorRel:TENANT +role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:TENANT +role:debitorRel.contact:ADMIN -.-> role:debitorRel:TENANT +role:debitorRel:TENANT -.-> role:debitorRel.anchorPerson:REFERRER +role:debitorRel:TENANT -.-> role:debitorRel.holderPerson:REFERRER +role:debitorRel:TENANT -.-> role:debitorRel.contact:REFERRER +role:global:ADMIN -.-> role:bankAccount:OWNER +role:bankAccount:OWNER -.-> role:bankAccount:ADMIN +role:bankAccount:ADMIN -.-> role:bankAccount:REFERRER +role:global:ADMIN ==> role:sepaMandate:OWNER +role:sepaMandate:OWNER ==> role:sepaMandate:ADMIN +role:sepaMandate:ADMIN ==> role:sepaMandate:AGENT +role:sepaMandate:AGENT ==> role:bankAccount:REFERRER +role:sepaMandate:AGENT ==> role:debitorRel:AGENT +role:sepaMandate:AGENT ==> role:sepaMandate:REFERRER +role:bankAccount:ADMIN ==> role:sepaMandate:REFERRER +role:debitorRel:AGENT ==> role:sepaMandate:REFERRER +role:sepaMandate:REFERRER ==> role:debitorRel:TENANT %% granting permissions to roles -role:sepaMandate:owner ==> perm:sepaMandate:DELETE -role:sepaMandate:admin ==> perm:sepaMandate:UPDATE -role:sepaMandate:referrer ==> perm:sepaMandate:SELECT -role:debitorRel:admin ==> perm:sepaMandate:INSERT +role:sepaMandate:OWNER ==> perm:sepaMandate:DELETE +role:sepaMandate:ADMIN ==> perm:sepaMandate:UPDATE +role:sepaMandate:REFERRER ==> perm:sepaMandate:SELECT +role:debitorRel:ADMIN ==> perm:sepaMandate:INSERT ``` diff --git a/src/main/resources/db/changelog/253-hs-office-sepamandate-rbac.sql b/src/main/resources/db/changelog/253-hs-office-sepamandate-rbac.sql index 0f168fd5..9f126a22 100644 --- a/src/main/resources/db/changelog/253-hs-office-sepamandate-rbac.sql +++ b/src/main/resources/db/changelog/253-hs-office-sepamandate-rbac.sql @@ -48,34 +48,34 @@ begin perform createRoleWithGrants( - hsOfficeSepaMandateOwner(NEW), + hsOfficeSepaMandateOWNER(NEW), permissions => array['DELETE'], - incomingSuperRoles => array[globalAdmin()], + incomingSuperRoles => array[globalADMIN()], userUuids => array[currentUserUuid()] ); perform createRoleWithGrants( - hsOfficeSepaMandateAdmin(NEW), + hsOfficeSepaMandateADMIN(NEW), permissions => array['UPDATE'], - incomingSuperRoles => array[hsOfficeSepaMandateOwner(NEW)] + incomingSuperRoles => array[hsOfficeSepaMandateOWNER(NEW)] ); perform createRoleWithGrants( - hsOfficeSepaMandateAgent(NEW), - incomingSuperRoles => array[hsOfficeSepaMandateAdmin(NEW)], + hsOfficeSepaMandateAGENT(NEW), + incomingSuperRoles => array[hsOfficeSepaMandateADMIN(NEW)], outgoingSubRoles => array[ - hsOfficeBankAccountReferrer(newBankAccount), - hsOfficeRelationAgent(newDebitorRel)] + hsOfficeBankAccountREFERRER(newBankAccount), + hsOfficeRelationAGENT(newDebitorRel)] ); perform createRoleWithGrants( - hsOfficeSepaMandateReferrer(NEW), + hsOfficeSepaMandateREFERRER(NEW), permissions => array['SELECT'], incomingSuperRoles => array[ - hsOfficeBankAccountAdmin(newBankAccount), - hsOfficeRelationAgent(newDebitorRel), - hsOfficeSepaMandateAgent(NEW)], - outgoingSubRoles => array[hsOfficeRelationTenant(newDebitorRel)] + hsOfficeBankAccountADMIN(newBankAccount), + hsOfficeRelationAGENT(newDebitorRel), + hsOfficeSepaMandateAGENT(NEW)], + outgoingSubRoles => array[hsOfficeRelationTENANT(newDebitorRel)] ); call leaveTriggerForObjectUuid(NEW.uuid); @@ -118,7 +118,7 @@ do language plpgsql $$ LOOP call grantPermissionToRole( createPermission(row.uuid, 'INSERT', 'hs_office_sepamandate'), - hsOfficeRelationAdmin(row)); + hsOfficeRelationADMIN(row)); END LOOP; END; $$; @@ -133,7 +133,7 @@ create or replace function hs_office_sepamandate_hs_office_relation_insert_tf() begin call grantPermissionToRole( createPermission(NEW.uuid, 'INSERT', 'hs_office_sepamandate'), - hsOfficeRelationAdmin(NEW)); + hsOfficeRelationADMIN(NEW)); return NEW; end; $$; diff --git a/src/main/resources/db/changelog/258-hs-office-sepamandate-test-data.sql b/src/main/resources/db/changelog/258-hs-office-sepamandate-test-data.sql index 11999980..69d39165 100644 --- a/src/main/resources/db/changelog/258-hs-office-sepamandate-test-data.sql +++ b/src/main/resources/db/changelog/258-hs-office-sepamandate-test-data.sql @@ -20,7 +20,7 @@ declare relatedBankAccount hs_office_bankAccount; begin currentTask := 'creating SEPA-mandate test-data ' || forPartnerNumber::text || forDebitorSuffix::text; - call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global.admin'); + call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN'); execute format('set local hsadminng.currentTask to %L', currentTask); select debitor.* into relatedDebitor diff --git a/src/main/resources/db/changelog/273-hs-office-debitor-rbac.md b/src/main/resources/db/changelog/273-hs-office-debitor-rbac.md index a1baa702..5c43e03d 100644 --- a/src/main/resources/db/changelog/273-hs-office-debitor-rbac.md +++ b/src/main/resources/db/changelog/273-hs-office-debitor-rbac.md @@ -13,9 +13,9 @@ subgraph debitorRel.anchorPerson["`**debitorRel.anchorPerson**`"] subgraph debitorRel.anchorPerson:roles[ ] style debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white - role:debitorRel.anchorPerson:owner[[debitorRel.anchorPerson:owner]] - role:debitorRel.anchorPerson:admin[[debitorRel.anchorPerson:admin]] - role:debitorRel.anchorPerson:referrer[[debitorRel.anchorPerson:referrer]] + role:debitorRel.anchorPerson:OWNER[[debitorRel.anchorPerson:OWNER]] + role:debitorRel.anchorPerson:ADMIN[[debitorRel.anchorPerson:ADMIN]] + role:debitorRel.anchorPerson:REFERRER[[debitorRel.anchorPerson:REFERRER]] end end @@ -26,9 +26,9 @@ subgraph debitorRel.holderPerson["`**debitorRel.holderPerson**`"] subgraph debitorRel.holderPerson:roles[ ] style debitorRel.holderPerson:roles fill:#99bcdb,stroke:white - role:debitorRel.holderPerson:owner[[debitorRel.holderPerson:owner]] - role:debitorRel.holderPerson:admin[[debitorRel.holderPerson:admin]] - role:debitorRel.holderPerson:referrer[[debitorRel.holderPerson:referrer]] + role:debitorRel.holderPerson:OWNER[[debitorRel.holderPerson:OWNER]] + role:debitorRel.holderPerson:ADMIN[[debitorRel.holderPerson:ADMIN]] + role:debitorRel.holderPerson:REFERRER[[debitorRel.holderPerson:REFERRER]] end end @@ -39,9 +39,9 @@ subgraph partnerRel.holderPerson["`**partnerRel.holderPerson**`"] subgraph partnerRel.holderPerson:roles[ ] style partnerRel.holderPerson:roles fill:#99bcdb,stroke:white - role:partnerRel.holderPerson:owner[[partnerRel.holderPerson:owner]] - role:partnerRel.holderPerson:admin[[partnerRel.holderPerson:admin]] - role:partnerRel.holderPerson:referrer[[partnerRel.holderPerson:referrer]] + role:partnerRel.holderPerson:OWNER[[partnerRel.holderPerson:OWNER]] + role:partnerRel.holderPerson:ADMIN[[partnerRel.holderPerson:ADMIN]] + role:partnerRel.holderPerson:REFERRER[[partnerRel.holderPerson:REFERRER]] end end @@ -61,52 +61,14 @@ subgraph debitor["`**debitor**`"] subgraph debitorRel["`**debitorRel**`"] direction TB style debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px - subgraph debitorRel.anchorPerson["`**debitorRel.anchorPerson**`"] - direction TB - style debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph debitorRel.anchorPerson:roles[ ] - style debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white - - role:debitorRel.anchorPerson:owner[[debitorRel.anchorPerson:owner]] - role:debitorRel.anchorPerson:admin[[debitorRel.anchorPerson:admin]] - role:debitorRel.anchorPerson:referrer[[debitorRel.anchorPerson:referrer]] - end - end - - subgraph debitorRel.holderPerson["`**debitorRel.holderPerson**`"] - direction TB - style debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph debitorRel.holderPerson:roles[ ] - style debitorRel.holderPerson:roles fill:#99bcdb,stroke:white - - role:debitorRel.holderPerson:owner[[debitorRel.holderPerson:owner]] - role:debitorRel.holderPerson:admin[[debitorRel.holderPerson:admin]] - role:debitorRel.holderPerson:referrer[[debitorRel.holderPerson:referrer]] - end - end - - subgraph debitorRel.contact["`**debitorRel.contact**`"] - direction TB - style debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph debitorRel.contact:roles[ ] - style debitorRel.contact:roles fill:#99bcdb,stroke:white - - role:debitorRel.contact:owner[[debitorRel.contact:owner]] - role:debitorRel.contact:admin[[debitorRel.contact:admin]] - role:debitorRel.contact:referrer[[debitorRel.contact:referrer]] - end - end subgraph debitorRel:roles[ ] style debitorRel:roles fill:#99bcdb,stroke:white - role:debitorRel:owner[[debitorRel:owner]] - role:debitorRel:admin[[debitorRel:admin]] - role:debitorRel:agent[[debitorRel:agent]] - role:debitorRel:tenant[[debitorRel:tenant]] + role:debitorRel:OWNER[[debitorRel:OWNER]] + role:debitorRel:ADMIN[[debitorRel:ADMIN]] + role:debitorRel:AGENT[[debitorRel:AGENT]] + role:debitorRel:TENANT[[debitorRel:TENANT]] end end end @@ -115,52 +77,13 @@ subgraph partnerRel["`**partnerRel**`"] direction TB style partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px - subgraph partnerRel.holderPerson["`**partnerRel.holderPerson**`"] - direction TB - style partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph partnerRel.holderPerson:roles[ ] - style partnerRel.holderPerson:roles fill:#99bcdb,stroke:white - - role:partnerRel.holderPerson:owner[[partnerRel.holderPerson:owner]] - role:partnerRel.holderPerson:admin[[partnerRel.holderPerson:admin]] - role:partnerRel.holderPerson:referrer[[partnerRel.holderPerson:referrer]] - end - end - - subgraph partnerRel.contact["`**partnerRel.contact**`"] - direction TB - style partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph partnerRel.contact:roles[ ] - style partnerRel.contact:roles fill:#99bcdb,stroke:white - - role:partnerRel.contact:owner[[partnerRel.contact:owner]] - role:partnerRel.contact:admin[[partnerRel.contact:admin]] - role:partnerRel.contact:referrer[[partnerRel.contact:referrer]] - end - end - - subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"] - direction TB - style partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph partnerRel.anchorPerson:roles[ ] - style partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white - - role:partnerRel.anchorPerson:owner[[partnerRel.anchorPerson:owner]] - role:partnerRel.anchorPerson:admin[[partnerRel.anchorPerson:admin]] - role:partnerRel.anchorPerson:referrer[[partnerRel.anchorPerson:referrer]] - end - end - subgraph partnerRel:roles[ ] style partnerRel:roles fill:#99bcdb,stroke:white - role:partnerRel:owner[[partnerRel:owner]] - role:partnerRel:admin[[partnerRel:admin]] - role:partnerRel:agent[[partnerRel:agent]] - role:partnerRel:tenant[[partnerRel:tenant]] + role:partnerRel:OWNER[[partnerRel:OWNER]] + role:partnerRel:ADMIN[[partnerRel:ADMIN]] + role:partnerRel:AGENT[[partnerRel:AGENT]] + role:partnerRel:TENANT[[partnerRel:TENANT]] end end @@ -171,9 +94,9 @@ subgraph partnerRel.contact["`**partnerRel.contact**`"] subgraph partnerRel.contact:roles[ ] style partnerRel.contact:roles fill:#99bcdb,stroke:white - role:partnerRel.contact:owner[[partnerRel.contact:owner]] - role:partnerRel.contact:admin[[partnerRel.contact:admin]] - role:partnerRel.contact:referrer[[partnerRel.contact:referrer]] + role:partnerRel.contact:OWNER[[partnerRel.contact:OWNER]] + role:partnerRel.contact:ADMIN[[partnerRel.contact:ADMIN]] + role:partnerRel.contact:REFERRER[[partnerRel.contact:REFERRER]] end end @@ -184,9 +107,9 @@ subgraph debitorRel.contact["`**debitorRel.contact**`"] subgraph debitorRel.contact:roles[ ] style debitorRel.contact:roles fill:#99bcdb,stroke:white - role:debitorRel.contact:owner[[debitorRel.contact:owner]] - role:debitorRel.contact:admin[[debitorRel.contact:admin]] - role:debitorRel.contact:referrer[[debitorRel.contact:referrer]] + role:debitorRel.contact:OWNER[[debitorRel.contact:OWNER]] + role:debitorRel.contact:ADMIN[[debitorRel.contact:ADMIN]] + role:debitorRel.contact:REFERRER[[debitorRel.contact:REFERRER]] end end @@ -197,9 +120,9 @@ subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"] subgraph partnerRel.anchorPerson:roles[ ] style partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white - role:partnerRel.anchorPerson:owner[[partnerRel.anchorPerson:owner]] - role:partnerRel.anchorPerson:admin[[partnerRel.anchorPerson:admin]] - role:partnerRel.anchorPerson:referrer[[partnerRel.anchorPerson:referrer]] + role:partnerRel.anchorPerson:OWNER[[partnerRel.anchorPerson:OWNER]] + role:partnerRel.anchorPerson:ADMIN[[partnerRel.anchorPerson:ADMIN]] + role:partnerRel.anchorPerson:REFERRER[[partnerRel.anchorPerson:REFERRER]] end end @@ -210,66 +133,66 @@ subgraph refundBankAccount["`**refundBankAccount**`"] subgraph refundBankAccount:roles[ ] style refundBankAccount:roles fill:#99bcdb,stroke:white - role:refundBankAccount:owner[[refundBankAccount:owner]] - role:refundBankAccount:admin[[refundBankAccount:admin]] - role:refundBankAccount:referrer[[refundBankAccount:referrer]] + role:refundBankAccount:OWNER[[refundBankAccount:OWNER]] + role:refundBankAccount:ADMIN[[refundBankAccount:ADMIN]] + role:refundBankAccount:REFERRER[[refundBankAccount:REFERRER]] end end %% granting roles to roles -role:global:admin -.-> role:debitorRel.anchorPerson:owner -role:debitorRel.anchorPerson:owner -.-> role:debitorRel.anchorPerson:admin -role:debitorRel.anchorPerson:admin -.-> role:debitorRel.anchorPerson:referrer -role:global:admin -.-> role:debitorRel.holderPerson:owner -role:debitorRel.holderPerson:owner -.-> role:debitorRel.holderPerson:admin -role:debitorRel.holderPerson:admin -.-> role:debitorRel.holderPerson:referrer -role:global:admin -.-> role:debitorRel.contact:owner -role:debitorRel.contact:owner -.-> role:debitorRel.contact:admin -role:debitorRel.contact:admin -.-> role:debitorRel.contact:referrer -role:global:admin -.-> role:debitorRel:owner -role:debitorRel:owner -.-> role:debitorRel:admin -role:debitorRel.anchorPerson:admin -.-> role:debitorRel:admin -role:debitorRel:admin -.-> role:debitorRel:agent -role:debitorRel.holderPerson:admin -.-> role:debitorRel:agent -role:debitorRel:agent -.-> role:debitorRel:tenant -role:debitorRel.holderPerson:admin -.-> role:debitorRel:tenant -role:debitorRel.contact:admin -.-> role:debitorRel:tenant -role:debitorRel:tenant -.-> role:debitorRel.anchorPerson:referrer -role:debitorRel:tenant -.-> role:debitorRel.holderPerson:referrer -role:debitorRel:tenant -.-> role:debitorRel.contact:referrer -role:global:admin -.-> role:refundBankAccount:owner -role:refundBankAccount:owner -.-> role:refundBankAccount:admin -role:refundBankAccount:admin -.-> role:refundBankAccount:referrer -role:refundBankAccount:admin ==> role:debitorRel:agent -role:debitorRel:agent ==> role:refundBankAccount:referrer -role:global:admin -.-> role:partnerRel.anchorPerson:owner -role:partnerRel.anchorPerson:owner -.-> role:partnerRel.anchorPerson:admin -role:partnerRel.anchorPerson:admin -.-> role:partnerRel.anchorPerson:referrer -role:global:admin -.-> role:partnerRel.holderPerson:owner -role:partnerRel.holderPerson:owner -.-> role:partnerRel.holderPerson:admin -role:partnerRel.holderPerson:admin -.-> role:partnerRel.holderPerson:referrer -role:global:admin -.-> role:partnerRel.contact:owner -role:partnerRel.contact:owner -.-> role:partnerRel.contact:admin -role:partnerRel.contact:admin -.-> role:partnerRel.contact:referrer -role:global:admin -.-> role:partnerRel:owner -role:partnerRel:owner -.-> role:partnerRel:admin -role:partnerRel.anchorPerson:admin -.-> role:partnerRel:admin -role:partnerRel:admin -.-> role:partnerRel:agent -role:partnerRel.holderPerson:admin -.-> role:partnerRel:agent -role:partnerRel:agent -.-> role:partnerRel:tenant -role:partnerRel.holderPerson:admin -.-> role:partnerRel:tenant -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:debitorRel:admin -role:partnerRel:agent ==> role:debitorRel:agent -role:debitorRel:agent ==> role:partnerRel:tenant +role:global:ADMIN -.-> role:debitorRel.anchorPerson:OWNER +role:debitorRel.anchorPerson:OWNER -.-> role:debitorRel.anchorPerson:ADMIN +role:debitorRel.anchorPerson:ADMIN -.-> role:debitorRel.anchorPerson:REFERRER +role:global:ADMIN -.-> role:debitorRel.holderPerson:OWNER +role:debitorRel.holderPerson:OWNER -.-> role:debitorRel.holderPerson:ADMIN +role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel.holderPerson:REFERRER +role:global:ADMIN -.-> role:debitorRel.contact:OWNER +role:debitorRel.contact:OWNER -.-> role:debitorRel.contact:ADMIN +role:debitorRel.contact:ADMIN -.-> role:debitorRel.contact:REFERRER +role:global:ADMIN -.-> role:debitorRel:OWNER +role:debitorRel:OWNER -.-> role:debitorRel:ADMIN +role:debitorRel.anchorPerson:ADMIN -.-> role:debitorRel:ADMIN +role:debitorRel:ADMIN -.-> role:debitorRel:AGENT +role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:AGENT +role:debitorRel:AGENT -.-> role:debitorRel:TENANT +role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:TENANT +role:debitorRel.contact:ADMIN -.-> role:debitorRel:TENANT +role:debitorRel:TENANT -.-> role:debitorRel.anchorPerson:REFERRER +role:debitorRel:TENANT -.-> role:debitorRel.holderPerson:REFERRER +role:debitorRel:TENANT -.-> role:debitorRel.contact:REFERRER +role:global:ADMIN -.-> role:refundBankAccount:OWNER +role:refundBankAccount:OWNER -.-> role:refundBankAccount:ADMIN +role:refundBankAccount:ADMIN -.-> role:refundBankAccount:REFERRER +role:refundBankAccount:ADMIN ==> role:debitorRel:AGENT +role:debitorRel:AGENT ==> role:refundBankAccount:REFERRER +role:global:ADMIN -.-> role:partnerRel.anchorPerson:OWNER +role:partnerRel.anchorPerson:OWNER -.-> role:partnerRel.anchorPerson:ADMIN +role:partnerRel.anchorPerson:ADMIN -.-> role:partnerRel.anchorPerson:REFERRER +role:global:ADMIN -.-> role:partnerRel.holderPerson:OWNER +role:partnerRel.holderPerson:OWNER -.-> role:partnerRel.holderPerson:ADMIN +role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel.holderPerson:REFERRER +role:global:ADMIN -.-> role:partnerRel.contact:OWNER +role:partnerRel.contact:OWNER -.-> role:partnerRel.contact:ADMIN +role:partnerRel.contact:ADMIN -.-> role:partnerRel.contact:REFERRER +role:global:ADMIN -.-> role:partnerRel:OWNER +role:partnerRel:OWNER -.-> role:partnerRel:ADMIN +role:partnerRel.anchorPerson:ADMIN -.-> role:partnerRel:ADMIN +role:partnerRel:ADMIN -.-> role:partnerRel:AGENT +role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:AGENT +role:partnerRel:AGENT -.-> role:partnerRel:TENANT +role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:TENANT +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:debitorRel:ADMIN +role:partnerRel:AGENT ==> role:debitorRel:AGENT +role:debitorRel:AGENT ==> role:partnerRel:TENANT %% granting permissions to roles -role:global:admin ==> perm:debitor:INSERT -role:debitorRel:owner ==> perm:debitor:DELETE -role:debitorRel:admin ==> perm:debitor:UPDATE -role:debitorRel:tenant ==> perm:debitor:SELECT +role:global:ADMIN ==> perm:debitor:INSERT +role:debitorRel:OWNER ==> perm:debitor:DELETE +role:debitorRel:ADMIN ==> perm:debitor:UPDATE +role:debitorRel:TENANT ==> perm:debitor:SELECT ``` diff --git a/src/main/resources/db/changelog/273-hs-office-debitor-rbac.sql b/src/main/resources/db/changelog/273-hs-office-debitor-rbac.sql index 065efff6..152f980e 100644 --- a/src/main/resources/db/changelog/273-hs-office-debitor-rbac.sql +++ b/src/main/resources/db/changelog/273-hs-office-debitor-rbac.sql @@ -51,15 +51,15 @@ begin SELECT * FROM hs_office_bankaccount WHERE uuid = NEW.refundBankAccountUuid INTO newRefundBankAccount; - call grantRoleToRole(hsOfficeBankAccountReferrer(newRefundBankAccount), hsOfficeRelationAgent(newDebitorRel)); - call grantRoleToRole(hsOfficeRelationAdmin(newDebitorRel), hsOfficeRelationAdmin(newPartnerRel)); - call grantRoleToRole(hsOfficeRelationAgent(newDebitorRel), hsOfficeBankAccountAdmin(newRefundBankAccount)); - call grantRoleToRole(hsOfficeRelationAgent(newDebitorRel), hsOfficeRelationAgent(newPartnerRel)); - call grantRoleToRole(hsOfficeRelationTenant(newPartnerRel), hsOfficeRelationAgent(newDebitorRel)); + call grantRoleToRole(hsOfficeBankAccountREFERRER(newRefundBankAccount), hsOfficeRelationAGENT(newDebitorRel)); + call grantRoleToRole(hsOfficeRelationADMIN(newDebitorRel), hsOfficeRelationADMIN(newPartnerRel)); + call grantRoleToRole(hsOfficeRelationAGENT(newDebitorRel), hsOfficeBankAccountADMIN(newRefundBankAccount)); + call grantRoleToRole(hsOfficeRelationAGENT(newDebitorRel), hsOfficeRelationAGENT(newPartnerRel)); + call grantRoleToRole(hsOfficeRelationTENANT(newPartnerRel), hsOfficeRelationAGENT(newDebitorRel)); - call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationOwner(newDebitorRel)); - call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationTenant(newDebitorRel)); - call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationAdmin(newDebitorRel)); + call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationOWNER(newDebitorRel)); + call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationTENANT(newDebitorRel)); + call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationADMIN(newDebitorRel)); call leaveTriggerForObjectUuid(NEW.uuid); end; $$; @@ -143,7 +143,7 @@ do language plpgsql $$ LOOP call grantPermissionToRole( createPermission(row.uuid, 'INSERT', 'hs_office_debitor'), - globalAdmin()); + globalADMIN()); END LOOP; END; $$; @@ -158,7 +158,7 @@ create or replace function hs_office_debitor_global_insert_tf() begin call grantPermissionToRole( createPermission(NEW.uuid, 'INSERT', 'hs_office_debitor'), - globalAdmin()); + globalADMIN()); return NEW; end; $$; diff --git a/src/main/resources/db/changelog/278-hs-office-debitor-test-data.sql b/src/main/resources/db/changelog/278-hs-office-debitor-test-data.sql index 5a485b31..ed965104 100644 --- a/src/main/resources/db/changelog/278-hs-office-debitor-test-data.sql +++ b/src/main/resources/db/changelog/278-hs-office-debitor-test-data.sql @@ -23,7 +23,7 @@ declare begin idName := cleanIdentifier( forPartnerPersonName|| '-' || forBillingContactLabel); currentTask := 'creating debitor test-data ' || idName; - call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global.admin'); + call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN'); execute format('set local hsadminng.currentTask to %L', currentTask); select debitorRel.uuid diff --git a/src/main/resources/db/changelog/303-hs-office-membership-rbac.md b/src/main/resources/db/changelog/303-hs-office-membership-rbac.md index 4f425f6e..d458212c 100644 --- a/src/main/resources/db/changelog/303-hs-office-membership-rbac.md +++ b/src/main/resources/db/changelog/303-hs-office-membership-rbac.md @@ -10,52 +10,13 @@ subgraph partnerRel["`**partnerRel**`"] direction TB style partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px - subgraph partnerRel.contact["`**partnerRel.contact**`"] - direction TB - style partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph partnerRel.contact:roles[ ] - style partnerRel.contact:roles fill:#99bcdb,stroke:white - - role:partnerRel.contact:owner[[partnerRel.contact:owner]] - role:partnerRel.contact:admin[[partnerRel.contact:admin]] - role:partnerRel.contact:referrer[[partnerRel.contact:referrer]] - end - end - - subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"] - direction TB - style partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph partnerRel.anchorPerson:roles[ ] - style partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white - - role:partnerRel.anchorPerson:owner[[partnerRel.anchorPerson:owner]] - role:partnerRel.anchorPerson:admin[[partnerRel.anchorPerson:admin]] - role:partnerRel.anchorPerson:referrer[[partnerRel.anchorPerson:referrer]] - end - end - - subgraph partnerRel.holderPerson["`**partnerRel.holderPerson**`"] - direction TB - style partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph partnerRel.holderPerson:roles[ ] - style partnerRel.holderPerson:roles fill:#99bcdb,stroke:white - - role:partnerRel.holderPerson:owner[[partnerRel.holderPerson:owner]] - role:partnerRel.holderPerson:admin[[partnerRel.holderPerson:admin]] - role:partnerRel.holderPerson:referrer[[partnerRel.holderPerson:referrer]] - end - end - subgraph partnerRel:roles[ ] style partnerRel:roles fill:#99bcdb,stroke:white - role:partnerRel:owner[[partnerRel:owner]] - role:partnerRel:admin[[partnerRel:admin]] - role:partnerRel:agent[[partnerRel:agent]] - role:partnerRel:tenant[[partnerRel:tenant]] + role:partnerRel:OWNER[[partnerRel:OWNER]] + role:partnerRel:ADMIN[[partnerRel:ADMIN]] + role:partnerRel:AGENT[[partnerRel:AGENT]] + role:partnerRel:TENANT[[partnerRel:TENANT]] end end @@ -66,9 +27,9 @@ subgraph partnerRel.contact["`**partnerRel.contact**`"] subgraph partnerRel.contact:roles[ ] style partnerRel.contact:roles fill:#99bcdb,stroke:white - role:partnerRel.contact:owner[[partnerRel.contact:owner]] - role:partnerRel.contact:admin[[partnerRel.contact:admin]] - role:partnerRel.contact:referrer[[partnerRel.contact:referrer]] + role:partnerRel.contact:OWNER[[partnerRel.contact:OWNER]] + role:partnerRel.contact:ADMIN[[partnerRel.contact:ADMIN]] + role:partnerRel.contact:REFERRER[[partnerRel.contact:REFERRER]] end end @@ -79,9 +40,9 @@ subgraph membership["`**membership**`"] subgraph membership:roles[ ] style membership:roles fill:#dd4901,stroke:white - role:membership:owner[[membership:owner]] - role:membership:admin[[membership:admin]] - role:membership:referrer[[membership:referrer]] + role:membership:OWNER[[membership:OWNER]] + role:membership:ADMIN[[membership:ADMIN]] + role:membership:REFERRER[[membership:REFERRER]] end subgraph membership:permissions[ ] @@ -101,9 +62,9 @@ subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"] subgraph partnerRel.anchorPerson:roles[ ] style partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white - role:partnerRel.anchorPerson:owner[[partnerRel.anchorPerson:owner]] - role:partnerRel.anchorPerson:admin[[partnerRel.anchorPerson:admin]] - role:partnerRel.anchorPerson:referrer[[partnerRel.anchorPerson:referrer]] + role:partnerRel.anchorPerson:OWNER[[partnerRel.anchorPerson:OWNER]] + role:partnerRel.anchorPerson:ADMIN[[partnerRel.anchorPerson:ADMIN]] + role:partnerRel.anchorPerson:REFERRER[[partnerRel.anchorPerson:REFERRER]] end end @@ -114,46 +75,46 @@ subgraph partnerRel.holderPerson["`**partnerRel.holderPerson**`"] subgraph partnerRel.holderPerson:roles[ ] style partnerRel.holderPerson:roles fill:#99bcdb,stroke:white - role:partnerRel.holderPerson:owner[[partnerRel.holderPerson:owner]] - role:partnerRel.holderPerson:admin[[partnerRel.holderPerson:admin]] - role:partnerRel.holderPerson:referrer[[partnerRel.holderPerson:referrer]] + role:partnerRel.holderPerson:OWNER[[partnerRel.holderPerson:OWNER]] + role:partnerRel.holderPerson:ADMIN[[partnerRel.holderPerson:ADMIN]] + role:partnerRel.holderPerson:REFERRER[[partnerRel.holderPerson:REFERRER]] end end %% granting roles to users -user:creator ==> role:membership:owner +user:creator ==> role:membership:OWNER %% granting roles to roles -role:global:admin -.-> role:partnerRel.anchorPerson:owner -role:partnerRel.anchorPerson:owner -.-> role:partnerRel.anchorPerson:admin -role:partnerRel.anchorPerson:admin -.-> role:partnerRel.anchorPerson:referrer -role:global:admin -.-> role:partnerRel.holderPerson:owner -role:partnerRel.holderPerson:owner -.-> role:partnerRel.holderPerson:admin -role:partnerRel.holderPerson:admin -.-> role:partnerRel.holderPerson:referrer -role:global:admin -.-> role:partnerRel.contact:owner -role:partnerRel.contact:owner -.-> role:partnerRel.contact:admin -role:partnerRel.contact:admin -.-> role:partnerRel.contact:referrer -role:global:admin -.-> role:partnerRel:owner -role:partnerRel:owner -.-> role:partnerRel:admin -role:partnerRel.anchorPerson:admin -.-> role:partnerRel:admin -role:partnerRel:admin -.-> role:partnerRel:agent -role:partnerRel.holderPerson:admin -.-> role:partnerRel:agent -role:partnerRel:agent -.-> role:partnerRel:tenant -role:partnerRel.holderPerson:admin -.-> role:partnerRel:tenant -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:global:ADMIN -.-> role:partnerRel.anchorPerson:OWNER +role:partnerRel.anchorPerson:OWNER -.-> role:partnerRel.anchorPerson:ADMIN +role:partnerRel.anchorPerson:ADMIN -.-> role:partnerRel.anchorPerson:REFERRER +role:global:ADMIN -.-> role:partnerRel.holderPerson:OWNER +role:partnerRel.holderPerson:OWNER -.-> role:partnerRel.holderPerson:ADMIN +role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel.holderPerson:REFERRER +role:global:ADMIN -.-> role:partnerRel.contact:OWNER +role:partnerRel.contact:OWNER -.-> role:partnerRel.contact:ADMIN +role:partnerRel.contact:ADMIN -.-> role:partnerRel.contact:REFERRER +role:global:ADMIN -.-> role:partnerRel:OWNER +role:partnerRel:OWNER -.-> role:partnerRel:ADMIN +role:partnerRel.anchorPerson:ADMIN -.-> role:partnerRel:ADMIN +role:partnerRel:ADMIN -.-> role:partnerRel:AGENT +role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:AGENT +role:partnerRel:AGENT -.-> role:partnerRel:TENANT +role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:TENANT +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 %% granting permissions to roles -role:global:admin ==> perm:membership:INSERT -role:membership:owner ==> perm:membership:DELETE -role:membership:admin ==> perm:membership:UPDATE -role:membership:referrer ==> perm:membership:SELECT +role:global:ADMIN ==> perm:membership:INSERT +role:membership:OWNER ==> perm:membership:DELETE +role:membership:ADMIN ==> perm:membership:UPDATE +role:membership:REFERRER ==> perm:membership:SELECT ``` diff --git a/src/main/resources/db/changelog/303-hs-office-membership-rbac.sql b/src/main/resources/db/changelog/303-hs-office-membership-rbac.sql index 17dbc84c..9c423ba4 100644 --- a/src/main/resources/db/changelog/303-hs-office-membership-rbac.sql +++ b/src/main/resources/db/changelog/303-hs-office-membership-rbac.sql @@ -44,25 +44,25 @@ begin perform createRoleWithGrants( - hsOfficeMembershipOwner(NEW), + hsOfficeMembershipOWNER(NEW), permissions => array['DELETE'], - incomingSuperRoles => array[hsOfficeRelationAdmin(newPartnerRel)], + incomingSuperRoles => array[hsOfficeRelationADMIN(newPartnerRel)], userUuids => array[currentUserUuid()] ); perform createRoleWithGrants( - hsOfficeMembershipAdmin(NEW), + hsOfficeMembershipADMIN(NEW), permissions => array['UPDATE'], incomingSuperRoles => array[ - hsOfficeMembershipOwner(NEW), - hsOfficeRelationAgent(newPartnerRel)] + hsOfficeMembershipOWNER(NEW), + hsOfficeRelationAGENT(newPartnerRel)] ); perform createRoleWithGrants( - hsOfficeMembershipReferrer(NEW), + hsOfficeMembershipREFERRER(NEW), permissions => array['SELECT'], - incomingSuperRoles => array[hsOfficeMembershipAdmin(NEW)], - outgoingSubRoles => array[hsOfficeRelationTenant(newPartnerRel)] + incomingSuperRoles => array[hsOfficeMembershipADMIN(NEW)], + outgoingSubRoles => array[hsOfficeRelationTENANT(newPartnerRel)] ); call leaveTriggerForObjectUuid(NEW.uuid); @@ -105,7 +105,7 @@ do language plpgsql $$ LOOP call grantPermissionToRole( createPermission(row.uuid, 'INSERT', 'hs_office_membership'), - globalAdmin()); + globalADMIN()); END LOOP; END; $$; @@ -120,7 +120,7 @@ create or replace function hs_office_membership_global_insert_tf() begin call grantPermissionToRole( createPermission(NEW.uuid, 'INSERT', 'hs_office_membership'), - globalAdmin()); + globalADMIN()); return NEW; end; $$; diff --git a/src/main/resources/db/changelog/308-hs-office-membership-test-data.sql b/src/main/resources/db/changelog/308-hs-office-membership-test-data.sql index 9d574a58..d49a5344 100644 --- a/src/main/resources/db/changelog/308-hs-office-membership-test-data.sql +++ b/src/main/resources/db/changelog/308-hs-office-membership-test-data.sql @@ -19,7 +19,7 @@ begin currentTask := 'creating Membership test-data ' || 'P-' || forPartnerNumber::text || 'M-...' || newMemberNumberSuffix; - call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global.admin'); + call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN'); execute format('set local hsadminng.currentTask to %L', currentTask); select partner.* from hs_office_partner partner diff --git a/src/test/java/net/hostsharing/hsadminng/context/ContextIntegrationTests.java b/src/test/java/net/hostsharing/hsadminng/context/ContextIntegrationTests.java index c02cb944..0daa0a15 100644 --- a/src/test/java/net/hostsharing/hsadminng/context/ContextIntegrationTests.java +++ b/src/test/java/net/hostsharing/hsadminng/context/ContextIntegrationTests.java @@ -59,13 +59,13 @@ class ContextIntegrationTests { void defineWithoutCurrentUserButWithAssumedRoles() { // when final var result = jpaAttempt.transacted(() -> - context.define(null, "test_package#yyy00.admin") + context.define(null, "test_package#yyy00:ADMIN") ); // then result.assertExceptionWithRootCauseMessage( jakarta.persistence.PersistenceException.class, - "ERROR: [403] undefined has no permission to assume role test_package#yyy00.admin"); + "ERROR: [403] undefined has no permission to assume role test_package#yyy00:ADMIN"); } @Test @@ -85,7 +85,7 @@ class ContextIntegrationTests { @Transactional void defineWithCurrentUserAndAssumedRoles() { // given - context.define("superuser-alex@hostsharing.net", "test_customer#xxx.owner;test_customer#yyy.owner"); + context.define("superuser-alex@hostsharing.net", "test_customer#xxx:OWNER;test_customer#yyy:OWNER"); // when final var currentUser = context.getCurrentUser(); @@ -93,7 +93,7 @@ class ContextIntegrationTests { // then assertThat(context.getAssumedRoles()) - .isEqualTo(Array.of("test_customer#xxx.owner", "test_customer#yyy.owner")); + .isEqualTo(Array.of("test_customer#xxx:OWNER", "test_customer#yyy:OWNER")); assertThat(context.currentSubjectsUuids()).hasSize(2); } @@ -101,12 +101,12 @@ class ContextIntegrationTests { public void defineContextWithCurrentUserAndAssumeInaccessibleRole() { // when final var result = jpaAttempt.transacted(() -> - context.define("customer-admin@xxx.example.com", "test_package#yyy00.admin") + context.define("customer-admin@xxx.example.com", "test_package#yyy00:ADMIN") ); // then result.assertExceptionWithRootCauseMessage( jakarta.persistence.PersistenceException.class, - "ERROR: [403] user customer-admin@xxx.example.com has no permission to assume role test_package#yyy00.admin"); + "ERROR: [403] user customer-admin@xxx.example.com has no permission to assume role test_package#yyy00:ADMIN"); } } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountRepositoryIntegrationTest.java index fd484c4c..f0541813 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountRepositoryIntegrationTest.java @@ -102,21 +102,21 @@ class HsOfficeBankAccountRepositoryIntegrationTest extends ContextBasedTestWithC final var roles = rawRoleRepo.findAll(); assertThat(distinctRoleNamesOf(roles)).containsExactlyInAnyOrder(Array.from( initialRoleNames, - "hs_office_bankaccount#DE25500105176934832579.owner", - "hs_office_bankaccount#DE25500105176934832579.admin", - "hs_office_bankaccount#DE25500105176934832579.referrer" + "hs_office_bankaccount#DE25500105176934832579:OWNER", + "hs_office_bankaccount#DE25500105176934832579:ADMIN", + "hs_office_bankaccount#DE25500105176934832579:REFERRER" )); assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll())).containsExactlyInAnyOrder(Array.fromFormatted( initialGrantNames, - "{ grant perm DELETE on hs_office_bankaccount#DE25500105176934832579 to role hs_office_bankaccount#DE25500105176934832579.owner by system and assume }", - "{ grant role hs_office_bankaccount#DE25500105176934832579.owner to role global#global.admin by system and assume }", - "{ grant role hs_office_bankaccount#DE25500105176934832579.owner to user selfregistered-user-drew@hostsharing.org by hs_office_bankaccount#DE25500105176934832579.owner and assume }", + "{ grant perm:hs_office_bankaccount#DE25500105176934832579:DELETE to role:hs_office_bankaccount#DE25500105176934832579:OWNER by system and assume }", + "{ grant role:hs_office_bankaccount#DE25500105176934832579:OWNER to role:global#global:ADMIN by system and assume }", + "{ grant role:hs_office_bankaccount#DE25500105176934832579:OWNER to user:selfregistered-user-drew@hostsharing.org by hs_office_bankaccount#DE25500105176934832579:OWNER and assume }", - "{ grant role hs_office_bankaccount#DE25500105176934832579.admin to role hs_office_bankaccount#DE25500105176934832579.owner by system and assume }", - "{ grant perm UPDATE on hs_office_bankaccount#DE25500105176934832579 to role hs_office_bankaccount#DE25500105176934832579.admin by system and assume }", + "{ grant role:hs_office_bankaccount#DE25500105176934832579:ADMIN to role:hs_office_bankaccount#DE25500105176934832579:OWNER by system and assume }", + "{ grant perm:hs_office_bankaccount#DE25500105176934832579:UPDATE to role:hs_office_bankaccount#DE25500105176934832579:ADMIN by system and assume }", - "{ grant perm SELECT on hs_office_bankaccount#DE25500105176934832579 to role hs_office_bankaccount#DE25500105176934832579.referrer by system and assume }", - "{ grant role hs_office_bankaccount#DE25500105176934832579.referrer to role hs_office_bankaccount#DE25500105176934832579.admin by system and assume }", + "{ grant perm:hs_office_bankaccount#DE25500105176934832579:SELECT to role:hs_office_bankaccount#DE25500105176934832579:REFERRER by system and assume }", + "{ grant role:hs_office_bankaccount#DE25500105176934832579:REFERRER to role:hs_office_bankaccount#DE25500105176934832579:ADMIN by system and assume }", null )); } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactRepositoryIntegrationTest.java index 259f88fe..3187a4f4 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactRepositoryIntegrationTest.java @@ -103,20 +103,20 @@ class HsOfficeContactRepositoryIntegrationTest extends ContextBasedTestWithClean final var roles = rawRoleRepo.findAll(); assertThat(distinctRoleNamesOf(roles)).containsExactlyInAnyOrder(Array.from( initialRoleNames, - "hs_office_contact#anothernewcontact.owner", - "hs_office_contact#anothernewcontact.admin", - "hs_office_contact#anothernewcontact.referrer" + "hs_office_contact#anothernewcontact:OWNER", + "hs_office_contact#anothernewcontact:ADMIN", + "hs_office_contact#anothernewcontact:REFERRER" )); assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll())).containsExactlyInAnyOrder(Array.fromFormatted( initialGrantNames, - "{ grant role hs_office_contact#anothernewcontact.owner to role global#global.admin by system and assume }", - "{ grant perm UPDATE on hs_office_contact#anothernewcontact to role hs_office_contact#anothernewcontact.admin by system and assume }", - "{ grant role hs_office_contact#anothernewcontact.owner to user selfregistered-user-drew@hostsharing.org by hs_office_contact#anothernewcontact.owner and assume }", - "{ grant perm DELETE on hs_office_contact#anothernewcontact to role hs_office_contact#anothernewcontact.owner by system and assume }", - "{ grant role hs_office_contact#anothernewcontact.admin to role hs_office_contact#anothernewcontact.owner by system and assume }", + "{ grant role:hs_office_contact#anothernewcontact:OWNER to role:global#global:ADMIN by system and assume }", + "{ grant perm:hs_office_contact#anothernewcontact:UPDATE to role:hs_office_contact#anothernewcontact:ADMIN by system and assume }", + "{ grant role:hs_office_contact#anothernewcontact:OWNER to user:selfregistered-user-drew@hostsharing.org by hs_office_contact#anothernewcontact:OWNER and assume }", + "{ grant perm:hs_office_contact#anothernewcontact:DELETE to role:hs_office_contact#anothernewcontact:OWNER by system and assume }", + "{ grant role:hs_office_contact#anothernewcontact:ADMIN to role:hs_office_contact#anothernewcontact:OWNER by system and assume }", - "{ grant perm SELECT on hs_office_contact#anothernewcontact to role hs_office_contact#anothernewcontact.referrer by system and assume }", - "{ grant role hs_office_contact#anothernewcontact.referrer to role hs_office_contact#anothernewcontact.admin by system and assume }" + "{ grant perm:hs_office_contact#anothernewcontact:SELECT to role:hs_office_contact#anothernewcontact:REFERRER by system and assume }", + "{ grant role:hs_office_contact#anothernewcontact:REFERRER to role:hs_office_contact#anothernewcontact:ADMIN by system and assume }" )); } 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 7031476e..40163eab 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,8 +112,8 @@ class HsOfficeCoopAssetsTransactionRepositoryIntegrationTest extends ContextBase .map(s -> s.replace("hs_office_", "")) .containsExactlyInAnyOrder(Array.fromFormatted( initialGrantNames, - "{ grant perm SELECT on coopassetstransaction#temprefB to role membership#M-1000101.admin by system and assume }", - "{ grant perm UPDATE on coopassetstransaction#temprefB to role membership#M-1000101.admin by system and assume }", + "{ grant perm:coopassetstransaction#temprefB:SELECT to role:membership#M-1000101:ADMIN by system and assume }", + "{ grant perm:coopassetstransaction#temprefB:UPDATE to role:membership#M-1000101:ADMIN by system and assume }", null)); } @@ -194,7 +194,7 @@ class HsOfficeCoopAssetsTransactionRepositoryIntegrationTest extends ContextBase @Test public void partnerPersonAdmin_canViewRelatedCoopAssetsTransactions() { // given: - context("superuser-alex@hostsharing.net", "hs_office_person#FirstGmbH.admin"); + context("superuser-alex@hostsharing.net", "hs_office_person#FirstGmbH:ADMIN"); // when: final var result = coopAssetsTransactionRepo.findCoopAssetsTransactionByOptionalMembershipUuidAndDateRange( 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 16880741..37d67592 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,8 +111,8 @@ class HsOfficeCoopSharesTransactionRepositoryIntegrationTest extends ContextBase .map(s -> s.replace("hs_office_", "")) .containsExactlyInAnyOrder(Array.fromFormatted( initialGrantNames, - "{ grant perm SELECT on coopsharestransaction#temprefB to role membership#M-1000101.admin by system and assume }", - "{ grant perm UPDATE on coopsharestransaction#temprefB to role membership#M-1000101.admin by system and assume }", + "{ grant perm:coopsharestransaction#temprefB:SELECT to role:membership#M-1000101.admin by system and assume }", + "{ grant perm:coopsharestransaction#temprefB:UPDATE to role:membership#M-1000101.admin by system and assume }", null)); } @@ -193,7 +193,7 @@ class HsOfficeCoopSharesTransactionRepositoryIntegrationTest extends ContextBase @Test public void normalUser_canViewOnlyRelatedCoopSharesTransactions() { // given: - context("superuser-alex@hostsharing.net", "hs_office_membership#M-1000101.admin"); + context("superuser-alex@hostsharing.net", "hs_office_membership#M-1000101:ADMIN"); // when: final var result = coopSharesTransactionRepo.findCoopSharesTransactionByOptionalMembershipUuidAndDateRange( diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorControllerAcceptanceTest.java index 975ad961..c2e3fffd 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorControllerAcceptanceTest.java @@ -635,7 +635,7 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu RestAssured // @formatter:off .given() .header("current-user", "superuser-alex@hostsharing.net") - .header("assumed-roles", "hs_office_contact#fourthcontact.admin") + .header("assumed-roles", "hs_office_contact#fourthcontact:ADMIN") .contentType(ContentType.JSON) .body(""" { diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java index 5f53df24..7a3dfbb7 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java @@ -172,44 +172,44 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean // then assertThat(distinctRoleNamesOf(rawRoleRepo.findAll())).containsExactlyInAnyOrder(Array.from( initialRoleNames, - "hs_office_relation#FirstGmbH-with-DEBITOR-FourtheG.owner", - "hs_office_relation#FirstGmbH-with-DEBITOR-FourtheG.admin", - "hs_office_relation#FirstGmbH-with-DEBITOR-FourtheG.agent", - "hs_office_relation#FirstGmbH-with-DEBITOR-FourtheG.tenant")); + "hs_office_relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER", + "hs_office_relation#FirstGmbH-with-DEBITOR-FourtheG:ADMIN", + "hs_office_relation#FirstGmbH-with-DEBITOR-FourtheG:AGENT", + "hs_office_relation#FirstGmbH-with-DEBITOR-FourtheG:TENANT")); assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll())) .map(s -> s.replace("hs_office_", "")) .containsExactlyInAnyOrder(Array.fromFormatted( initialGrantNames, - "{ grant perm INSERT into sepamandate with relation#FirstGmbH-with-DEBITOR-FourtheG to role relation#FirstGmbH-with-DEBITOR-FourtheG.admin by system and assume }", + "{ grant perm:relation#FirstGmbH-with-DEBITOR-FourtheG:INSERT>sepamandate to role:relation#FirstGmbH-with-DEBITOR-FourtheG:ADMIN by system and assume }", // owner - "{ grant perm DELETE on debitor#D-1000122 to role relation#FirstGmbH-with-DEBITOR-FourtheG.owner by system and assume }", - "{ grant perm DELETE on relation#FirstGmbH-with-DEBITOR-FourtheG to role relation#FirstGmbH-with-DEBITOR-FourtheG.owner by system and assume }", - "{ grant role relation#FirstGmbH-with-DEBITOR-FourtheG.owner to role global#global.admin by system and assume }", - "{ grant role relation#FirstGmbH-with-DEBITOR-FourtheG.owner to user superuser-alex@hostsharing.net by relation#FirstGmbH-with-DEBITOR-FourtheG.owner and assume }", + "{ grant perm:debitor#D-1000122:DELETE to role:relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER by system and assume }", + "{ grant perm:relation#FirstGmbH-with-DEBITOR-FourtheG:DELETE to role:relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER by system and assume }", + "{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER to role:global#global:ADMIN by system and assume }", + "{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER to user:superuser-alex@hostsharing.net by relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER and assume }", // admin - "{ grant perm UPDATE on debitor#D-1000122 to role relation#FirstGmbH-with-DEBITOR-FourtheG.admin by system and assume }", - "{ grant perm UPDATE on relation#FirstGmbH-with-DEBITOR-FourtheG to role relation#FirstGmbH-with-DEBITOR-FourtheG.admin by system and assume }", - "{ grant role relation#FirstGmbH-with-DEBITOR-FourtheG.admin to role relation#FirstGmbH-with-DEBITOR-FourtheG.owner by system and assume }", - "{ grant role relation#FirstGmbH-with-DEBITOR-FourtheG.admin to role person#FirstGmbH.admin by system and assume }", - "{ grant role relation#FirstGmbH-with-DEBITOR-FourtheG.admin to role relation#HostsharingeG-with-PARTNER-FirstGmbH.admin by system and assume }", + "{ grant perm:debitor#D-1000122:UPDATE to role:relation#FirstGmbH-with-DEBITOR-FourtheG:ADMIN by system and assume }", + "{ grant perm:relation#FirstGmbH-with-DEBITOR-FourtheG:UPDATE to role:relation#FirstGmbH-with-DEBITOR-FourtheG:ADMIN by system and assume }", + "{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:ADMIN to role:relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER by system and assume }", + "{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:ADMIN to role:person#FirstGmbH:ADMIN by system and assume }", + "{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:ADMIN to role:relation#HostsharingeG-with-PARTNER-FirstGmbH:ADMIN by system and assume }", // agent - "{ grant role relation#FirstGmbH-with-DEBITOR-FourtheG.agent to role person#FourtheG.admin by system and assume }", - "{ grant role relation#FirstGmbH-with-DEBITOR-FourtheG.agent to role relation#FirstGmbH-with-DEBITOR-FourtheG.admin by system and assume }", - "{ grant role relation#FirstGmbH-with-DEBITOR-FourtheG.agent to role relation#HostsharingeG-with-PARTNER-FirstGmbH.agent by system and assume }", + "{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:AGENT to role:person#FourtheG:ADMIN by system and assume }", + "{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:AGENT to role:relation#FirstGmbH-with-DEBITOR-FourtheG:ADMIN by system and assume }", + "{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:AGENT to role:relation#HostsharingeG-with-PARTNER-FirstGmbH:AGENT by system and assume }", // tenant - "{ grant perm SELECT on debitor#D-1000122 to role relation#FirstGmbH-with-DEBITOR-FourtheG.tenant by system and assume }", - "{ grant perm SELECT on relation#FirstGmbH-with-DEBITOR-FourtheG to role relation#FirstGmbH-with-DEBITOR-FourtheG.tenant by system and assume }", - "{ grant role relation#HostsharingeG-with-PARTNER-FirstGmbH.tenant to role relation#FirstGmbH-with-DEBITOR-FourtheG.agent by system and assume }", - "{ grant role contact#fourthcontact.referrer to role relation#FirstGmbH-with-DEBITOR-FourtheG.tenant by system and assume }", - "{ grant role person#FirstGmbH.referrer to role relation#FirstGmbH-with-DEBITOR-FourtheG.tenant by system and assume }", - "{ grant role person#FourtheG.referrer to role relation#FirstGmbH-with-DEBITOR-FourtheG.tenant by system and assume }", - "{ grant role relation#FirstGmbH-with-DEBITOR-FourtheG.tenant to role contact#fourthcontact.admin by system and assume }", - "{ grant role relation#FirstGmbH-with-DEBITOR-FourtheG.tenant to role person#FourtheG.admin by system and assume }", - "{ grant role relation#FirstGmbH-with-DEBITOR-FourtheG.tenant to role relation#FirstGmbH-with-DEBITOR-FourtheG.agent by system and assume }", + "{ grant perm:debitor#D-1000122:SELECT to role:relation#FirstGmbH-with-DEBITOR-FourtheG:TENANT by system and assume }", + "{ grant perm:relation#FirstGmbH-with-DEBITOR-FourtheG:SELECT to role:relation#FirstGmbH-with-DEBITOR-FourtheG:TENANT by system and assume }", + "{ grant role:relation#HostsharingeG-with-PARTNER-FirstGmbH:TENANT to role:relation#FirstGmbH-with-DEBITOR-FourtheG:AGENT by system and assume }", + "{ grant role:contact#fourthcontact:REFERRER to role:relation#FirstGmbH-with-DEBITOR-FourtheG:TENANT by system and assume }", + "{ grant role:person#FirstGmbH:REFERRER to role:relation#FirstGmbH-with-DEBITOR-FourtheG:TENANT by system and assume }", + "{ grant role:person#FourtheG:REFERRER to role:relation#FirstGmbH-with-DEBITOR-FourtheG:TENANT by system and assume }", + "{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:TENANT to role:contact#fourthcontact:ADMIN by system and assume }", + "{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:TENANT to role:person#FourtheG:ADMIN by system and assume }", + "{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:TENANT to role:relation#FirstGmbH-with-DEBITOR-FourtheG:AGENT by system and assume }", null)); } @@ -243,9 +243,9 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean @ParameterizedTest @Disabled // TODO: reactivate once partner.person + partner.contact are removed @ValueSource(strings = { - "hs_office_partner#10001:FirstGmbH-firstcontact.admin", - "hs_office_person#FirstGmbH.admin", - "hs_office_contact#firstcontact.admin", + "hs_office_partner#10001:FirstGmbH-firstcontact:ADMIN", + "hs_office_person#FirstGmbH:ADMIN", + "hs_office_contact#firstcontact:ADMIN", }) public void relatedPersonAdmin_canViewRelatedDebitors(final String assumedRole) { // given: @@ -317,7 +317,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean assertThatDebitorIsVisibleForUserWithRole( givenDebitor, - "hs_office_relation#FourtheG-with-DEBITOR-FourtheG.admin", true); + "hs_office_relation#FourtheG-with-DEBITOR-FourtheG:ADMIN", true); final var givenNewPartnerPerson = one(personRepo.findPersonByOptionalNameLike("First")); final var givenNewBillingPerson = one(personRepo.findPersonByOptionalNameLike("Firby")); final var givenNewContact = one(contactRepo.findContactByOptionalLabelLike("sixth contact")); @@ -346,31 +346,31 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean result.assertSuccessful(); assertThatDebitorIsVisibleForUserWithRole( result.returnedValue(), - "global#global.admin", true); + "global#global:ADMIN", true); // ... partner role was reassigned: assertThatDebitorIsNotVisibleForUserWithRole( result.returnedValue(), - "hs_office_relation#FourtheG-with-DEBITOR-FourtheG.admin"); + "hs_office_relation#FourtheG-with-DEBITOR-FourtheG:ADMIN"); assertThatDebitorIsVisibleForUserWithRole( result.returnedValue(), - "hs_office_relation#FirstGmbH-with-DEBITOR-FirbySusan.agent", true); + "hs_office_relation#FirstGmbH-with-DEBITOR-FirbySusan:AGENT", true); // ... contact role was reassigned: assertThatDebitorIsNotVisibleForUserWithRole( result.returnedValue(), - "hs_office_contact#fifthcontact.admin"); + "hs_office_contact#fifthcontact:ADMIN"); assertThatDebitorIsVisibleForUserWithRole( result.returnedValue(), - "hs_office_contact#sixthcontact.admin", false); + "hs_office_contact#sixthcontact:ADMIN", false); // ... bank-account role was reassigned: assertThatDebitorIsNotVisibleForUserWithRole( result.returnedValue(), - "hs_office_bankaccount#DE02200505501015871393.admin"); + "hs_office_bankaccount#DE02200505501015871393:ADMIN"); assertThatDebitorIsVisibleForUserWithRole( result.returnedValue(), - "hs_office_bankaccount#DE02120300000000202051.admin", true); + "hs_office_bankaccount#DE02120300000000202051:ADMIN", true); } @Test @@ -380,7 +380,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean final var givenDebitor = givenSomeTemporaryDebitor("Fourth", "fifth contact", null, "fig"); assertThatDebitorIsVisibleForUserWithRole( givenDebitor, - "hs_office_relation#FourtheG-with-DEBITOR-FourtheG.admin", true); + "hs_office_relation#FourtheG-with-DEBITOR-FourtheG:ADMIN", true); assertThatDebitorActuallyInDatabase(givenDebitor, true); final var givenNewBankAccount = one(bankAccountRepo.findByOptionalHolderLike("first")); @@ -395,12 +395,12 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean result.assertSuccessful(); assertThatDebitorIsVisibleForUserWithRole( result.returnedValue(), - "global#global.admin", true); + "global#global:ADMIN", true); // ... bank-account role was assigned: assertThatDebitorIsVisibleForUserWithRole( result.returnedValue(), - "hs_office_bankaccount#DE02120300000000202051.admin", true); + "hs_office_bankaccount#DE02120300000000202051:ADMIN", true); } @Test @@ -410,7 +410,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean final var givenDebitor = givenSomeTemporaryDebitor("Fourth", "fifth contact", "Fourth", "fih"); assertThatDebitorIsVisibleForUserWithRole( givenDebitor, - "hs_office_relation#HostsharingeG-with-PARTNER-FourtheG.agent", true); + "hs_office_relation#HostsharingeG-with-PARTNER-FourtheG:AGENT", true); assertThatDebitorActuallyInDatabase(givenDebitor, true); // when @@ -424,12 +424,12 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean result.assertSuccessful(); assertThatDebitorIsVisibleForUserWithRole( result.returnedValue(), - "global#global.admin", true); + "global#global:ADMIN", true); // ... bank-account role was removed from previous bank-account admin: assertThatDebitorIsNotVisibleForUserWithRole( result.returnedValue(), - "hs_office_bankaccount#DE02200505501015871393.admin"); + "hs_office_bankaccount#DE02200505501015871393:ADMIN"); } @Test @@ -439,12 +439,12 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean final var givenDebitor = givenSomeTemporaryDebitor("Fourth", "eighth", "Fourth", "eig"); assertThatDebitorIsVisibleForUserWithRole( givenDebitor, - "hs_office_relation#HostsharingeG-with-PARTNER-FourtheG.agent", true); + "hs_office_relation#HostsharingeG-with-PARTNER-FourtheG:AGENT", true); assertThatDebitorActuallyInDatabase(givenDebitor, true); // when final var result = jpaAttempt.transacted(() -> { - context("superuser-alex@hostsharing.net", "hs_office_relation#HostsharingeG-with-PARTNER-FourtheG.agent"); + context("superuser-alex@hostsharing.net", "hs_office_relation#HostsharingeG-with-PARTNER-FourtheG:AGENT"); givenDebitor.setVatId("NEW-VAT-ID"); return toCleanup(debitorRepo.save(givenDebitor)); }); @@ -462,11 +462,11 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean assertThatDebitorActuallyInDatabase(givenDebitor, true); assertThatDebitorIsVisibleForUserWithRole( givenDebitor, - "hs_office_contact#ninthcontact.admin", false); + "hs_office_contact#ninthcontact:ADMIN", false); // when final var result = jpaAttempt.transacted(() -> { - context("superuser-alex@hostsharing.net", "hs_office_contact#ninthcontact.admin"); + context("superuser-alex@hostsharing.net", "hs_office_contact#ninthcontact:ADMIN"); givenDebitor.setVatId("NEW-VAT-ID"); return toCleanup(debitorRepo.save(givenDebitor)); }); @@ -545,7 +545,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean // when final var result = jpaAttempt.transacted(() -> { - context("superuser-alex@hostsharing.net", "hs_office_relation#FourtheG-with-DEBITOR-FourtheG.admin"); + context("superuser-alex@hostsharing.net", "hs_office_relation#FourtheG-with-DEBITOR-FourtheG:ADMIN"); assertThat(debitorRepo.findByUuid(givenDebitor.getUuid())).isPresent(); debitorRepo.deleteByUuid(givenDebitor.getUuid()); 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 c0d69951..c0def119 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 @@ -269,7 +269,7 @@ class HsOfficeMembershipControllerAcceptanceTest extends ContextBasedTestWithCle RestAssured // @formatter:off .given() .header("current-user", "superuser-alex@hostsharing.net") - .header("assumed-roles", "hs_office_relation#HostsharingeG-with-PARTNER-ThirdOHG.agent") + .header("assumed-roles", "hs_office_relation#HostsharingeG-with-PARTNER-ThirdOHG:AGENT") .port(port) .when() .get("http://localhost/api/hs/office/memberships/" + givenMembershipUuid) @@ -338,7 +338,7 @@ class HsOfficeMembershipControllerAcceptanceTest extends ContextBasedTestWithCle void partnerRelAgent_canPatchValidityOfRelatedMembership() { // given - final var givenPartnerAgent = "hs_office_relation#HostsharingeG-with-PARTNER-FirstGmbH.agent"; + final var givenPartnerAgent = "hs_office_relation#HostsharingeG-with-PARTNER-FirstGmbH:AGENT"; context.define("superuser-alex@hostsharing.net", givenPartnerAgent); final var givenMembership = givenSomeTemporaryMembershipBessler("First"); @@ -401,7 +401,7 @@ class HsOfficeMembershipControllerAcceptanceTest extends ContextBasedTestWithCle RestAssured // @formatter:off .given() .header("current-user", "superuser-alex@hostsharing.net") - .header("assumed-roles", "hs_office_relation#HostsharingeG-with-PARTNER-FirstGmbH.agent") + .header("assumed-roles", "hs_office_relation#HostsharingeG-with-PARTNER-FirstGmbH:AGENT") .port(port) .when() .delete("http://localhost/api/hs/office/memberships/" + givenMembership.getUuid()) 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 a53b2705..f6f7e518 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 @@ -91,7 +91,6 @@ class HsOfficeMembershipRepositoryIntegrationTest extends ContextBasedTestWithCl context("superuser-alex@hostsharing.net"); final var initialRoleNames = distinctRoleNamesOf(rawRoleRepo.findAll()); final var initialGrantNames = distinctGrantDisplaysOf(rawGrantRepo.findAll()).stream() - .map(s -> s.replace("GmbH-firstcontact", "")) .map(s -> s.replace("hs_office_", "")) .toList(); @@ -111,31 +110,30 @@ 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:OWNER", + "hs_office_membership#M-1000117:REFERRER")); assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll())) - .map(s -> s.replace("GmbH-firstcontact", "")) .map(s -> s.replace("hs_office_", "")) .containsExactlyInAnyOrder(Array.fromFormatted( initialGrantNames, // owner - "{ grant perm DELETE on membership#M-1000117 to role membership#M-1000117.owner by system and assume }", + "{ grant perm:membership#M-1000117:DELETE to role:membership#M-1000117:OWNER by system and assume }", // admin - "{ grant perm UPDATE on membership#M-1000117 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: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 }", // agent - "{ grant role membership#M-1000117.admin to role relation#HostsharingeG-with-PARTNER-FirstGmbH.agent by system and assume }", + "{ grant role:membership#M-1000117:ADMIN to role:relation#HostsharingeG-with-PARTNER-FirstGmbH:AGENT by system and assume }", // referrer - "{ grant perm SELECT on membership#M-1000117 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 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 }", null)); } @@ -230,13 +228,13 @@ class HsOfficeMembershipRepositoryIntegrationTest extends ContextBasedTestWithCl assertThatMembershipExistsAndIsAccessibleToCurrentContext(givenMembership); assertThatMembershipIsVisibleForRole( givenMembership, - "hs_office_membership#M-1000113.referrer"); + "hs_office_membership#M-1000113:REFERRER"); 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:REFERRER"); givenMembership.setValidity( Range.closedOpen(givenMembership.getValidity().lower(), newValidityEnd)); return membershipRepo.save(givenMembership); @@ -294,7 +292,7 @@ class HsOfficeMembershipRepositoryIntegrationTest extends ContextBasedTestWithCl // when final var result = jpaAttempt.transacted(() -> { - context("superuser-alex@hostsharing.net", "hs_office_relation#HostsharingeG-with-PARTNER-FirstGmbH.agent"); + context("superuser-alex@hostsharing.net", "hs_office_relation#HostsharingeG-with-PARTNER-FirstGmbH:AGENT"); assertThat(membershipRepo.findByUuid(givenMembership.getUuid())).isPresent(); membershipRepo.deleteByUuid(givenMembership.getUuid()); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java b/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java index bb42901d..4010167d 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java @@ -106,7 +106,7 @@ import static org.assertj.core.api.Fail.fail; @Tag("import") @DataJpaTest(properties = { "spring.datasource.url=${HSADMINNG_POSTGRES_JDBC_URL:jdbc:tc:postgresql:15.5-bookworm:///spring_boot_testcontainers}", - "spring.datasource.username=${HSADMINNG_POSTGRES_ADMIN_USERNAME:admin}", + "spring.datasource.username=${HSADMINNG_POSTGRES_ADMIN_USERNAME:ADMIN}", "spring.datasource.password=${HSADMINNG_POSTGRES_ADMIN_PASSWORD:password}", "hsadminng.superuser=${HSADMINNG_SUPERUSER:superuser-alex@hostsharing.net}" }) diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepositoryIntegrationTest.java index 94bcb9fe..98bff812 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepositoryIntegrationTest.java @@ -132,52 +132,52 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean // then assertThat(distinctRoleNamesOf(rawRoleRepo.findAll())).containsExactlyInAnyOrder(Array.from( initialRoleNames, - "hs_office_relation#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler.owner", - "hs_office_relation#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler.admin", - "hs_office_relation#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler.agent", - "hs_office_relation#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler.tenant")); + "hs_office_relation#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler:OWNER", + "hs_office_relation#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler:ADMIN", + "hs_office_relation#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler:AGENT", + "hs_office_relation#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler:TENANT")); assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll())) .map(s -> s.replace("ErbenBesslerMelBessler", "EBess")) .map(s -> s.replace("fourthcontact", "4th")) .map(s -> s.replace("hs_office_", "")) .containsExactlyInAnyOrder(distinct(fromFormatted( initialGrantNames, - "{ grant perm INSERT into sepamandate with relation#HostsharingeG-with-PARTNER-EBess to role relation#HostsharingeG-with-PARTNER-EBess.admin by system and assume }", + "{ grant perm:relation#HostsharingeG-with-PARTNER-EBess:INSERT>sepamandate to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }", // permissions on partner - "{ grant perm DELETE on partner#P-20032 to role relation#HostsharingeG-with-PARTNER-EBess.admin by system and assume }", - "{ grant perm UPDATE on partner#P-20032 to role relation#HostsharingeG-with-PARTNER-EBess.agent by system and assume }", - "{ grant perm SELECT on partner#P-20032 to role relation#HostsharingeG-with-PARTNER-EBess.tenant by system and assume }", + "{ grant perm:partner#P-20032:DELETE to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }", + "{ grant perm:partner#P-20032:UPDATE to role:relation#HostsharingeG-with-PARTNER-EBess:AGENT by system and assume }", + "{ grant perm:partner#P-20032:SELECT to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }", // permissions on partner-details - "{ grant perm DELETE on partner_details#P-20032-details to role relation#HostsharingeG-with-PARTNER-EBess.admin by system and assume }", - "{ grant perm UPDATE on partner_details#P-20032-details to role relation#HostsharingeG-with-PARTNER-EBess.agent by system and assume }", - "{ grant perm SELECT on partner_details#P-20032-details to role relation#HostsharingeG-with-PARTNER-EBess.agent by system and assume }", + "{ grant perm:partner_details#P-20032:DELETE to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }", + "{ grant perm:partner_details#P-20032:UPDATE to role:relation#HostsharingeG-with-PARTNER-EBess:AGENT by system and assume }", + "{ grant perm:partner_details#P-20032:SELECT to role:relation#HostsharingeG-with-PARTNER-EBess:AGENT by system and assume }", // permissions on partner-relation - "{ grant perm DELETE on relation#HostsharingeG-with-PARTNER-EBess to role relation#HostsharingeG-with-PARTNER-EBess.owner by system and assume }", - "{ grant perm UPDATE on relation#HostsharingeG-with-PARTNER-EBess to role relation#HostsharingeG-with-PARTNER-EBess.admin by system and assume }", - "{ grant perm SELECT on relation#HostsharingeG-with-PARTNER-EBess to role relation#HostsharingeG-with-PARTNER-EBess.tenant by system and assume }", + "{ grant perm:relation#HostsharingeG-with-PARTNER-EBess:DELETE to role:relation#HostsharingeG-with-PARTNER-EBess:OWNER by system and assume }", + "{ grant perm:relation#HostsharingeG-with-PARTNER-EBess:UPDATE to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }", + "{ grant perm:relation#HostsharingeG-with-PARTNER-EBess:SELECT to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }", // relation owner - "{ grant role relation#HostsharingeG-with-PARTNER-EBess.owner to role global#global.admin by system and assume }", - "{ grant role relation#HostsharingeG-with-PARTNER-EBess.owner to user superuser-alex@hostsharing.net by relation#HostsharingeG-with-PARTNER-EBess.owner and assume }", + "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:OWNER to role:global#global:ADMIN by system and assume }", + "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:OWNER to user:superuser-alex@hostsharing.net by relation#HostsharingeG-with-PARTNER-EBess:OWNER and assume }", // relation admin - "{ grant role relation#HostsharingeG-with-PARTNER-EBess.admin to role relation#HostsharingeG-with-PARTNER-EBess.owner by system and assume }", - "{ grant role relation#HostsharingeG-with-PARTNER-EBess.admin to role person#HostsharingeG.admin by system and assume }", + "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN to role:relation#HostsharingeG-with-PARTNER-EBess:OWNER by system and assume }", + "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN to role:person#HostsharingeG:ADMIN by system and assume }", // relation agent - "{ grant role relation#HostsharingeG-with-PARTNER-EBess.agent to role person#EBess.admin by system and assume }", - "{ grant role relation#HostsharingeG-with-PARTNER-EBess.agent to role relation#HostsharingeG-with-PARTNER-EBess.admin by system and assume }", + "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:AGENT to role:person#EBess:ADMIN by system and assume }", + "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:AGENT to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }", // relation tenant - "{ grant role contact#4th.referrer to role relation#HostsharingeG-with-PARTNER-EBess.tenant by system and assume }", - "{ grant role person#EBess.referrer to role relation#HostsharingeG-with-PARTNER-EBess.tenant by system and assume }", - "{ grant role person#HostsharingeG.referrer to role relation#HostsharingeG-with-PARTNER-EBess.tenant by system and assume }", - "{ grant role relation#HostsharingeG-with-PARTNER-EBess.tenant to role contact#4th.admin by system and assume }", - "{ grant role relation#HostsharingeG-with-PARTNER-EBess.tenant to role person#EBess.admin by system and assume }", - "{ grant role relation#HostsharingeG-with-PARTNER-EBess.tenant to role relation#HostsharingeG-with-PARTNER-EBess.agent by system and assume }", + "{ grant role:contact#4th:REFERRER to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }", + "{ grant role:person#EBess:REFERRER to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }", + "{ grant role:person#HostsharingeG:REFERRER to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }", + "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:TENANT to role:contact#4th:ADMIN by system and assume }", + "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:TENANT to role:person#EBess:ADMIN by system and assume }", + "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:TENANT to role:relation#HostsharingeG-with-PARTNER-EBess:AGENT by system and assume }", null))); } @@ -266,7 +266,7 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean final var givenPartner = givenSomeTemporaryHostsharingPartner(20036, "Erben Bessler", "fifth contact"); assertThatPartnerIsVisibleForUserWithRole( givenPartner, - "hs_office_person#ErbenBesslerMelBessler.admin"); + "hs_office_person#ErbenBesslerMelBessler:ADMIN"); assertThatPartnerActuallyInDatabase(givenPartner); // when @@ -281,13 +281,13 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean assertThatPartnerIsVisibleForUserWithRole( givenPartner, - "global#global.admin"); + "global#global:ADMIN"); assertThatPartnerIsVisibleForUserWithRole( givenPartner, - "hs_office_person#ThirdOHG.admin"); + "hs_office_person#ThirdOHG:ADMIN"); assertThatPartnerIsNotVisibleForUserWithRole( givenPartner, - "hs_office_person#ErbenBesslerMelBessler.admin"); + "hs_office_person#ErbenBesslerMelBessler:ADMIN"); } @Test @@ -297,13 +297,13 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean final var givenPartner = givenSomeTemporaryHostsharingPartner(20037, "Erben Bessler", "ninth"); assertThatPartnerIsVisibleForUserWithRole( givenPartner, - "hs_office_person#ErbenBesslerMelBessler.admin"); + "hs_office_person#ErbenBesslerMelBessler:ADMIN"); assertThatPartnerActuallyInDatabase(givenPartner); // when final var result = jpaAttempt.transacted(() -> { context("superuser-alex@hostsharing.net", - "hs_office_person#ErbenBesslerMelBessler.admin"); + "hs_office_person#ErbenBesslerMelBessler:ADMIN"); givenPartner.getDetails().setBirthName("new birthname"); return partnerRepo.save(givenPartner); }); @@ -319,20 +319,20 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean final var givenPartner = givenSomeTemporaryHostsharingPartner(20037, "Erben Bessler", "ninth"); assertThatPartnerIsVisibleForUserWithRole( givenPartner, - "hs_office_person#ErbenBesslerMelBessler.admin"); + "hs_office_person#ErbenBesslerMelBessler:ADMIN"); assertThatPartnerActuallyInDatabase(givenPartner); // when final var result = jpaAttempt.transacted(() -> { context("superuser-alex@hostsharing.net", - "hs_office_relation#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler.tenant"); + "hs_office_relation#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler:TENANT"); givenPartner.getDetails().setBirthName("new birthname"); return partnerRepo.save(givenPartner); }); // then result.assertExceptionWithRootCauseMessage(JpaSystemException.class, - "[403] insert into hs_office_partner_details not allowed for current subjects {hs_office_relation#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler.tenant}"); + "[403] insert into hs_office_partner_details not allowed for current subjects {hs_office_relation#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler:TENANT}"); } private void assertThatPartnerActuallyInDatabase(final HsOfficePartnerEntity saved) { diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRepositoryIntegrationTest.java index de198b47..ca4d82d4 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRepositoryIntegrationTest.java @@ -102,23 +102,23 @@ class HsOfficePersonRepositoryIntegrationTest extends ContextBasedTestWithCleanu assertThat(distinctRoleNamesOf(rawRoleRepo.findAll())).containsExactlyInAnyOrder( Array.from( initialRoleNames, - "hs_office_person#anothernewperson.owner", - "hs_office_person#anothernewperson.admin", - "hs_office_person#anothernewperson.referrer" + "hs_office_person#anothernewperson:OWNER", + "hs_office_person#anothernewperson:ADMIN", + "hs_office_person#anothernewperson:REFERRER" )); assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll())).containsExactlyInAnyOrder( - Array.from( + Array.fromFormatted( initialGrantNames, - "{ grant perm INSERT into hs_office_relation with hs_office_person#anothernewperson to role hs_office_person#anothernewperson.admin by system and assume }", + "{ grant perm:hs_office_person#anothernewperson:INSERT>hs_office_relation to role:hs_office_person#anothernewperson:ADMIN by system and assume }", - "{ grant role hs_office_person#anothernewperson.owner to user selfregistered-user-drew@hostsharing.org by hs_office_person#anothernewperson.owner and assume }", - "{ grant role hs_office_person#anothernewperson.owner to role global#global.admin by system and assume }", - "{ grant perm UPDATE on hs_office_person#anothernewperson to role hs_office_person#anothernewperson.admin by system and assume }", - "{ grant perm DELETE on hs_office_person#anothernewperson to role hs_office_person#anothernewperson.owner by system and assume }", - "{ grant role hs_office_person#anothernewperson.admin to role hs_office_person#anothernewperson.owner by system and assume }", + "{ grant role:hs_office_person#anothernewperson:OWNER to user:selfregistered-user-drew@hostsharing.org by hs_office_person#anothernewperson:OWNER and assume }", + "{ grant role:hs_office_person#anothernewperson:OWNER to role:global#global:ADMIN by system and assume }", + "{ grant perm:hs_office_person#anothernewperson:UPDATE to role:hs_office_person#anothernewperson:ADMIN by system and assume }", + "{ grant perm:hs_office_person#anothernewperson:DELETE to role:hs_office_person#anothernewperson:OWNER by system and assume }", + "{ grant role:hs_office_person#anothernewperson:ADMIN to role:hs_office_person#anothernewperson:OWNER by system and assume }", - "{ grant perm SELECT on hs_office_person#anothernewperson to role hs_office_person#anothernewperson.referrer by system and assume }", - "{ grant role hs_office_person#anothernewperson.referrer to role hs_office_person#anothernewperson.admin by system and assume }" + "{ grant perm:hs_office_person#anothernewperson:SELECT to role:hs_office_person#anothernewperson:REFERRER by system and assume }", + "{ grant role:hs_office_person#anothernewperson:REFERRER to role:hs_office_person#anothernewperson:ADMIN by system and assume }" )); } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java index 58ad8ae7..f474de0c 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java @@ -125,35 +125,35 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea // then assertThat(distinctRoleNamesOf(rawRoleRepo.findAll())).containsExactlyInAnyOrder(Array.from( initialRoleNames, - "hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.owner", - "hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.admin", - "hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.agent", - "hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.tenant")); + "hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:OWNER", + "hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN", + "hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:AGENT", + "hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:TENANT")); assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll())).containsExactlyInAnyOrder(Array.fromFormatted( initialGrantNames, // TODO: this grant should only be created for DEBITOR-Relationships, thus the RBAC DSL needs to support conditional grants - "{ grant perm INSERT into hs_office_sepamandate with hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert to role hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.admin by system and assume }", + "{ grant perm:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:INSERT>hs_office_sepamandate to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN by system and assume }", - "{ grant perm DELETE on hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert to role hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.owner by system and assume }", - "{ grant role hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.owner to role global#global.admin by system and assume }", - "{ grant role hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.owner to user superuser-alex@hostsharing.net by hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.owner and assume }", + "{ grant perm:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:DELETE to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:OWNER by system and assume }", + "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:OWNER to role:global#global:ADMIN by system and assume }", + "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:OWNER to user:superuser-alex@hostsharing.net by hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:OWNER and assume }", - "{ grant perm UPDATE on hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert to role hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.admin by system and assume }", - "{ grant role hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.admin to role hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.owner by system and assume }", - "{ grant role hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.admin to role hs_office_person#ErbenBesslerMelBessler.admin by system and assume }", + "{ grant perm:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:UPDATE to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN by system and assume }", + "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:OWNER by system and assume }", + "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN to role:hs_office_person#ErbenBesslerMelBessler:ADMIN by system and assume }", - "{ grant role hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.agent to role hs_office_person#BesslerBert.admin by system and assume }", - "{ grant role hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.agent to role hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.admin by system and assume }", + "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:AGENT to role:hs_office_person#BesslerBert:ADMIN by system and assume }", + "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:AGENT to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN by system and assume }", - "{ grant perm SELECT on hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert to role hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.tenant by system and assume }", - "{ grant role hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.tenant to role hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.agent by system and assume }", - "{ grant role hs_office_person#BesslerBert.referrer to role hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.tenant by system and assume }", - "{ grant role hs_office_person#ErbenBesslerMelBessler.referrer to role hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.tenant by system and assume }", - "{ grant role hs_office_contact#fourthcontact.referrer to role hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.tenant by system and assume }", + "{ grant perm:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:SELECT to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:TENANT by system and assume }", + "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:TENANT to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:AGENT by system and assume }", + "{ grant role:hs_office_person#BesslerBert:REFERRER to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:TENANT by system and assume }", + "{ grant role:hs_office_person#ErbenBesslerMelBessler:REFERRER to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:TENANT by system and assume }", + "{ grant role:hs_office_contact#fourthcontact:REFERRER to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:TENANT by system and assume }", // REPRESENTATIVE holder person -> (represented) anchor person - "{ grant role hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.tenant to role hs_office_contact#fourthcontact.admin by system and assume }", - "{ grant role hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert.tenant to role hs_office_person#BesslerBert.admin by system and assume }", + "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:TENANT to role:hs_office_contact#fourthcontact:ADMIN by system and assume }", + "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:TENANT to role:hs_office_person#BesslerBert:ADMIN by system and assume }", null) ); @@ -219,7 +219,7 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea "Bert", "fifth contact"); assertThatRelationIsVisibleForUserWithRole( givenRelation, - "hs_office_person#ErbenBesslerMelBessler.admin"); + "hs_office_person#ErbenBesslerMelBessler:ADMIN"); assertThatRelationActuallyInDatabase(givenRelation); context("superuser-alex@hostsharing.net"); final var givenContact = contactRepo.findContactByOptionalLabelLike("sixth contact").stream().findFirst().orElseThrow(); @@ -236,14 +236,14 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea assertThat(result.returnedValue().getContact().getLabel()).isEqualTo("sixth contact"); assertThatRelationIsVisibleForUserWithRole( result.returnedValue(), - "global#global.admin"); + "global#global:ADMIN"); assertThatRelationIsVisibleForUserWithRole( result.returnedValue(), - "hs_office_contact#sixthcontact.admin"); + "hs_office_contact#sixthcontact:ADMIN"); assertThatRelationIsNotVisibleForUserWithRole( result.returnedValue(), - "hs_office_contact#fifthcontact.admin"); + "hs_office_contact#fifthcontact:ADMIN"); relationRepo.deleteByUuid(givenRelation.getUuid()); } @@ -256,12 +256,12 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea "Anita", "eighth"); assertThatRelationIsVisibleForUserWithRole( givenRelation, - "hs_office_person#BesslerAnita.admin"); + "hs_office_person#BesslerAnita:ADMIN"); assertThatRelationActuallyInDatabase(givenRelation); // when final var result = jpaAttempt.transacted(() -> { - context("superuser-alex@hostsharing.net", "hs_office_person#BesslerAnita.admin"); + context("superuser-alex@hostsharing.net", "hs_office_person#BesslerAnita:ADMIN"); givenRelation.setContact(null); return relationRepo.save(givenRelation); }); @@ -279,12 +279,12 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea "Anita", "ninth"); assertThatRelationIsVisibleForUserWithRole( givenRelation, - "hs_office_contact#ninthcontact.admin"); + "hs_office_contact#ninthcontact:ADMIN"); assertThatRelationActuallyInDatabase(givenRelation); // when final var result = jpaAttempt.transacted(() -> { - context("superuser-alex@hostsharing.net", "hs_office_contact#ninthcontact.admin"); + context("superuser-alex@hostsharing.net", "hs_office_contact#ninthcontact:ADMIN"); givenRelation.setContact(null); // TODO return relationRepo.save(givenRelation); }); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateRepositoryIntegrationTest.java index 9ffa28f2..a0555579 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateRepositoryIntegrationTest.java @@ -117,35 +117,35 @@ class HsOfficeSepaMandateRepositoryIntegrationTest extends ContextBasedTestWithC final var all = rawRoleRepo.findAll(); assertThat(distinctRoleNamesOf(all)).containsExactlyInAnyOrder(Array.from( initialRoleNames, - "hs_office_sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).admin", - "hs_office_sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).agent", - "hs_office_sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).owner", - "hs_office_sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).referrer")); + "hs_office_sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01):ADMIN", + "hs_office_sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01):AGENT", + "hs_office_sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01):OWNER", + "hs_office_sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01):REFERRER")); assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll())) .map(s -> s.replace("hs_office_", "")) .containsExactlyInAnyOrder(fromFormatted( initialGrantNames, // owner - "{ grant perm DELETE on sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01) to role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).owner by system and assume }", - "{ grant role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).owner to role global#global.admin by system and assume }", - "{ grant role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).owner to user superuser-alex@hostsharing.net by sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).owner and assume }", + "{ grant perm:sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01):DELETE to role:sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01):OWNER by system and assume }", + "{ grant role:sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01):OWNER to role:global#global:ADMIN by system and assume }", + "{ grant role:sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01):OWNER to user:superuser-alex@hostsharing.net by sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01):OWNER and assume }", // admin - "{ grant perm UPDATE on sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01) to role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).admin by system and assume }", - "{ grant role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).admin to role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).owner by system and assume }", + "{ grant perm:sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01):UPDATE to role:sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01):ADMIN by system and assume }", + "{ grant role:sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01):ADMIN to role:sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01):OWNER by system and assume }", // agent - "{ grant role bankaccount#DE02600501010002034304.referrer to role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).agent by system and assume }", - "{ grant role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).agent to role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).admin by system and assume }", - "{ grant role relation#FirstGmbH-with-DEBITOR-FirstGmbH.agent to role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).agent by system and assume }", + "{ grant role:bankaccount#DE02600501010002034304:REFERRER to role:sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01):AGENT by system and assume }", + "{ grant role:sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01):AGENT to role:sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01):ADMIN by system and assume }", + "{ grant role:relation#FirstGmbH-with-DEBITOR-FirstGmbH:AGENT to role:sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01):AGENT by system and assume }", // referrer - "{ grant perm SELECT on sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01) to role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).referrer by system and assume }", - "{ grant role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).referrer to role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).agent by system and assume }", - "{ grant role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).referrer to role bankaccount#DE02600501010002034304.admin by system and assume }", - "{ grant role relation#FirstGmbH-with-DEBITOR-FirstGmbH.tenant to role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).referrer by system and assume }", - "{ grant role sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01).referrer to role relation#FirstGmbH-with-DEBITOR-FirstGmbH.agent by system and assume }", + "{ grant perm:sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01):SELECT to role:sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01):REFERRER by system and assume }", + "{ grant role:sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01):REFERRER to role:sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01):AGENT by system and assume }", + "{ grant role:sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01):REFERRER to role:bankaccount#DE02600501010002034304:ADMIN by system and assume }", + "{ grant role:relation#FirstGmbH-with-DEBITOR-FirstGmbH:TENANT to role:sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01):REFERRER by system and assume }", + "{ grant role:sepamandate#DE02600501010002034304-[2020-01-01,2023-01-01):REFERRER to role:relation#FirstGmbH-with-DEBITOR-FirstGmbH:AGENT by system and assume }", null)); } @@ -233,7 +233,7 @@ class HsOfficeSepaMandateRepositoryIntegrationTest extends ContextBasedTestWithC final var givenSepaMandate = givenSomeTemporarySepaMandate("DE02600501010002034304"); assertThatSepaMandateIsVisibleForUserWithRole( givenSepaMandate, - "hs_office_bankaccount#DE02600501010002034304.admin"); + "hs_office_bankaccount#DE02600501010002034304:ADMIN"); // when final var result = jpaAttempt.transacted(() -> { @@ -262,13 +262,13 @@ class HsOfficeSepaMandateRepositoryIntegrationTest extends ContextBasedTestWithC final var givenSepaMandate = givenSomeTemporarySepaMandate("DE02300606010002474689"); assertThatSepaMandateIsVisibleForUserWithRole( givenSepaMandate, - "hs_office_bankaccount#DE02300606010002474689.admin"); + "hs_office_bankaccount#DE02300606010002474689:ADMIN"); assertThatSepaMandateActuallyInDatabase(givenSepaMandate); final var newValidityEnd = LocalDate.now(); // when final var result = jpaAttempt.transacted(() -> { - context("superuser-alex@hostsharing.net", "hs_office_bankaccount#DE02300606010002474689.admin"); + context("superuser-alex@hostsharing.net", "hs_office_bankaccount#DE02300606010002474689:ADMIN"); givenSepaMandate.setValidity(Range.closedOpen( givenSepaMandate.getValidity().lower(), newValidityEnd)); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/test/ContextBasedTestWithCleanup.java b/src/test/java/net/hostsharing/hsadminng/hs/office/test/ContextBasedTestWithCleanup.java index 722fd87e..1866f483 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/test/ContextBasedTestWithCleanup.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/test/ContextBasedTestWithCleanup.java @@ -6,7 +6,7 @@ import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantEntity; import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantRepository; import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantsDiagramService; import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject; -import net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleEntity; +import net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleRvEntity; import net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleRepository; import net.hostsharing.test.JpaAttempt; import org.jetbrains.annotations.NotNull; @@ -255,7 +255,7 @@ public abstract class ContextBasedTestWithCleanup extends ContextBasedTest { return jpaAttempt.transacted(() -> { context.define("superuser-alex@hostsharing.net", null); return rbacRoleRepo.findAll().stream() - .map(RbacRoleEntity::getRoleName) + .map(RbacRoleRvEntity::getRoleName) .collect(toSet()); }).assertSuccessful().returnedValue(); } 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 f56baf34..8bcfd28e 100644 --- a/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantControllerAcceptanceTest.java @@ -5,7 +5,7 @@ import io.restassured.http.ContentType; import io.restassured.response.ValidatableResponse; import net.hostsharing.hsadminng.HsadminNgApplication; import net.hostsharing.hsadminng.context.ContextBasedTest; -import net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleEntity; +import net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleRvEntity; import net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleRepository; import net.hostsharing.hsadminng.rbac.rbacuser.RbacUserEntity; import net.hostsharing.hsadminng.rbac.rbacuser.RbacUserRepository; @@ -74,37 +74,37 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest { .body("", hasItem( allOf( // TODO: should there be a grantedByRole or just a grantedByTrigger? - hasEntry("grantedByRoleIdName", "test_customer#xxx.owner"), - hasEntry("grantedRoleIdName", "test_customer#xxx.admin"), + hasEntry("grantedByRoleIdName", "test_customer#xxx:OWNER"), + hasEntry("grantedRoleIdName", "test_customer#xxx:ADMIN"), hasEntry("granteeUserName", "customer-admin@xxx.example.com") ) )) .body("", hasItem( allOf( // TODO: should there be a grantedByRole or just a grantedByTrigger? - hasEntry("grantedByRoleIdName", "test_customer#yyy.owner"), - hasEntry("grantedRoleIdName", "test_customer#yyy.admin"), + hasEntry("grantedByRoleIdName", "test_customer#yyy:OWNER"), + hasEntry("grantedRoleIdName", "test_customer#yyy:ADMIN"), hasEntry("granteeUserName", "customer-admin@yyy.example.com") ) )) .body("", hasItem( allOf( - hasEntry("grantedByRoleIdName", "global#global.admin"), - hasEntry("grantedRoleIdName", "global#global.admin"), + hasEntry("grantedByRoleIdName", "global#global:ADMIN"), + hasEntry("grantedRoleIdName", "global#global:ADMIN"), hasEntry("granteeUserName", "superuser-fran@hostsharing.net") ) )) .body("", hasItem( allOf( - hasEntry("grantedByRoleIdName", "test_customer#xxx.admin"), - hasEntry("grantedRoleIdName", "test_package#xxx00.admin"), + hasEntry("grantedByRoleIdName", "test_customer#xxx:ADMIN"), + hasEntry("grantedRoleIdName", "test_package#xxx00:ADMIN"), hasEntry("granteeUserName", "pac-admin-xxx00@xxx.example.com") ) )) .body("", hasItem( allOf( - hasEntry("grantedByRoleIdName", "test_customer#zzz.admin"), - hasEntry("grantedRoleIdName", "test_package#zzz02.admin"), + hasEntry("grantedByRoleIdName", "test_customer#zzz:ADMIN"), + hasEntry("grantedRoleIdName", "test_package#zzz02:ADMIN"), hasEntry("granteeUserName", "pac-admin-zzz02@zzz.example.com") ) )) @@ -118,7 +118,7 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest { RestAssured // @formatter:off .given() .header("current-user", "superuser-alex@hostsharing.net") - .header("assumed-roles", "test_package#yyy00.admin") + .header("assumed-roles", "test_package#yyy00:ADMIN") .port(port) .when() .get("http://localhost/api/rbac/grants") @@ -127,8 +127,8 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest { .contentType("application/json") .body("", hasItem( allOf( - hasEntry("grantedByRoleIdName", "test_customer#yyy.admin"), - hasEntry("grantedRoleIdName", "test_package#yyy00.admin"), + hasEntry("grantedByRoleIdName", "test_customer#yyy:ADMIN"), + hasEntry("grantedRoleIdName", "test_package#yyy00:ADMIN"), hasEntry("granteeUserName", "pac-admin-yyy00@yyy.example.com") ) )) @@ -150,13 +150,13 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest { .contentType("application/json") .body("", hasItem( allOf( - hasEntry("grantedByRoleIdName", "test_customer#yyy.admin"), - hasEntry("grantedRoleIdName", "test_package#yyy00.admin"), + hasEntry("grantedByRoleIdName", "test_customer#yyy:ADMIN"), + hasEntry("grantedRoleIdName", "test_package#yyy00:ADMIN"), hasEntry("granteeUserName", "pac-admin-yyy00@yyy.example.com") ) )) - .body("[0].grantedByRoleIdName", is("test_customer#yyy.admin")) - .body("[0].grantedRoleIdName", is("test_package#yyy00.admin")) + .body("[0].grantedByRoleIdName", is("test_customer#yyy:ADMIN")) + .body("[0].grantedRoleIdName", is("test_package#yyy00:ADMIN")) .body("[0].granteeUserName", is("pac-admin-yyy00@yyy.example.com")); // @formatter:on } @@ -171,7 +171,7 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest { // given final var givenCurrentUserAsPackageAdmin = new Subject("customer-admin@xxx.example.com"); final var givenGranteeUser = findRbacUserByName("pac-admin-xxx00@xxx.example.com"); - final var givenGrantedRole = findRbacRoleByName("test_package#xxx00.admin"); + final var givenGrantedRole = getRbacRoleByName("test_package#xxx00:ADMIN"); // when final var grant = givenCurrentUserAsPackageAdmin.getGrantById() @@ -180,8 +180,8 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest { // then grant.assertThat() .statusCode(200) - .body("grantedByRoleIdName", is("test_customer#xxx.admin")) - .body("grantedRoleIdName", is("test_package#xxx00.admin")) + .body("grantedByRoleIdName", is("test_customer#xxx:ADMIN")) + .body("grantedRoleIdName", is("test_package#xxx00:ADMIN")) .body("granteeUserName", is("pac-admin-xxx00@xxx.example.com")); } @@ -191,7 +191,7 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest { // given final var givenCurrentUserAsPackageAdmin = new Subject("pac-admin-xxx00@xxx.example.com"); final var givenGranteeUser = findRbacUserByName("pac-admin-xxx00@xxx.example.com"); - final var givenGrantedRole = findRbacRoleByName("test_package#xxx00.admin"); + final var givenGrantedRole = getRbacRoleByName("test_package#xxx00:ADMIN"); // when final var grant = givenCurrentUserAsPackageAdmin.getGrantById() @@ -200,8 +200,8 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest { // then grant.assertThat() .statusCode(200) - .body("grantedByRoleIdName", is("test_customer#xxx.admin")) - .body("grantedRoleIdName", is("test_package#xxx00.admin")) + .body("grantedByRoleIdName", is("test_customer#xxx:ADMIN")) + .body("grantedRoleIdName", is("test_package#xxx00:ADMIN")) .body("granteeUserName", is("pac-admin-xxx00@xxx.example.com")); } @@ -211,9 +211,9 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest { // given final var givenCurrentUserAsPackageAdmin = new Subject( "pac-admin-xxx00@xxx.example.com", - "test_package#xxx00.admin"); + "test_package#xxx00:ADMIN"); final var givenGranteeUser = findRbacUserByName("pac-admin-xxx00@xxx.example.com"); - final var givenGrantedRole = findRbacRoleByName("test_package#xxx00.admin"); + final var givenGrantedRole = getRbacRoleByName("test_package#xxx00:ADMIN"); // when final var grant = givenCurrentUserAsPackageAdmin.getGrantById() @@ -222,8 +222,8 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest { // then grant.assertThat() .statusCode(200) - .body("grantedByRoleIdName", is("test_customer#xxx.admin")) - .body("grantedRoleIdName", is("test_package#xxx00.admin")) + .body("grantedByRoleIdName", is("test_customer#xxx:ADMIN")) + .body("grantedRoleIdName", is("test_package#xxx00:ADMIN")) .body("granteeUserName", is("pac-admin-xxx00@xxx.example.com")); } @@ -234,9 +234,9 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest { // given final var givenCurrentUserAsPackageAdmin = new Subject( "pac-admin-xxx00@xxx.example.com", - "test_package#xxx00.tenant"); + "test_package#xxx00:TENANT"); final var givenGranteeUser = findRbacUserByName("pac-admin-xxx00@xxx.example.com"); - final var givenGrantedRole = findRbacRoleByName("test_package#xxx00.admin"); + final var givenGrantedRole = getRbacRoleByName("test_package#xxx00:ADMIN"); final var grant = givenCurrentUserAsPackageAdmin.getGrantById() .forGrantedRole(givenGrantedRole).toGranteeUser(givenGranteeUser); @@ -255,10 +255,10 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest { // given final var givenNewUser = createRBacUser(); - final var givenRoleToGrant = "test_package#xxx00.admin"; + final var givenRoleToGrant = "test_package#xxx00:ADMIN"; final var givenCurrentUserAsPackageAdmin = new Subject("pac-admin-xxx00@xxx.example.com", givenRoleToGrant); final var givenOwnPackageAdminRole = - findRbacRoleByName(givenCurrentUserAsPackageAdmin.assumedRole); + getRbacRoleByName(givenCurrentUserAsPackageAdmin.assumedRole); // when final var response = givenCurrentUserAsPackageAdmin @@ -268,15 +268,15 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest { // then response.assertThat() .statusCode(201) - .body("grantedByRoleIdName", is("test_package#xxx00.admin")) + .body("grantedByRoleIdName", is("test_package#xxx00:ADMIN")) .body("assumed", is(true)) - .body("grantedRoleIdName", is("test_package#xxx00.admin")) + .body("grantedRoleIdName", is("test_package#xxx00:ADMIN")) .body("granteeUserName", is(givenNewUser.getName())); assertThat(findAllGrantsOf(givenCurrentUserAsPackageAdmin)) .extracting(RbacGrantEntity::toDisplay) - .contains("{ grant role " + givenOwnPackageAdminRole.getRoleName() + - " to user " + givenNewUser.getName() + - " by role " + givenRoleToGrant + " and assume }"); + .contains("{ grant role:" + givenOwnPackageAdminRole.getRoleName() + + " to user:" + givenNewUser.getName() + + " by role:" + givenRoleToGrant + " and assume }"); } @Test @@ -285,9 +285,9 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest { // given final var givenNewUser = createRBacUser(); - final var givenRoleToGrant = "test_package#xxx00.admin"; + final var givenRoleToGrant = "test_package#xxx00:ADMIN"; final var givenCurrentUserAsPackageAdmin = new Subject("pac-admin-xxx00@xxx.example.com", givenRoleToGrant); - final var givenAlienPackageAdminRole = findRbacRoleByName("test_package#yyy00.admin"); + final var givenAlienPackageAdminRole = getRbacRoleByName("test_package#yyy00:ADMIN"); // when final var result = givenCurrentUserAsPackageAdmin @@ -298,7 +298,7 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest { result.assertThat() .statusCode(403) .body("message", containsString("Access to granted role")) - .body("message", containsString("forbidden for test_package#xxx00.admin")); + .body("message", containsString("forbidden for test_package#xxx00:ADMIN")); assertThat(findAllGrantsOf(givenCurrentUserAsPackageAdmin)) .extracting(RbacGrantEntity::getGranteeUserName) .doesNotContain(givenNewUser.getName()); @@ -315,9 +315,9 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest { // given final var givenArbitraryUser = createRBacUser(); - final var givenRoleToGrant = "test_package#xxx00.admin"; + final var givenRoleToGrant = "test_package#xxx00:ADMIN"; final var givenCurrentUserAsPackageAdmin = new Subject("pac-admin-xxx00@xxx.example.com", givenRoleToGrant); - final var givenOwnPackageAdminRole = findRbacRoleByName("test_package#xxx00.admin"); + final var givenOwnPackageAdminRole = getRbacRoleByName("test_package#xxx00:ADMIN"); // and given an existing grant assumeCreated(givenCurrentUserAsPackageAdmin @@ -325,7 +325,7 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest { .toUser(givenArbitraryUser)); assumeGrantExists( givenCurrentUserAsPackageAdmin, - "{ grant role %s to user %s by role %s and assume }".formatted( + "{ grant role:%s to user:%s by role:%s and assume }".formatted( givenOwnPackageAdminRole.getRoleName(), givenArbitraryUser.getName(), givenCurrentUserAsPackageAdmin.assumedRole)); @@ -361,11 +361,11 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest { this(currentUser, ""); } - GrantFixture grantsRole(final RbacRoleEntity givenOwnPackageAdminRole) { + GrantFixture grantsRole(final RbacRoleRvEntity givenOwnPackageAdminRole) { return new GrantFixture(givenOwnPackageAdminRole); } - RevokeFixture revokesRole(final RbacRoleEntity givenOwnPackageAdminRole) { + RevokeFixture revokesRole(final RbacRoleRvEntity givenOwnPackageAdminRole) { return new RevokeFixture(givenOwnPackageAdminRole); } @@ -376,11 +376,11 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest { class GrantFixture { private Subject grantingSubject = Subject.this; - private final RbacRoleEntity grantedRole; + private final RbacRoleRvEntity grantedRole; private boolean assumed; private RbacUserEntity granteeUser; - public GrantFixture(final RbacRoleEntity roleToGrant) { + public GrantFixture(final RbacRoleRvEntity roleToGrant) { this.grantedRole = roleToGrant; } @@ -417,11 +417,11 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest { class RevokeFixture { private Subject currentSubject = Subject.this; - private final RbacRoleEntity grantedRole; + private final RbacRoleRvEntity grantedRole; private boolean assumed; private RbacUserEntity granteeUser; - public RevokeFixture(final RbacRoleEntity roleToGrant) { + public RevokeFixture(final RbacRoleRvEntity roleToGrant) { this.grantedRole = roleToGrant; } @@ -455,9 +455,9 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest { private class GetGrantByIdFixture { private Subject currentSubject = Subject.this; - private RbacRoleEntity grantedRole; + private RbacRoleRvEntity grantedRole; - GetGrantByIdFixture forGrantedRole(final RbacRoleEntity grantedRole) { + GetGrantByIdFixture forGrantedRole(final RbacRoleRvEntity grantedRole) { this.grantedRole = grantedRole; return this; } @@ -504,13 +504,13 @@ class RbacGrantControllerAcceptanceTest extends ContextBasedTest { return jpaAttempt.transacted(() -> { context("superuser-alex@hostsharing.net", null); return rbacUserRepository.findByName(userName); - }).returnedValue(); + }).assertNotNull().returnedValue(); } - RbacRoleEntity findRbacRoleByName(final String roleName) { + RbacRoleRvEntity getRbacRoleByName(final String roleName) { return jpaAttempt.transacted(() -> { context("superuser-alex@hostsharing.net", null); return rbacRoleRepository.findByRoleName(roleName); - }).returnedValue(); + }).assertNotNull().returnedValue(); } } diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantEntityUnitTest.java b/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantEntityUnitTest.java index eea18932..c0bd82cc 100644 --- a/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantEntityUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantEntityUnitTest.java @@ -34,13 +34,13 @@ class RbacGrantEntityUnitTest { "GrantEE", UUID.randomUUID(), true, "ObjectTable", "ObjectId", UUID.randomUUID(), - RbacRoleType.admin); // @formatter:on + RbacRoleType.ADMIN); // @formatter:on // when final var display = entity.toDisplay(); // then - assertThat(display).isEqualTo("{ grant role GrantED to user GrantEE by role GrantER and assume }"); + assertThat(display).isEqualTo("{ grant role:GrantED to user:GrantEE by role:GrantER and assume }"); } @Test @@ -52,12 +52,12 @@ class RbacGrantEntityUnitTest { "GrantEE", UUID.randomUUID(), false, "ObjectTable", "ObjectId", UUID.randomUUID(), - RbacRoleType.owner); // @formatter:on + RbacRoleType.OWNER); // @formatter:on // when final var display = entity.toDisplay(); // then - assertThat(display).isEqualTo("{ grant role GrantED to user GrantEE by role GrantER }"); + assertThat(display).isEqualTo("{ grant role:GrantED to user:GrantEE by role:GrantER }"); } } diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantRepositoryIntegrationTest.java index 8ce615b7..0ee1f297 100644 --- a/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantRepositoryIntegrationTest.java @@ -69,7 +69,7 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest { // then exactlyTheseRbacGrantsAreReturned( result, - "{ grant role test_package#xxx00.admin to user pac-admin-xxx00@xxx.example.com by role test_customer#xxx.admin and assume }"); + "{ grant role:test_package#xxx00:ADMIN to user:pac-admin-xxx00@xxx.example.com by role:test_customer#xxx:ADMIN and assume }"); } @Test @@ -84,17 +84,17 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest { // then exactlyTheseRbacGrantsAreReturned( result, - "{ grant role test_customer#xxx.admin to user customer-admin@xxx.example.com by role test_customer#xxx.owner and assume }", - "{ grant role test_package#xxx00.admin to user pac-admin-xxx00@xxx.example.com by role test_customer#xxx.admin and assume }", - "{ grant role test_package#xxx01.admin to user pac-admin-xxx01@xxx.example.com by role test_customer#xxx.admin and assume }", - "{ grant role test_package#xxx02.admin to user pac-admin-xxx02@xxx.example.com by role test_customer#xxx.admin and assume }"); + "{ grant role:test_customer#xxx:ADMIN to user:customer-admin@xxx.example.com by role:test_customer#xxx:OWNER and assume }", + "{ grant role:test_package#xxx00:ADMIN to user:pac-admin-xxx00@xxx.example.com by role:test_customer#xxx:ADMIN and assume }", + "{ grant role:test_package#xxx01:ADMIN to user:pac-admin-xxx01@xxx.example.com by role:test_customer#xxx:ADMIN and assume }", + "{ grant role:test_package#xxx02:ADMIN to user:pac-admin-xxx02@xxx.example.com by role:test_customer#xxx:ADMIN and assume }"); } @Test @Accepts({ "GRT:L(List)" }) public void customerAdmin_withAssumedRole_canOnlyViewRbacGrantsVisibleByAssumedRole() { // given: - context("customer-admin@xxx.example.com", "test_package#xxx00.admin"); + context("customer-admin@xxx.example.com", "test_package#xxx00:ADMIN"); // when final var result = rbacGrantRepository.findAll(); @@ -102,7 +102,7 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest { // then exactlyTheseRbacGrantsAreReturned( result, - "{ grant role test_package#xxx00.admin to user pac-admin-xxx00@xxx.example.com by role test_customer#xxx.admin and assume }"); + "{ grant role:test_package#xxx00:ADMIN to user:pac-admin-xxx00@xxx.example.com by role:test_customer#xxx:ADMIN and assume }"); } } @@ -112,9 +112,9 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest { @Test public void customerAdmin_canGrantOwnPackageAdminRole_toArbitraryUser() { // given - context("customer-admin@xxx.example.com", "test_customer#xxx.admin"); + context("customer-admin@xxx.example.com", "test_customer#xxx:ADMIN"); final var givenArbitraryUserUuid = rbacUserRepository.findByName("pac-admin-zzz00@zzz.example.com").getUuid(); - final var givenOwnPackageRoleUuid = rbacRoleRepository.findByRoleName("test_package#xxx00.admin").getUuid(); + final var givenOwnPackageRoleUuid = rbacRoleRepository.findByRoleName("test_package#xxx00:ADMIN").getUuid(); // when final var grant = RbacGrantEntity.builder() @@ -130,7 +130,7 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest { assertThat(rbacGrantRepository.findAll()) .extracting(RbacGrantEntity::toDisplay) .contains( - "{ grant role test_package#xxx00.admin to user pac-admin-zzz00@zzz.example.com by role test_customer#xxx.admin and assume }"); + "{ grant role:test_package#xxx00:ADMIN to user:pac-admin-zzz00@zzz.example.com by role:test_customer#xxx:ADMIN and assume }"); } @Test @@ -143,14 +143,14 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest { context("customer-admin@xxx.example.com", null); return new Given( createNewUser(), - rbacRoleRepository.findByRoleName("test_package#xxx00.owner").getUuid() + rbacRoleRepository.findByRoleName("test_package#xxx00:OWNER").getUuid() ); }).assumeSuccessful().returnedValue(); // when final var attempt = jpaAttempt.transacted(() -> { // now we try to use these uuids as a less privileged user - context("pac-admin-xxx00@xxx.example.com", "test_package#xxx00.admin"); + context("pac-admin-xxx00@xxx.example.com", "test_package#xxx00:ADMIN"); final var grant = RbacGrantEntity.builder() .granteeUserUuid(given.arbitraryUser.getUuid()) .grantedRoleUuid(given.packageOwnerRoleUuid) @@ -162,8 +162,8 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest { // then attempt.assertExceptionWithRootCauseMessage( JpaSystemException.class, - "ERROR: [403] Access to granted role test_package#xxx00.owner", - "forbidden for test_package#xxx00.admin"); + "ERROR: [403] Access to granted role test_package#xxx00:OWNER", + "forbidden for test_package#xxx00:ADMIN"); jpaAttempt.transacted(() -> { // finally, we use the new user to make sure, no roles were granted context(given.arbitraryUser.getName(), null); @@ -180,16 +180,16 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest { public void customerAdmin_canRevokeSelfGrantedPackageAdminRole() { // given final var grant = create(grant() - .byUser("customer-admin@xxx.example.com").withAssumedRole("test_customer#xxx.admin") - .grantingRole("test_package#xxx00.admin").toUser("pac-admin-zzz00@zzz.example.com")); + .byUser("customer-admin@xxx.example.com").withAssumedRole("test_customer#xxx:ADMIN") + .grantingRole("test_package#xxx00:ADMIN").toUser("pac-admin-zzz00@zzz.example.com")); // when - context("customer-admin@xxx.example.com", "test_customer#xxx.admin"); + context("customer-admin@xxx.example.com", "test_customer#xxx:ADMIN"); final var revokeAttempt = attempt(em, () -> rbacGrantRepository.deleteByRbacGrantId(grant.getRbacGrantId())); // then - context("customer-admin@xxx.example.com", "test_customer#xxx.admin"); + context("customer-admin@xxx.example.com", "test_customer#xxx:ADMIN"); assertThat(revokeAttempt.caughtExceptionsRootCause()).isNull(); assertThat(rbacGrantRepository.findAll()) .extracting(RbacGrantEntity::getGranteeUserName) @@ -201,17 +201,17 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest { // given final var newUser = createNewUserTransacted(); final var grant = create(grant() - .byUser("customer-admin@xxx.example.com").withAssumedRole("test_package#xxx00.admin") - .grantingRole("test_package#xxx00.admin").toUser(newUser.getName())); + .byUser("customer-admin@xxx.example.com").withAssumedRole("test_package#xxx00:ADMIN") + .grantingRole("test_package#xxx00:ADMIN").toUser(newUser.getName())); // when - context("pac-admin-xxx00@xxx.example.com", "test_package#xxx00.admin"); + context("pac-admin-xxx00@xxx.example.com", "test_package#xxx00:ADMIN"); final var revokeAttempt = attempt(em, () -> rbacGrantRepository.deleteByRbacGrantId(grant.getRbacGrantId())); // then assertThat(revokeAttempt.caughtExceptionsRootCause()).isNull(); - context("customer-admin@xxx.example.com", "test_customer#xxx.admin"); + context("customer-admin@xxx.example.com", "test_customer#xxx:ADMIN"); assertThat(rbacGrantRepository.findAll()) .extracting(RbacGrantEntity::getGranteeUserName) .doesNotContain("pac-admin-zzz00@zzz.example.com"); @@ -221,19 +221,19 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest { public void packageAdmin_canNotRevokeOwnPackageAdminRoleGrantedByOwnerRoleOfThatPackage() { // given final var grant = create(grant() - .byUser("customer-admin@xxx.example.com").withAssumedRole("test_package#xxx00.owner") - .grantingRole("test_package#xxx00.admin").toUser("pac-admin-zzz00@zzz.example.com")); - final var grantedByRole = rbacRoleRepository.findByRoleName("test_package#xxx00.owner"); + .byUser("customer-admin@xxx.example.com").withAssumedRole("test_package#xxx00:OWNER") + .grantingRole("test_package#xxx00:ADMIN").toUser("pac-admin-zzz00@zzz.example.com")); + final var grantedByRole = rbacRoleRepository.findByRoleName("test_package#xxx00:OWNER"); // when - context("pac-admin-xxx00@xxx.example.com", "test_package#xxx00.admin"); + context("pac-admin-xxx00@xxx.example.com", "test_package#xxx00:ADMIN"); final var revokeAttempt = attempt(em, () -> rbacGrantRepository.deleteByRbacGrantId(grant.getRbacGrantId())); // then revokeAttempt.assertExceptionWithRootCauseMessage( JpaSystemException.class, - "ERROR: [403] Revoking role created by %s is forbidden for {test_package#xxx00.admin}.".formatted( + "ERROR: [403] Revoking role created by %s is forbidden for {test_package#xxx00:ADMIN}.".formatted( grantedByRole.getUuid() )); } @@ -254,7 +254,7 @@ class RbacGrantRepositoryIntegrationTest extends ContextBasedTest { assertThat(grantAttempt.caughtException()).isNull(); assertThat(rawRbacGrantRepository.findAll()) .extracting(RawRbacGrantEntity::toDisplay) - .contains("{ grant role %s to user %s by %s and assume }".formatted( + .contains("{ grant role:%s to user:%s by %s and assume }".formatted( with.grantedRole, with.granteeUserName, with.assumedRole )); diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantsDiagramServiceIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantsDiagramServiceIntegrationTest.java index 0e0421c8..5d228314 100644 --- a/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantsDiagramServiceIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantsDiagramServiceIntegrationTest.java @@ -54,43 +54,43 @@ class RbacGrantsDiagramServiceIntegrationTest extends ContextBasedTestWithCleanu @Test void allGrantsToCurrentUser() { - context("superuser-alex@hostsharing.net", "test_domain#xxx00-aaaa.owner"); + context("superuser-alex@hostsharing.net", "test_domain#xxx00-aaaa:OWNER"); final var graph = grantsMermaidService.allGrantsToCurrentUser(EnumSet.of(Include.TEST_ENTITIES)); assertThat(graph).isEqualTo(""" flowchart TB - role:test_domain#xxx00-aaaa.admin --> role:test_package#xxx00.tenant - role:test_domain#xxx00-aaaa.owner --> role:test_domain#xxx00-aaaa.admin - role:test_domain#xxx00-aaaa.owner --> role:test_package#xxx00.tenant - role:test_package#xxx00.tenant --> role:test_customer#xxx.tenant + role:test_domain#xxx00-aaaa:ADMIN --> role:test_package#xxx00:TENANT + role:test_domain#xxx00-aaaa:OWNER --> role:test_domain#xxx00-aaaa:ADMIN + role:test_domain#xxx00-aaaa:OWNER --> role:test_package#xxx00:TENANT + role:test_package#xxx00:TENANT --> role:test_customer#xxx:TENANT """.trim()); } @Test void allGrantsToCurrentUserIncludingPermissions() { - context("superuser-alex@hostsharing.net", "test_domain#xxx00-aaaa.owner"); + context("superuser-alex@hostsharing.net", "test_domain#xxx00-aaaa:OWNER"); final var graph = grantsMermaidService.allGrantsToCurrentUser(EnumSet.of(Include.TEST_ENTITIES, Include.PERMISSIONS)); assertThat(graph).isEqualTo(""" flowchart TB - role:test_customer#xxx.tenant --> perm:SELECT:on:test_customer#xxx - role:test_domain#xxx00-aaaa.admin --> perm:SELECT:on:test_domain#xxx00-aaaa - role:test_domain#xxx00-aaaa.admin --> role:test_package#xxx00.tenant - role:test_domain#xxx00-aaaa.owner --> perm:DELETE:on:test_domain#xxx00-aaaa - role:test_domain#xxx00-aaaa.owner --> perm:UPDATE:on:test_domain#xxx00-aaaa - role:test_domain#xxx00-aaaa.owner --> role:test_domain#xxx00-aaaa.admin - role:test_domain#xxx00-aaaa.owner --> role:test_package#xxx00.tenant - role:test_package#xxx00.tenant --> perm:SELECT:on:test_package#xxx00 - role:test_package#xxx00.tenant --> role:test_customer#xxx.tenant + role:test_customer#xxx:TENANT --> perm:test_customer#xxx:SELECT + role:test_domain#xxx00-aaaa:ADMIN --> perm:test_domain#xxx00-aaaa:SELECT + role:test_domain#xxx00-aaaa:ADMIN --> role:test_package#xxx00:TENANT + role:test_domain#xxx00-aaaa:OWNER --> perm:test_domain#xxx00-aaaa:DELETE + role:test_domain#xxx00-aaaa:OWNER --> perm:test_domain#xxx00-aaaa:UPDATE + role:test_domain#xxx00-aaaa:OWNER --> role:test_domain#xxx00-aaaa:ADMIN + role:test_domain#xxx00-aaaa:OWNER --> role:test_package#xxx00:TENANT + role:test_package#xxx00:TENANT --> perm:test_package#xxx00:SELECT + role:test_package#xxx00:TENANT --> role:test_customer#xxx:TENANT """.trim()); } @Test @Disabled // enable to generate from a real database void print() throws IOException { - //context("superuser-alex@hostsharing.net", "hs_office_person#FirbySusan.admin"); + //context("superuser-alex@hostsharing.net", "hs_office_person#FirbySusan:ADMIN"); context("superuser-alex@hostsharing.net"); //final var graph = grantsMermaidService.allGrantsToCurrentUser(EnumSet.of(Include.NON_TEST_ENTITIES, Include.PERMISSIONS)); 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 2f4d15f5..e80f8ce6 100644 --- a/src/test/java/net/hostsharing/hsadminng/rbac/rbacrole/RawRbacRoleEntity.java +++ b/src/test/java/net/hostsharing/hsadminng/rbac/rbacrole/RawRbacRoleEntity.java @@ -35,7 +35,7 @@ public class RawRbacRoleEntity { @Enumerated(EnumType.STRING) private RbacRoleType roleType; - @Formula("objectTable||'#'||objectIdName||'.'||roleType") + @Formula("objectTable||'#'||objectIdName||':'||roleType") private String roleName; @NotNull diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleControllerAcceptanceTest.java index 5de93348..d318cc04 100644 --- a/src/test/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleControllerAcceptanceTest.java @@ -45,14 +45,14 @@ class RbacRoleControllerAcceptanceTest { .then().assertThat() .statusCode(200) .contentType("application/json") - .body("", hasItem(hasEntry("roleName", "test_customer#xxx.admin"))) - .body("", hasItem(hasEntry("roleName", "test_customer#xxx.owner"))) - .body("", hasItem(hasEntry("roleName", "test_customer#xxx.tenant"))) + .body("", hasItem(hasEntry("roleName", "test_customer#xxx:ADMIN"))) + .body("", hasItem(hasEntry("roleName", "test_customer#xxx:OWNER"))) + .body("", hasItem(hasEntry("roleName", "test_customer#xxx:TENANT"))) // ... - .body("", hasItem(hasEntry("roleName", "global#global.admin"))) - .body("", hasItem(hasEntry("roleName", "test_customer#yyy.admin"))) - .body("", hasItem(hasEntry("roleName", "test_package#yyy00.admin"))) - .body("", hasItem(hasEntry("roleName", "test_domain#yyy00-aaaa.owner"))) + .body("", hasItem(hasEntry("roleName", "global#global:ADMIN"))) + .body("", hasItem(hasEntry("roleName", "test_customer#yyy:ADMIN"))) + .body("", hasItem(hasEntry("roleName", "test_package#yyy00:ADMIN"))) + .body("", hasItem(hasEntry("roleName", "test_domain#yyy00-aaaa:OWNER"))) .body( "size()", greaterThanOrEqualTo(73)); // increases with new test data // @formatter:on } @@ -65,7 +65,7 @@ class RbacRoleControllerAcceptanceTest { RestAssured .given() .header("current-user", "superuser-alex@hostsharing.net") - .header("assumed-roles", "test_package#yyy00.admin") + .header("assumed-roles", "test_package#yyy00:ADMIN") .port(port) .when() .get("http://localhost/api/rbac/roles") @@ -75,18 +75,18 @@ class RbacRoleControllerAcceptanceTest { .statusCode(200) .contentType("application/json") - .body("", hasItem(hasEntry("roleName", "test_customer#yyy.tenant"))) - .body("", hasItem(hasEntry("roleName", "test_domain#yyy00-aaaa.owner"))) - .body("", hasItem(hasEntry("roleName", "test_domain#yyy00-aaaa.admin"))) - .body("", hasItem(hasEntry("roleName", "test_domain#yyy00-aaab.owner"))) - .body("", hasItem(hasEntry("roleName", "test_domain#yyy00-aaab.admin"))) - .body("", hasItem(hasEntry("roleName", "test_package#yyy00.admin"))) - .body("", hasItem(hasEntry("roleName", "test_package#yyy00.tenant"))) + .body("", hasItem(hasEntry("roleName", "test_customer#yyy:TENANT"))) + .body("", hasItem(hasEntry("roleName", "test_domain#yyy00-aaaa:OWNER"))) + .body("", hasItem(hasEntry("roleName", "test_domain#yyy00-aaaa:ADMIN"))) + .body("", hasItem(hasEntry("roleName", "test_domain#yyy00-aaab:OWNER"))) + .body("", hasItem(hasEntry("roleName", "test_domain#yyy00-aaab:ADMIN"))) + .body("", hasItem(hasEntry("roleName", "test_package#yyy00:ADMIN"))) + .body("", hasItem(hasEntry("roleName", "test_package#yyy00:TENANT"))) - .body("", not(hasItem(hasEntry("roleName", "test_customer#xxx.tenant")))) - .body("", not(hasItem(hasEntry("roleName", "test_domain#xxx00-aaaa.admin")))) - .body("", not(hasItem(hasEntry("roleName", "test_package#xxx00.admin")))) - .body("", not(hasItem(hasEntry("roleName", "test_package#xxx00.tenant")))) + .body("", not(hasItem(hasEntry("roleName", "test_customer#xxx:TENANT")))) + .body("", not(hasItem(hasEntry("roleName", "test_domain#xxx00-aaaa:ADMIN")))) + .body("", not(hasItem(hasEntry("roleName", "test_package#xxx00:ADMIN")))) + .body("", not(hasItem(hasEntry("roleName", "test_package#xxx00:TENANT")))) ; // @formatter:on } @@ -106,15 +106,15 @@ class RbacRoleControllerAcceptanceTest { .statusCode(200) .contentType("application/json") - .body("", hasItem(hasEntry("roleName", "test_customer#zzz.tenant"))) - .body("", hasItem(hasEntry("roleName", "test_domain#zzz00-aaaa.admin"))) - .body("", hasItem(hasEntry("roleName", "test_package#zzz00.admin"))) - .body("", hasItem(hasEntry("roleName", "test_package#zzz00.tenant"))) + .body("", hasItem(hasEntry("roleName", "test_customer#zzz:TENANT"))) + .body("", hasItem(hasEntry("roleName", "test_domain#zzz00-aaaa:ADMIN"))) + .body("", hasItem(hasEntry("roleName", "test_package#zzz00:ADMIN"))) + .body("", hasItem(hasEntry("roleName", "test_package#zzz00:TENANT"))) - .body("", not(hasItem(hasEntry("roleName", "test_customer#yyy.tenant")))) - .body("", not(hasItem(hasEntry("roleName", "test_domain#yyy00-aaaa.admin")))) - .body("", not(hasItem(hasEntry("roleName", "test_package#yyy00.admin")))) - .body("", not(hasItem(hasEntry("roleName", "test_package#yyy00.tenant")))); + .body("", not(hasItem(hasEntry("roleName", "test_customer#yyy:TENANT")))) + .body("", not(hasItem(hasEntry("roleName", "test_domain#yyy00-aaaa:ADMIN")))) + .body("", not(hasItem(hasEntry("roleName", "test_package#yyy00:ADMIN")))) + .body("", not(hasItem(hasEntry("roleName", "test_package#yyy00:TENANT")))); // @formatter:on } } diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleControllerRestTest.java b/src/test/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleControllerRestTest.java index c10a9cbc..44b3885e 100644 --- a/src/test/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleControllerRestTest.java +++ b/src/test/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleControllerRestTest.java @@ -73,9 +73,9 @@ class RbacRoleControllerRestTest { // then .andExpect(status().isOk()) .andExpect(jsonPath("$", hasSize(3))) - .andExpect(jsonPath("$[0].roleName", is("global#global.admin"))) - .andExpect(jsonPath("$[1].roleName", is("test_customer#xxx.owner"))) - .andExpect(jsonPath("$[2].roleName", is("test_customer#xxx.admin"))) + .andExpect(jsonPath("$[0].roleName", is("global#global:ADMIN"))) + .andExpect(jsonPath("$[1].roleName", is("test_customer#xxx:OWNER"))) + .andExpect(jsonPath("$[2].roleName", is("test_customer#xxx:ADMIN"))) .andExpect(jsonPath("$[2].uuid", is(customerXxxAdmin.getUuid().toString()))) .andExpect(jsonPath("$[2].objectUuid", is(customerXxxAdmin.getObjectUuid().toString()))) .andExpect(jsonPath("$[2].objectTable", is(customerXxxAdmin.getObjectTable().toString()))) diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleRepositoryIntegrationTest.java index 197e0bc0..d94382d7 100644 --- a/src/test/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleRepositoryIntegrationTest.java @@ -39,19 +39,19 @@ class RbacRoleRepositoryIntegrationTest { private static final String[] ALL_TEST_DATA_ROLES = Array.of( // @formatter:off - "global#global.admin", - "test_customer#xxx.admin", "test_customer#xxx.owner", "test_customer#xxx.tenant", - "test_package#xxx00.admin", "test_package#xxx00.owner", "test_package#xxx00.tenant", - "test_package#xxx01.admin", "test_package#xxx01.owner", "test_package#xxx01.tenant", - "test_package#xxx02.admin", "test_package#xxx02.owner", "test_package#xxx02.tenant", - "test_customer#yyy.admin", "test_customer#yyy.owner", "test_customer#yyy.tenant", - "test_package#yyy00.admin", "test_package#yyy00.owner", "test_package#yyy00.tenant", - "test_package#yyy01.admin", "test_package#yyy01.owner", "test_package#yyy01.tenant", - "test_package#yyy02.admin", "test_package#yyy02.owner", "test_package#yyy02.tenant", - "test_customer#zzz.admin", "test_customer#zzz.owner", "test_customer#zzz.tenant", - "test_package#zzz00.admin", "test_package#zzz00.owner", "test_package#zzz00.tenant", - "test_package#zzz01.admin", "test_package#zzz01.owner", "test_package#zzz01.tenant", - "test_package#zzz02.admin", "test_package#zzz02.owner", "test_package#zzz02.tenant" + "global#global:ADMIN", + "test_customer#xxx:ADMIN", "test_customer#xxx:OWNER", "test_customer#xxx:TENANT", + "test_package#xxx00:ADMIN", "test_package#xxx00:OWNER", "test_package#xxx00:TENANT", + "test_package#xxx01:ADMIN", "test_package#xxx01:OWNER", "test_package#xxx01:TENANT", + "test_package#xxx02:ADMIN", "test_package#xxx02:OWNER", "test_package#xxx02:TENANT", + "test_customer#yyy:ADMIN", "test_customer#yyy:OWNER", "test_customer#yyy:TENANT", + "test_package#yyy00:ADMIN", "test_package#yyy00:OWNER", "test_package#yyy00:TENANT", + "test_package#yyy01:ADMIN", "test_package#yyy01:OWNER", "test_package#yyy01:TENANT", + "test_package#yyy02:ADMIN", "test_package#yyy02:OWNER", "test_package#yyy02:TENANT", + "test_customer#zzz:ADMIN", "test_customer#zzz:OWNER", "test_customer#zzz:TENANT", + "test_package#zzz00:ADMIN", "test_package#zzz00:OWNER", "test_package#zzz00:TENANT", + "test_package#zzz01:ADMIN", "test_package#zzz01:OWNER", "test_package#zzz01:TENANT", + "test_package#zzz02:ADMIN", "test_package#zzz02:OWNER", "test_package#zzz02:TENANT" // @formatter:on ); @@ -70,7 +70,7 @@ class RbacRoleRepositoryIntegrationTest { @Test public void globalAdmin_withAssumedglobalAdminRole_canViewAllRbacRoles() { given: - context.define("superuser-alex@hostsharing.net", "global#global.admin"); + context.define("superuser-alex@hostsharing.net", "global#global:ADMIN"); // when final var result = rbacRoleRepository.findAll(); @@ -91,49 +91,49 @@ class RbacRoleRepositoryIntegrationTest { allTheseRbacRolesAreReturned( result, // @formatter:off - "test_customer#xxx.admin", - "test_customer#xxx.tenant", - "test_package#xxx00.admin", - "test_package#xxx00.owner", - "test_package#xxx00.tenant", - "test_package#xxx01.admin", - "test_package#xxx01.owner", - "test_package#xxx01.tenant", + "test_customer#xxx:ADMIN", + "test_customer#xxx:TENANT", + "test_package#xxx00:ADMIN", + "test_package#xxx00:OWNER", + "test_package#xxx00:TENANT", + "test_package#xxx01:ADMIN", + "test_package#xxx01:OWNER", + "test_package#xxx01:TENANT", // ... - "test_domain#xxx00-aaaa.admin", - "test_domain#xxx00-aaaa.owner", + "test_domain#xxx00-aaaa:ADMIN", + "test_domain#xxx00-aaaa:OWNER", // .. - "test_domain#xxx01-aaab.admin", - "test_domain#xxx01-aaab.owner" + "test_domain#xxx01-aaab:ADMIN", + "test_domain#xxx01-aaab:OWNER" // @formatter:on ); noneOfTheseRbacRolesIsReturned( result, // @formatter:off - "global#global.admin", - "test_customer#xxx.owner", - "test_package#yyy00.admin", - "test_package#yyy00.owner", - "test_package#yyy00.tenant" + "global#global:ADMIN", + "test_customer#xxx:OWNER", + "test_package#yyy00:ADMIN", + "test_package#yyy00:OWNER", + "test_package#yyy00:TENANT" // @formatter:on ); } @Test public void customerAdmin_withAssumedOwnedPackageAdminRole_canViewOnlyItsOwnRbacRole() { - context.define("customer-admin@xxx.example.com", "test_package#xxx00.admin"); + context.define("customer-admin@xxx.example.com", "test_package#xxx00:ADMIN"); final var result = rbacRoleRepository.findAll(); exactlyTheseRbacRolesAreReturned( result, - "test_customer#xxx.tenant", - "test_package#xxx00.admin", - "test_package#xxx00.tenant", - "test_domain#xxx00-aaaa.admin", - "test_domain#xxx00-aaaa.owner", - "test_domain#xxx00-aaab.admin", - "test_domain#xxx00-aaab.owner"); + "test_customer#xxx:TENANT", + "test_package#xxx00:ADMIN", + "test_package#xxx00:TENANT", + "test_domain#xxx00-aaaa:ADMIN", + "test_domain#xxx00-aaaa:OWNER", + "test_domain#xxx00-aaab:ADMIN", + "test_domain#xxx00-aaab:OWNER"); } @Test @@ -157,39 +157,39 @@ class RbacRoleRepositoryIntegrationTest { void customerAdmin_withoutAssumedRole_canFindItsOwnRolesByName() { context.define("customer-admin@xxx.example.com"); - final var result = rbacRoleRepository.findByRoleName("test_customer#xxx.admin"); + final var result = rbacRoleRepository.findByRoleName("test_customer#xxx:ADMIN"); assertThat(result).isNotNull(); assertThat(result.getObjectTable()).isEqualTo("test_customer"); assertThat(result.getObjectIdName()).isEqualTo("xxx"); - assertThat(result.getRoleType()).isEqualTo(RbacRoleType.admin); + assertThat(result.getRoleType()).isEqualTo(RbacRoleType.ADMIN); } @Test void customerAdmin_withoutAssumedRole_canNotFindAlienRolesByName() { context.define("customer-admin@xxx.example.com"); - final var result = rbacRoleRepository.findByRoleName("test_customer#bbb.admin"); + final var result = rbacRoleRepository.findByRoleName("test_customer#bbb:ADMIN"); assertThat(result).isNull(); } } - void exactlyTheseRbacRolesAreReturned(final List actualResult, final String... expectedRoleNames) { + void exactlyTheseRbacRolesAreReturned(final List actualResult, final String... expectedRoleNames) { assertThat(actualResult) - .extracting(RbacRoleEntity::getRoleName) + .extracting(RbacRoleRvEntity::getRoleName) .containsExactlyInAnyOrder(expectedRoleNames); } - void allTheseRbacRolesAreReturned(final List actualResult, final String... expectedRoleNames) { + void allTheseRbacRolesAreReturned(final List actualResult, final String... expectedRoleNames) { assertThat(actualResult) - .extracting(RbacRoleEntity::getRoleName) + .extracting(RbacRoleRvEntity::getRoleName) .contains(expectedRoleNames); } - void noneOfTheseRbacRolesIsReturned(final List actualResult, final String... unexpectedRoleNames) { + void noneOfTheseRbacRolesIsReturned(final List actualResult, final String... unexpectedRoleNames) { assertThat(actualResult) - .extracting(RbacRoleEntity::getRoleName) + .extracting(RbacRoleRvEntity::getRoleName) .doesNotContain(unexpectedRoleNames); } 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 652679f3..9eb0f3c7 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 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); + 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); - static public RbacRoleEntity rbacRole(final String objectTable, final String objectIdName, final RbacRoleType roleType) { - return new RbacRoleEntity(randomUUID(), randomUUID(), objectTable, objectIdName, roleType, objectTable+'#'+objectIdName+'.'+roleType); + static public RbacRoleRvEntity rbacRole(final String objectTable, final String objectIdName, final RbacRoleType roleType) { + return new RbacRoleRvEntity(randomUUID(), randomUUID(), objectTable, objectIdName, roleType, objectTable+'#'+objectIdName+':'+roleType); } } diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/rbacuser/RbacUserControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/rbac/rbacuser/RbacUserControllerAcceptanceTest.java index 9d7e16ca..6faa28ff 100644 --- a/src/test/java/net/hostsharing/hsadminng/rbac/rbacuser/RbacUserControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/rbac/rbacuser/RbacUserControllerAcceptanceTest.java @@ -104,7 +104,7 @@ class RbacUserControllerAcceptanceTest { RestAssured .given() .header("current-user", "superuser-alex@hostsharing.net") - .header("assumed-roles", "test_customer#yyy.admin") + .header("assumed-roles", "test_customer#yyy:ADMIN") .port(port) .when() .get("http://localhost/api/rbac/users/" + givenUser.getUuid()) @@ -210,7 +210,7 @@ class RbacUserControllerAcceptanceTest { RestAssured .given() .header("current-user", "superuser-alex@hostsharing.net") - .header("assumed-roles", "test_customer#yyy.admin") + .header("assumed-roles", "test_customer#yyy:ADMIN") .port(port) .when() .get("http://localhost/api/rbac/users") @@ -287,12 +287,12 @@ class RbacUserControllerAcceptanceTest { .contentType("application/json") .body("", hasItem( allOf( - hasEntry("roleName", "test_customer#yyy.tenant"), + hasEntry("roleName", "test_customer#yyy:TENANT"), hasEntry("op", "SELECT")) )) .body("", hasItem( allOf( - hasEntry("roleName", "test_domain#yyy00-aaaa.owner"), + hasEntry("roleName", "test_domain#yyy00-aaaa:OWNER"), hasEntry("op", "DELETE")) )) // actual content tested in integration test, so this is enough for here: @@ -309,7 +309,7 @@ class RbacUserControllerAcceptanceTest { RestAssured .given() .header("current-user", "superuser-alex@hostsharing.net") - .header("assumed-roles", "test_customer#yyy.admin") + .header("assumed-roles", "test_customer#yyy:ADMIN") .port(port) .when() .get("http://localhost/api/rbac/users/" + givenUser.getUuid() + "/permissions") @@ -318,12 +318,12 @@ class RbacUserControllerAcceptanceTest { .contentType("application/json") .body("", hasItem( allOf( - hasEntry("roleName", "test_customer#yyy.tenant"), + hasEntry("roleName", "test_customer#yyy:TENANT"), hasEntry("op", "SELECT")) )) .body("", hasItem( allOf( - hasEntry("roleName", "test_domain#yyy00-aaaa.owner"), + hasEntry("roleName", "test_domain#yyy00-aaaa:OWNER"), hasEntry("op", "DELETE")) )) // actual content tested in integration test, so this is enough for here: @@ -348,12 +348,12 @@ class RbacUserControllerAcceptanceTest { .contentType("application/json") .body("", hasItem( allOf( - hasEntry("roleName", "test_customer#yyy.tenant"), + hasEntry("roleName", "test_customer#yyy:TENANT"), hasEntry("op", "SELECT")) )) .body("", hasItem( allOf( - hasEntry("roleName", "test_domain#yyy00-aaaa.owner"), + hasEntry("roleName", "test_domain#yyy00-aaaa:OWNER"), hasEntry("op", "DELETE")) )) // actual content tested in integration test, so this is enough for here: diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/rbacuser/RbacUserRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/rbac/rbacuser/RbacUserRepositoryIntegrationTest.java index c63047ed..43c8bff1 100644 --- a/src/test/java/net/hostsharing/hsadminng/rbac/rbacuser/RbacUserRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/rbac/rbacuser/RbacUserRepositoryIntegrationTest.java @@ -116,7 +116,7 @@ class RbacUserRepositoryIntegrationTest extends ContextBasedTest { @Test public void globalAdmin_withAssumedglobalAdminRole_canViewAllRbacUsers() { given: - context("superuser-alex@hostsharing.net", "global#global.admin"); + context("superuser-alex@hostsharing.net", "global#global:ADMIN"); // when final var result = rbacUserRepository.findByOptionalNameLike(null); @@ -128,7 +128,7 @@ class RbacUserRepositoryIntegrationTest extends ContextBasedTest { @Test public void globalAdmin_withAssumedCustomerAdminRole_canViewOnlyUsersHavingRolesInThatCustomersRealm() { given: - context("superuser-alex@hostsharing.net", "test_customer#xxx.admin"); + context("superuser-alex@hostsharing.net", "test_customer#xxx:ADMIN"); // when final var result = rbacUserRepository.findByOptionalNameLike(null); @@ -159,7 +159,7 @@ class RbacUserRepositoryIntegrationTest extends ContextBasedTest { @Test public void customerAdmin_withAssumedOwnedPackageAdminRole_canViewOnlyUsersHavingRolesInThatPackage() { - context("customer-admin@xxx.example.com", "test_package#xxx00.admin"); + context("customer-admin@xxx.example.com", "test_package#xxx00:ADMIN"); final var result = rbacUserRepository.findByOptionalNameLike(null); @@ -182,47 +182,47 @@ class RbacUserRepositoryIntegrationTest extends ContextBasedTest { private static final String[] ALL_USER_PERMISSIONS = Array.of( // @formatter:off - "test_customer#xxx.admin -> test_customer#xxx: SELECT", - "test_customer#xxx.owner -> test_customer#xxx: DELETE", - "test_customer#xxx.tenant -> test_customer#xxx: SELECT", - "test_customer#xxx.admin -> test_customer#xxx: INSERT:test_package", - "test_package#xxx00.admin -> test_package#xxx00: INSERT:test_domain", - "test_package#xxx00.admin -> test_package#xxx00: INSERT:test_domain", - "test_package#xxx00.tenant -> test_package#xxx00: SELECT", - "test_package#xxx01.admin -> test_package#xxx01: INSERT:test_domain", - "test_package#xxx01.admin -> test_package#xxx01: INSERT:test_domain", - "test_package#xxx01.tenant -> test_package#xxx01: SELECT", - "test_package#xxx02.admin -> test_package#xxx02: INSERT:test_domain", - "test_package#xxx02.admin -> test_package#xxx02: INSERT:test_domain", - "test_package#xxx02.tenant -> test_package#xxx02: SELECT", + "test_customer#xxx:ADMIN -> test_customer#xxx: SELECT", + "test_customer#xxx:OWNER -> test_customer#xxx: DELETE", + "test_customer#xxx:TENANT -> test_customer#xxx: SELECT", + "test_customer#xxx:ADMIN -> test_customer#xxx: INSERT:test_package", + "test_package#xxx00:ADMIN -> test_package#xxx00: INSERT:test_domain", + "test_package#xxx00:ADMIN -> test_package#xxx00: INSERT:test_domain", + "test_package#xxx00:TENANT -> test_package#xxx00: SELECT", + "test_package#xxx01:ADMIN -> test_package#xxx01: INSERT:test_domain", + "test_package#xxx01:ADMIN -> test_package#xxx01: INSERT:test_domain", + "test_package#xxx01:TENANT -> test_package#xxx01: SELECT", + "test_package#xxx02:ADMIN -> test_package#xxx02: INSERT:test_domain", + "test_package#xxx02:ADMIN -> test_package#xxx02: INSERT:test_domain", + "test_package#xxx02:TENANT -> test_package#xxx02: SELECT", - "test_customer#yyy.admin -> test_customer#yyy: SELECT", - "test_customer#yyy.owner -> test_customer#yyy: DELETE", - "test_customer#yyy.tenant -> test_customer#yyy: SELECT", - "test_customer#yyy.admin -> test_customer#yyy: INSERT:test_package", - "test_package#yyy00.admin -> test_package#yyy00: INSERT:test_domain", - "test_package#yyy00.admin -> test_package#yyy00: INSERT:test_domain", - "test_package#yyy00.tenant -> test_package#yyy00: SELECT", - "test_package#yyy01.admin -> test_package#yyy01: INSERT:test_domain", - "test_package#yyy01.admin -> test_package#yyy01: INSERT:test_domain", - "test_package#yyy01.tenant -> test_package#yyy01: SELECT", - "test_package#yyy02.admin -> test_package#yyy02: INSERT:test_domain", - "test_package#yyy02.admin -> test_package#yyy02: INSERT:test_domain", - "test_package#yyy02.tenant -> test_package#yyy02: SELECT", + "test_customer#yyy:ADMIN -> test_customer#yyy: SELECT", + "test_customer#yyy:OWNER -> test_customer#yyy: DELETE", + "test_customer#yyy:TENANT -> test_customer#yyy: SELECT", + "test_customer#yyy:ADMIN -> test_customer#yyy: INSERT:test_package", + "test_package#yyy00:ADMIN -> test_package#yyy00: INSERT:test_domain", + "test_package#yyy00:ADMIN -> test_package#yyy00: INSERT:test_domain", + "test_package#yyy00:TENANT -> test_package#yyy00: SELECT", + "test_package#yyy01:ADMIN -> test_package#yyy01: INSERT:test_domain", + "test_package#yyy01:ADMIN -> test_package#yyy01: INSERT:test_domain", + "test_package#yyy01:TENANT -> test_package#yyy01: SELECT", + "test_package#yyy02:ADMIN -> test_package#yyy02: INSERT:test_domain", + "test_package#yyy02:ADMIN -> test_package#yyy02: INSERT:test_domain", + "test_package#yyy02:TENANT -> test_package#yyy02: SELECT", - "test_customer#zzz.admin -> test_customer#zzz: SELECT", - "test_customer#zzz.owner -> test_customer#zzz: DELETE", - "test_customer#zzz.tenant -> test_customer#zzz: SELECT", - "test_customer#zzz.admin -> test_customer#zzz: INSERT:test_package", - "test_package#zzz00.admin -> test_package#zzz00: INSERT:test_domain", - "test_package#zzz00.admin -> test_package#zzz00: INSERT:test_domain", - "test_package#zzz00.tenant -> test_package#zzz00: SELECT", - "test_package#zzz01.admin -> test_package#zzz01: INSERT:test_domain", - "test_package#zzz01.admin -> test_package#zzz01: INSERT:test_domain", - "test_package#zzz01.tenant -> test_package#zzz01: SELECT", - "test_package#zzz02.admin -> test_package#zzz02: INSERT:test_domain", - "test_package#zzz02.admin -> test_package#zzz02: INSERT:test_domain", - "test_package#zzz02.tenant -> test_package#zzz02: SELECT" + "test_customer#zzz:ADMIN -> test_customer#zzz: SELECT", + "test_customer#zzz:OWNER -> test_customer#zzz: DELETE", + "test_customer#zzz:TENANT -> test_customer#zzz: SELECT", + "test_customer#zzz:ADMIN -> test_customer#zzz: INSERT:test_package", + "test_package#zzz00:ADMIN -> test_package#zzz00: INSERT:test_domain", + "test_package#zzz00:ADMIN -> test_package#zzz00: INSERT:test_domain", + "test_package#zzz00:TENANT -> test_package#zzz00: SELECT", + "test_package#zzz01:ADMIN -> test_package#zzz01: INSERT:test_domain", + "test_package#zzz01:ADMIN -> test_package#zzz01: INSERT:test_domain", + "test_package#zzz01:TENANT -> test_package#zzz01: SELECT", + "test_package#zzz02:ADMIN -> test_package#zzz02: INSERT:test_domain", + "test_package#zzz02:ADMIN -> test_package#zzz02: INSERT:test_domain", + "test_package#zzz02:TENANT -> test_package#zzz02: SELECT" // @formatter:on ); @@ -252,32 +252,32 @@ class RbacUserRepositoryIntegrationTest extends ContextBasedTest { allTheseRbacPermissionsAreReturned( result, // @formatter:off - "test_customer#xxx.admin -> test_customer#xxx: INSERT:test_package", - "test_customer#xxx.admin -> test_customer#xxx: SELECT", - "test_customer#xxx.tenant -> test_customer#xxx: SELECT", + "test_customer#xxx:ADMIN -> test_customer#xxx: INSERT:test_package", + "test_customer#xxx:ADMIN -> test_customer#xxx: SELECT", + "test_customer#xxx:TENANT -> test_customer#xxx: SELECT", - "test_package#xxx00.admin -> test_package#xxx00: INSERT:test_domain", - "test_package#xxx00.admin -> test_package#xxx00: INSERT:test_domain", - "test_package#xxx00.tenant -> test_package#xxx00: SELECT", - "test_domain#xxx00-aaaa.owner -> test_domain#xxx00-aaaa: DELETE", + "test_package#xxx00:ADMIN -> test_package#xxx00: INSERT:test_domain", + "test_package#xxx00:ADMIN -> test_package#xxx00: INSERT:test_domain", + "test_package#xxx00:TENANT -> test_package#xxx00: SELECT", + "test_domain#xxx00-aaaa:OWNER -> test_domain#xxx00-aaaa: DELETE", - "test_package#xxx01.admin -> test_package#xxx01: INSERT:test_domain", - "test_package#xxx01.admin -> test_package#xxx01: INSERT:test_domain", - "test_package#xxx01.tenant -> test_package#xxx01: SELECT", - "test_domain#xxx01-aaaa.owner -> test_domain#xxx01-aaaa: DELETE", + "test_package#xxx01:ADMIN -> test_package#xxx01: INSERT:test_domain", + "test_package#xxx01:ADMIN -> test_package#xxx01: INSERT:test_domain", + "test_package#xxx01:TENANT -> test_package#xxx01: SELECT", + "test_domain#xxx01-aaaa:OWNER -> test_domain#xxx01-aaaa: DELETE", - "test_package#xxx02.admin -> test_package#xxx02: INSERT:test_domain", - "test_package#xxx02.admin -> test_package#xxx02: INSERT:test_domain", - "test_package#xxx02.tenant -> test_package#xxx02: SELECT", - "test_domain#xxx02-aaaa.owner -> test_domain#xxx02-aaaa: DELETE" + "test_package#xxx02:ADMIN -> test_package#xxx02: INSERT:test_domain", + "test_package#xxx02:ADMIN -> test_package#xxx02: INSERT:test_domain", + "test_package#xxx02:TENANT -> test_package#xxx02: SELECT", + "test_domain#xxx02-aaaa:OWNER -> test_domain#xxx02-aaaa: DELETE" // @formatter:on ); noneOfTheseRbacPermissionsAreReturned( result, // @formatter:off - "test_customer#yyy.admin -> test_customer#yyy: INSERT:test_package", - "test_customer#yyy.admin -> test_customer#yyy: SELECT", - "test_customer#yyy.tenant -> test_customer#yyy: SELECT" + "test_customer#yyy:ADMIN -> test_customer#yyy: INSERT:test_package", + "test_customer#yyy:ADMIN -> test_customer#yyy: SELECT", + "test_customer#yyy:TENANT -> test_customer#yyy: SELECT" // @formatter:on ); } @@ -312,26 +312,26 @@ class RbacUserRepositoryIntegrationTest extends ContextBasedTest { allTheseRbacPermissionsAreReturned( result, // @formatter:off - "test_customer#xxx.tenant -> test_customer#xxx: SELECT", - // "test_customer#xxx.admin -> test_customer#xxx: view" - Not permissions through the customer admin! - "test_package#xxx00.admin -> test_package#xxx00: INSERT:test_domain", - "test_package#xxx00.admin -> test_package#xxx00: INSERT:test_domain", - "test_package#xxx00.tenant -> test_package#xxx00: SELECT", - "test_domain#xxx00-aaaa.owner -> test_domain#xxx00-aaaa: DELETE", - "test_domain#xxx00-aaab.owner -> test_domain#xxx00-aaab: DELETE" + "test_customer#xxx:TENANT -> test_customer#xxx: SELECT", + // "test_customer#xxx:ADMIN -> test_customer#xxx: view" - Not permissions through the customer admin! + "test_package#xxx00:ADMIN -> test_package#xxx00: INSERT:test_domain", + "test_package#xxx00:ADMIN -> test_package#xxx00: INSERT:test_domain", + "test_package#xxx00:TENANT -> test_package#xxx00: SELECT", + "test_domain#xxx00-aaaa:OWNER -> test_domain#xxx00-aaaa: DELETE", + "test_domain#xxx00-aaab:OWNER -> test_domain#xxx00-aaab: DELETE" // @formatter:on ); noneOfTheseRbacPermissionsAreReturned( result, // @formatter:off - "test_customer#yyy.admin -> test_customer#yyy: INSERT:test_package", - "test_customer#yyy.admin -> test_customer#yyy: SELECT", - "test_customer#yyy.tenant -> test_customer#yyy: SELECT", - "test_package#yyy00.admin -> test_package#yyy00: INSERT:test_domain", - "test_package#yyy00.admin -> test_package#yyy00: INSERT:test_domain", - "test_package#yyy00.tenant -> test_package#yyy00: SELECT", - "test_domain#yyy00-aaaa.owner -> test_domain#yyy00-aaaa: DELETE", - "test_domain#yyy00-aaab.owner -> test_domain#yyy00-aaab: DELETE" + "test_customer#yyy:ADMIN -> test_customer#yyy: INSERT:test_package", + "test_customer#yyy:ADMIN -> test_customer#yyy: SELECT", + "test_customer#yyy:TENANT -> test_customer#yyy: SELECT", + "test_package#yyy00:ADMIN -> test_package#yyy00: INSERT:test_domain", + "test_package#yyy00:ADMIN -> test_package#yyy00: INSERT:test_domain", + "test_package#yyy00:TENANT -> test_package#yyy00: SELECT", + "test_domain#yyy00-aaaa:OWNER -> test_domain#yyy00-aaaa: DELETE", + "test_domain#yyy00-aaab:OWNER -> test_domain#yyy00-aaab: DELETE" // @formatter:on ); } @@ -360,26 +360,26 @@ class RbacUserRepositoryIntegrationTest extends ContextBasedTest { allTheseRbacPermissionsAreReturned( result, // @formatter:off - "test_customer#xxx.tenant -> test_customer#xxx: SELECT", - // "test_customer#xxx.admin -> test_customer#xxx: view" - Not permissions through the customer admin! - "test_package#xxx00.admin -> test_package#xxx00: INSERT:test_domain", - "test_package#xxx00.tenant -> test_package#xxx00: SELECT" + "test_customer#xxx:TENANT -> test_customer#xxx: SELECT", + // "test_customer#xxx:ADMIN -> test_customer#xxx: view" - Not permissions through the customer admin! + "test_package#xxx00:ADMIN -> test_package#xxx00: INSERT:test_domain", + "test_package#xxx00:TENANT -> test_package#xxx00: SELECT" // @formatter:on ); noneOfTheseRbacPermissionsAreReturned( result, // @formatter:off // no customer admin permissions - "test_customer#xxx.admin -> test_customer#xxx: add-package", + "test_customer#xxx:ADMIN -> test_customer#xxx: add-package", // no permissions on other customer's objects - "test_customer#yyy.admin -> test_customer#yyy: add-package", - "test_customer#yyy.admin -> test_customer#yyy: SELECT", - "test_customer#yyy.tenant -> test_customer#yyy: SELECT", - "test_package#yyy00.admin -> test_package#yyy00: INSERT:test_domain", - "test_package#yyy00.admin -> test_package#yyy00: INSERT:test_domain", - "test_package#yyy00.tenant -> test_package#yyy00: SELECT", - "test_domain#yyy00-aaaa.owner -> test_domain#yyy00-aaaa: DELETE", - "test_domain#yyy00-xxxb.owner -> test_domain#yyy00-xxxb: DELETE" + "test_customer#yyy:ADMIN -> test_customer#yyy: add-package", + "test_customer#yyy:ADMIN -> test_customer#yyy: SELECT", + "test_customer#yyy:TENANT -> test_customer#yyy: SELECT", + "test_package#yyy00:ADMIN -> test_package#yyy00: INSERT:test_domain", + "test_package#yyy00:ADMIN -> test_package#yyy00: INSERT:test_domain", + "test_package#yyy00:TENANT -> test_package#yyy00: SELECT", + "test_domain#yyy00-aaaa:OWNER -> test_domain#yyy00-aaaa: DELETE", + "test_domain#yyy00-xxxb:OWNER -> test_domain#yyy00-xxxb: DELETE" // @formatter:on ); } diff --git a/src/test/java/net/hostsharing/hsadminng/test/cust/TestCustomerControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/test/cust/TestCustomerControllerAcceptanceTest.java index e9e1d47c..1d7bf4e5 100644 --- a/src/test/java/net/hostsharing/hsadminng/test/cust/TestCustomerControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/test/cust/TestCustomerControllerAcceptanceTest.java @@ -89,7 +89,7 @@ class TestCustomerControllerAcceptanceTest { RestAssured // @formatter:off .given() .header("current-user", "superuser-alex@hostsharing.net") - .header("assumed-roles", "test_customer#yyy.admin") + .header("assumed-roles", "test_customer#yyy:ADMIN") .port(port) .when() .get("http://localhost/api/test/customers") @@ -148,7 +148,7 @@ class TestCustomerControllerAcceptanceTest { // finally, the new customer can be viewed by its own admin final var newUserUuid = UUID.fromString( location.substring(location.lastIndexOf('/') + 1)); - context.define("superuser-fran@hostsharing.net", "test_customer#uuu.admin"); + context.define("superuser-fran@hostsharing.net", "test_customer#uuu:ADMIN"); assertThat(testCustomerRepository.findByUuid(newUserUuid)) .hasValueSatisfying(c -> assertThat(c.getPrefix()).isEqualTo("uuu")); } @@ -159,7 +159,7 @@ class TestCustomerControllerAcceptanceTest { RestAssured // @formatter:off .given() .header("current-user", "superuser-alex@hostsharing.net") - .header("assumed-roles", "test_customer#xxx.admin") + .header("assumed-roles", "test_customer#xxx:ADMIN") .contentType(ContentType.JSON) .body(""" { @@ -175,7 +175,7 @@ class TestCustomerControllerAcceptanceTest { .statusCode(403) .contentType(ContentType.JSON) .statusCode(403) - .body("message", containsString("insert into test_customer not allowed for current subjects {test_customer#xxx.admin}")); + .body("message", containsString("insert into test_customer not allowed for current subjects {test_customer#xxx:ADMIN}")); // @formatter:on // finally, the new customer was not created diff --git a/src/test/java/net/hostsharing/hsadminng/test/cust/TestCustomerEntityUnitTest.java b/src/test/java/net/hostsharing/hsadminng/test/cust/TestCustomerEntityUnitTest.java index d576396a..962cef38 100644 --- a/src/test/java/net/hostsharing/hsadminng/test/cust/TestCustomerEntityUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/test/cust/TestCustomerEntityUnitTest.java @@ -21,9 +21,9 @@ class TestCustomerEntityUnitTest { subgraph customer:roles[ ] style customer:roles fill:#dd4901,stroke:white - role:customer:owner[[customer:owner]] - role:customer:admin[[customer:admin]] - role:customer:tenant[[customer:tenant]] + role:customer:OWNER[[customer:OWNER]] + role:customer:ADMIN[[customer:ADMIN]] + role:customer:TENANT[[customer:TENANT]] end subgraph customer:permissions[ ] @@ -37,18 +37,18 @@ class TestCustomerEntityUnitTest { end %% granting roles to users - user:creator ==>|XX| role:customer:owner + user:creator ==>|XX| role:customer:OWNER %% granting roles to roles - role:global:admin ==>|XX| role:customer:owner - role:customer:owner ==> role:customer:admin - role:customer:admin ==> role:customer:tenant + role:global:ADMIN ==>|XX| role:customer:OWNER + role:customer:OWNER ==> role:customer:ADMIN + role:customer:ADMIN ==> role:customer:TENANT %% granting permissions to roles - role:global:admin ==> perm:customer:INSERT - role:customer:owner ==> perm:customer:DELETE - role:customer:admin ==> perm:customer:UPDATE - role:customer:tenant ==> perm:customer:SELECT + role:global:ADMIN ==> perm:customer:INSERT + role:customer:OWNER ==> perm:customer:DELETE + role:customer:ADMIN ==> perm:customer:UPDATE + role:customer:TENANT ==> perm:customer:SELECT """); } } diff --git a/src/test/java/net/hostsharing/hsadminng/test/cust/TestCustomerRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/test/cust/TestCustomerRepositoryIntegrationTest.java index 27458b14..591ce0eb 100644 --- a/src/test/java/net/hostsharing/hsadminng/test/cust/TestCustomerRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/test/cust/TestCustomerRepositoryIntegrationTest.java @@ -54,7 +54,7 @@ class TestCustomerRepositoryIntegrationTest extends ContextBasedTest { @Test public void globalAdmin_withAssumedCustomerRole_cannotCreateNewCustomer() { // given - context("superuser-alex@hostsharing.net", "test_customer#xxx.admin"); + context("superuser-alex@hostsharing.net", "test_customer#xxx:ADMIN"); // when final var result = attempt(em, () -> { @@ -66,7 +66,7 @@ class TestCustomerRepositoryIntegrationTest extends ContextBasedTest { // then result.assertExceptionWithRootCauseMessage( PersistenceException.class, - "ERROR: [403] insert into test_customer not allowed for current subjects {test_customer#xxx.admin}"); + "ERROR: [403] insert into test_customer not allowed for current subjects {test_customer#xxx:ADMIN}"); } @Test @@ -112,7 +112,7 @@ class TestCustomerRepositoryIntegrationTest extends ContextBasedTest { @Test public void globalAdmin_withAssumedCustomerOwnerRole_canViewExactlyThatCustomer() { given: - context("superuser-alex@hostsharing.net", "test_customer#yyy.owner"); + context("superuser-alex@hostsharing.net", "test_customer#yyy:OWNER"); // when final var result = testCustomerRepository.findCustomerByOptionalPrefixLike(null); @@ -137,7 +137,7 @@ class TestCustomerRepositoryIntegrationTest extends ContextBasedTest { public void customerAdmin_withAssumedOwnedPackageAdminRole_canViewOnlyItsOwnCustomer() { context("customer-admin@xxx.example.com"); - context("customer-admin@xxx.example.com", "test_package#xxx00.admin"); + context("customer-admin@xxx.example.com", "test_package#xxx00:ADMIN"); final var result = testCustomerRepository.findCustomerByOptionalPrefixLike(null); diff --git a/src/test/java/net/hostsharing/hsadminng/test/pac/TestPackageControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/test/pac/TestPackageControllerAcceptanceTest.java index fd51ebf8..0e52cc40 100644 --- a/src/test/java/net/hostsharing/hsadminng/test/pac/TestPackageControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/test/pac/TestPackageControllerAcceptanceTest.java @@ -44,7 +44,7 @@ class TestPackageControllerAcceptanceTest { RestAssured .given() .header("current-user", "superuser-alex@hostsharing.net") - .header("assumed-roles", "test_customer#xxx.admin") + .header("assumed-roles", "test_customer#xxx:ADMIN") .port(port) .when() .get("http://localhost/api/test/packages") @@ -66,7 +66,7 @@ class TestPackageControllerAcceptanceTest { RestAssured .given() .header("current-user", "superuser-alex@hostsharing.net") - .header("assumed-roles", "test_customer#xxx.admin") + .header("assumed-roles", "test_customer#xxx:ADMIN") .port(port) .when() .get("http://localhost/api/test/packages?name=xxx01") @@ -95,7 +95,7 @@ class TestPackageControllerAcceptanceTest { RestAssured .given() .header("current-user", "superuser-alex@hostsharing.net") - .header("assumed-roles", "test_customer#xxx.admin") + .header("assumed-roles", "test_customer#xxx:ADMIN") .contentType(ContentType.JSON) .body(format(""" { @@ -126,7 +126,7 @@ class TestPackageControllerAcceptanceTest { RestAssured .given() .header("current-user", "superuser-alex@hostsharing.net") - .header("assumed-roles", "test_customer#xxx.admin") + .header("assumed-roles", "test_customer#xxx:ADMIN") .contentType(ContentType.JSON) .body(""" { @@ -156,7 +156,7 @@ class TestPackageControllerAcceptanceTest { RestAssured .given() .header("current-user", "superuser-alex@hostsharing.net") - .header("assumed-roles", "test_customer#xxx.admin") + .header("assumed-roles", "test_customer#xxx:ADMIN") .contentType(ContentType.JSON) .body("{}") .port(port) @@ -176,7 +176,7 @@ class TestPackageControllerAcceptanceTest { return UUID.fromString(RestAssured .given() .header("current-user", "superuser-alex@hostsharing.net") - .header("assumed-roles", "test_customer#xxx.admin") + .header("assumed-roles", "test_customer#xxx:ADMIN") .port(port) .when() .get("http://localhost/api/test/packages?name={packageName}", packageName) @@ -188,7 +188,7 @@ class TestPackageControllerAcceptanceTest { } String getDescriptionOfPackage(final String packageName) { - context.define("superuser-alex@hostsharing.net","test_customer#xxx.admin"); + context.define("superuser-alex@hostsharing.net","test_customer#xxx:ADMIN"); return testPackageRepository.findAllByOptionalNameLike(packageName).get(0).getDescription(); } } diff --git a/src/test/java/net/hostsharing/hsadminng/test/pac/TestPackageEntityUnitTest.java b/src/test/java/net/hostsharing/hsadminng/test/pac/TestPackageEntityUnitTest.java index c5dccfd3..79dcfec2 100644 --- a/src/test/java/net/hostsharing/hsadminng/test/pac/TestPackageEntityUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/test/pac/TestPackageEntityUnitTest.java @@ -21,9 +21,9 @@ class TestPackageEntityUnitTest { subgraph package:roles[ ] style package:roles fill:#dd4901,stroke:white - role:package:owner[[package:owner]] - role:package:admin[[package:admin]] - role:package:tenant[[package:tenant]] + role:package:OWNER[[package:OWNER]] + role:package:ADMIN[[package:ADMIN]] + role:package:TENANT[[package:TENANT]] end subgraph package:permissions[ ] @@ -43,26 +43,26 @@ class TestPackageEntityUnitTest { subgraph customer:roles[ ] style customer:roles fill:#99bcdb,stroke:white - role:customer:owner[[customer:owner]] - role:customer:admin[[customer:admin]] - role:customer:tenant[[customer:tenant]] + role:customer:OWNER[[customer:OWNER]] + role:customer:ADMIN[[customer:ADMIN]] + role:customer:TENANT[[customer:TENANT]] end end %% granting roles to roles - role:global:admin -.->|XX| role:customer:owner - role:customer:owner -.-> role:customer:admin - role:customer:admin -.-> role:customer:tenant - role:customer:admin ==> role:package:owner - role:package:owner ==> role:package:admin - role:package:admin ==> role:package:tenant - role:package:tenant ==> role:customer:tenant + role:global:ADMIN -.->|XX| role:customer:OWNER + role:customer:OWNER -.-> role:customer:ADMIN + role:customer:ADMIN -.-> role:customer:TENANT + role:customer:ADMIN ==> role:package:OWNER + role:package:OWNER ==> role:package:ADMIN + role:package:ADMIN ==> role:package:TENANT + role:package:TENANT ==> role:customer:TENANT %% granting permissions to roles - role:customer:admin ==> perm:package:INSERT - role:package:owner ==> perm:package:DELETE - role:package:owner ==> perm:package:UPDATE - role:package:tenant ==> perm:package:SELECT + role:customer:ADMIN ==> perm:package:INSERT + role:package:OWNER ==> perm:package:DELETE + role:package:OWNER ==> perm:package:UPDATE + role:package:TENANT ==> perm:package:SELECT """); } } diff --git a/src/test/java/net/hostsharing/hsadminng/test/pac/TestPackageRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/test/pac/TestPackageRepositoryIntegrationTest.java index a201d79e..49412b3b 100644 --- a/src/test/java/net/hostsharing/hsadminng/test/pac/TestPackageRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/test/pac/TestPackageRepositoryIntegrationTest.java @@ -53,7 +53,7 @@ class TestPackageRepositoryIntegrationTest extends ContextBasedTest { @Test public void globalAdmin_withAssumedglobalAdminRole__canNotViewAnyPackages_becauseThoseGrantsAreNotAssumed() { given: - context.define("superuser-alex@hostsharing.net", "global#global.admin"); + context.define("superuser-alex@hostsharing.net", "global#global:ADMIN"); // when final var result = testPackageRepository.findAllByOptionalNameLike(null); @@ -76,7 +76,7 @@ class TestPackageRepositoryIntegrationTest extends ContextBasedTest { @Test public void customerAdmin_withAssumedOwnedPackageAdminRole_canViewOnlyItsOwnPackages() { - context.define("customer-admin@xxx.example.com", "test_package#xxx00.admin"); + context.define("customer-admin@xxx.example.com", "test_package#xxx00:ADMIN"); final var result = testPackageRepository.findAllByOptionalNameLike(null); @@ -90,17 +90,17 @@ class TestPackageRepositoryIntegrationTest extends ContextBasedTest { @Test public void supportsOptimisticLocking() { // given - globalAdminWithAssumedRole("test_package#xxx00.admin"); + globalAdminWithAssumedRole("test_package#xxx00:ADMIN"); final var pac = testPackageRepository.findAllByOptionalNameLike("%").get(0); // when final var result1 = jpaAttempt.transacted(() -> { - globalAdminWithAssumedRole("test_package#xxx00.owner"); + globalAdminWithAssumedRole("test_package#xxx00:OWNER"); pac.setDescription("description set by thread 1"); testPackageRepository.save(pac); }); final var result2 = jpaAttempt.transacted(() -> { - globalAdminWithAssumedRole("test_package#xxx00.owner"); + globalAdminWithAssumedRole("test_package#xxx00:OWNER"); pac.setDescription("description set by thread 2"); testPackageRepository.save(pac); sleep(1500); diff --git a/src/test/java/net/hostsharing/test/JpaAttempt.java b/src/test/java/net/hostsharing/test/JpaAttempt.java index 3d5c50ee..86a332cd 100644 --- a/src/test/java/net/hostsharing/test/JpaAttempt.java +++ b/src/test/java/net/hostsharing/test/JpaAttempt.java @@ -154,6 +154,11 @@ public class JpaAttempt { return this; } + public JpaResult assertNotNull() { + assertThat(returnedValue()).isNotNull(); + return this; + } + private String firstRootCauseMessageLineOf(final RuntimeException exception) { final var rootCause = NestedExceptionUtils.getRootCause(exception); return Optional.ofNullable(rootCause) -- 2.39.5 From d816275776acbe3273f5b45595bc1c367453db27 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Sat, 30 Mar 2024 13:29:25 +0100 Subject: [PATCH 05/29] fix missing insert perm grants --- .../HsOfficeMembershipRepositoryIntegrationTest.java | 3 +++ 1 file changed, 3 insertions(+) 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 f6f7e518..64ef6803 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 @@ -117,6 +117,9 @@ class HsOfficeMembershipRepositoryIntegrationTest extends ContextBasedTestWithCl .map(s -> s.replace("hs_office_", "")) .containsExactlyInAnyOrder(Array.fromFormatted( initialGrantNames, + // insert + "{ grant perm:membership#M-1000117:INSERT>coopassetstransaction to role:membership#M-1000117:ADMIN by system and assume }", + "{ 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 }", -- 2.39.5 From b1da9a5fb8930a9941dcad51372159c476a8e7a5 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Sat, 30 Mar 2024 13:29:37 +0100 Subject: [PATCH 06/29] fix missed .admin -> :ADMIN --- ...sOfficeCoopSharesTransactionRepositoryIntegrationTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 37d67592..b0b01d65 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,8 +111,8 @@ 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:UPDATE to role:membership#M-1000101.admin by system and assume }", + "{ grant perm:coopsharestransaction#temprefB:SELECT to role:membership#M-1000101:ADMIN by system and assume }", + "{ grant perm:coopsharestransaction#temprefB:UPDATE to role:membership#M-1000101:ADMIN by system and assume }", null)); } -- 2.39.5 From 0f9b410d4fd4756a33ec65f4bb12316a9a41ca6f Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Fri, 29 Mar 2024 20:48:41 +0100 Subject: [PATCH 07/29] structured liquibase files --- .../HsOfficeBankAccountEntity.java | 2 +- .../office/contact/HsOfficeContactEntity.java | 2 +- .../HsOfficeCoopAssetsTransactionEntity.java | 2 +- .../HsOfficeCoopSharesTransactionEntity.java | 2 +- .../office/debitor/HsOfficeDebitorEntity.java | 2 +- .../membership/HsOfficeMembershipEntity.java | 2 +- .../partner/HsOfficePartnerDetailsEntity.java | 2 +- .../office/partner/HsOfficePartnerEntity.java | 2 +- .../office/person/HsOfficePersonEntity.java | 2 +- .../relation/HsOfficeRelationEntity.java | 2 +- .../HsOfficeSepaMandateEntity.java | 2 +- .../test/cust/TestCustomerEntity.java | 2 +- .../hsadminng/test/dom/TestDomainEntity.java | 2 +- .../hsadminng/test/pac/TestPackageEntity.java | 2 +- .../changelog/{ => 0-basis}/000-template.sql | 0 .../{ => 0-basis}/001-last-row-count.sql | 0 .../{ => 0-basis}/002-int-to-var.sql | 0 .../{ => 0-basis}/003-random-in-range.sql | 0 .../{ => 0-basis}/004-jsonb-changes-delta.sql | 0 .../{ => 0-basis}/005-uuid-ossp-extension.sql | 0 .../006-numeric-hash-functions.sql | 0 .../{ => 0-basis}/007-table-columns.sql | 0 .../{ => 0-basis}/009-check-environment.sql | 0 .../changelog/{ => 0-basis}/010-context.sql | 0 .../changelog/{ => 0-basis}/020-audit-log.sql | 0 .../1050-rbac-base.sql} | 0 .../1051-rbac-user-grant.sql} | 0 .../1054-rbac-context.sql} | 0 .../1055-rbac-views.sql} | 0 .../1056-rbac-trigger-context.sql} | 0 .../1057-rbac-role-builder.sql} | 0 .../1058-rbac-generators.sql} | 0 .../1059-rbac-statistics.sql} | 0 .../1080-rbac-global.sql} | 0 .../201-test-customer/2010-test-customer.sql} | 0 .../2013-test-customer-rbac.md} | 0 .../2013-test-customer-rbac.sql} | 0 .../2018-test-customer-test-data.sql} | 0 .../202-test-package/2020-test-package.sql} | 0 .../2023-test-package-rbac.md} | 0 .../2023-test-package-rbac.sql} | 0 .../2028-test-package-test-data.sql} | 0 .../203-test-domain/2030-test-domain.sql} | 0 .../203-test-domain/2033-test-domain-rbac.md} | 0 .../2033-test-domain-rbac.sql} | 0 .../2038-test-domain-test-data.sql} | 0 .../313-hs-office-coopshares-rbac.md | 250 ------------------ .../323-hs-office-coopassets-rbac.md | 250 ------------------ .../501-contact/5010-hs-office-contact.sql} | 0 .../5013-hs-office-contact-rbac.md} | 0 .../5013-hs-office-contact-rbac.sql} | 0 .../5016-hs-office-contact-migration.sql} | 0 .../5018-hs-office-contact-test-data.sql} | 0 .../502-person/5020-hs-office-person.sql} | 0 .../502-person/5023-hs-office-person-rbac.md} | 0 .../5023-hs-office-person-rbac.sql} | 0 .../5028-hs-office-person-test-data.sql} | 0 .../503-relation/5030-hs-office-relation.sql} | 0 .../5033-hs-office-relation-rbac.md} | 0 .../5033-hs-office-relation-rbac.sql} | 0 .../5038-hs-office-relation-test-data.sql} | 0 .../504-partner/5040-hs-office-partner.sql} | 0 .../5043-hs-office-partner-rbac.md} | 0 .../5043-hs-office-partner-rbac.sql} | 0 .../5044-hs-office-partner-details-rbac.md} | 0 .../5044-hs-office-partner-details-rbac.sql} | 0 .../5046-hs-office-partner-migration.sql} | 0 .../5048-hs-office-partner-test-data.sql} | 0 .../5050-hs-office-bankaccount.sql} | 0 .../5053-hs-office-bankaccount-rbac.md} | 0 .../5053-hs-office-bankaccount-rbac.sql} | 0 .../5058-hs-office-bankaccount-test-data.sql} | 0 .../506-debitor/5060-hs-office-debitor.sql} | 0 .../5063-hs-office-debitor-rbac.md} | 0 .../5063-hs-office-debitor-rbac.sql} | 0 .../5068-hs-office-debitor-test-data.sql} | 0 .../5070-hs-office-sepamandate.sql} | 0 .../5073-hs-office-sepamandate-rbac.md} | 0 .../5073-hs-office-sepamandate-rbac.sql} | 0 .../5076-hs-office-sepamandate-migration.sql} | 0 .../5078-hs-office-sepamandate-test-data.sql} | 0 .../5100-hs-office-membership.sql} | 0 .../5103-hs-office-membership-rbac.md} | 0 .../5103-hs-office-membership-rbac.sql} | 0 .../5108-hs-office-membership-test-data.sql} | 0 .../5110-hs-office-coopshares.sql} | 0 .../5113-hs-office-coopshares-rbac.md | 120 +++++++++ .../5113-hs-office-coopshares-rbac.sql} | 8 +- .../5116-hs-office-coopshares-migration.sql} | 0 .../5118-hs-office-coopshares-test-data.sql} | 0 .../5120-hs-office-coopassets.sql} | 0 .../5123-hs-office-coopassets-rbac.md | 120 +++++++++ .../5123-hs-office-coopassets-rbac.sql} | 8 +- .../5126-hs-office-coopassets-migration.sql} | 0 .../5128-hs-office-coopassets-test-data.sql} | 0 .../db/changelog/db.changelog-master.yaml | 128 ++++----- 96 files changed, 326 insertions(+), 586 deletions(-) rename src/main/resources/db/changelog/{ => 0-basis}/000-template.sql (100%) rename src/main/resources/db/changelog/{ => 0-basis}/001-last-row-count.sql (100%) rename src/main/resources/db/changelog/{ => 0-basis}/002-int-to-var.sql (100%) rename src/main/resources/db/changelog/{ => 0-basis}/003-random-in-range.sql (100%) rename src/main/resources/db/changelog/{ => 0-basis}/004-jsonb-changes-delta.sql (100%) rename src/main/resources/db/changelog/{ => 0-basis}/005-uuid-ossp-extension.sql (100%) rename src/main/resources/db/changelog/{ => 0-basis}/006-numeric-hash-functions.sql (100%) rename src/main/resources/db/changelog/{ => 0-basis}/007-table-columns.sql (100%) rename src/main/resources/db/changelog/{ => 0-basis}/009-check-environment.sql (100%) rename src/main/resources/db/changelog/{ => 0-basis}/010-context.sql (100%) rename src/main/resources/db/changelog/{ => 0-basis}/020-audit-log.sql (100%) rename src/main/resources/db/changelog/{050-rbac-base.sql => 1-rbac/1050-rbac-base.sql} (100%) rename src/main/resources/db/changelog/{051-rbac-user-grant.sql => 1-rbac/1051-rbac-user-grant.sql} (100%) rename src/main/resources/db/changelog/{054-rbac-context.sql => 1-rbac/1054-rbac-context.sql} (100%) rename src/main/resources/db/changelog/{055-rbac-views.sql => 1-rbac/1055-rbac-views.sql} (100%) rename src/main/resources/db/changelog/{056-rbac-trigger-context.sql => 1-rbac/1056-rbac-trigger-context.sql} (100%) rename src/main/resources/db/changelog/{057-rbac-role-builder.sql => 1-rbac/1057-rbac-role-builder.sql} (100%) rename src/main/resources/db/changelog/{058-rbac-generators.sql => 1-rbac/1058-rbac-generators.sql} (100%) rename src/main/resources/db/changelog/{059-rbac-statistics.sql => 1-rbac/1059-rbac-statistics.sql} (100%) rename src/main/resources/db/changelog/{080-rbac-global.sql => 1-rbac/1080-rbac-global.sql} (100%) rename src/main/resources/db/changelog/{110-test-customer.sql => 2-test/201-test-customer/2010-test-customer.sql} (100%) rename src/main/resources/db/changelog/{113-test-customer-rbac.md => 2-test/201-test-customer/2013-test-customer-rbac.md} (100%) rename src/main/resources/db/changelog/{113-test-customer-rbac.sql => 2-test/201-test-customer/2013-test-customer-rbac.sql} (100%) rename src/main/resources/db/changelog/{118-test-customer-test-data.sql => 2-test/201-test-customer/2018-test-customer-test-data.sql} (100%) rename src/main/resources/db/changelog/{120-test-package.sql => 2-test/202-test-package/2020-test-package.sql} (100%) rename src/main/resources/db/changelog/{123-test-package-rbac.md => 2-test/202-test-package/2023-test-package-rbac.md} (100%) rename src/main/resources/db/changelog/{123-test-package-rbac.sql => 2-test/202-test-package/2023-test-package-rbac.sql} (100%) rename src/main/resources/db/changelog/{128-test-package-test-data.sql => 2-test/202-test-package/2028-test-package-test-data.sql} (100%) rename src/main/resources/db/changelog/{130-test-domain.sql => 2-test/203-test-domain/2030-test-domain.sql} (100%) rename src/main/resources/db/changelog/{133-test-domain-rbac.md => 2-test/203-test-domain/2033-test-domain-rbac.md} (100%) rename src/main/resources/db/changelog/{133-test-domain-rbac.sql => 2-test/203-test-domain/2033-test-domain-rbac.sql} (100%) rename src/main/resources/db/changelog/{138-test-domain-test-data.sql => 2-test/203-test-domain/2038-test-domain-test-data.sql} (100%) delete mode 100644 src/main/resources/db/changelog/313-hs-office-coopshares-rbac.md delete mode 100644 src/main/resources/db/changelog/323-hs-office-coopassets-rbac.md rename src/main/resources/db/changelog/{200-hs-office-contact.sql => 5-hs-office/501-contact/5010-hs-office-contact.sql} (100%) rename src/main/resources/db/changelog/{203-hs-office-contact-rbac.md => 5-hs-office/501-contact/5013-hs-office-contact-rbac.md} (100%) rename src/main/resources/db/changelog/{203-hs-office-contact-rbac.sql => 5-hs-office/501-contact/5013-hs-office-contact-rbac.sql} (100%) rename src/main/resources/db/changelog/{206-hs-office-contact-migration.sql => 5-hs-office/501-contact/5016-hs-office-contact-migration.sql} (100%) rename src/main/resources/db/changelog/{208-hs-office-contact-test-data.sql => 5-hs-office/501-contact/5018-hs-office-contact-test-data.sql} (100%) rename src/main/resources/db/changelog/{210-hs-office-person.sql => 5-hs-office/502-person/5020-hs-office-person.sql} (100%) rename src/main/resources/db/changelog/{213-hs-office-person-rbac.md => 5-hs-office/502-person/5023-hs-office-person-rbac.md} (100%) rename src/main/resources/db/changelog/{213-hs-office-person-rbac.sql => 5-hs-office/502-person/5023-hs-office-person-rbac.sql} (100%) rename src/main/resources/db/changelog/{218-hs-office-person-test-data.sql => 5-hs-office/502-person/5028-hs-office-person-test-data.sql} (100%) rename src/main/resources/db/changelog/{220-hs-office-relation.sql => 5-hs-office/503-relation/5030-hs-office-relation.sql} (100%) rename src/main/resources/db/changelog/{223-hs-office-relation-rbac.md => 5-hs-office/503-relation/5033-hs-office-relation-rbac.md} (100%) rename src/main/resources/db/changelog/{223-hs-office-relation-rbac.sql => 5-hs-office/503-relation/5033-hs-office-relation-rbac.sql} (100%) rename src/main/resources/db/changelog/{228-hs-office-relation-test-data.sql => 5-hs-office/503-relation/5038-hs-office-relation-test-data.sql} (100%) rename src/main/resources/db/changelog/{230-hs-office-partner.sql => 5-hs-office/504-partner/5040-hs-office-partner.sql} (100%) rename src/main/resources/db/changelog/{233-hs-office-partner-rbac.md => 5-hs-office/504-partner/5043-hs-office-partner-rbac.md} (100%) rename src/main/resources/db/changelog/{233-hs-office-partner-rbac.sql => 5-hs-office/504-partner/5043-hs-office-partner-rbac.sql} (100%) rename src/main/resources/db/changelog/{234-hs-office-partner-details-rbac.md => 5-hs-office/504-partner/5044-hs-office-partner-details-rbac.md} (100%) rename src/main/resources/db/changelog/{234-hs-office-partner-details-rbac.sql => 5-hs-office/504-partner/5044-hs-office-partner-details-rbac.sql} (100%) rename src/main/resources/db/changelog/{236-hs-office-partner-migration.sql => 5-hs-office/504-partner/5046-hs-office-partner-migration.sql} (100%) rename src/main/resources/db/changelog/{238-hs-office-partner-test-data.sql => 5-hs-office/504-partner/5048-hs-office-partner-test-data.sql} (100%) rename src/main/resources/db/changelog/{240-hs-office-bankaccount.sql => 5-hs-office/505-bankaccount/5050-hs-office-bankaccount.sql} (100%) rename src/main/resources/db/changelog/{243-hs-office-bankaccount-rbac.md => 5-hs-office/505-bankaccount/5053-hs-office-bankaccount-rbac.md} (100%) rename src/main/resources/db/changelog/{243-hs-office-bankaccount-rbac.sql => 5-hs-office/505-bankaccount/5053-hs-office-bankaccount-rbac.sql} (100%) rename src/main/resources/db/changelog/{248-hs-office-bankaccount-test-data.sql => 5-hs-office/505-bankaccount/5058-hs-office-bankaccount-test-data.sql} (100%) rename src/main/resources/db/changelog/{270-hs-office-debitor.sql => 5-hs-office/506-debitor/5060-hs-office-debitor.sql} (100%) rename src/main/resources/db/changelog/{273-hs-office-debitor-rbac.md => 5-hs-office/506-debitor/5063-hs-office-debitor-rbac.md} (100%) rename src/main/resources/db/changelog/{273-hs-office-debitor-rbac.sql => 5-hs-office/506-debitor/5063-hs-office-debitor-rbac.sql} (100%) rename src/main/resources/db/changelog/{278-hs-office-debitor-test-data.sql => 5-hs-office/506-debitor/5068-hs-office-debitor-test-data.sql} (100%) rename src/main/resources/db/changelog/{250-hs-office-sepamandate.sql => 5-hs-office/507-sepamandate/5070-hs-office-sepamandate.sql} (100%) rename src/main/resources/db/changelog/{253-hs-office-sepamandate-rbac.md => 5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.md} (100%) rename src/main/resources/db/changelog/{253-hs-office-sepamandate-rbac.sql => 5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.sql} (100%) rename src/main/resources/db/changelog/{256-hs-office-sepamandate-migration.sql => 5-hs-office/507-sepamandate/5076-hs-office-sepamandate-migration.sql} (100%) rename src/main/resources/db/changelog/{258-hs-office-sepamandate-test-data.sql => 5-hs-office/507-sepamandate/5078-hs-office-sepamandate-test-data.sql} (100%) rename src/main/resources/db/changelog/{300-hs-office-membership.sql => 5-hs-office/510-membership/5100-hs-office-membership.sql} (100%) rename src/main/resources/db/changelog/{303-hs-office-membership-rbac.md => 5-hs-office/510-membership/5103-hs-office-membership-rbac.md} (100%) rename src/main/resources/db/changelog/{303-hs-office-membership-rbac.sql => 5-hs-office/510-membership/5103-hs-office-membership-rbac.sql} (100%) rename src/main/resources/db/changelog/{308-hs-office-membership-test-data.sql => 5-hs-office/510-membership/5108-hs-office-membership-test-data.sql} (100%) rename src/main/resources/db/changelog/{310-hs-office-coopshares.sql => 5-hs-office/511-coopshares/5110-hs-office-coopshares.sql} (100%) create mode 100644 src/main/resources/db/changelog/5-hs-office/511-coopshares/5113-hs-office-coopshares-rbac.md rename src/main/resources/db/changelog/{313-hs-office-coopshares-rbac.sql => 5-hs-office/511-coopshares/5113-hs-office-coopshares-rbac.sql} (96%) rename src/main/resources/db/changelog/{316-hs-office-coopshares-migration.sql => 5-hs-office/511-coopshares/5116-hs-office-coopshares-migration.sql} (100%) rename src/main/resources/db/changelog/{318-hs-office-coopshares-test-data.sql => 5-hs-office/511-coopshares/5118-hs-office-coopshares-test-data.sql} (100%) rename src/main/resources/db/changelog/{320-hs-office-coopassets.sql => 5-hs-office/512-coopassets/5120-hs-office-coopassets.sql} (100%) create mode 100644 src/main/resources/db/changelog/5-hs-office/512-coopassets/5123-hs-office-coopassets-rbac.md rename src/main/resources/db/changelog/{323-hs-office-coopassets-rbac.sql => 5-hs-office/512-coopassets/5123-hs-office-coopassets-rbac.sql} (96%) rename src/main/resources/db/changelog/{326-hs-office-coopassets-migration.sql => 5-hs-office/512-coopassets/5126-hs-office-coopassets-migration.sql} (100%) rename src/main/resources/db/changelog/{328-hs-office-coopassets-test-data.sql => 5-hs-office/512-coopassets/5128-hs-office-coopassets-test-data.sql} (100%) diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountEntity.java index 664ed8fe..99bb50ea 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountEntity.java @@ -78,6 +78,6 @@ public class HsOfficeBankAccountEntity implements HasUuid, Stringifyable { } public static void main(String[] args) throws IOException { - rbac().generateWithBaseFileName("243-hs-office-bankaccount-rbac"); + rbac().generateWithBaseFileName("5-hs-office/505-bankaccount/5053-hs-office-bankaccount-rbac"); } } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactEntity.java index 62f5316a..4927b4bc 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactEntity.java @@ -80,6 +80,6 @@ public class HsOfficeContactEntity implements Stringifyable, HasUuid { } public static void main(String[] args) throws IOException { - rbac().generateWithBaseFileName("203-hs-office-contact-rbac"); + rbac().generateWithBaseFileName("5-hs-office/501-contact/5013-hs-office-contact-rbac"); } } 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 2fd6c430..542f1cd7 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 @@ -113,6 +113,6 @@ public class HsOfficeCoopAssetsTransactionEntity implements Stringifyable, HasUu } public static void main(String[] args) throws IOException { - rbac().generateWithBaseFileName("323-hs-office-coopassets-rbac"); + rbac().generateWithBaseFileName("5-hs-office/512-coopassets/5123-hs-office-coopassets-rbac"); } } 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 4a36f63d..f45b52d4 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 @@ -109,6 +109,6 @@ public class HsOfficeCoopSharesTransactionEntity implements Stringifyable, HasUu } public static void main(String[] args) throws IOException { - rbac().generateWithBaseFileName("313-hs-office-coopshares-rbac"); + rbac().generateWithBaseFileName("5-hs-office/511-coopshares/5113-hs-office-coopshares-rbac"); } } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java index ee8e88a7..1c784078 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java @@ -188,6 +188,6 @@ public class HsOfficeDebitorEntity implements HasUuid, Stringifyable { } public static void main(String[] args) throws IOException { - rbac().generateWithBaseFileName("273-hs-office-debitor-rbac"); + rbac().generateWithBaseFileName("5-hs-office/506-debitor/5063-hs-office-debitor-rbac"); } } 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 ac1e5053..f21f5013 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 @@ -159,6 +159,6 @@ public class HsOfficeMembershipEntity implements HasUuid, Stringifyable { } public static void main(String[] args) throws IOException { - rbac().generateWithBaseFileName("303-hs-office-membership-rbac"); + rbac().generateWithBaseFileName("5-hs-office/510-membership/5103-hs-office-membership-rbac"); } } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerDetailsEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerDetailsEntity.java index 9a120ea3..a18dbc77 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerDetailsEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerDetailsEntity.java @@ -90,6 +90,6 @@ public class HsOfficePartnerDetailsEntity implements HasUuid, Stringifyable { } public static void main(String[] args) throws IOException { - rbac().generateWithBaseFileName("234-hs-office-partner-details-rbac"); + rbac().generateWithBaseFileName("5-hs-office/504-partner/5044-hs-office-partner-details-rbac"); } } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntity.java index 41db9bfc..7c9346ea 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntity.java @@ -113,6 +113,6 @@ public class HsOfficePartnerEntity implements Stringifyable, HasUuid { } public static void main(String[] args) throws IOException { - rbac().generateWithBaseFileName("233-hs-office-partner-rbac"); + rbac().generateWithBaseFileName("5-hs-office/504-partner/5043-hs-office-partner-rbac"); } } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonEntity.java index b930f9b6..e8865ce5 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonEntity.java @@ -86,6 +86,6 @@ public class HsOfficePersonEntity implements HasUuid, Stringifyable { public static void main(String[] args) throws IOException { - rbac().generateWithBaseFileName("213-hs-office-person-rbac"); + rbac().generateWithBaseFileName("5-hs-office/502-person/5023-hs-office-person-rbac"); } } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java index 5301983f..2077cf4a 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java @@ -130,6 +130,6 @@ public class HsOfficeRelationEntity implements HasUuid, Stringifyable { } public static void main(String[] args) throws IOException { - rbac().generateWithBaseFileName("223-hs-office-relation-rbac"); + rbac().generateWithBaseFileName("5-hs-office/503-relation/5033-hs-office-relation-rbac"); } } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntity.java index 897f89b8..403e2972 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntity.java @@ -141,6 +141,6 @@ public class HsOfficeSepaMandateEntity implements Stringifyable, HasUuid { } public static void main(String[] args) throws IOException { - rbac().generateWithBaseFileName("253-hs-office-sepamandate-rbac"); + rbac().generateWithBaseFileName("5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac"); } } diff --git a/src/main/java/net/hostsharing/hsadminng/test/cust/TestCustomerEntity.java b/src/main/java/net/hostsharing/hsadminng/test/cust/TestCustomerEntity.java index b4152fa9..94caa1de 100644 --- a/src/main/java/net/hostsharing/hsadminng/test/cust/TestCustomerEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/test/cust/TestCustomerEntity.java @@ -57,6 +57,6 @@ public class TestCustomerEntity implements HasUuid { } public static void main(String[] args) throws IOException { - rbac().generateWithBaseFileName("113-test-customer-rbac"); + rbac().generateWithBaseFileName("2-test/201-test-customer/2013-test-customer-rbac"); } } diff --git a/src/main/java/net/hostsharing/hsadminng/test/dom/TestDomainEntity.java b/src/main/java/net/hostsharing/hsadminng/test/dom/TestDomainEntity.java index 70626f89..d3d387d7 100644 --- a/src/main/java/net/hostsharing/hsadminng/test/dom/TestDomainEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/test/dom/TestDomainEntity.java @@ -67,6 +67,6 @@ public class TestDomainEntity implements HasUuid { } public static void main(String[] args) throws IOException { - rbac().generateWithBaseFileName("133-test-domain-rbac"); + rbac().generateWithBaseFileName("2-test/203-test-domain/2033-test-domain-rbac"); } } diff --git a/src/main/java/net/hostsharing/hsadminng/test/pac/TestPackageEntity.java b/src/main/java/net/hostsharing/hsadminng/test/pac/TestPackageEntity.java index 8f72fc4c..3ac28f34 100644 --- a/src/main/java/net/hostsharing/hsadminng/test/pac/TestPackageEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/test/pac/TestPackageEntity.java @@ -68,6 +68,6 @@ public class TestPackageEntity implements HasUuid { } public static void main(String[] args) throws IOException { - rbac().generateWithBaseFileName("123-test-package-rbac"); + rbac().generateWithBaseFileName("2-test/202-test-package/2023-test-package-rbac"); } } diff --git a/src/main/resources/db/changelog/000-template.sql b/src/main/resources/db/changelog/0-basis/000-template.sql similarity index 100% rename from src/main/resources/db/changelog/000-template.sql rename to src/main/resources/db/changelog/0-basis/000-template.sql diff --git a/src/main/resources/db/changelog/001-last-row-count.sql b/src/main/resources/db/changelog/0-basis/001-last-row-count.sql similarity index 100% rename from src/main/resources/db/changelog/001-last-row-count.sql rename to src/main/resources/db/changelog/0-basis/001-last-row-count.sql diff --git a/src/main/resources/db/changelog/002-int-to-var.sql b/src/main/resources/db/changelog/0-basis/002-int-to-var.sql similarity index 100% rename from src/main/resources/db/changelog/002-int-to-var.sql rename to src/main/resources/db/changelog/0-basis/002-int-to-var.sql diff --git a/src/main/resources/db/changelog/003-random-in-range.sql b/src/main/resources/db/changelog/0-basis/003-random-in-range.sql similarity index 100% rename from src/main/resources/db/changelog/003-random-in-range.sql rename to src/main/resources/db/changelog/0-basis/003-random-in-range.sql diff --git a/src/main/resources/db/changelog/004-jsonb-changes-delta.sql b/src/main/resources/db/changelog/0-basis/004-jsonb-changes-delta.sql similarity index 100% rename from src/main/resources/db/changelog/004-jsonb-changes-delta.sql rename to src/main/resources/db/changelog/0-basis/004-jsonb-changes-delta.sql diff --git a/src/main/resources/db/changelog/005-uuid-ossp-extension.sql b/src/main/resources/db/changelog/0-basis/005-uuid-ossp-extension.sql similarity index 100% rename from src/main/resources/db/changelog/005-uuid-ossp-extension.sql rename to src/main/resources/db/changelog/0-basis/005-uuid-ossp-extension.sql diff --git a/src/main/resources/db/changelog/006-numeric-hash-functions.sql b/src/main/resources/db/changelog/0-basis/006-numeric-hash-functions.sql similarity index 100% rename from src/main/resources/db/changelog/006-numeric-hash-functions.sql rename to src/main/resources/db/changelog/0-basis/006-numeric-hash-functions.sql diff --git a/src/main/resources/db/changelog/007-table-columns.sql b/src/main/resources/db/changelog/0-basis/007-table-columns.sql similarity index 100% rename from src/main/resources/db/changelog/007-table-columns.sql rename to src/main/resources/db/changelog/0-basis/007-table-columns.sql diff --git a/src/main/resources/db/changelog/009-check-environment.sql b/src/main/resources/db/changelog/0-basis/009-check-environment.sql similarity index 100% rename from src/main/resources/db/changelog/009-check-environment.sql rename to src/main/resources/db/changelog/0-basis/009-check-environment.sql diff --git a/src/main/resources/db/changelog/010-context.sql b/src/main/resources/db/changelog/0-basis/010-context.sql similarity index 100% rename from src/main/resources/db/changelog/010-context.sql rename to src/main/resources/db/changelog/0-basis/010-context.sql diff --git a/src/main/resources/db/changelog/020-audit-log.sql b/src/main/resources/db/changelog/0-basis/020-audit-log.sql similarity index 100% rename from src/main/resources/db/changelog/020-audit-log.sql rename to src/main/resources/db/changelog/0-basis/020-audit-log.sql diff --git a/src/main/resources/db/changelog/050-rbac-base.sql b/src/main/resources/db/changelog/1-rbac/1050-rbac-base.sql similarity index 100% rename from src/main/resources/db/changelog/050-rbac-base.sql rename to src/main/resources/db/changelog/1-rbac/1050-rbac-base.sql diff --git a/src/main/resources/db/changelog/051-rbac-user-grant.sql b/src/main/resources/db/changelog/1-rbac/1051-rbac-user-grant.sql similarity index 100% rename from src/main/resources/db/changelog/051-rbac-user-grant.sql rename to src/main/resources/db/changelog/1-rbac/1051-rbac-user-grant.sql diff --git a/src/main/resources/db/changelog/054-rbac-context.sql b/src/main/resources/db/changelog/1-rbac/1054-rbac-context.sql similarity index 100% rename from src/main/resources/db/changelog/054-rbac-context.sql rename to src/main/resources/db/changelog/1-rbac/1054-rbac-context.sql diff --git a/src/main/resources/db/changelog/055-rbac-views.sql b/src/main/resources/db/changelog/1-rbac/1055-rbac-views.sql similarity index 100% rename from src/main/resources/db/changelog/055-rbac-views.sql rename to src/main/resources/db/changelog/1-rbac/1055-rbac-views.sql diff --git a/src/main/resources/db/changelog/056-rbac-trigger-context.sql b/src/main/resources/db/changelog/1-rbac/1056-rbac-trigger-context.sql similarity index 100% rename from src/main/resources/db/changelog/056-rbac-trigger-context.sql rename to src/main/resources/db/changelog/1-rbac/1056-rbac-trigger-context.sql diff --git a/src/main/resources/db/changelog/057-rbac-role-builder.sql b/src/main/resources/db/changelog/1-rbac/1057-rbac-role-builder.sql similarity index 100% rename from src/main/resources/db/changelog/057-rbac-role-builder.sql rename to src/main/resources/db/changelog/1-rbac/1057-rbac-role-builder.sql diff --git a/src/main/resources/db/changelog/058-rbac-generators.sql b/src/main/resources/db/changelog/1-rbac/1058-rbac-generators.sql similarity index 100% rename from src/main/resources/db/changelog/058-rbac-generators.sql rename to src/main/resources/db/changelog/1-rbac/1058-rbac-generators.sql diff --git a/src/main/resources/db/changelog/059-rbac-statistics.sql b/src/main/resources/db/changelog/1-rbac/1059-rbac-statistics.sql similarity index 100% rename from src/main/resources/db/changelog/059-rbac-statistics.sql rename to src/main/resources/db/changelog/1-rbac/1059-rbac-statistics.sql diff --git a/src/main/resources/db/changelog/080-rbac-global.sql b/src/main/resources/db/changelog/1-rbac/1080-rbac-global.sql similarity index 100% rename from src/main/resources/db/changelog/080-rbac-global.sql rename to src/main/resources/db/changelog/1-rbac/1080-rbac-global.sql diff --git a/src/main/resources/db/changelog/110-test-customer.sql b/src/main/resources/db/changelog/2-test/201-test-customer/2010-test-customer.sql similarity index 100% rename from src/main/resources/db/changelog/110-test-customer.sql rename to src/main/resources/db/changelog/2-test/201-test-customer/2010-test-customer.sql diff --git a/src/main/resources/db/changelog/113-test-customer-rbac.md b/src/main/resources/db/changelog/2-test/201-test-customer/2013-test-customer-rbac.md similarity index 100% rename from src/main/resources/db/changelog/113-test-customer-rbac.md rename to src/main/resources/db/changelog/2-test/201-test-customer/2013-test-customer-rbac.md diff --git a/src/main/resources/db/changelog/113-test-customer-rbac.sql b/src/main/resources/db/changelog/2-test/201-test-customer/2013-test-customer-rbac.sql similarity index 100% rename from src/main/resources/db/changelog/113-test-customer-rbac.sql rename to src/main/resources/db/changelog/2-test/201-test-customer/2013-test-customer-rbac.sql diff --git a/src/main/resources/db/changelog/118-test-customer-test-data.sql b/src/main/resources/db/changelog/2-test/201-test-customer/2018-test-customer-test-data.sql similarity index 100% rename from src/main/resources/db/changelog/118-test-customer-test-data.sql rename to src/main/resources/db/changelog/2-test/201-test-customer/2018-test-customer-test-data.sql diff --git a/src/main/resources/db/changelog/120-test-package.sql b/src/main/resources/db/changelog/2-test/202-test-package/2020-test-package.sql similarity index 100% rename from src/main/resources/db/changelog/120-test-package.sql rename to src/main/resources/db/changelog/2-test/202-test-package/2020-test-package.sql diff --git a/src/main/resources/db/changelog/123-test-package-rbac.md b/src/main/resources/db/changelog/2-test/202-test-package/2023-test-package-rbac.md similarity index 100% rename from src/main/resources/db/changelog/123-test-package-rbac.md rename to src/main/resources/db/changelog/2-test/202-test-package/2023-test-package-rbac.md diff --git a/src/main/resources/db/changelog/123-test-package-rbac.sql b/src/main/resources/db/changelog/2-test/202-test-package/2023-test-package-rbac.sql similarity index 100% rename from src/main/resources/db/changelog/123-test-package-rbac.sql rename to src/main/resources/db/changelog/2-test/202-test-package/2023-test-package-rbac.sql diff --git a/src/main/resources/db/changelog/128-test-package-test-data.sql b/src/main/resources/db/changelog/2-test/202-test-package/2028-test-package-test-data.sql similarity index 100% rename from src/main/resources/db/changelog/128-test-package-test-data.sql rename to src/main/resources/db/changelog/2-test/202-test-package/2028-test-package-test-data.sql diff --git a/src/main/resources/db/changelog/130-test-domain.sql b/src/main/resources/db/changelog/2-test/203-test-domain/2030-test-domain.sql similarity index 100% rename from src/main/resources/db/changelog/130-test-domain.sql rename to src/main/resources/db/changelog/2-test/203-test-domain/2030-test-domain.sql diff --git a/src/main/resources/db/changelog/133-test-domain-rbac.md b/src/main/resources/db/changelog/2-test/203-test-domain/2033-test-domain-rbac.md similarity index 100% rename from src/main/resources/db/changelog/133-test-domain-rbac.md rename to src/main/resources/db/changelog/2-test/203-test-domain/2033-test-domain-rbac.md diff --git a/src/main/resources/db/changelog/133-test-domain-rbac.sql b/src/main/resources/db/changelog/2-test/203-test-domain/2033-test-domain-rbac.sql similarity index 100% rename from src/main/resources/db/changelog/133-test-domain-rbac.sql rename to src/main/resources/db/changelog/2-test/203-test-domain/2033-test-domain-rbac.sql diff --git a/src/main/resources/db/changelog/138-test-domain-test-data.sql b/src/main/resources/db/changelog/2-test/203-test-domain/2038-test-domain-test-data.sql similarity index 100% rename from src/main/resources/db/changelog/138-test-domain-test-data.sql rename to src/main/resources/db/changelog/2-test/203-test-domain/2038-test-domain-test-data.sql diff --git a/src/main/resources/db/changelog/313-hs-office-coopshares-rbac.md b/src/main/resources/db/changelog/313-hs-office-coopshares-rbac.md deleted file mode 100644 index cdc18b6f..00000000 --- a/src/main/resources/db/changelog/313-hs-office-coopshares-rbac.md +++ /dev/null @@ -1,250 +0,0 @@ -### rbac coopSharesTransaction - -This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually. - -```mermaid -%%{init:{'flowchart':{'htmlLabels':false}}}%% -flowchart TB - -subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"] - direction TB - style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.holderPerson:roles[ ] - style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel.holderPerson:owner[[membership.partnerRel.holderPerson:owner]] - role:membership.partnerRel.holderPerson:admin[[membership.partnerRel.holderPerson:admin]] - role:membership.partnerRel.holderPerson:referrer[[membership.partnerRel.holderPerson:referrer]] - end -end - -subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"] - direction TB - style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.anchorPerson:roles[ ] - style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel.anchorPerson:owner[[membership.partnerRel.anchorPerson:owner]] - role:membership.partnerRel.anchorPerson:admin[[membership.partnerRel.anchorPerson:admin]] - role:membership.partnerRel.anchorPerson:referrer[[membership.partnerRel.anchorPerson:referrer]] - end -end - -subgraph coopSharesTransaction["`**coopSharesTransaction**`"] - direction TB - style coopSharesTransaction fill:#dd4901,stroke:#274d6e,stroke-width:8px - - subgraph coopSharesTransaction:permissions[ ] - style coopSharesTransaction:permissions fill:#dd4901,stroke:white - - perm:coopSharesTransaction:INSERT{{coopSharesTransaction:INSERT}} - perm:coopSharesTransaction:UPDATE{{coopSharesTransaction:UPDATE}} - perm:coopSharesTransaction:SELECT{{coopSharesTransaction:SELECT}} - end -end - -subgraph membership["`**membership**`"] - direction TB - style membership fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"] - direction TB - style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.holderPerson:roles[ ] - style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel.holderPerson:owner[[membership.partnerRel.holderPerson:owner]] - role:membership.partnerRel.holderPerson:admin[[membership.partnerRel.holderPerson:admin]] - role:membership.partnerRel.holderPerson:referrer[[membership.partnerRel.holderPerson:referrer]] - end - end - - subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"] - direction TB - style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.anchorPerson:roles[ ] - style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel.anchorPerson:owner[[membership.partnerRel.anchorPerson:owner]] - role:membership.partnerRel.anchorPerson:admin[[membership.partnerRel.anchorPerson:admin]] - role:membership.partnerRel.anchorPerson:referrer[[membership.partnerRel.anchorPerson:referrer]] - end - end - - subgraph membership.partnerRel["`**membership.partnerRel**`"] - direction TB - style membership.partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px - subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"] - direction TB - style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.holderPerson:roles[ ] - style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel.holderPerson:owner[[membership.partnerRel.holderPerson:owner]] - role:membership.partnerRel.holderPerson:admin[[membership.partnerRel.holderPerson:admin]] - role:membership.partnerRel.holderPerson:referrer[[membership.partnerRel.holderPerson:referrer]] - end - end - - subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"] - direction TB - style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.anchorPerson:roles[ ] - style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel.anchorPerson:owner[[membership.partnerRel.anchorPerson:owner]] - role:membership.partnerRel.anchorPerson:admin[[membership.partnerRel.anchorPerson:admin]] - role:membership.partnerRel.anchorPerson:referrer[[membership.partnerRel.anchorPerson:referrer]] - end - end - - subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"] - direction TB - style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.contact:roles[ ] - style membership.partnerRel.contact:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel.contact:owner[[membership.partnerRel.contact:owner]] - role:membership.partnerRel.contact:admin[[membership.partnerRel.contact:admin]] - role:membership.partnerRel.contact:referrer[[membership.partnerRel.contact:referrer]] - end - end - - subgraph membership.partnerRel:roles[ ] - style membership.partnerRel:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel:owner[[membership.partnerRel:owner]] - role:membership.partnerRel:admin[[membership.partnerRel:admin]] - role:membership.partnerRel:agent[[membership.partnerRel:agent]] - role:membership.partnerRel:tenant[[membership.partnerRel:tenant]] - end - end - - subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"] - direction TB - style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.contact:roles[ ] - style membership.partnerRel.contact:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel.contact:owner[[membership.partnerRel.contact:owner]] - role:membership.partnerRel.contact:admin[[membership.partnerRel.contact:admin]] - role:membership.partnerRel.contact:referrer[[membership.partnerRel.contact:referrer]] - end - end - - subgraph membership:roles[ ] - style membership:roles fill:#99bcdb,stroke:white - - role:membership:owner[[membership:owner]] - role:membership:admin[[membership:admin]] - role:membership:referrer[[membership:referrer]] - end -end - -subgraph membership.partnerRel["`**membership.partnerRel**`"] - direction TB - style membership.partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"] - direction TB - style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.holderPerson:roles[ ] - style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel.holderPerson:owner[[membership.partnerRel.holderPerson:owner]] - role:membership.partnerRel.holderPerson:admin[[membership.partnerRel.holderPerson:admin]] - role:membership.partnerRel.holderPerson:referrer[[membership.partnerRel.holderPerson:referrer]] - end - end - - subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"] - direction TB - style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.anchorPerson:roles[ ] - style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel.anchorPerson:owner[[membership.partnerRel.anchorPerson:owner]] - role:membership.partnerRel.anchorPerson:admin[[membership.partnerRel.anchorPerson:admin]] - role:membership.partnerRel.anchorPerson:referrer[[membership.partnerRel.anchorPerson:referrer]] - end - end - - subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"] - direction TB - style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.contact:roles[ ] - style membership.partnerRel.contact:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel.contact:owner[[membership.partnerRel.contact:owner]] - role:membership.partnerRel.contact:admin[[membership.partnerRel.contact:admin]] - role:membership.partnerRel.contact:referrer[[membership.partnerRel.contact:referrer]] - end - end - - subgraph membership.partnerRel:roles[ ] - style membership.partnerRel:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel:owner[[membership.partnerRel:owner]] - role:membership.partnerRel:admin[[membership.partnerRel:admin]] - role:membership.partnerRel:agent[[membership.partnerRel:agent]] - role:membership.partnerRel:tenant[[membership.partnerRel:tenant]] - end -end - -subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"] - direction TB - style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.contact:roles[ ] - style membership.partnerRel.contact:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel.contact:owner[[membership.partnerRel.contact:owner]] - role:membership.partnerRel.contact:admin[[membership.partnerRel.contact:admin]] - role:membership.partnerRel.contact:referrer[[membership.partnerRel.contact:referrer]] - end -end - -%% granting roles to roles -role:global:admin -.-> role:membership.partnerRel.anchorPerson:owner -role:membership.partnerRel.anchorPerson:owner -.-> role:membership.partnerRel.anchorPerson:admin -role:membership.partnerRel.anchorPerson:admin -.-> role:membership.partnerRel.anchorPerson:referrer -role:global:admin -.-> role:membership.partnerRel.holderPerson:owner -role:membership.partnerRel.holderPerson:owner -.-> role:membership.partnerRel.holderPerson:admin -role:membership.partnerRel.holderPerson:admin -.-> role:membership.partnerRel.holderPerson:referrer -role:global:admin -.-> role:membership.partnerRel.contact:owner -role:membership.partnerRel.contact:owner -.-> role:membership.partnerRel.contact:admin -role:membership.partnerRel.contact:admin -.-> role:membership.partnerRel.contact:referrer -role:global:admin -.-> role:membership.partnerRel:owner -role:membership.partnerRel:owner -.-> role:membership.partnerRel:admin -role:membership.partnerRel.anchorPerson:admin -.-> role:membership.partnerRel:admin -role:membership.partnerRel:admin -.-> role:membership.partnerRel:agent -role:membership.partnerRel.holderPerson:admin -.-> role:membership.partnerRel:agent -role:membership.partnerRel:agent -.-> role:membership.partnerRel:tenant -role:membership.partnerRel.holderPerson:admin -.-> role:membership.partnerRel:tenant -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 - -%% granting permissions to roles -role:membership:admin ==> perm:coopSharesTransaction:INSERT -role:membership:admin ==> perm:coopSharesTransaction:UPDATE -role:membership:admin ==> perm:coopSharesTransaction:SELECT - -``` diff --git a/src/main/resources/db/changelog/323-hs-office-coopassets-rbac.md b/src/main/resources/db/changelog/323-hs-office-coopassets-rbac.md deleted file mode 100644 index cbbe3fad..00000000 --- a/src/main/resources/db/changelog/323-hs-office-coopassets-rbac.md +++ /dev/null @@ -1,250 +0,0 @@ -### rbac coopAssetsTransaction - -This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually. - -```mermaid -%%{init:{'flowchart':{'htmlLabels':false}}}%% -flowchart TB - -subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"] - direction TB - style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.holderPerson:roles[ ] - style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel.holderPerson:owner[[membership.partnerRel.holderPerson:owner]] - role:membership.partnerRel.holderPerson:admin[[membership.partnerRel.holderPerson:admin]] - role:membership.partnerRel.holderPerson:referrer[[membership.partnerRel.holderPerson:referrer]] - end -end - -subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"] - direction TB - style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.anchorPerson:roles[ ] - style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel.anchorPerson:owner[[membership.partnerRel.anchorPerson:owner]] - role:membership.partnerRel.anchorPerson:admin[[membership.partnerRel.anchorPerson:admin]] - role:membership.partnerRel.anchorPerson:referrer[[membership.partnerRel.anchorPerson:referrer]] - end -end - -subgraph coopAssetsTransaction["`**coopAssetsTransaction**`"] - direction TB - style coopAssetsTransaction fill:#dd4901,stroke:#274d6e,stroke-width:8px - - subgraph coopAssetsTransaction:permissions[ ] - style coopAssetsTransaction:permissions fill:#dd4901,stroke:white - - perm:coopAssetsTransaction:INSERT{{coopAssetsTransaction:INSERT}} - perm:coopAssetsTransaction:UPDATE{{coopAssetsTransaction:UPDATE}} - perm:coopAssetsTransaction:SELECT{{coopAssetsTransaction:SELECT}} - end -end - -subgraph membership["`**membership**`"] - direction TB - style membership fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"] - direction TB - style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.holderPerson:roles[ ] - style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel.holderPerson:owner[[membership.partnerRel.holderPerson:owner]] - role:membership.partnerRel.holderPerson:admin[[membership.partnerRel.holderPerson:admin]] - role:membership.partnerRel.holderPerson:referrer[[membership.partnerRel.holderPerson:referrer]] - end - end - - subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"] - direction TB - style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.anchorPerson:roles[ ] - style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel.anchorPerson:owner[[membership.partnerRel.anchorPerson:owner]] - role:membership.partnerRel.anchorPerson:admin[[membership.partnerRel.anchorPerson:admin]] - role:membership.partnerRel.anchorPerson:referrer[[membership.partnerRel.anchorPerson:referrer]] - end - end - - subgraph membership.partnerRel["`**membership.partnerRel**`"] - direction TB - style membership.partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px - subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"] - direction TB - style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.holderPerson:roles[ ] - style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel.holderPerson:owner[[membership.partnerRel.holderPerson:owner]] - role:membership.partnerRel.holderPerson:admin[[membership.partnerRel.holderPerson:admin]] - role:membership.partnerRel.holderPerson:referrer[[membership.partnerRel.holderPerson:referrer]] - end - end - - subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"] - direction TB - style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.anchorPerson:roles[ ] - style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel.anchorPerson:owner[[membership.partnerRel.anchorPerson:owner]] - role:membership.partnerRel.anchorPerson:admin[[membership.partnerRel.anchorPerson:admin]] - role:membership.partnerRel.anchorPerson:referrer[[membership.partnerRel.anchorPerson:referrer]] - end - end - - subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"] - direction TB - style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.contact:roles[ ] - style membership.partnerRel.contact:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel.contact:owner[[membership.partnerRel.contact:owner]] - role:membership.partnerRel.contact:admin[[membership.partnerRel.contact:admin]] - role:membership.partnerRel.contact:referrer[[membership.partnerRel.contact:referrer]] - end - end - - subgraph membership.partnerRel:roles[ ] - style membership.partnerRel:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel:owner[[membership.partnerRel:owner]] - role:membership.partnerRel:admin[[membership.partnerRel:admin]] - role:membership.partnerRel:agent[[membership.partnerRel:agent]] - role:membership.partnerRel:tenant[[membership.partnerRel:tenant]] - end - end - - subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"] - direction TB - style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.contact:roles[ ] - style membership.partnerRel.contact:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel.contact:owner[[membership.partnerRel.contact:owner]] - role:membership.partnerRel.contact:admin[[membership.partnerRel.contact:admin]] - role:membership.partnerRel.contact:referrer[[membership.partnerRel.contact:referrer]] - end - end - - subgraph membership:roles[ ] - style membership:roles fill:#99bcdb,stroke:white - - role:membership:owner[[membership:owner]] - role:membership:admin[[membership:admin]] - role:membership:referrer[[membership:referrer]] - end -end - -subgraph membership.partnerRel["`**membership.partnerRel**`"] - direction TB - style membership.partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"] - direction TB - style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.holderPerson:roles[ ] - style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel.holderPerson:owner[[membership.partnerRel.holderPerson:owner]] - role:membership.partnerRel.holderPerson:admin[[membership.partnerRel.holderPerson:admin]] - role:membership.partnerRel.holderPerson:referrer[[membership.partnerRel.holderPerson:referrer]] - end - end - - subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"] - direction TB - style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.anchorPerson:roles[ ] - style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel.anchorPerson:owner[[membership.partnerRel.anchorPerson:owner]] - role:membership.partnerRel.anchorPerson:admin[[membership.partnerRel.anchorPerson:admin]] - role:membership.partnerRel.anchorPerson:referrer[[membership.partnerRel.anchorPerson:referrer]] - end - end - - subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"] - direction TB - style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.contact:roles[ ] - style membership.partnerRel.contact:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel.contact:owner[[membership.partnerRel.contact:owner]] - role:membership.partnerRel.contact:admin[[membership.partnerRel.contact:admin]] - role:membership.partnerRel.contact:referrer[[membership.partnerRel.contact:referrer]] - end - end - - subgraph membership.partnerRel:roles[ ] - style membership.partnerRel:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel:owner[[membership.partnerRel:owner]] - role:membership.partnerRel:admin[[membership.partnerRel:admin]] - role:membership.partnerRel:agent[[membership.partnerRel:agent]] - role:membership.partnerRel:tenant[[membership.partnerRel:tenant]] - end -end - -subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"] - direction TB - style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph membership.partnerRel.contact:roles[ ] - style membership.partnerRel.contact:roles fill:#99bcdb,stroke:white - - role:membership.partnerRel.contact:owner[[membership.partnerRel.contact:owner]] - role:membership.partnerRel.contact:admin[[membership.partnerRel.contact:admin]] - role:membership.partnerRel.contact:referrer[[membership.partnerRel.contact:referrer]] - end -end - -%% granting roles to roles -role:global:admin -.-> role:membership.partnerRel.anchorPerson:owner -role:membership.partnerRel.anchorPerson:owner -.-> role:membership.partnerRel.anchorPerson:admin -role:membership.partnerRel.anchorPerson:admin -.-> role:membership.partnerRel.anchorPerson:referrer -role:global:admin -.-> role:membership.partnerRel.holderPerson:owner -role:membership.partnerRel.holderPerson:owner -.-> role:membership.partnerRel.holderPerson:admin -role:membership.partnerRel.holderPerson:admin -.-> role:membership.partnerRel.holderPerson:referrer -role:global:admin -.-> role:membership.partnerRel.contact:owner -role:membership.partnerRel.contact:owner -.-> role:membership.partnerRel.contact:admin -role:membership.partnerRel.contact:admin -.-> role:membership.partnerRel.contact:referrer -role:global:admin -.-> role:membership.partnerRel:owner -role:membership.partnerRel:owner -.-> role:membership.partnerRel:admin -role:membership.partnerRel.anchorPerson:admin -.-> role:membership.partnerRel:admin -role:membership.partnerRel:admin -.-> role:membership.partnerRel:agent -role:membership.partnerRel.holderPerson:admin -.-> role:membership.partnerRel:agent -role:membership.partnerRel:agent -.-> role:membership.partnerRel:tenant -role:membership.partnerRel.holderPerson:admin -.-> role:membership.partnerRel:tenant -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 - -%% granting permissions to roles -role:membership:admin ==> perm:coopAssetsTransaction:INSERT -role:membership:admin ==> perm:coopAssetsTransaction:UPDATE -role:membership:admin ==> perm:coopAssetsTransaction:SELECT - -``` diff --git a/src/main/resources/db/changelog/200-hs-office-contact.sql b/src/main/resources/db/changelog/5-hs-office/501-contact/5010-hs-office-contact.sql similarity index 100% rename from src/main/resources/db/changelog/200-hs-office-contact.sql rename to src/main/resources/db/changelog/5-hs-office/501-contact/5010-hs-office-contact.sql diff --git a/src/main/resources/db/changelog/203-hs-office-contact-rbac.md b/src/main/resources/db/changelog/5-hs-office/501-contact/5013-hs-office-contact-rbac.md similarity index 100% rename from src/main/resources/db/changelog/203-hs-office-contact-rbac.md rename to src/main/resources/db/changelog/5-hs-office/501-contact/5013-hs-office-contact-rbac.md diff --git a/src/main/resources/db/changelog/203-hs-office-contact-rbac.sql b/src/main/resources/db/changelog/5-hs-office/501-contact/5013-hs-office-contact-rbac.sql similarity index 100% rename from src/main/resources/db/changelog/203-hs-office-contact-rbac.sql rename to src/main/resources/db/changelog/5-hs-office/501-contact/5013-hs-office-contact-rbac.sql diff --git a/src/main/resources/db/changelog/206-hs-office-contact-migration.sql b/src/main/resources/db/changelog/5-hs-office/501-contact/5016-hs-office-contact-migration.sql similarity index 100% rename from src/main/resources/db/changelog/206-hs-office-contact-migration.sql rename to src/main/resources/db/changelog/5-hs-office/501-contact/5016-hs-office-contact-migration.sql diff --git a/src/main/resources/db/changelog/208-hs-office-contact-test-data.sql b/src/main/resources/db/changelog/5-hs-office/501-contact/5018-hs-office-contact-test-data.sql similarity index 100% rename from src/main/resources/db/changelog/208-hs-office-contact-test-data.sql rename to src/main/resources/db/changelog/5-hs-office/501-contact/5018-hs-office-contact-test-data.sql diff --git a/src/main/resources/db/changelog/210-hs-office-person.sql b/src/main/resources/db/changelog/5-hs-office/502-person/5020-hs-office-person.sql similarity index 100% rename from src/main/resources/db/changelog/210-hs-office-person.sql rename to src/main/resources/db/changelog/5-hs-office/502-person/5020-hs-office-person.sql diff --git a/src/main/resources/db/changelog/213-hs-office-person-rbac.md b/src/main/resources/db/changelog/5-hs-office/502-person/5023-hs-office-person-rbac.md similarity index 100% rename from src/main/resources/db/changelog/213-hs-office-person-rbac.md rename to src/main/resources/db/changelog/5-hs-office/502-person/5023-hs-office-person-rbac.md diff --git a/src/main/resources/db/changelog/213-hs-office-person-rbac.sql b/src/main/resources/db/changelog/5-hs-office/502-person/5023-hs-office-person-rbac.sql similarity index 100% rename from src/main/resources/db/changelog/213-hs-office-person-rbac.sql rename to src/main/resources/db/changelog/5-hs-office/502-person/5023-hs-office-person-rbac.sql diff --git a/src/main/resources/db/changelog/218-hs-office-person-test-data.sql b/src/main/resources/db/changelog/5-hs-office/502-person/5028-hs-office-person-test-data.sql similarity index 100% rename from src/main/resources/db/changelog/218-hs-office-person-test-data.sql rename to src/main/resources/db/changelog/5-hs-office/502-person/5028-hs-office-person-test-data.sql diff --git a/src/main/resources/db/changelog/220-hs-office-relation.sql b/src/main/resources/db/changelog/5-hs-office/503-relation/5030-hs-office-relation.sql similarity index 100% rename from src/main/resources/db/changelog/220-hs-office-relation.sql rename to src/main/resources/db/changelog/5-hs-office/503-relation/5030-hs-office-relation.sql diff --git a/src/main/resources/db/changelog/223-hs-office-relation-rbac.md b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md similarity index 100% rename from src/main/resources/db/changelog/223-hs-office-relation-rbac.md rename to src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md diff --git a/src/main/resources/db/changelog/223-hs-office-relation-rbac.sql b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql similarity index 100% rename from src/main/resources/db/changelog/223-hs-office-relation-rbac.sql rename to src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql diff --git a/src/main/resources/db/changelog/228-hs-office-relation-test-data.sql b/src/main/resources/db/changelog/5-hs-office/503-relation/5038-hs-office-relation-test-data.sql similarity index 100% rename from src/main/resources/db/changelog/228-hs-office-relation-test-data.sql rename to src/main/resources/db/changelog/5-hs-office/503-relation/5038-hs-office-relation-test-data.sql diff --git a/src/main/resources/db/changelog/230-hs-office-partner.sql b/src/main/resources/db/changelog/5-hs-office/504-partner/5040-hs-office-partner.sql similarity index 100% rename from src/main/resources/db/changelog/230-hs-office-partner.sql rename to src/main/resources/db/changelog/5-hs-office/504-partner/5040-hs-office-partner.sql diff --git a/src/main/resources/db/changelog/233-hs-office-partner-rbac.md b/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.md similarity index 100% rename from src/main/resources/db/changelog/233-hs-office-partner-rbac.md rename to src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.md diff --git a/src/main/resources/db/changelog/233-hs-office-partner-rbac.sql b/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.sql similarity index 100% rename from src/main/resources/db/changelog/233-hs-office-partner-rbac.sql rename to src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.sql diff --git a/src/main/resources/db/changelog/234-hs-office-partner-details-rbac.md b/src/main/resources/db/changelog/5-hs-office/504-partner/5044-hs-office-partner-details-rbac.md similarity index 100% rename from src/main/resources/db/changelog/234-hs-office-partner-details-rbac.md rename to src/main/resources/db/changelog/5-hs-office/504-partner/5044-hs-office-partner-details-rbac.md diff --git a/src/main/resources/db/changelog/234-hs-office-partner-details-rbac.sql b/src/main/resources/db/changelog/5-hs-office/504-partner/5044-hs-office-partner-details-rbac.sql similarity index 100% rename from src/main/resources/db/changelog/234-hs-office-partner-details-rbac.sql rename to src/main/resources/db/changelog/5-hs-office/504-partner/5044-hs-office-partner-details-rbac.sql diff --git a/src/main/resources/db/changelog/236-hs-office-partner-migration.sql b/src/main/resources/db/changelog/5-hs-office/504-partner/5046-hs-office-partner-migration.sql similarity index 100% rename from src/main/resources/db/changelog/236-hs-office-partner-migration.sql rename to src/main/resources/db/changelog/5-hs-office/504-partner/5046-hs-office-partner-migration.sql diff --git a/src/main/resources/db/changelog/238-hs-office-partner-test-data.sql b/src/main/resources/db/changelog/5-hs-office/504-partner/5048-hs-office-partner-test-data.sql similarity index 100% rename from src/main/resources/db/changelog/238-hs-office-partner-test-data.sql rename to src/main/resources/db/changelog/5-hs-office/504-partner/5048-hs-office-partner-test-data.sql diff --git a/src/main/resources/db/changelog/240-hs-office-bankaccount.sql b/src/main/resources/db/changelog/5-hs-office/505-bankaccount/5050-hs-office-bankaccount.sql similarity index 100% rename from src/main/resources/db/changelog/240-hs-office-bankaccount.sql rename to src/main/resources/db/changelog/5-hs-office/505-bankaccount/5050-hs-office-bankaccount.sql diff --git a/src/main/resources/db/changelog/243-hs-office-bankaccount-rbac.md b/src/main/resources/db/changelog/5-hs-office/505-bankaccount/5053-hs-office-bankaccount-rbac.md similarity index 100% rename from src/main/resources/db/changelog/243-hs-office-bankaccount-rbac.md rename to src/main/resources/db/changelog/5-hs-office/505-bankaccount/5053-hs-office-bankaccount-rbac.md diff --git a/src/main/resources/db/changelog/243-hs-office-bankaccount-rbac.sql b/src/main/resources/db/changelog/5-hs-office/505-bankaccount/5053-hs-office-bankaccount-rbac.sql similarity index 100% rename from src/main/resources/db/changelog/243-hs-office-bankaccount-rbac.sql rename to src/main/resources/db/changelog/5-hs-office/505-bankaccount/5053-hs-office-bankaccount-rbac.sql diff --git a/src/main/resources/db/changelog/248-hs-office-bankaccount-test-data.sql b/src/main/resources/db/changelog/5-hs-office/505-bankaccount/5058-hs-office-bankaccount-test-data.sql similarity index 100% rename from src/main/resources/db/changelog/248-hs-office-bankaccount-test-data.sql rename to src/main/resources/db/changelog/5-hs-office/505-bankaccount/5058-hs-office-bankaccount-test-data.sql diff --git a/src/main/resources/db/changelog/270-hs-office-debitor.sql b/src/main/resources/db/changelog/5-hs-office/506-debitor/5060-hs-office-debitor.sql similarity index 100% rename from src/main/resources/db/changelog/270-hs-office-debitor.sql rename to src/main/resources/db/changelog/5-hs-office/506-debitor/5060-hs-office-debitor.sql diff --git a/src/main/resources/db/changelog/273-hs-office-debitor-rbac.md b/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.md similarity index 100% rename from src/main/resources/db/changelog/273-hs-office-debitor-rbac.md rename to src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.md diff --git a/src/main/resources/db/changelog/273-hs-office-debitor-rbac.sql b/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.sql similarity index 100% rename from src/main/resources/db/changelog/273-hs-office-debitor-rbac.sql rename to src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.sql diff --git a/src/main/resources/db/changelog/278-hs-office-debitor-test-data.sql b/src/main/resources/db/changelog/5-hs-office/506-debitor/5068-hs-office-debitor-test-data.sql similarity index 100% rename from src/main/resources/db/changelog/278-hs-office-debitor-test-data.sql rename to src/main/resources/db/changelog/5-hs-office/506-debitor/5068-hs-office-debitor-test-data.sql diff --git a/src/main/resources/db/changelog/250-hs-office-sepamandate.sql b/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5070-hs-office-sepamandate.sql similarity index 100% rename from src/main/resources/db/changelog/250-hs-office-sepamandate.sql rename to src/main/resources/db/changelog/5-hs-office/507-sepamandate/5070-hs-office-sepamandate.sql diff --git a/src/main/resources/db/changelog/253-hs-office-sepamandate-rbac.md b/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.md similarity index 100% rename from src/main/resources/db/changelog/253-hs-office-sepamandate-rbac.md rename to src/main/resources/db/changelog/5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.md diff --git a/src/main/resources/db/changelog/253-hs-office-sepamandate-rbac.sql b/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.sql similarity index 100% rename from src/main/resources/db/changelog/253-hs-office-sepamandate-rbac.sql rename to src/main/resources/db/changelog/5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.sql diff --git a/src/main/resources/db/changelog/256-hs-office-sepamandate-migration.sql b/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5076-hs-office-sepamandate-migration.sql similarity index 100% rename from src/main/resources/db/changelog/256-hs-office-sepamandate-migration.sql rename to src/main/resources/db/changelog/5-hs-office/507-sepamandate/5076-hs-office-sepamandate-migration.sql diff --git a/src/main/resources/db/changelog/258-hs-office-sepamandate-test-data.sql b/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5078-hs-office-sepamandate-test-data.sql similarity index 100% rename from src/main/resources/db/changelog/258-hs-office-sepamandate-test-data.sql rename to src/main/resources/db/changelog/5-hs-office/507-sepamandate/5078-hs-office-sepamandate-test-data.sql diff --git a/src/main/resources/db/changelog/300-hs-office-membership.sql b/src/main/resources/db/changelog/5-hs-office/510-membership/5100-hs-office-membership.sql similarity index 100% rename from src/main/resources/db/changelog/300-hs-office-membership.sql rename to src/main/resources/db/changelog/5-hs-office/510-membership/5100-hs-office-membership.sql diff --git a/src/main/resources/db/changelog/303-hs-office-membership-rbac.md b/src/main/resources/db/changelog/5-hs-office/510-membership/5103-hs-office-membership-rbac.md similarity index 100% rename from src/main/resources/db/changelog/303-hs-office-membership-rbac.md rename to src/main/resources/db/changelog/5-hs-office/510-membership/5103-hs-office-membership-rbac.md diff --git a/src/main/resources/db/changelog/303-hs-office-membership-rbac.sql b/src/main/resources/db/changelog/5-hs-office/510-membership/5103-hs-office-membership-rbac.sql similarity index 100% rename from src/main/resources/db/changelog/303-hs-office-membership-rbac.sql rename to src/main/resources/db/changelog/5-hs-office/510-membership/5103-hs-office-membership-rbac.sql diff --git a/src/main/resources/db/changelog/308-hs-office-membership-test-data.sql b/src/main/resources/db/changelog/5-hs-office/510-membership/5108-hs-office-membership-test-data.sql similarity index 100% rename from src/main/resources/db/changelog/308-hs-office-membership-test-data.sql rename to src/main/resources/db/changelog/5-hs-office/510-membership/5108-hs-office-membership-test-data.sql diff --git a/src/main/resources/db/changelog/310-hs-office-coopshares.sql b/src/main/resources/db/changelog/5-hs-office/511-coopshares/5110-hs-office-coopshares.sql similarity index 100% rename from src/main/resources/db/changelog/310-hs-office-coopshares.sql rename to src/main/resources/db/changelog/5-hs-office/511-coopshares/5110-hs-office-coopshares.sql 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 new file mode 100644 index 00000000..129de47c --- /dev/null +++ b/src/main/resources/db/changelog/5-hs-office/511-coopshares/5113-hs-office-coopshares-rbac.md @@ -0,0 +1,120 @@ +### rbac coopSharesTransaction + +This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually. + +```mermaid +%%{init:{'flowchart':{'htmlLabels':false}}}%% +flowchart TB + +subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"] + direction TB + style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.holderPerson:roles[ ] + style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.holderPerson:OWNER[[membership.partnerRel.holderPerson:OWNER]] + role:membership.partnerRel.holderPerson:ADMIN[[membership.partnerRel.holderPerson:ADMIN]] + role:membership.partnerRel.holderPerson:REFERRER[[membership.partnerRel.holderPerson:REFERRER]] + end +end + +subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"] + direction TB + style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.anchorPerson:roles[ ] + style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.anchorPerson:OWNER[[membership.partnerRel.anchorPerson:OWNER]] + role:membership.partnerRel.anchorPerson:ADMIN[[membership.partnerRel.anchorPerson:ADMIN]] + role:membership.partnerRel.anchorPerson:REFERRER[[membership.partnerRel.anchorPerson:REFERRER]] + end +end + +subgraph coopSharesTransaction["`**coopSharesTransaction**`"] + direction TB + style coopSharesTransaction fill:#dd4901,stroke:#274d6e,stroke-width:8px + + subgraph coopSharesTransaction:permissions[ ] + style coopSharesTransaction:permissions fill:#dd4901,stroke:white + + perm:coopSharesTransaction:INSERT{{coopSharesTransaction:INSERT}} + perm:coopSharesTransaction:UPDATE{{coopSharesTransaction:UPDATE}} + perm:coopSharesTransaction:SELECT{{coopSharesTransaction:SELECT}} + end +end + +subgraph membership["`**membership**`"] + direction TB + style membership fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership:roles[ ] + style membership:roles fill:#99bcdb,stroke:white + + role:membership:OWNER[[membership:OWNER]] + role:membership:ADMIN[[membership:ADMIN]] + role:membership:REFERRER[[membership:REFERRER]] + end +end + +subgraph membership.partnerRel["`**membership.partnerRel**`"] + direction TB + style membership.partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel:roles[ ] + style membership.partnerRel:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel:OWNER[[membership.partnerRel:OWNER]] + role:membership.partnerRel:ADMIN[[membership.partnerRel:ADMIN]] + role:membership.partnerRel:AGENT[[membership.partnerRel:AGENT]] + role:membership.partnerRel:TENANT[[membership.partnerRel:TENANT]] + end +end + +subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"] + direction TB + style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.contact:roles[ ] + style membership.partnerRel.contact:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.contact:OWNER[[membership.partnerRel.contact:OWNER]] + role:membership.partnerRel.contact:ADMIN[[membership.partnerRel.contact:ADMIN]] + role:membership.partnerRel.contact:REFERRER[[membership.partnerRel.contact:REFERRER]] + end +end + +%% granting roles to roles +role:global:ADMIN -.-> role:membership.partnerRel.anchorPerson:OWNER +role:membership.partnerRel.anchorPerson:OWNER -.-> role:membership.partnerRel.anchorPerson:ADMIN +role:membership.partnerRel.anchorPerson:ADMIN -.-> role:membership.partnerRel.anchorPerson:REFERRER +role:global:ADMIN -.-> role:membership.partnerRel.holderPerson:OWNER +role:membership.partnerRel.holderPerson:OWNER -.-> role:membership.partnerRel.holderPerson:ADMIN +role:membership.partnerRel.holderPerson:ADMIN -.-> role:membership.partnerRel.holderPerson:REFERRER +role:global:ADMIN -.-> role:membership.partnerRel.contact:OWNER +role:membership.partnerRel.contact:OWNER -.-> role:membership.partnerRel.contact:ADMIN +role:membership.partnerRel.contact:ADMIN -.-> role:membership.partnerRel.contact:REFERRER +role:global:ADMIN -.-> role:membership.partnerRel:OWNER +role:membership.partnerRel:OWNER -.-> role:membership.partnerRel:ADMIN +role:membership.partnerRel.anchorPerson:ADMIN -.-> role:membership.partnerRel:ADMIN +role:membership.partnerRel:ADMIN -.-> role:membership.partnerRel:AGENT +role:membership.partnerRel.holderPerson:ADMIN -.-> role:membership.partnerRel:AGENT +role:membership.partnerRel:AGENT -.-> role:membership.partnerRel:TENANT +role:membership.partnerRel.holderPerson:ADMIN -.-> role:membership.partnerRel:TENANT +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 + +%% granting permissions to roles +role:membership:ADMIN ==> perm:coopSharesTransaction:INSERT +role:membership:ADMIN ==> perm:coopSharesTransaction:UPDATE +role:membership:ADMIN ==> perm:coopSharesTransaction:SELECT + +``` diff --git a/src/main/resources/db/changelog/313-hs-office-coopshares-rbac.sql b/src/main/resources/db/changelog/5-hs-office/511-coopshares/5113-hs-office-coopshares-rbac.sql similarity index 96% rename from src/main/resources/db/changelog/313-hs-office-coopshares-rbac.sql rename to src/main/resources/db/changelog/5-hs-office/511-coopshares/5113-hs-office-coopshares-rbac.sql index 0f063309..1e894300 100644 --- a/src/main/resources/db/changelog/313-hs-office-coopshares-rbac.sql +++ b/src/main/resources/db/changelog/5-hs-office/511-coopshares/5113-hs-office-coopshares-rbac.sql @@ -38,8 +38,8 @@ 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, 'UPDATE'), hsOfficeMembershipAdmin(newMembership)); + call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeMembershipADMIN(newMembership)); + call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeMembershipADMIN(newMembership)); call leaveTriggerForObjectUuid(NEW.uuid); end; $$; @@ -81,7 +81,7 @@ do language plpgsql $$ LOOP call grantPermissionToRole( createPermission(row.uuid, 'INSERT', 'hs_office_coopsharestransaction'), - hsOfficeMembershipAdmin(row)); + hsOfficeMembershipADMIN(row)); END LOOP; END; $$; @@ -96,7 +96,7 @@ create or replace function hs_office_coopsharestransaction_hs_office_membership_ begin call grantPermissionToRole( createPermission(NEW.uuid, 'INSERT', 'hs_office_coopsharestransaction'), - hsOfficeMembershipAdmin(NEW)); + hsOfficeMembershipADMIN(NEW)); return NEW; end; $$; diff --git a/src/main/resources/db/changelog/316-hs-office-coopshares-migration.sql b/src/main/resources/db/changelog/5-hs-office/511-coopshares/5116-hs-office-coopshares-migration.sql similarity index 100% rename from src/main/resources/db/changelog/316-hs-office-coopshares-migration.sql rename to src/main/resources/db/changelog/5-hs-office/511-coopshares/5116-hs-office-coopshares-migration.sql diff --git a/src/main/resources/db/changelog/318-hs-office-coopshares-test-data.sql b/src/main/resources/db/changelog/5-hs-office/511-coopshares/5118-hs-office-coopshares-test-data.sql similarity index 100% rename from src/main/resources/db/changelog/318-hs-office-coopshares-test-data.sql rename to src/main/resources/db/changelog/5-hs-office/511-coopshares/5118-hs-office-coopshares-test-data.sql diff --git a/src/main/resources/db/changelog/320-hs-office-coopassets.sql b/src/main/resources/db/changelog/5-hs-office/512-coopassets/5120-hs-office-coopassets.sql similarity index 100% rename from src/main/resources/db/changelog/320-hs-office-coopassets.sql rename to src/main/resources/db/changelog/5-hs-office/512-coopassets/5120-hs-office-coopassets.sql 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 new file mode 100644 index 00000000..2b96a199 --- /dev/null +++ b/src/main/resources/db/changelog/5-hs-office/512-coopassets/5123-hs-office-coopassets-rbac.md @@ -0,0 +1,120 @@ +### rbac coopAssetsTransaction + +This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually. + +```mermaid +%%{init:{'flowchart':{'htmlLabels':false}}}%% +flowchart TB + +subgraph membership.partnerRel.holderPerson["`**membership.partnerRel.holderPerson**`"] + direction TB + style membership.partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.holderPerson:roles[ ] + style membership.partnerRel.holderPerson:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.holderPerson:OWNER[[membership.partnerRel.holderPerson:OWNER]] + role:membership.partnerRel.holderPerson:ADMIN[[membership.partnerRel.holderPerson:ADMIN]] + role:membership.partnerRel.holderPerson:REFERRER[[membership.partnerRel.holderPerson:REFERRER]] + end +end + +subgraph membership.partnerRel.anchorPerson["`**membership.partnerRel.anchorPerson**`"] + direction TB + style membership.partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.anchorPerson:roles[ ] + style membership.partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.anchorPerson:OWNER[[membership.partnerRel.anchorPerson:OWNER]] + role:membership.partnerRel.anchorPerson:ADMIN[[membership.partnerRel.anchorPerson:ADMIN]] + role:membership.partnerRel.anchorPerson:REFERRER[[membership.partnerRel.anchorPerson:REFERRER]] + end +end + +subgraph coopAssetsTransaction["`**coopAssetsTransaction**`"] + direction TB + style coopAssetsTransaction fill:#dd4901,stroke:#274d6e,stroke-width:8px + + subgraph coopAssetsTransaction:permissions[ ] + style coopAssetsTransaction:permissions fill:#dd4901,stroke:white + + perm:coopAssetsTransaction:INSERT{{coopAssetsTransaction:INSERT}} + perm:coopAssetsTransaction:UPDATE{{coopAssetsTransaction:UPDATE}} + perm:coopAssetsTransaction:SELECT{{coopAssetsTransaction:SELECT}} + end +end + +subgraph membership["`**membership**`"] + direction TB + style membership fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership:roles[ ] + style membership:roles fill:#99bcdb,stroke:white + + role:membership:OWNER[[membership:OWNER]] + role:membership:ADMIN[[membership:ADMIN]] + role:membership:REFERRER[[membership:REFERRER]] + end +end + +subgraph membership.partnerRel["`**membership.partnerRel**`"] + direction TB + style membership.partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel:roles[ ] + style membership.partnerRel:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel:OWNER[[membership.partnerRel:OWNER]] + role:membership.partnerRel:ADMIN[[membership.partnerRel:ADMIN]] + role:membership.partnerRel:AGENT[[membership.partnerRel:AGENT]] + role:membership.partnerRel:TENANT[[membership.partnerRel:TENANT]] + end +end + +subgraph membership.partnerRel.contact["`**membership.partnerRel.contact**`"] + direction TB + style membership.partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph membership.partnerRel.contact:roles[ ] + style membership.partnerRel.contact:roles fill:#99bcdb,stroke:white + + role:membership.partnerRel.contact:OWNER[[membership.partnerRel.contact:OWNER]] + role:membership.partnerRel.contact:ADMIN[[membership.partnerRel.contact:ADMIN]] + role:membership.partnerRel.contact:REFERRER[[membership.partnerRel.contact:REFERRER]] + end +end + +%% granting roles to roles +role:global:ADMIN -.-> role:membership.partnerRel.anchorPerson:OWNER +role:membership.partnerRel.anchorPerson:OWNER -.-> role:membership.partnerRel.anchorPerson:ADMIN +role:membership.partnerRel.anchorPerson:ADMIN -.-> role:membership.partnerRel.anchorPerson:REFERRER +role:global:ADMIN -.-> role:membership.partnerRel.holderPerson:OWNER +role:membership.partnerRel.holderPerson:OWNER -.-> role:membership.partnerRel.holderPerson:ADMIN +role:membership.partnerRel.holderPerson:ADMIN -.-> role:membership.partnerRel.holderPerson:REFERRER +role:global:ADMIN -.-> role:membership.partnerRel.contact:OWNER +role:membership.partnerRel.contact:OWNER -.-> role:membership.partnerRel.contact:ADMIN +role:membership.partnerRel.contact:ADMIN -.-> role:membership.partnerRel.contact:REFERRER +role:global:ADMIN -.-> role:membership.partnerRel:OWNER +role:membership.partnerRel:OWNER -.-> role:membership.partnerRel:ADMIN +role:membership.partnerRel.anchorPerson:ADMIN -.-> role:membership.partnerRel:ADMIN +role:membership.partnerRel:ADMIN -.-> role:membership.partnerRel:AGENT +role:membership.partnerRel.holderPerson:ADMIN -.-> role:membership.partnerRel:AGENT +role:membership.partnerRel:AGENT -.-> role:membership.partnerRel:TENANT +role:membership.partnerRel.holderPerson:ADMIN -.-> role:membership.partnerRel:TENANT +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 + +%% granting permissions to roles +role:membership:ADMIN ==> perm:coopAssetsTransaction:INSERT +role:membership:ADMIN ==> perm:coopAssetsTransaction:UPDATE +role:membership:ADMIN ==> perm:coopAssetsTransaction:SELECT + +``` diff --git a/src/main/resources/db/changelog/323-hs-office-coopassets-rbac.sql b/src/main/resources/db/changelog/5-hs-office/512-coopassets/5123-hs-office-coopassets-rbac.sql similarity index 96% rename from src/main/resources/db/changelog/323-hs-office-coopassets-rbac.sql rename to src/main/resources/db/changelog/5-hs-office/512-coopassets/5123-hs-office-coopassets-rbac.sql index d1218873..2c292436 100644 --- a/src/main/resources/db/changelog/323-hs-office-coopassets-rbac.sql +++ b/src/main/resources/db/changelog/5-hs-office/512-coopassets/5123-hs-office-coopassets-rbac.sql @@ -38,8 +38,8 @@ 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, 'UPDATE'), hsOfficeMembershipAdmin(newMembership)); + call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeMembershipADMIN(newMembership)); + call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeMembershipADMIN(newMembership)); call leaveTriggerForObjectUuid(NEW.uuid); end; $$; @@ -81,7 +81,7 @@ do language plpgsql $$ LOOP call grantPermissionToRole( createPermission(row.uuid, 'INSERT', 'hs_office_coopassetstransaction'), - hsOfficeMembershipAdmin(row)); + hsOfficeMembershipADMIN(row)); END LOOP; END; $$; @@ -96,7 +96,7 @@ create or replace function hs_office_coopassetstransaction_hs_office_membership_ begin call grantPermissionToRole( createPermission(NEW.uuid, 'INSERT', 'hs_office_coopassetstransaction'), - hsOfficeMembershipAdmin(NEW)); + hsOfficeMembershipADMIN(NEW)); return NEW; end; $$; diff --git a/src/main/resources/db/changelog/326-hs-office-coopassets-migration.sql b/src/main/resources/db/changelog/5-hs-office/512-coopassets/5126-hs-office-coopassets-migration.sql similarity index 100% rename from src/main/resources/db/changelog/326-hs-office-coopassets-migration.sql rename to src/main/resources/db/changelog/5-hs-office/512-coopassets/5126-hs-office-coopassets-migration.sql diff --git a/src/main/resources/db/changelog/328-hs-office-coopassets-test-data.sql b/src/main/resources/db/changelog/5-hs-office/512-coopassets/5128-hs-office-coopassets-test-data.sql similarity index 100% rename from src/main/resources/db/changelog/328-hs-office-coopassets-test-data.sql rename to src/main/resources/db/changelog/5-hs-office/512-coopassets/5128-hs-office-coopassets-test-data.sql diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index 6047befa..11a5f956 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -1,129 +1,129 @@ databaseChangeLog: - include: - file: db/changelog/001-last-row-count.sql + file: db/changelog/0-basis/001-last-row-count.sql - include: - file: db/changelog/002-int-to-var.sql + file: db/changelog/0-basis/002-int-to-var.sql - include: - file: db/changelog/003-random-in-range.sql + file: db/changelog/0-basis/003-random-in-range.sql - include: - file: db/changelog/004-jsonb-changes-delta.sql + file: db/changelog/0-basis/004-jsonb-changes-delta.sql - include: - file: db/changelog/005-uuid-ossp-extension.sql + file: db/changelog/0-basis/005-uuid-ossp-extension.sql - include: - file: db/changelog/006-numeric-hash-functions.sql + file: db/changelog/0-basis/006-numeric-hash-functions.sql - include: - file: db/changelog/007-table-columns.sql + file: db/changelog/0-basis/007-table-columns.sql - include: - file: db/changelog/009-check-environment.sql + file: db/changelog/0-basis/009-check-environment.sql - include: - file: db/changelog/010-context.sql + file: db/changelog/0-basis/010-context.sql - include: - file: db/changelog/020-audit-log.sql + file: db/changelog/0-basis/020-audit-log.sql - include: - file: db/changelog/050-rbac-base.sql + file: db/changelog/1-rbac/1050-rbac-base.sql - include: - file: db/changelog/051-rbac-user-grant.sql + file: db/changelog/1-rbac/1051-rbac-user-grant.sql - include: - file: db/changelog/054-rbac-context.sql + file: db/changelog/1-rbac/1054-rbac-context.sql - include: - file: db/changelog/055-rbac-views.sql + file: db/changelog/1-rbac/1055-rbac-views.sql - include: - file: db/changelog/056-rbac-trigger-context.sql + file: db/changelog/1-rbac/1056-rbac-trigger-context.sql - include: - file: db/changelog/057-rbac-role-builder.sql + file: db/changelog/1-rbac/1057-rbac-role-builder.sql - include: - file: db/changelog/058-rbac-generators.sql + file: db/changelog/1-rbac/1058-rbac-generators.sql - include: - file: db/changelog/059-rbac-statistics.sql + file: db/changelog/1-rbac/1059-rbac-statistics.sql - include: - file: db/changelog/080-rbac-global.sql + file: db/changelog/1-rbac/1080-rbac-global.sql - include: - file: db/changelog/110-test-customer.sql + file: db/changelog/2-test/201-test-customer/2010-test-customer.sql - include: - file: db/changelog/113-test-customer-rbac.sql + file: db/changelog/2-test/201-test-customer/2013-test-customer-rbac.sql - include: - file: db/changelog/118-test-customer-test-data.sql + file: db/changelog/2-test/201-test-customer/2018-test-customer-test-data.sql - include: - file: db/changelog/120-test-package.sql + file: db/changelog/2-test/202-test-package/2020-test-package.sql - include: - file: db/changelog/123-test-package-rbac.sql + file: db/changelog/2-test/202-test-package/2023-test-package-rbac.sql - include: - file: db/changelog/128-test-package-test-data.sql + file: db/changelog/2-test/202-test-package/2028-test-package-test-data.sql - include: - file: db/changelog/130-test-domain.sql + file: db/changelog/2-test/203-test-domain/2030-test-domain.sql - include: - file: db/changelog/133-test-domain-rbac.sql + file: db/changelog/2-test/203-test-domain/2033-test-domain-rbac.sql - include: - file: db/changelog/138-test-domain-test-data.sql + file: db/changelog/2-test/203-test-domain/2038-test-domain-test-data.sql - include: - file: db/changelog/200-hs-office-contact.sql + file: db/changelog/5-hs-office/501-contact/5010-hs-office-contact.sql - include: - file: db/changelog/203-hs-office-contact-rbac.sql + file: db/changelog/5-hs-office/501-contact/5013-hs-office-contact-rbac.sql - include: - file: db/changelog/206-hs-office-contact-migration.sql + file: db/changelog/5-hs-office/501-contact/5016-hs-office-contact-migration.sql - include: - file: db/changelog/208-hs-office-contact-test-data.sql + file: db/changelog/5-hs-office/501-contact/5018-hs-office-contact-test-data.sql - include: - file: db/changelog/210-hs-office-person.sql + file: db/changelog/5-hs-office/502-person/5020-hs-office-person.sql - include: - file: db/changelog/213-hs-office-person-rbac.sql + file: db/changelog/5-hs-office/502-person/5023-hs-office-person-rbac.sql - include: - file: db/changelog/218-hs-office-person-test-data.sql + file: db/changelog/5-hs-office/502-person/5028-hs-office-person-test-data.sql - include: - file: db/changelog/220-hs-office-relation.sql + file: db/changelog/5-hs-office/503-relation/5030-hs-office-relation.sql - include: - file: db/changelog/223-hs-office-relation-rbac.sql + file: db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql - include: - file: db/changelog/228-hs-office-relation-test-data.sql + file: db/changelog/5-hs-office/503-relation/5038-hs-office-relation-test-data.sql - include: - file: db/changelog/230-hs-office-partner.sql + file: db/changelog/5-hs-office/504-partner/5040-hs-office-partner.sql - include: - file: db/changelog/233-hs-office-partner-rbac.sql + file: db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.sql - include: - file: db/changelog/234-hs-office-partner-details-rbac.sql + file: db/changelog/5-hs-office/504-partner/5044-hs-office-partner-details-rbac.sql - include: - file: db/changelog/236-hs-office-partner-migration.sql + file: db/changelog/5-hs-office/504-partner/5046-hs-office-partner-migration.sql - include: - file: db/changelog/238-hs-office-partner-test-data.sql + file: db/changelog/5-hs-office/504-partner/5048-hs-office-partner-test-data.sql - include: - file: db/changelog/240-hs-office-bankaccount.sql + file: db/changelog/5-hs-office/505-bankaccount/5050-hs-office-bankaccount.sql - include: - file: db/changelog/243-hs-office-bankaccount-rbac.sql + file: db/changelog/5-hs-office/505-bankaccount/5053-hs-office-bankaccount-rbac.sql - include: - file: db/changelog/248-hs-office-bankaccount-test-data.sql + file: db/changelog/5-hs-office/505-bankaccount/5058-hs-office-bankaccount-test-data.sql - include: - file: db/changelog/270-hs-office-debitor.sql + file: db/changelog/5-hs-office/506-debitor/5060-hs-office-debitor.sql - include: - file: db/changelog/273-hs-office-debitor-rbac.sql + file: db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.sql - include: - file: db/changelog/278-hs-office-debitor-test-data.sql + file: db/changelog/5-hs-office/506-debitor/5068-hs-office-debitor-test-data.sql - include: - file: db/changelog/250-hs-office-sepamandate.sql + file: db/changelog/5-hs-office/507-sepamandate/5070-hs-office-sepamandate.sql - include: - file: db/changelog/253-hs-office-sepamandate-rbac.sql + file: db/changelog/5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.sql - include: - file: db/changelog/256-hs-office-sepamandate-migration.sql + file: db/changelog/5-hs-office/507-sepamandate/5076-hs-office-sepamandate-migration.sql - include: - file: db/changelog/258-hs-office-sepamandate-test-data.sql + file: db/changelog/5-hs-office/507-sepamandate/5078-hs-office-sepamandate-test-data.sql - include: - file: db/changelog/300-hs-office-membership.sql + file: db/changelog/5-hs-office/510-membership/5100-hs-office-membership.sql - include: - file: db/changelog/303-hs-office-membership-rbac.sql + file: db/changelog/5-hs-office/510-membership/5103-hs-office-membership-rbac.sql - include: - file: db/changelog/308-hs-office-membership-test-data.sql + file: db/changelog/5-hs-office/510-membership/5108-hs-office-membership-test-data.sql - include: - file: db/changelog/310-hs-office-coopshares.sql + file: db/changelog/5-hs-office/511-coopshares/5110-hs-office-coopshares.sql - include: - file: db/changelog/313-hs-office-coopshares-rbac.sql + file: db/changelog/5-hs-office/511-coopshares/5113-hs-office-coopshares-rbac.sql - include: - file: db/changelog/316-hs-office-coopshares-migration.sql + file: db/changelog/5-hs-office/511-coopshares/5116-hs-office-coopshares-migration.sql - include: - file: db/changelog/318-hs-office-coopshares-test-data.sql + file: db/changelog/5-hs-office/511-coopshares/5118-hs-office-coopshares-test-data.sql - include: - file: db/changelog/320-hs-office-coopassets.sql + file: db/changelog/5-hs-office/512-coopassets/5120-hs-office-coopassets.sql - include: - file: db/changelog/323-hs-office-coopassets-rbac.sql + file: db/changelog/5-hs-office/512-coopassets/5123-hs-office-coopassets-rbac.sql - include: - file: db/changelog/326-hs-office-coopassets-migration.sql + file: db/changelog/5-hs-office/512-coopassets/5126-hs-office-coopassets-migration.sql - include: - file: db/changelog/328-hs-office-coopassets-test-data.sql + file: db/changelog/5-hs-office/512-coopassets/5128-hs-office-coopassets-test-data.sql -- 2.39.5 From 22953ba38efe12cdec09e5e2fce795003aba9622 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Sat, 30 Mar 2024 13:25:28 +0100 Subject: [PATCH 08/29] debitorNumberSuffix as String --- .../hs/office/debitor/HsOfficeDebitorEntity.java | 11 +++++++---- .../office/membership/HsOfficeMembershipEntity.java | 3 +++ .../506-debitor/5060-hs-office-debitor.sql | 2 +- .../506-debitor/5063-hs-office-debitor-rbac.sql | 2 +- .../5078-hs-office-sepamandate-test-data.sql | 8 ++++---- .../510-membership/5100-hs-office-membership.sql | 3 +-- .../HsOfficeDebitorControllerAcceptanceTest.java | 6 +++++- .../office/debitor/HsOfficeDebitorEntityUnitTest.java | 10 +++++----- .../HsOfficeDebitorRepositoryIntegrationTest.java | 8 ++++---- .../hs/office/debitor/TestHsOfficeDebitor.java | 2 +- .../hs/office/migration/ImportOfficeData.java | 2 +- 11 files changed, 33 insertions(+), 24 deletions(-) diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java index 1c784078..0a63d0b1 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java @@ -16,6 +16,7 @@ import org.hibernate.annotations.NotFound; import org.hibernate.annotations.NotFoundAction; import jakarta.persistence.*; +import jakarta.validation.constraints.Pattern; import java.io.IOException; import java.util.UUID; @@ -45,6 +46,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify; public class HsOfficeDebitorEntity implements HasUuid, Stringifyable { public static final String DEBITOR_NUMBER_TAG = "D-"; + public static final String TWO_DECIMAL_DIGITS = "^([0-9]{2})$"; private static Stringify stringify = stringify(HsOfficeDebitorEntity.class, "debitor") @@ -75,8 +77,9 @@ public class HsOfficeDebitorEntity implements HasUuid, Stringifyable { @NotFound(action = NotFoundAction.IGNORE) private HsOfficePartnerEntity partner; - @Column(name = "debitornumbersuffix", columnDefinition = "numeric(2)") - private Byte debitorNumberSuffix; // TODO maybe rather as a formatted String? + @Column(name = "debitornumbersuffix", length = 2) + @Pattern(regexp = TWO_DECIMAL_DIGITS) + private String debitorNumberSuffix; @ManyToOne(cascade = { PERSIST, MERGE, REFRESH, DETACH }, optional = false) @JoinColumn(name = "debitorreluuid", nullable = false) @@ -109,7 +112,7 @@ public class HsOfficeDebitorEntity implements HasUuid, Stringifyable { .filter(partner -> debitorNumberSuffix != null) .map(HsOfficePartnerEntity::getPartnerNumber) .map(Object::toString) - .map(partnerNumber -> partnerNumber + String.format("%02d", debitorNumberSuffix)) + .map(partnerNumber -> partnerNumber + debitorNumberSuffix) .orElse(null); } @@ -138,7 +141,7 @@ public class HsOfficeDebitorEntity implements HasUuid, Stringifyable { JOIN hs_office_relation debitorRel ON debitorRel.anchorUuid = partnerRel.holderUuid AND debitorRel.type = 'DEBITOR' WHERE debitorRel.uuid = debitor.debitorRelUuid) - || to_char(debitorNumberSuffix, 'fm00') as idName + || debitorNumberSuffix as idName FROM hs_office_debitor AS debitor """)) .withRestrictedViewOrderBy(SQL.projection("defaultPrefix")) 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..668d7cb9 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 @@ -14,6 +14,7 @@ import net.hostsharing.hsadminng.stringify.Stringifyable; import org.hibernate.annotations.Type; import jakarta.persistence.*; +import jakarta.validation.constraints.Pattern; import java.io.IOException; import java.time.LocalDate; import java.util.UUID; @@ -44,6 +45,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify; public class HsOfficeMembershipEntity implements HasUuid, Stringifyable { public static final String MEMBER_NUMBER_TAG = "M-"; + public static final String TWO_DECIMAL_DIGITS = "^([0-9]{2})$"; private static Stringify stringify = stringify(HsOfficeMembershipEntity.class) .withProp(e -> MEMBER_NUMBER_TAG + e.getMemberNumber()) @@ -61,6 +63,7 @@ public class HsOfficeMembershipEntity implements HasUuid, Stringifyable { private HsOfficePartnerEntity partner; @Column(name = "membernumbersuffix", length = 2) + @Pattern(regexp = TWO_DECIMAL_DIGITS) private String memberNumberSuffix; @Column(name = "validity", columnDefinition = "daterange") diff --git a/src/main/resources/db/changelog/5-hs-office/506-debitor/5060-hs-office-debitor.sql b/src/main/resources/db/changelog/5-hs-office/506-debitor/5060-hs-office-debitor.sql index e2174eca..59ad01e0 100644 --- a/src/main/resources/db/changelog/5-hs-office/506-debitor/5060-hs-office-debitor.sql +++ b/src/main/resources/db/changelog/5-hs-office/506-debitor/5060-hs-office-debitor.sql @@ -7,7 +7,7 @@ create table hs_office_debitor ( uuid uuid unique references RbacObject (uuid) initially deferred, - debitorNumberSuffix numeric(2) not null, + debitorNumberSuffix char(2) not null check (debitorNumberSuffix::text ~ '^[0-9][0-9]$'), debitorRelUuid uuid not null references hs_office_relation(uuid), billable boolean not null default true, vatId varchar(24), -- TODO.spec: here or in person? diff --git a/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.sql b/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.sql index 152f980e..59ac43e8 100644 --- a/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.sql +++ b/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.sql @@ -201,7 +201,7 @@ create trigger hs_office_debitor_insert_permission_check_tg JOIN hs_office_relation debitorRel ON debitorRel.anchorUuid = partnerRel.holderUuid AND debitorRel.type = 'DEBITOR' WHERE debitorRel.uuid = debitor.debitorRelUuid) - || to_char(debitorNumberSuffix, 'fm00') as idName + || debitorNumberSuffix as idName FROM hs_office_debitor AS debitor $idName$); --// diff --git a/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5078-hs-office-sepamandate-test-data.sql b/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5078-hs-office-sepamandate-test-data.sql index 69d39165..e664d8c5 100644 --- a/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5078-hs-office-sepamandate-test-data.sql +++ b/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5078-hs-office-sepamandate-test-data.sql @@ -10,7 +10,7 @@ */ create or replace procedure createHsOfficeSepaMandateTestData( forPartnerNumber numeric(5), - forDebitorSuffix numeric(2), + forDebitorSuffix char(2), forIban varchar, withReference varchar) language plpgsql as $$ @@ -48,9 +48,9 @@ end; $$; do language plpgsql $$ begin - call createHsOfficeSepaMandateTestData(10001, 11, 'DE02120300000000202051', 'ref-10001-11'); - call createHsOfficeSepaMandateTestData(10002, 12, 'DE02100500000054540402', 'ref-10002-12'); - call createHsOfficeSepaMandateTestData(10003, 13, 'DE02300209000106531065', 'ref-10003-13'); + call createHsOfficeSepaMandateTestData(10001, '11', 'DE02120300000000202051', 'ref-10001-11'); + call createHsOfficeSepaMandateTestData(10002, '12', 'DE02100500000054540402', 'ref-10002-12'); + call createHsOfficeSepaMandateTestData(10003, '13', 'DE02300209000106531065', 'ref-10003-13'); end; $$; --// diff --git a/src/main/resources/db/changelog/5-hs-office/510-membership/5100-hs-office-membership.sql b/src/main/resources/db/changelog/5-hs-office/510-membership/5100-hs-office-membership.sql index f2a560e2..28ec1249 100644 --- a/src/main/resources/db/changelog/5-hs-office/510-membership/5100-hs-office-membership.sql +++ b/src/main/resources/db/changelog/5-hs-office/510-membership/5100-hs-office-membership.sql @@ -12,8 +12,7 @@ create table if not exists hs_office_membership ( uuid uuid unique references RbacObject (uuid) initially deferred, partnerUuid uuid not null references hs_office_partner(uuid), - memberNumberSuffix char(2) not null check ( - memberNumberSuffix::text ~ '^[0-9][0-9]$'), + memberNumberSuffix char(2) not null check (memberNumberSuffix::text ~ '^[0-9][0-9]$'), validity daterange not null, reasonForTermination HsOfficeReasonForTermination not null default 'NONE', membershipFeeBillable boolean not null default true, diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorControllerAcceptanceTest.java index c2e3fffd..07ecb5f5 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorControllerAcceptanceTest.java @@ -722,7 +722,7 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu final var givenPartner = partnerRepo.findPartnerByOptionalNameLike("Fourth").get(0); final var givenContact = contactRepo.findContactByOptionalLabelLike("fourth contact").get(0); final var newDebitor = HsOfficeDebitorEntity.builder() - .debitorNumberSuffix(++nextDebitorSuffix) + .debitorNumberSuffix(nextDebitorSuffix()) .billable(true) .debitorRel( HsOfficeRelationEntity.builder() @@ -751,4 +751,8 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu System.out.printf("deleted %d entities%n", count); }); } + + private String nextDebitorSuffix() { + return String.format("%02d", nextDebitorSuffix++); + } } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntityUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntityUnitTest.java index 3ad1c8ea..cb629b2b 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntityUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntityUnitTest.java @@ -26,7 +26,7 @@ class HsOfficeDebitorEntityUnitTest { @Test void toStringContainsPartnerAndContact() { final var given = HsOfficeDebitorEntity.builder() - .debitorNumberSuffix((byte)67) + .debitorNumberSuffix("67") .debitorRel(givenDebitorRel) .defaultPrefix("som") .partner(HsOfficePartnerEntity.builder() @@ -43,7 +43,7 @@ class HsOfficeDebitorEntityUnitTest { void toShortStringContainsDebitorNumber() { final var given = HsOfficeDebitorEntity.builder() .debitorRel(givenDebitorRel) - .debitorNumberSuffix((byte)67) + .debitorNumberSuffix("67") .partner(HsOfficePartnerEntity.builder() .partnerNumber(12345) .build()) @@ -58,7 +58,7 @@ class HsOfficeDebitorEntityUnitTest { void getDebitorNumberWithPartnerNumberAndDebitorNumberSuffix() { final var given = HsOfficeDebitorEntity.builder() .debitorRel(givenDebitorRel) - .debitorNumberSuffix((byte)67) + .debitorNumberSuffix("67") .partner(HsOfficePartnerEntity.builder() .partnerNumber(12345) .build()) @@ -73,7 +73,7 @@ class HsOfficeDebitorEntityUnitTest { void getDebitorNumberWithoutPartnerReturnsNull() { final var given = HsOfficeDebitorEntity.builder() .debitorRel(givenDebitorRel) - .debitorNumberSuffix((byte)67) + .debitorNumberSuffix("67") .partner(null) .build(); @@ -86,7 +86,7 @@ class HsOfficeDebitorEntityUnitTest { void getDebitorNumberWithoutPartnerNumberReturnsNull() { final var given = HsOfficeDebitorEntity.builder() .debitorRel(givenDebitorRel) - .debitorNumberSuffix((byte)67) + .debitorNumberSuffix("67") .partner(HsOfficePartnerEntity.builder().build()) .build(); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java index 7a3dfbb7..32f441af 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java @@ -89,7 +89,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean // when final var result = attempt(em, () -> { final var newDebitor = HsOfficeDebitorEntity.builder() - .debitorNumberSuffix((byte)21) + .debitorNumberSuffix("21") .debitorRel(HsOfficeRelationEntity.builder() .type(HsOfficeRelationType.DEBITOR) .anchor(givenPartnerPerson) @@ -121,7 +121,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean // when final var result = attempt(em, () -> { final var newDebitor = HsOfficeDebitorEntity.builder() - .debitorNumberSuffix((byte)21) + .debitorNumberSuffix("21") .debitorRel(HsOfficeRelationEntity.builder() .type(HsOfficeRelationType.DEBITOR) .anchor(givenPartnerPerson) @@ -156,7 +156,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean final var givenDebitorPerson = one(personRepo.findPersonByOptionalNameLike("Fourth eG")); final var givenContact = one(contactRepo.findContactByOptionalLabelLike("fourth contact")); final var newDebitor = HsOfficeDebitorEntity.builder() - .debitorNumberSuffix((byte)22) + .debitorNumberSuffix("22") .debitorRel(HsOfficeRelationEntity.builder() .type(HsOfficeRelationType.DEBITOR) .anchor(givenPartnerPerson) @@ -613,7 +613,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean final var givenBankAccount = bankAccountHolder != null ? one(bankAccountRepo.findByOptionalHolderLike(bankAccountHolder)) : null; final var newDebitor = HsOfficeDebitorEntity.builder() - .debitorNumberSuffix((byte)20) + .debitorNumberSuffix("20") .debitorRel(HsOfficeRelationEntity.builder() .type(HsOfficeRelationType.DEBITOR) .anchor(givenPartnerPerson) diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/TestHsOfficeDebitor.java b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/TestHsOfficeDebitor.java index 2970ea1b..4305b87a 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/TestHsOfficeDebitor.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/TestHsOfficeDebitor.java @@ -10,7 +10,7 @@ import static net.hostsharing.hsadminng.hs.office.partner.TestHsOfficePartner.TE @UtilityClass public class TestHsOfficeDebitor { - public byte DEFAULT_DEBITOR_SUFFIX = 0; + public String DEFAULT_DEBITOR_SUFFIX = "00"; public static final HsOfficeDebitorEntity TEST_DEBITOR = HsOfficeDebitorEntity.builder() .debitorNumberSuffix(DEFAULT_DEBITOR_SUFFIX) diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java b/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java index 4010167d..8da1f12f 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java @@ -724,7 +724,7 @@ public class ImportOfficeData extends ContextBasedTest { relations.put(relationId++, debitorRel); final var debitor = HsOfficeDebitorEntity.builder() - .debitorNumberSuffix((byte) 0) + .debitorNumberSuffix("00") .partner(partner) .debitorRel(debitorRel) .defaultPrefix(rec.getString("member_code").replace("hsh00-", "")) -- 2.39.5 From 84a25ac51d23bcff3d6df15e325ea70d5ee09b46 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Sat, 30 Mar 2024 16:16:54 +0100 Subject: [PATCH 09/29] cleanup TODOs and fixing some varchar length --- .gitignore | 1 - README.md | 9 +-- doc/rbac.md | 2 +- doc/test-concept.md | 4 +- sql/historization.sql | 32 +++++----- .../hsadminng/context/Context.java | 19 +++--- .../HsOfficeBankAccountEntity.java | 4 +- .../office/contact/HsOfficeContactEntity.java | 10 ++-- .../HsOfficeCoopAssetsTransactionEntity.java | 4 +- .../HsOfficeCoopSharesTransactionEntity.java | 4 +- .../office/debitor/HsOfficeDebitorEntity.java | 6 +- .../membership/HsOfficeMembershipEntity.java | 4 +- .../partner/HsOfficePartnerDetailsEntity.java | 4 +- .../office/partner/HsOfficePartnerEntity.java | 4 +- .../partner/HsOfficePartnerRepository.java | 2 +- .../office/person/HsOfficePersonEntity.java | 4 +- .../relation/HsOfficeRelationEntity.java | 4 +- .../HsOfficeSepaMandateEntity.java | 4 +- .../hsadminng/persistence/HasUuid.java | 7 --- .../hsadminng/rbac/rbacdef/RbacView.java | 14 ++--- .../test/cust/TestCustomerEntity.java | 4 +- .../hsadminng/test/dom/TestDomainEntity.java | 4 +- .../hsadminng/test/pac/TestPackageEntity.java | 4 +- .../rbac/rbac-role-schemas.yaml | 2 +- .../db/changelog/0-basis/010-context.sql | 8 +-- .../db/changelog/1-rbac/1050-rbac-base.sql | 59 +------------------ .../db/changelog/1-rbac/1054-rbac-context.sql | 8 +-- .../1-rbac/1057-rbac-role-builder.sql | 25 +++----- .../changelog/1-rbac/1058-rbac-generators.sql | 9 --- .../hsadminng/arch/ArchitectureTest.java | 2 +- .../hsadminng/context/ContextUnitTest.java | 39 ++++-------- .../test/ContextBasedTestWithCleanup.java | 6 +- .../hsadminng/hs/office/test/EntityList.java | 4 +- .../java/net/hostsharing/test/JpaAttempt.java | 1 - .../hostsharing/test/PatchUnitTestBase.java | 4 +- 35 files changed, 107 insertions(+), 214 deletions(-) delete mode 100644 src/main/java/net/hostsharing/hsadminng/persistence/HasUuid.java diff --git a/.gitignore b/.gitignore index d6a2e347..522bf4fa 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,6 @@ /build/www/** /src/test/javascript/coverage/ /worktrees/ -TODO-progress.png ###################### # Node diff --git a/README.md b/README.md index 4301d8fe..8bdd9461 100644 --- a/README.md +++ b/README.md @@ -380,12 +380,6 @@ You can explore the prototype as follows: `src/` The actual source-code, see [Source Code Package Structure](#source-code-package-structure) for details. -`TODO.md` - Requirements of initial project. Do not touch! - -`TODO-progress.png` - Generated diagram image of the project progress. - `tools/` Some shell-scripts to useful tasks. @@ -765,5 +759,4 @@ The output will list the generated files. ## Further Documentation - the `doc` directory contains architecture concepts and a glossary -- TODO.md tracks requirements and progress for the contract of the initial project, - please do not amend anything in this document +- the `ideas` directory contains unstructured ideas for future development or documentation diff --git a/doc/rbac.md b/doc/rbac.md index 3cf58e25..3213d740 100644 --- a/doc/rbac.md +++ b/doc/rbac.md @@ -694,7 +694,7 @@ Users can view only the roles to which are granted to them. Grant can be `empowered`, this means that the grantee user can grant the granted role to other users and revoke grants to that role. -(TODO: access control part not yet implemented) +(TODO: access control part not yet implemented, currently all accessible roles can be granted to other users) Grants can be `managed`, which means they are created and deleted by system-defined rules. If a grant is not managed, it was created by an empowered user and can be deleted by empowered users. diff --git a/doc/test-concept.md b/doc/test-concept.md index c8946342..690d1558 100644 --- a/doc/test-concept.md +++ b/doc/test-concept.md @@ -87,7 +87,7 @@ Acceptance-Tests run on a fully integrated and deployed system with deployed dou Acceptance-tests, are blackbox-tests and do not count into test-code-coverage. -TODO: Complete the Acceptance-Tests test concept. +TODO.test: Complete the Acceptance-Tests test concept. #### Performance-Tests @@ -107,4 +107,4 @@ We define System-Integration-Tests as test in which this system is deployed in a System-Integration-tests, are blackbox-tests and do not count into test-code-coverage. -TODO: Complete the System-Integration-Tests test concept. +TODO.test: Complete the System-Integration-Tests test concept. diff --git a/sql/historization.sql b/sql/historization.sql index 2f4087b4..1bd0db44 100644 --- a/sql/historization.sql +++ b/sql/historization.sql @@ -18,8 +18,8 @@ CREATE OR REPLACE FUNCTION historicize() RETURNS trigger LANGUAGE plpgsql STRICT AS $$ DECLARE -currentUser VARCHAR(64); - currentTask varchar; + currentUser VARCHAR(63); + currentTask VARCHAR(127); "row" RECORD; "alive" BOOLEAN; "sql" varchar; @@ -37,27 +37,27 @@ END IF; -- determine task currentTask = current_setting('hsadminng.currentTask'); - IF (currentTask IS NULL OR length(currentTask) < 12) THEN - RAISE EXCEPTION 'hsadminng.currentTask (%) must be defined and min 12 characters long, please use "SET LOCAL ...;"', currentTask; -END IF; - RAISE NOTICE 'currentTask: %', currentTask; + assert currentTask IS NOT NULL AND length(currentTask) >= 12, + format('hsadminng.currentTask (%s) must be defined and min 12 characters long, please use "SET LOCAL ...;"', currentTask); + assert length(currentTask) <= 127, + format('hsadminng.currentTask (%s) must not be longer than 127 characters"', currentTask); IF (TG_OP = 'INSERT') OR (TG_OP = 'UPDATE') THEN "row" := NEW; "alive" := TRUE; -ELSE -- DELETE or TRUNCATE - "row" := OLD; - "alive" := FALSE; -END IF; + ELSE -- DELETE or TRUNCATE + "row" := OLD; + "alive" := FALSE; + END IF; -sql := format('INSERT INTO tx_history VALUES (txid_current(), now(), %1L, %2L) ON CONFLICT DO NOTHING', currentUser, currentTask); + sql := format('INSERT INTO tx_history VALUES (txid_current(), now(), %1L, %2L) ON CONFLICT DO NOTHING', currentUser, currentTask); RAISE NOTICE 'sql: %', sql; -EXECUTE sql; -sql := format('INSERT INTO %3$I_versions VALUES (DEFAULT, txid_current(), %1$L, %2$L, $1.*)', TG_OP, alive, TG_TABLE_NAME); - RAISE NOTICE 'sql: %', sql; -EXECUTE sql USING "row"; + EXECUTE sql; + sql := format('INSERT INTO %3$I_versions VALUES (DEFAULT, txid_current(), %1$L, %2$L, $1.*)', TG_OP, alive, TG_TABLE_NAME); + RAISE NOTICE 'sql: %', sql; + EXECUTE sql USING "row"; -RETURN "row"; + RETURN "row"; END; $$; CREATE OR REPLACE PROCEDURE create_historical_view(baseTable varchar) diff --git a/src/main/java/net/hostsharing/hsadminng/context/Context.java b/src/main/java/net/hostsharing/hsadminng/context/Context.java index 2730147d..9a5084f0 100644 --- a/src/main/java/net/hostsharing/hsadminng/context/Context.java +++ b/src/main/java/net/hostsharing/hsadminng/context/Context.java @@ -55,16 +55,15 @@ public class Context { final String currentRequest, final String currentUser, final String assumedRoles) { - final var query = em.createNativeQuery( - """ - call defineContext( - cast(:currentTask as varchar), - cast(:currentRequest as varchar), - cast(:currentUser as varchar), - cast(:assumedRoles as varchar)); - """); - query.setParameter("currentTask", shortenToMaxLength(currentTask, 96)); - query.setParameter("currentRequest", shortenToMaxLength(currentRequest, 512)); // TODO.spec: length? + final var query = em.createNativeQuery(""" + call defineContext( + cast(:currentTask as varchar(127)), + cast(:currentRequest as text), + cast(:currentUser as varchar(63)), + cast(:assumedRoles as varchar(1023))); + """); + query.setParameter("currentTask", shortenToMaxLength(currentTask, 127)); + query.setParameter("currentRequest", currentRequest); query.setParameter("currentUser", currentUser); query.setParameter("assumedRoles", assumedRoles != null ? assumedRoles : ""); query.executeUpdate(); diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountEntity.java index 99bb50ea..6542084e 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountEntity.java @@ -3,7 +3,7 @@ package net.hostsharing.hsadminng.hs.office.bankaccount; import lombok.*; import lombok.experimental.FieldNameConstants; import net.hostsharing.hsadminng.errors.DisplayName; -import net.hostsharing.hsadminng.persistence.HasUuid; +import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.stringify.Stringify; import net.hostsharing.hsadminng.stringify.Stringifyable; @@ -30,7 +30,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify; @AllArgsConstructor @FieldNameConstants @DisplayName("BankAccount") -public class HsOfficeBankAccountEntity implements HasUuid, Stringifyable { +public class HsOfficeBankAccountEntity implements RbacObject, Stringifyable { private static Stringify toString = stringify(HsOfficeBankAccountEntity.class, "bankAccount") .withIdProp(HsOfficeBankAccountEntity::getIban) diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactEntity.java index 4927b4bc..1ce3a557 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactEntity.java @@ -3,7 +3,7 @@ package net.hostsharing.hsadminng.hs.office.contact; import lombok.*; import lombok.experimental.FieldNameConstants; import net.hostsharing.hsadminng.errors.DisplayName; -import net.hostsharing.hsadminng.persistence.HasUuid; +import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL; import net.hostsharing.hsadminng.stringify.Stringify; @@ -30,7 +30,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify; @AllArgsConstructor @FieldNameConstants @DisplayName("Contact") -public class HsOfficeContactEntity implements Stringifyable, HasUuid { +public class HsOfficeContactEntity implements Stringifyable, RbacObject { private static Stringify toString = stringify(HsOfficeContactEntity.class, "contact") .withProp(Fields.label, HsOfficeContactEntity::getLabel) @@ -43,13 +43,13 @@ public class HsOfficeContactEntity implements Stringifyable, HasUuid { private String label; @Column(name = "postaladdress") - private String postalAddress; // TODO: check if we really want multiple, if so: JSON-Array or Postgres-Array? + private String postalAddress; // TODO.spec: check if we really want multiple, if so: JSON-Array or Postgres-Array? @Column(name = "emailaddresses", columnDefinition = "json") - private String emailAddresses; // TODO: check if we can really add multiple. format: ["eins@...", "zwei@..."] + private String emailAddresses; // TODO.spec: check if we can really add multiple. format: ["eins@...", "zwei@..."] @Column(name = "phonenumbers", columnDefinition = "json") - private String phoneNumbers; // TODO: check if we can really add multiple. format: { "office": "+49 40 12345-10", "fax": "+49 40 12345-05" } + private String phoneNumbers; // TODO.spec: check if we can really add multiple. format: { "office": "+49 40 12345-10", "fax": "+49 40 12345-05" } @Override public String toString() { 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..32bf8bee 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 @@ -4,7 +4,7 @@ package net.hostsharing.hsadminng.hs.office.coopassets; import lombok.*; import net.hostsharing.hsadminng.errors.DisplayName; import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity; -import net.hostsharing.hsadminng.persistence.HasUuid; +import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.stringify.Stringify; import net.hostsharing.hsadminng.stringify.Stringifyable; @@ -34,7 +34,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify; @NoArgsConstructor @AllArgsConstructor @DisplayName("CoopAssetsTransaction") -public class HsOfficeCoopAssetsTransactionEntity implements Stringifyable, HasUuid { +public class HsOfficeCoopAssetsTransactionEntity implements Stringifyable, RbacObject { private static Stringify stringify = stringify(HsOfficeCoopAssetsTransactionEntity.class) .withIdProp(HsOfficeCoopAssetsTransactionEntity::getTaggedMemberNumber) 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..57318afb 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 @@ -3,7 +3,7 @@ package net.hostsharing.hsadminng.hs.office.coopshares; import lombok.*; import net.hostsharing.hsadminng.errors.DisplayName; import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity; -import net.hostsharing.hsadminng.persistence.HasUuid; +import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL; import net.hostsharing.hsadminng.stringify.Stringify; @@ -32,7 +32,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify; @NoArgsConstructor @AllArgsConstructor @DisplayName("CoopShareTransaction") -public class HsOfficeCoopSharesTransactionEntity implements Stringifyable, HasUuid { +public class HsOfficeCoopSharesTransactionEntity implements Stringifyable, RbacObject { private static Stringify stringify = stringify(HsOfficeCoopSharesTransactionEntity.class) .withProp(HsOfficeCoopSharesTransactionEntity::getMemberNumberTagged) diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java index 0a63d0b1..08c70f66 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java @@ -5,7 +5,7 @@ import net.hostsharing.hsadminng.errors.DisplayName; import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity; import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity; -import net.hostsharing.hsadminng.persistence.HasUuid; +import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL; import net.hostsharing.hsadminng.stringify.Stringify; @@ -43,7 +43,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify; @NoArgsConstructor @AllArgsConstructor @DisplayName("Debitor") -public class HsOfficeDebitorEntity implements HasUuid, Stringifyable { +public class HsOfficeDebitorEntity implements RbacObject, Stringifyable { public static final String DEBITOR_NUMBER_TAG = "D-"; public static final String TWO_DECIMAL_DIGITS = "^([0-9]{2})$"; @@ -153,7 +153,7 @@ public class HsOfficeDebitorEntity implements HasUuid, Stringifyable { "vatCountryCode", "vatBusiness", "vatReverseCharge", - "defaultPrefix" /* TODO: do we want that updatable? */) + "defaultPrefix" /* TODO.spec: do we want that updatable? */) .toRole("global", ADMIN).grantPermission(INSERT) .importRootEntityAliasProxy("debitorRel", HsOfficeRelationEntity.class, 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 668d7cb9..4905efc2 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 @@ -5,7 +5,7 @@ import com.vladmihalcea.hibernate.type.range.Range; import lombok.*; import net.hostsharing.hsadminng.errors.DisplayName; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity; -import net.hostsharing.hsadminng.persistence.HasUuid; +import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject; import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL; @@ -42,7 +42,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify; @NoArgsConstructor @AllArgsConstructor @DisplayName("Membership") -public class HsOfficeMembershipEntity implements HasUuid, Stringifyable { +public class HsOfficeMembershipEntity implements RbacObject, Stringifyable { public static final String MEMBER_NUMBER_TAG = "M-"; public static final String TWO_DECIMAL_DIGITS = "^([0-9]{2})$"; diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerDetailsEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerDetailsEntity.java index a18dbc77..6fae8dc0 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerDetailsEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerDetailsEntity.java @@ -2,7 +2,7 @@ package net.hostsharing.hsadminng.hs.office.partner; import lombok.*; import net.hostsharing.hsadminng.errors.DisplayName; -import net.hostsharing.hsadminng.persistence.HasUuid; +import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL; import net.hostsharing.hsadminng.stringify.Stringify; @@ -26,7 +26,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify; @NoArgsConstructor @AllArgsConstructor @DisplayName("PartnerDetails") -public class HsOfficePartnerDetailsEntity implements HasUuid, Stringifyable { +public class HsOfficePartnerDetailsEntity implements RbacObject, Stringifyable { private static Stringify stringify = stringify( HsOfficePartnerDetailsEntity.class, diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntity.java index 7c9346ea..43b78fca 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntity.java @@ -8,7 +8,7 @@ import lombok.Setter; import net.hostsharing.hsadminng.errors.DisplayName; import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity; import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity; -import net.hostsharing.hsadminng.persistence.HasUuid; +import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL; @@ -45,7 +45,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify; @NoArgsConstructor @AllArgsConstructor @DisplayName("Partner") -public class HsOfficePartnerEntity implements Stringifyable, HasUuid { +public class HsOfficePartnerEntity implements Stringifyable, RbacObject { public static final String PARTNER_NUMBER_TAG = "P-"; diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepository.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepository.java index d334c741..6594cb1b 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepository.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepository.java @@ -11,7 +11,7 @@ public interface HsOfficePartnerRepository extends Repository findByUuid(UUID id); - List findAll(); // TODO: move to a repo in test sources + List findAll(); // TODO.impl: move to a repo in test sources @Query(""" SELECT partner FROM HsOfficePartnerEntity partner diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonEntity.java index e8865ce5..4d07790d 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonEntity.java @@ -3,7 +3,7 @@ package net.hostsharing.hsadminng.hs.office.person; import lombok.*; import lombok.experimental.FieldNameConstants; import net.hostsharing.hsadminng.errors.DisplayName; -import net.hostsharing.hsadminng.persistence.HasUuid; +import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL; import net.hostsharing.hsadminng.stringify.Stringify; @@ -30,7 +30,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify; @AllArgsConstructor @FieldNameConstants @DisplayName("Person") -public class HsOfficePersonEntity implements HasUuid, Stringifyable { +public class HsOfficePersonEntity implements RbacObject, Stringifyable { private static Stringify toString = stringify(HsOfficePersonEntity.class, "person") .withProp(Fields.personType, HsOfficePersonEntity::getPersonType) diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java index 2077cf4a..8d6c6fe8 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java @@ -4,7 +4,7 @@ import lombok.*; import lombok.experimental.FieldNameConstants; import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity; import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity; -import net.hostsharing.hsadminng.persistence.HasUuid; +import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL; import net.hostsharing.hsadminng.stringify.Stringify; @@ -32,7 +32,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify; @NoArgsConstructor @AllArgsConstructor @FieldNameConstants -public class HsOfficeRelationEntity implements HasUuid, Stringifyable { +public class HsOfficeRelationEntity implements RbacObject, Stringifyable { private static Stringify toString = stringify(HsOfficeRelationEntity.class, "rel") .withProp(Fields.anchor, HsOfficeRelationEntity::getAnchor) diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntity.java index 403e2972..6ae8ff64 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntity.java @@ -7,7 +7,7 @@ import net.hostsharing.hsadminng.errors.DisplayName; import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity; import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity; -import net.hostsharing.hsadminng.persistence.HasUuid; +import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.stringify.Stringify; import net.hostsharing.hsadminng.stringify.Stringifyable; @@ -37,7 +37,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify; @NoArgsConstructor @AllArgsConstructor @DisplayName("SEPA-Mandate") -public class HsOfficeSepaMandateEntity implements Stringifyable, HasUuid { +public class HsOfficeSepaMandateEntity implements Stringifyable, RbacObject { private static Stringify stringify = stringify(HsOfficeSepaMandateEntity.class) .withProp(e -> e.getBankAccount().getIban()) diff --git a/src/main/java/net/hostsharing/hsadminng/persistence/HasUuid.java b/src/main/java/net/hostsharing/hsadminng/persistence/HasUuid.java deleted file mode 100644 index 03e6abf3..00000000 --- a/src/main/java/net/hostsharing/hsadminng/persistence/HasUuid.java +++ /dev/null @@ -1,7 +0,0 @@ -package net.hostsharing.hsadminng.persistence; - -import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject; - -// TODO: remove this interface, I just wanted to avoid to many changes in that PR -public interface HasUuid extends RbacObject { -} diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java index 6bba2b12..cb048455 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java @@ -13,7 +13,7 @@ import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity; import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity; import net.hostsharing.hsadminng.hs.office.sepamandate.HsOfficeSepaMandateEntity; -import net.hostsharing.hsadminng.persistence.HasUuid; +import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject; import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject; import net.hostsharing.hsadminng.test.cust.TestCustomerEntity; import net.hostsharing.hsadminng.test.dom.TestDomainEntity; @@ -277,7 +277,7 @@ public class RbacView { */ public RbacView importRootEntityAliasProxy( final String aliasName, - final Class entityClass, + final Class entityClass, final SQL fetchSql, final Column dependsOnColum) { if (rootEntityAliasProxy != null) { @@ -300,7 +300,7 @@ public class RbacView { * a JPA entity class extending RbacObject */ public RbacView importSubEntityAlias( - final String aliasName, final Class entityClass, + final String aliasName, final Class entityClass, final SQL fetchSql, final Column dependsOnColum) { importEntityAliasImpl(aliasName, entityClass, fetchSql, dependsOnColum, true, NOT_NULL); return this; @@ -334,7 +334,7 @@ public class RbacView { * a JPA entity class extending RbacObject */ public RbacView importEntityAlias( - final String aliasName, final Class entityClass, + final String aliasName, final Class entityClass, final Column dependsOnColum, final SQL fetchSql, final Nullable nullable) { importEntityAliasImpl(aliasName, entityClass, fetchSql, dependsOnColum, false, nullable); return this; @@ -342,14 +342,14 @@ public class RbacView { // TODO: remove once it's not used in HsOffice...Entity anymore public RbacView importEntityAlias( - final String aliasName, final Class entityClass, + final String aliasName, final Class entityClass, final Column dependsOnColum) { importEntityAliasImpl(aliasName, entityClass, directlyFetchedByDependsOnColumn(), dependsOnColum, false, null); return this; } private EntityAlias importEntityAliasImpl( - final String aliasName, final Class entityClass, + final String aliasName, final Class entityClass, final SQL fetchSql, final Column dependsOnColum, boolean asSubEntity, final Nullable nullable) { final var entityAlias = new EntityAlias(aliasName, entityClass, fetchSql, dependsOnColum, asSubEntity, nullable); entityAliases.put(aliasName, entityAlias); @@ -1046,7 +1046,7 @@ public class RbacView { } } - private static void generateRbacView(final Class c) { + private static void generateRbacView(final Class c) { final Method mainMethod = stream(c.getMethods()).filter( m -> isStatic(m.getModifiers()) && m.getName().equals("main") ) diff --git a/src/main/java/net/hostsharing/hsadminng/test/cust/TestCustomerEntity.java b/src/main/java/net/hostsharing/hsadminng/test/cust/TestCustomerEntity.java index 94caa1de..19340440 100644 --- a/src/main/java/net/hostsharing/hsadminng/test/cust/TestCustomerEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/test/cust/TestCustomerEntity.java @@ -4,7 +4,7 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import net.hostsharing.hsadminng.persistence.HasUuid; +import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL; @@ -24,7 +24,7 @@ import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor; @Setter @NoArgsConstructor @AllArgsConstructor -public class TestCustomerEntity implements HasUuid { +public class TestCustomerEntity implements RbacObject { @Id @GeneratedValue diff --git a/src/main/java/net/hostsharing/hsadminng/test/dom/TestDomainEntity.java b/src/main/java/net/hostsharing/hsadminng/test/dom/TestDomainEntity.java index d3d387d7..b6d659c5 100644 --- a/src/main/java/net/hostsharing/hsadminng/test/dom/TestDomainEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/test/dom/TestDomainEntity.java @@ -4,7 +4,7 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import net.hostsharing.hsadminng.persistence.HasUuid; +import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL; import net.hostsharing.hsadminng.test.pac.TestPackageEntity; @@ -26,7 +26,7 @@ import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor; @Setter @NoArgsConstructor @AllArgsConstructor -public class TestDomainEntity implements HasUuid { +public class TestDomainEntity implements RbacObject { @Id @GeneratedValue diff --git a/src/main/java/net/hostsharing/hsadminng/test/pac/TestPackageEntity.java b/src/main/java/net/hostsharing/hsadminng/test/pac/TestPackageEntity.java index 3ac28f34..e8430863 100644 --- a/src/main/java/net/hostsharing/hsadminng/test/pac/TestPackageEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/test/pac/TestPackageEntity.java @@ -4,7 +4,7 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import net.hostsharing.hsadminng.persistence.HasUuid; +import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL; import net.hostsharing.hsadminng.test.cust.TestCustomerEntity; @@ -26,7 +26,7 @@ import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor; @Setter @NoArgsConstructor @AllArgsConstructor -public class TestPackageEntity implements HasUuid { +public class TestPackageEntity implements RbacObject { @Id @GeneratedValue diff --git a/src/main/resources/api-definition/rbac/rbac-role-schemas.yaml b/src/main/resources/api-definition/rbac/rbac-role-schemas.yaml index 45736dc3..4e5b5f4d 100644 --- a/src/main/resources/api-definition/rbac/rbac-role-schemas.yaml +++ b/src/main/resources/api-definition/rbac/rbac-role-schemas.yaml @@ -23,7 +23,7 @@ components: - ADMIN - AGENT - TENANT - - GUEST - REFERRER + - GUEST roleName: type: string diff --git a/src/main/resources/db/changelog/0-basis/010-context.sql b/src/main/resources/db/changelog/0-basis/010-context.sql index 3bb37037..8ea73f45 100644 --- a/src/main/resources/db/changelog/0-basis/010-context.sql +++ b/src/main/resources/db/changelog/0-basis/010-context.sql @@ -10,10 +10,10 @@ This function will be overwritten by later changesets. */ create procedure contextDefined( - currentTask varchar, - currentRequest varchar, - currentUser varchar, - assumedRoles varchar + currentTask varchar(127), + currentRequest text, + currentUser varchar(63), + assumedRoles varchar(1023) ) language plpgsql as $$ begin 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 6a3387fb..bfe897a4 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.refact: extract function toRbacRoleDescriptor(roleIdName varchar) + find other occurrences + -- TODO.refa: 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,16 +356,13 @@ create trigger deleteRbacRolesOfRbacObject_Trigger /* */ -create domain RbacOp as varchar(67) -- TODO: shorten to 8, once the deprecated values are gone +create domain RbacOp as varchar(6) 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 @@ -417,37 +414,6 @@ 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 @@ -649,25 +615,6 @@ 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 @@ -691,7 +638,7 @@ declare superRoleId uuid; subRoleId uuid; begin - -- TODO: maybe separate method grantRoleToRoleIfNotNull(...) for NULLABLE references + -- TODO.refa: 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/1054-rbac-context.sql b/src/main/resources/db/changelog/1-rbac/1054-rbac-context.sql index faae1782..ab3a9bd5 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 @@ -85,10 +85,10 @@ end; $$; This function will be overwritten by later changesets. */ create or replace procedure contextDefined( - currentTask varchar, - currentRequest varchar, - currentUser varchar, - assumedRoles varchar + currentTask varchar(127), + currentRequest text, + currentUser varchar(63), + assumedRoles varchar(1023) ) language plpgsql as $$ declare diff --git a/src/main/resources/db/changelog/1-rbac/1057-rbac-role-builder.sql b/src/main/resources/db/changelog/1-rbac/1057-rbac-role-builder.sql index 57a97a2f..57ba3cb7 100644 --- a/src/main/resources/db/changelog/1-rbac/1057-rbac-role-builder.sql +++ b/src/main/resources/db/changelog/1-rbac/1057-rbac-role-builder.sql @@ -1,18 +1,5 @@ --liquibase formatted sql --- ============================================================================ --- PERMISSIONS ---changeset rbac-role-builder-to-uuids:1 endDelimiter:--// --- ---------------------------------------------------------------------------- - -create or replace function toPermissionUuids(forObjectUuid uuid, permitOps RbacOp[]) - returns uuid[] - language plpgsql - strict as $$ -begin - return createPermissions(forObjectUuid, permitOps); -end; $$; - -- ================================================================= -- CREATE ROLE @@ -32,6 +19,8 @@ create or replace function createRoleWithGrants( language plpgsql as $$ declare roleUuid uuid; + permission RbacOp; + permissionUuid uuid; subRoleDesc RbacRoleDescriptor; superRoleDesc RbacRoleDescriptor; subRoleUuid uuid; @@ -41,9 +30,11 @@ declare begin roleUuid := createRole(roleDescriptor); - if cardinality(permissions) > 0 then - call grantPermissionsToRole(roleUuid, toPermissionUuids(roleDescriptor.objectuuid, permissions)); - end if; + foreach permission in array permissions + loop + permissionUuid := createPermission(roleDescriptor.objectuuid, permission); + call grantPermissionToRole(permissionUuid, roleUuid); + end loop; foreach superRoleDesc in array array_remove(incomingSuperRoles, null) loop @@ -60,7 +51,7 @@ begin if cardinality(userUuids) > 0 then -- direct grants to users need a grantedByRole which can revoke the grant if grantedByRole is null then - userGrantsByRoleUuid := roleUuid; -- TODO: or do we want to require an explicit userGrantsByRoleUuid? + userGrantsByRoleUuid := roleUuid; -- TODO.spec: or do we want to require an explicit userGrantsByRoleUuid? else userGrantsByRoleUuid := getRoleId(grantedByRole); 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 958d3afe..cf0804a0 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,15 +73,6 @@ 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/test/java/net/hostsharing/hsadminng/arch/ArchitectureTest.java b/src/test/java/net/hostsharing/hsadminng/arch/ArchitectureTest.java index be612e90..497c60de 100644 --- a/src/test/java/net/hostsharing/hsadminng/arch/ArchitectureTest.java +++ b/src/test/java/net/hostsharing/hsadminng/arch/ArchitectureTest.java @@ -121,7 +121,7 @@ public class ArchitectureTest { .should().onlyBeAccessed().byClassesThat() .resideInAnyPackage( "..hs.office.(*)..", - "..rbac.rbacgrant" // TODO: just because of RbacGrantsDiagramServiceIntegrationTest + "..rbac.rbacgrant" // TODO.test: just because of RbacGrantsDiagramServiceIntegrationTest ); @ArchTest diff --git a/src/test/java/net/hostsharing/hsadminng/context/ContextUnitTest.java b/src/test/java/net/hostsharing/hsadminng/context/ContextUnitTest.java index af78c76a..2104f297 100644 --- a/src/test/java/net/hostsharing/hsadminng/context/ContextUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/context/ContextUnitTest.java @@ -27,12 +27,12 @@ import static org.mockito.Mockito.verify; class ContextUnitTest { private static final String DEFINE_CONTEXT_QUERY_STRING = """ - call defineContext( - cast(:currentTask as varchar), - cast(:currentRequest as varchar), - cast(:currentUser as varchar), - cast(:assumedRoles as varchar)); - """; + call defineContext( + cast(:currentTask as varchar(127)), + cast(:currentRequest as text), + cast(:currentUser as varchar(63)), + cast(:assumedRoles as varchar(1023))); + """; @Nested class WithoutHttpRequest { @@ -71,7 +71,7 @@ class ContextUnitTest { context.define("current-user"); verify(em).createNativeQuery(DEFINE_CONTEXT_QUERY_STRING); - verify(nativeQuery).setParameter("currentRequest", ""); + verify(nativeQuery).setParameter("currentRequest", null); } } @@ -142,8 +142,8 @@ class ContextUnitTest { } @Test - void shortensCurrentTaskTo96Chars() throws IOException { - givenRequest("GET", "http://localhost:9999/api/endpoint/" + "0123456789".repeat(10), + void shortensCurrentTaskToMaxLength() throws IOException { + givenRequest("GET", "http://localhost:9999/api/endpoint/" + "0123456789".repeat(13), Map.ofEntries( Map.entry("current-user", "given-user"), Map.entry("content-type", "application/json"), @@ -153,26 +153,7 @@ class ContextUnitTest { context.define("current-user"); verify(em).createNativeQuery(DEFINE_CONTEXT_QUERY_STRING); - verify(nativeQuery).setParameter(eq("currentTask"), argThat((String t) -> t.length() == 96)); - } - - @Test - void shortensCurrentRequestTo512Chars() throws IOException { - givenRequest("GET", "http://localhost:9999/api/endpoint", - Map.ofEntries( - Map.entry("current-user", "given-user"), - Map.entry("content-type", "application/json"), - Map.entry("user-agent", "given-user-agent")), - """ - { - "dummy": "%s" - } - """.formatted("0123456789".repeat(60))); - - context.define("current-user"); - - verify(em).createNativeQuery(DEFINE_CONTEXT_QUERY_STRING); - verify(nativeQuery).setParameter(eq("currentRequest"), argThat((String t) -> t.length() == 512)); + verify(nativeQuery).setParameter(eq("currentTask"), argThat((String t) -> t.length() == 127)); } private void givenRequest(final String method, final String url, final Map headers, final String body) diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/test/ContextBasedTestWithCleanup.java b/src/test/java/net/hostsharing/hsadminng/hs/office/test/ContextBasedTestWithCleanup.java index 1866f483..81930ee3 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/test/ContextBasedTestWithCleanup.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/test/ContextBasedTestWithCleanup.java @@ -1,7 +1,7 @@ package net.hostsharing.hsadminng.hs.office.test; import net.hostsharing.hsadminng.context.ContextBasedTest; -import net.hostsharing.hsadminng.persistence.HasUuid; +import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject; import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantEntity; import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantRepository; import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantsDiagramService; @@ -66,7 +66,7 @@ public abstract class ContextBasedTestWithCleanup extends ContextBasedTest { return merged; } - public UUID toCleanup(final Class entityClass, final UUID uuidToCleanup) { + public UUID toCleanup(final Class entityClass, final UUID uuidToCleanup) { out.println("toCleanup(" + entityClass.getSimpleName() + ", " + uuidToCleanup); entitiesToCleanup.put(uuidToCleanup, entityClass); return uuidToCleanup; @@ -81,7 +81,7 @@ public abstract class ContextBasedTestWithCleanup extends ContextBasedTest { return entity; } - protected void cleanupAllNew(final Class entityClass) { + protected void cleanupAllNew(final Class entityClass) { if (initialRbacObjects == null) { out.println("skipping cleanupAllNew: " + entityClass.getSimpleName()); return; // TODO: seems @AfterEach is called without any @BeforeEach diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/test/EntityList.java b/src/test/java/net/hostsharing/hsadminng/hs/office/test/EntityList.java index 1699a5d2..2cc55e61 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/test/EntityList.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/test/EntityList.java @@ -1,6 +1,6 @@ package net.hostsharing.hsadminng.hs.office.test; -import net.hostsharing.hsadminng.persistence.HasUuid; +import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject; import java.util.List; @@ -8,7 +8,7 @@ import static org.assertj.core.api.Assertions.assertThat; public class EntityList { - public static E one(final List entities) { + public static E one(final List entities) { assertThat(entities).hasSize(1); return entities.stream().findFirst().orElseThrow(); } diff --git a/src/test/java/net/hostsharing/test/JpaAttempt.java b/src/test/java/net/hostsharing/test/JpaAttempt.java index 86a332cd..d0ddd040 100644 --- a/src/test/java/net/hostsharing/test/JpaAttempt.java +++ b/src/test/java/net/hostsharing/test/JpaAttempt.java @@ -130,7 +130,6 @@ public class JpaAttempt { final Class expectedExceptionClass, final String... expectedRootCauseMessages) { assertThat(wasSuccessful()).as("wasSuccessful").isFalse(); - // TODO: also check the expected exception class itself final String firstRootCauseMessageLine = firstRootCauseMessageLineOf(caughtException(expectedExceptionClass)); for (String expectedRootCauseMessage : expectedRootCauseMessages) { assertThat(firstRootCauseMessageLine).contains(expectedRootCauseMessage); diff --git a/src/test/java/net/hostsharing/test/PatchUnitTestBase.java b/src/test/java/net/hostsharing/test/PatchUnitTestBase.java index ce7ff865..56f97938 100644 --- a/src/test/java/net/hostsharing/test/PatchUnitTestBase.java +++ b/src/test/java/net/hostsharing/test/PatchUnitTestBase.java @@ -1,6 +1,6 @@ package net.hostsharing.test; -import net.hostsharing.hsadminng.persistence.HasUuid; +import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject; import net.hostsharing.hsadminng.mapper.EntityPatcher; import org.junit.jupiter.api.Named; import org.junit.jupiter.api.Test; @@ -233,7 +233,7 @@ public abstract class PatchUnitTestBase { } } - protected static class JsonNullableProperty extends Property { + protected static class JsonNullableProperty extends Property { private final BiConsumer> resourceSetter; public final RV givenPatchValue; -- 2.39.5 From e5c01e70f59f095323dfbcde9a328a677fd418c7 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Sun, 31 Mar 2024 10:53:25 +0200 Subject: [PATCH 10/29] Spring Boot 3.2 upgrade --- build.gradle | 24 ++++++++-------- .../hsadminng/context/Context.java | 9 ++---- .../RestResponseEntityExceptionHandler.java | 28 +++++++++++++++++-- ...OfficeCoopAssetsTransactionController.java | 3 +- ...OfficeCoopSharesTransactionController.java | 3 +- .../HsOfficeMembershipController.java | 3 +- .../membership/HsOfficeMembershipEntity.java | 4 +-- .../HsOfficeSepaMandateController.java | 3 +- .../HsOfficeSepaMandateEntity.java | 4 +-- .../hsadminng/mapper/PostgresDateRange.java | 2 +- ...iceMembershipControllerAcceptanceTest.java | 2 +- ...OfficeMembershipEntityPatcherUnitTest.java | 2 +- .../HsOfficeMembershipEntityUnitTest.java | 2 +- ...ceMembershipRepositoryIntegrationTest.java | 2 +- .../office/membership/TestHsMembership.java | 2 +- ...ceSepaMandateControllerAcceptanceTest.java | 2 +- ...fficeSepaMandateEntityPatcherUnitTest.java | 2 +- ...eSepaMandateRepositoryIntegrationTest.java | 2 +- .../mapper/PostgresArrayIntegrationTest.java | 13 ++------- 19 files changed, 60 insertions(+), 52 deletions(-) diff --git a/build.gradle b/build.gradle index 6539242e..e0ea2844 100644 --- a/build.gradle +++ b/build.gradle @@ -1,15 +1,15 @@ plugins { id 'java' - id 'org.springframework.boot' version '3.1.7' + id 'org.springframework.boot' version '3.2.4' id 'io.spring.dependency-management' version '1.1.4' id 'io.openapiprocessor.openapi-processor' version '2023.2' - id 'com.github.jk1.dependency-license-report' version '2.5' - id "org.owasp.dependencycheck" version "9.0.7" - id "com.diffplug.spotless" version "6.23.3" + id 'com.github.jk1.dependency-license-report' version '2.6' + id "org.owasp.dependencycheck" version "9.0.10" + id "com.diffplug.spotless" version "6.25.0" id 'jacoco' id 'info.solidsoft.pitest' version '1.15.0' id 'se.patrikerdes.use-latest-versions' version '0.2.18' - id 'com.github.ben-manes.versions' version '0.50.0' + id 'com.github.ben-manes.versions' version '0.51.0' } group = 'net.hostsharing' @@ -59,17 +59,17 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'com.github.gavlyukovskiy:datasource-proxy-spring-boot-starter:1.9.1' - implementation 'org.springdoc:springdoc-openapi:2.3.0' - implementation 'org.postgresql:postgresql:42.7.1' - implementation 'org.liquibase:liquibase-core:4.25.1' - implementation 'com.vladmihalcea:hibernate-types-60:2.21.1' - implementation 'io.hypersistence:hypersistence-utils-hibernate-62:3.7.0' - implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.16.1' + implementation 'org.springdoc:springdoc-openapi:2.4.0' + implementation 'org.postgresql:postgresql:42.7.3' + implementation 'org.liquibase:liquibase-core:4.27.0' + //implementation 'com.vladmihalcea:hibernate-types-60:2.21.1' + implementation 'io.hypersistence:hypersistence-utils-hibernate-63:3.7.3' + implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.0' implementation 'org.openapitools:jackson-databind-nullable:0.2.6' implementation 'org.apache.commons:commons-text:1.11.0' implementation 'org.modelmapper:modelmapper:3.2.0' implementation 'org.iban4j:iban4j:3.2.7-RELEASE' - implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0' + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.4.0' // fixes vulnerability CVE-2022-1471 // The dependency usually comes from Spring Boot, just in the wrong version. diff --git a/src/main/java/net/hostsharing/hsadminng/context/Context.java b/src/main/java/net/hostsharing/hsadminng/context/Context.java index 9a5084f0..b3dac96b 100644 --- a/src/main/java/net/hostsharing/hsadminng/context/Context.java +++ b/src/main/java/net/hostsharing/hsadminng/context/Context.java @@ -15,11 +15,9 @@ import java.util.Collections; import java.util.Optional; import java.util.Set; import java.util.UUID; -import java.util.function.Function; import java.util.stream.Collectors; import static java.util.function.Predicate.not; -import static net.hostsharing.hsadminng.mapper.PostgresArray.fromPostgresArray; import static org.springframework.transaction.annotation.Propagation.MANDATORY; @Service @@ -82,14 +80,11 @@ public class Context { } public String[] getAssumedRoles() { - final byte[] result = (byte[]) em.createNativeQuery("select assumedRoles() as roles", String[].class).getSingleResult(); - return fromPostgresArray(result, String.class, Function.identity()); + return (String[]) em.createNativeQuery("select assumedRoles() as roles", String[].class).getSingleResult(); } public UUID[] currentSubjectsUuids() { - final byte[] result = (byte[]) em.createNativeQuery("select currentSubjectsUuids() as uuids", UUID[].class) - .getSingleResult(); - return fromPostgresArray(result, UUID.class, UUID::fromString); + return (UUID[]) em.createNativeQuery("select currentSubjectsUuids() as uuids", UUID[].class).getSingleResult(); } public static String getCallerMethodNameFromStackFrame(final int skipFrames) { diff --git a/src/main/java/net/hostsharing/hsadminng/errors/RestResponseEntityExceptionHandler.java b/src/main/java/net/hostsharing/hsadminng/errors/RestResponseEntityExceptionHandler.java index 6c36dfb8..5d675484 100644 --- a/src/main/java/net/hostsharing/hsadminng/errors/RestResponseEntityExceptionHandler.java +++ b/src/main/java/net/hostsharing/hsadminng/errors/RestResponseEntityExceptionHandler.java @@ -11,16 +11,18 @@ import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.lang.Nullable; import org.springframework.orm.jpa.JpaObjectRetrievalFailureException; import org.springframework.orm.jpa.JpaSystemException; +import org.springframework.validation.FieldError; +import org.springframework.validation.method.ParameterValidationResult; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.context.request.WebRequest; +import org.springframework.web.method.annotation.HandlerMethodValidationException; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; import jakarta.persistence.EntityNotFoundException; import jakarta.validation.ValidationException; -import java.util.NoSuchElementException; -import java.util.Optional; +import java.util.*; import java.util.regex.Pattern; import static net.hostsharing.hsadminng.errors.CustomErrorResponse.*; @@ -119,6 +121,28 @@ public class RestResponseEntityExceptionHandler return errorResponse(request, HttpStatus.BAD_REQUEST, errorList.toString()); } + @SuppressWarnings("unchecked,rawtypes") + + @Override + protected ResponseEntity handleHandlerMethodValidationException( + final HandlerMethodValidationException exc, + final HttpHeaders headers, + final HttpStatusCode status, + final WebRequest request) { + final var errorList = exc + .getAllValidationResults() + .stream() + .map(ParameterValidationResult::getResolvableErrors) + .flatMap(Collection::stream) + .filter(FieldError.class::isInstance) + .map(FieldError.class::cast) + .map(fieldError -> fieldError.getField() + " " + fieldError.getDefaultMessage() + " but is \"" + + fieldError.getRejectedValue() + "\"") + .toList(); + return errorResponse(request, HttpStatus.BAD_REQUEST, errorList.toString()); + } + + private String userReadableEntityClassName(final String exceptionMessage) { final var regex = "(net.hostsharing.hsadminng.[a-z0-9_.]*.[A-Za-z0-9_$]*Entity) "; final var pattern = Pattern.compile(regex); diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionController.java b/src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionController.java index 946b4626..add8333c 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionController.java @@ -13,7 +13,6 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder; -import jakarta.validation.Valid; import jakarta.validation.ValidationException; import java.time.LocalDate; import java.util.ArrayList; @@ -59,7 +58,7 @@ public class HsOfficeCoopAssetsTransactionController implements HsOfficeCoopAsse public ResponseEntity addCoopAssetsTransaction( final String currentUser, final String assumedRoles, - @Valid final HsOfficeCoopAssetsTransactionInsertResource requestBody) { + final HsOfficeCoopAssetsTransactionInsertResource requestBody) { context.define(currentUser, assumedRoles); validate(requestBody); diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionController.java b/src/main/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionController.java index 813d8b92..39dc9002 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionController.java @@ -13,7 +13,6 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder; -import jakarta.validation.Valid; import jakarta.validation.ValidationException; import java.time.LocalDate; import java.util.ArrayList; @@ -60,7 +59,7 @@ public class HsOfficeCoopSharesTransactionController implements HsOfficeCoopShar public ResponseEntity addCoopSharesTransaction( final String currentUser, final String assumedRoles, - @Valid final HsOfficeCoopSharesTransactionInsertResource requestBody) { + final HsOfficeCoopSharesTransactionInsertResource requestBody) { context.define(currentUser, assumedRoles); validate(requestBody); diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipController.java b/src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipController.java index 540ba2a2..3c783aae 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipController.java @@ -12,7 +12,6 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder; -import jakarta.validation.Valid; import java.util.List; import java.util.UUID; import java.util.function.BiConsumer; @@ -53,7 +52,7 @@ public class HsOfficeMembershipController implements HsOfficeMembershipsApi { public ResponseEntity addMembership( final String currentUser, final String assumedRoles, - @Valid final HsOfficeMembershipInsertResource body) { + final HsOfficeMembershipInsertResource body) { context.define(currentUser, assumedRoles); 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 4905efc2..6259b50d 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 @@ -1,7 +1,7 @@ package net.hostsharing.hsadminng.hs.office.membership; -import com.vladmihalcea.hibernate.type.range.PostgreSQLRangeType; -import com.vladmihalcea.hibernate.type.range.Range; +import io.hypersistence.utils.hibernate.type.range.PostgreSQLRangeType; +import io.hypersistence.utils.hibernate.type.range.Range; import lombok.*; import net.hostsharing.hsadminng.errors.DisplayName; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity; diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateController.java b/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateController.java index 364f4ba4..115b8948 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateController.java @@ -14,7 +14,6 @@ import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBui import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; -import jakarta.validation.Valid; import java.util.List; import java.util.UUID; import java.util.function.BiConsumer; @@ -57,7 +56,7 @@ public class HsOfficeSepaMandateController implements HsOfficeSepaMandatesApi { public ResponseEntity addSepaMandate( final String currentUser, final String assumedRoles, - @Valid final HsOfficeSepaMandateInsertResource body) { + final HsOfficeSepaMandateInsertResource body) { context.define(currentUser, assumedRoles); diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntity.java index 6ae8ff64..ac831295 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntity.java @@ -1,7 +1,7 @@ package net.hostsharing.hsadminng.hs.office.sepamandate; -import com.vladmihalcea.hibernate.type.range.PostgreSQLRangeType; -import com.vladmihalcea.hibernate.type.range.Range; +import io.hypersistence.utils.hibernate.type.range.PostgreSQLRangeType; +import io.hypersistence.utils.hibernate.type.range.Range; import lombok.*; import net.hostsharing.hsadminng.errors.DisplayName; import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity; diff --git a/src/main/java/net/hostsharing/hsadminng/mapper/PostgresDateRange.java b/src/main/java/net/hostsharing/hsadminng/mapper/PostgresDateRange.java index c360db1a..db6ad189 100644 --- a/src/main/java/net/hostsharing/hsadminng/mapper/PostgresDateRange.java +++ b/src/main/java/net/hostsharing/hsadminng/mapper/PostgresDateRange.java @@ -1,6 +1,6 @@ package net.hostsharing.hsadminng.mapper; -import com.vladmihalcea.hibernate.type.range.Range; +import io.hypersistence.utils.hibernate.type.range.Range; import lombok.experimental.UtilityClass; import java.time.LocalDate; 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..5b59c9cb 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 @@ -1,6 +1,6 @@ package net.hostsharing.hsadminng.hs.office.membership; -import com.vladmihalcea.hibernate.type.range.Range; +import io.hypersistence.utils.hibernate.type.range.Range; import io.restassured.RestAssured; import io.restassured.http.ContentType; import net.hostsharing.hsadminng.HsadminNgApplication; diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityPatcherUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityPatcherUnitTest.java index b691095b..ddad360e 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityPatcherUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityPatcherUnitTest.java @@ -1,6 +1,6 @@ package net.hostsharing.hsadminng.hs.office.membership; -import com.vladmihalcea.hibernate.type.range.Range; +import io.hypersistence.utils.hibernate.type.range.Range; import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeMembershipPatchResource; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeReasonForTerminationResource; diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityUnitTest.java index 1c4d2dc6..ef47eaa0 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityUnitTest.java @@ -1,6 +1,6 @@ package net.hostsharing.hsadminng.hs.office.membership; -import com.vladmihalcea.hibernate.type.range.Range; +import io.hypersistence.utils.hibernate.type.range.Range; import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity; import org.junit.jupiter.api.Test; 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..8ffc9e1b 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 @@ -1,6 +1,6 @@ package net.hostsharing.hsadminng.hs.office.membership; -import com.vladmihalcea.hibernate.type.range.Range; +import io.hypersistence.utils.hibernate.type.range.Range; import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorRepository; import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerRepository; diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/TestHsMembership.java b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/TestHsMembership.java index ff50eb58..857e9369 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/TestHsMembership.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/TestHsMembership.java @@ -1,6 +1,6 @@ package net.hostsharing.hsadminng.hs.office.membership; -import com.vladmihalcea.hibernate.type.range.Range; +import io.hypersistence.utils.hibernate.type.range.Range; import java.time.LocalDate; diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateControllerAcceptanceTest.java index ad94ca9d..33a6810a 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateControllerAcceptanceTest.java @@ -1,6 +1,6 @@ package net.hostsharing.hsadminng.hs.office.sepamandate; -import com.vladmihalcea.hibernate.type.range.Range; +import io.hypersistence.utils.hibernate.type.range.Range; import io.restassured.RestAssured; import io.restassured.http.ContentType; import net.hostsharing.hsadminng.HsadminNgApplication; diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntityPatcherUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntityPatcherUnitTest.java index 05f4ca07..04ba4fee 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntityPatcherUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntityPatcherUnitTest.java @@ -1,6 +1,6 @@ package net.hostsharing.hsadminng.hs.office.sepamandate; -import com.vladmihalcea.hibernate.type.range.Range; +import io.hypersistence.utils.hibernate.type.range.Range; import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeSepaMandatePatchResource; import net.hostsharing.test.PatchUnitTestBase; diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateRepositoryIntegrationTest.java index a0555579..4f558db8 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateRepositoryIntegrationTest.java @@ -1,6 +1,6 @@ package net.hostsharing.hsadminng.hs.office.sepamandate; -import com.vladmihalcea.hibernate.type.range.Range; +import io.hypersistence.utils.hibernate.type.range.Range; import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountRepository; import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorRepository; diff --git a/src/test/java/net/hostsharing/hsadminng/mapper/PostgresArrayIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/mapper/PostgresArrayIntegrationTest.java index 8f3e95e0..3542caa1 100644 --- a/src/test/java/net/hostsharing/hsadminng/mapper/PostgresArrayIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/mapper/PostgresArrayIntegrationTest.java @@ -7,7 +7,6 @@ import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import jakarta.persistence.EntityManager; import java.util.UUID; -import java.util.function.Function; import static org.assertj.core.api.Assertions.assertThat; @@ -30,9 +29,7 @@ class PostgresArrayIntegrationTest { return emptyArray; end; $$; """).executeUpdate(); - final byte[] pgArray = (byte[]) em.createNativeQuery("SELECT returnEmptyArray()", String[].class).getSingleResult(); - - final String[] result = PostgresArray.fromPostgresArray(pgArray, String.class, Function.identity()); + final String[] result = (String[]) em.createNativeQuery("SELECT returnEmptyArray()", String[].class).getSingleResult(); assertThat(result).isEmpty(); } @@ -53,9 +50,7 @@ class PostgresArrayIntegrationTest { return array[text1, text2, text3, null, text4]; end; $$; """).executeUpdate(); - final byte[] pgArray = (byte[]) em.createNativeQuery("SELECT returnStringArray()", String[].class).getSingleResult(); - - final String[] result = PostgresArray.fromPostgresArray(pgArray, String.class, Function.identity()); + final String[] result = (String[]) em.createNativeQuery("SELECT returnStringArray()", String[].class).getSingleResult(); assertThat(result).containsExactly("one", "two, three", "four; five", null, "say \"Hello\" to me"); } @@ -75,9 +70,7 @@ class PostgresArrayIntegrationTest { return ARRAY[uuid1, uuid2, null, uuid3]; end; $$; """).executeUpdate(); - final byte[] pgArray = (byte[]) em.createNativeQuery("SELECT returnUuidArray()", UUID[].class).getSingleResult(); - - final UUID[] result = PostgresArray.fromPostgresArray(pgArray, UUID.class, UUID::fromString); + final UUID[] result = (UUID[]) em.createNativeQuery("SELECT returnUuidArray()", UUID[].class).getSingleResult(); assertThat(result).containsExactly( UUID.fromString("f47ac10b-58cc-4372-a567-0e02b2c3d479"), -- 2.39.5 From f29dc8007495d5e2fc2d18a8a1b1056d0717d377 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Sun, 31 Mar 2024 12:27:34 +0200 Subject: [PATCH 11/29] remove version workarounds which are not necessary anymore --- build.gradle | 11 ----------- settings.gradle | 24 ------------------------ 2 files changed, 35 deletions(-) diff --git a/build.gradle b/build.gradle index e0ea2844..a11d9493 100644 --- a/build.gradle +++ b/build.gradle @@ -71,17 +71,6 @@ dependencies { implementation 'org.iban4j:iban4j:3.2.7-RELEASE' implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.4.0' - // fixes vulnerability CVE-2022-1471 - // The dependency usually comes from Spring Boot, just in the wrong version. - // TODO: Remove this explicit dependency once we are on SpringBoot 3.2.x - // as well as the related exclude in settings.gradle - // and the dependency suppression in owasp-dependency-check-suppression.xml. - implementation('org.yaml:snakeyaml') { - version { - strictly('2.2') - } - } - compileOnly 'org.projectlombok:lombok' testCompileOnly 'org.projectlombok:lombok' diff --git a/settings.gradle b/settings.gradle index 09d09d6f..d6f3f9eb 100644 --- a/settings.gradle +++ b/settings.gradle @@ -11,28 +11,4 @@ plugins { id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0' } -dependencyResolutionManagement { - components { - all { - allVariants { - withDependencies { - removeAll { - // Spring Boot 3.1.x has a transient dependency to snakeyaml 1.3 - // which contains a severe vulnerability. - // Here we remove this transient dependency and in build.gradle - // we add an explicit dependency to snakeyaml 2.2, - // which does not have this vulnerability anymore. - // - // TODO: Check Once we are on SpringBoot 3.2.x, check if this exclude - // is still neccessary. If not: - // Remove it // as well as the related explicit dependency in build.gradle - // and the dependency suppression in owasp-dependency-check-suppression.xml. - it.module in [ 'snakeyaml' ] - } - } - } - } - } -} - rootProject.name = 'hsadmin-ng' -- 2.39.5 From bdcde1519b26f122fec5e3057c7013008894d87f Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Sun, 31 Mar 2024 14:02:57 +0200 Subject: [PATCH 12/29] remove snakeyaml exclude --- etc/owasp-dependency-check-suppression.xml | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/etc/owasp-dependency-check-suppression.xml b/etc/owasp-dependency-check-suppression.xml index 39d77b47..f04711a8 100644 --- a/etc/owasp-dependency-check-suppression.xml +++ b/etc/owasp-dependency-check-suppression.xml @@ -49,17 +49,4 @@ ^pkg:maven/org\.pitest/pitest\-command\-line@.*$ cpe:/a:line:line - - - ^pkg:maven/org\.yaml/snakeyaml@.*$ - CVE-2022-1471 - -- 2.39.5 From 952fafffdb28426937f4168c34c15a51c56bd1bc Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Sun, 31 Mar 2024 14:05:32 +0200 Subject: [PATCH 13/29] remove further unnecessary excludes --- etc/owasp-dependency-check-suppression.xml | 35 ---------------------- 1 file changed, 35 deletions(-) diff --git a/etc/owasp-dependency-check-suppression.xml b/etc/owasp-dependency-check-suppression.xml index f04711a8..af4269d4 100644 --- a/etc/owasp-dependency-check-suppression.xml +++ b/etc/owasp-dependency-check-suppression.xml @@ -1,33 +1,5 @@ - - - ^pkg:maven/org\.springframework/spring-web@.*$ - CVE-2016-1000027 - - - - ^pkg:maven/com\.fasterxml\.jackson\.core/jackson\-databind@.*$ - CVE-2022-42003 - - - - ^pkg:maven/org\.eclipse\.angus/angus\-activation@.*$ - cpe:/a:eclipse:eclipse_ide - - - - ^pkg:maven/jakarta\.activation/jakarta\.activation\-api@.*$ - cpe:/a:eclipse:eclipse_ide - ^pkg:maven/com\.fasterxml\.jackson\.core/jackson\-databind@.*$ cpe:/a:fasterxml:jackson-databind - - - ^pkg:maven/com\.jayway\.jsonpath/json\-path@.*$ - CVE-2023-51074 - Date: Tue, 2 Apr 2024 09:32:16 +0200 Subject: [PATCH 14/29] remove superfluous grant to TENANT which was also granted to AGENT --- .../relation/HsOfficeRelationEntity.java | 1 - .../RolesGrantsAndPermissionsGenerator.java | 67 +++++++++++-------- .../5033-hs-office-relation-rbac.md | 1 - .../5033-hs-office-relation-rbac.sql | 1 - ...ficeRelationRepositoryIntegrationTest.java | 1 - 5 files changed, 40 insertions(+), 31 deletions(-) diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java index 8d6c6fe8..21c82852 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java @@ -118,7 +118,6 @@ public class HsOfficeRelationEntity implements RbacObject, Stringifyable { with.incomingSuperRole("holderPerson", ADMIN); }) .createSubRole(TENANT, (with) -> { - with.incomingSuperRole("holderPerson", ADMIN); with.incomingSuperRole("contact", ADMIN); with.outgoingSubRole("anchorPerson", REFERRER); with.outgoingSubRole("holderPerson", REFERRER); diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java index 484415f2..98f29973 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java @@ -1,5 +1,6 @@ package net.hostsharing.hsadminng.rbac.rbacdef; +import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacGrantDefinition; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacPermissionDefinition; import java.util.HashSet; @@ -22,7 +23,7 @@ import static org.apache.commons.lang3.StringUtils.uncapitalize; class RolesGrantsAndPermissionsGenerator { private final RbacView rbacDef; - private final Set rbacGrants = new HashSet<>(); + private final Set rbacGrants = new HashSet<>(); private final String liquibaseTagPrefix; private final String simpleEntityName; private final String simpleEntityVarName; @@ -31,7 +32,7 @@ class RolesGrantsAndPermissionsGenerator { RolesGrantsAndPermissionsGenerator(final RbacView rbacDef, final String liquibaseTagPrefix) { this.rbacDef = rbacDef; this.rbacGrants.addAll(rbacDef.getGrantDefs().stream() - .filter(RbacView.RbacGrantDefinition::isToCreate) + .filter(RbacGrantDefinition::isToCreate) .collect(toSet())); this.liquibaseTagPrefix = liquibaseTagPrefix; @@ -67,13 +68,11 @@ class RolesGrantsAndPermissionsGenerator { NEW ${rawTableName} ) language plpgsql as $$ - - declare """ .replace("${simpleEntityName}", simpleEntityName) .replace("${rawTableName}", rawTableName)); - plPgSql.chopEmptyLines(); + plPgSql.writeLn("declare"); plPgSql.indented(() -> { referencedEntityAliases() .forEach((ea) -> plPgSql.writeLn(entityRefVar(NEW, ea) + " " + ea.getRawTableName() + ";")); @@ -172,6 +171,10 @@ class RolesGrantsAndPermissionsGenerator { .anyMatch(e -> true); } + private boolean hasAnyConditionalGrants() { + return rbacDef.getGrantDefs().stream().anyMatch(RbacGrantDefinition::isConditional); + } + private void generateCreateRolesAndGrantsAfterInsert(final StringWriter plPgSql) { referencedEntityAliases() .forEach((ea) -> { @@ -248,7 +251,7 @@ class RolesGrantsAndPermissionsGenerator { private void updateGrantsDependingOn(final StringWriter plPgSql, final String columnName) { rbacDef.getGrantDefs().stream() - .filter(RbacView.RbacGrantDefinition::isToCreate) + .filter(RbacGrantDefinition::isToCreate) .filter(g -> g.dependsOnColumn(columnName)) .filter(g -> !isInsertPermissionGrant(g)) .forEach(g -> { @@ -259,21 +262,21 @@ class RolesGrantsAndPermissionsGenerator { }); } - private static Boolean isInsertPermissionGrant(final RbacView.RbacGrantDefinition g) { + private static Boolean isInsertPermissionGrant(final RbacGrantDefinition g) { final var isInsertPermissionGrant = ofNullable(g.getPermDef()).map(RbacPermissionDefinition::getPermission).map(p -> p == INSERT).orElse(false); return isInsertPermissionGrant; } - private void generateGrants(final StringWriter plPgSql, final RbacView.RbacGrantDefinition.GrantType grantType) { + private void generateGrants(final StringWriter plPgSql, final RbacGrantDefinition.GrantType grantType) { plPgSql.ensureSingleEmptyLine(); rbacGrants.stream() .filter(g -> g.grantType() == grantType) .map(this::generateGrant) .sorted() - .forEach(text -> plPgSql.writeLn(text)); + .forEach(text -> plPgSql.writeLn(text, with("ref", NEW.name()))); } - private String generateRevoke(RbacView.RbacGrantDefinition grantDef) { + private String generateRevoke(RbacGrantDefinition grantDef) { return switch (grantDef.grantType()) { case ROLE_TO_USER -> throw new IllegalArgumentException("unexpected grant"); case ROLE_TO_ROLE -> "call revokeRoleFromRole(${subRoleRef}, ${superRoleRef});" @@ -285,8 +288,8 @@ class RolesGrantsAndPermissionsGenerator { }; } - private String generateGrant(RbacView.RbacGrantDefinition grantDef) { - return switch (grantDef.grantType()) { + private String generateGrant(RbacGrantDefinition grantDef) { + final var grantSql = switch (grantDef.grantType()) { case ROLE_TO_USER -> throw new IllegalArgumentException("unexpected grant"); case ROLE_TO_ROLE -> "call grantRoleToRole(${subRoleRef}, ${superRoleRef}${assumed});" .replace("${assumed}", grantDef.isAssumed() ? "" : ", unassumed()") @@ -298,6 +301,12 @@ class RolesGrantsAndPermissionsGenerator { .replace("${permRef}", createPerm(NEW, grantDef.getPermDef())) .replace("${superRoleRef}", roleRef(NEW, grantDef.getSuperRoleDef())); }; + if (grantDef.isConditional()) { + return "if " + grantDef.getSqlWhere() + " then\n" + + " " + grantSql + "\n" + + "end if;"; + } + return grantSql; } private String findPerm(final PostgresTriggerReference ref, final RbacPermissionDefinition permDef) { @@ -380,7 +389,7 @@ class RolesGrantsAndPermissionsGenerator { final var grantsToUsers = findGrantsToUserForRole(rbacDef.getRootEntityAlias(), role); if (!grantsToUsers.isEmpty()) { final var arrayElements = grantsToUsers.stream() - .map(RbacView.RbacGrantDefinition::getUserDef) + .map(RbacGrantDefinition::getUserDef) .map(this::toPlPgSqlReference) .toList(); plPgSql.indented(() -> @@ -393,7 +402,7 @@ class RolesGrantsAndPermissionsGenerator { final var permissionGrantsForRole = findPermissionsGrantsForRole(rbacDef.getRootEntityAlias(), role); if (!permissionGrantsForRole.isEmpty()) { final var arrayElements = permissionGrantsForRole.stream() - .map(RbacView.RbacGrantDefinition::getPermDef) + .map(RbacGrantDefinition::getPermDef) .map(RbacPermissionDefinition::getPermission) .map(RbacView.Permission::name) .map(p -> "'" + p + "'") @@ -406,26 +415,30 @@ class RolesGrantsAndPermissionsGenerator { } private void generateIncomingSuperRolesForRole(final StringWriter plPgSql, final RbacView.Role role) { - final var incomingGrants = findIncomingSuperRolesForRole(rbacDef.getRootEntityAlias(), role); - if (!incomingGrants.isEmpty()) { - final var arrayElements = incomingGrants.stream() + final var unconditionalIncomingGrants = findIncomingSuperRolesForRole(rbacDef.getRootEntityAlias(), role).stream() + .filter(g -> !g.isConditional()) + .toList(); + if (!unconditionalIncomingGrants.isEmpty()) { + final var arrayElements = unconditionalIncomingGrants.stream() .map(g -> toPlPgSqlReference(NEW, g.getSuperRoleDef(), g.isAssumed())) .sorted().toList(); plPgSql.indented(() -> plPgSql.writeLn("incomingSuperRoles => array[" + joinArrayElements(arrayElements, 1) + "],\n")); - rbacGrants.removeAll(incomingGrants); + rbacGrants.removeAll(unconditionalIncomingGrants); } } private void generateOutgoingSubRolesForRole(final StringWriter plPgSql, final RbacView.Role role) { - final var outgoingGrants = findOutgoingSuperRolesForRole(rbacDef.getRootEntityAlias(), role); - if (!outgoingGrants.isEmpty()) { - final var arrayElements = outgoingGrants.stream() + final var unconditionalOutgoingGrants = findOutgoingSuperRolesForRole(rbacDef.getRootEntityAlias(), role).stream() + .filter(g -> !g.isConditional()) + .toList(); + if (!unconditionalOutgoingGrants.isEmpty()) { + final var arrayElements = unconditionalOutgoingGrants.stream() .map(g -> toPlPgSqlReference(NEW, g.getSubRoleDef(), g.isAssumed())) .sorted().toList(); plPgSql.indented(() -> plPgSql.writeLn("outgoingSubRoles => array[" + joinArrayElements(arrayElements, 1) + "],\n")); - rbacGrants.removeAll(outgoingGrants); + rbacGrants.removeAll(unconditionalOutgoingGrants); } } @@ -435,7 +448,7 @@ class RolesGrantsAndPermissionsGenerator { : arrayElements.stream().collect(joining(",\n\t", "\n\t", "")); } - private Set findPermissionsGrantsForRole( + private Set findPermissionsGrantsForRole( final RbacView.EntityAlias entityAlias, final RbacView.Role role) { final var roleDef = rbacDef.findRbacRole(entityAlias, role); @@ -444,7 +457,7 @@ class RolesGrantsAndPermissionsGenerator { .collect(toSet()); } - private Set findGrantsToUserForRole( + private Set findGrantsToUserForRole( final RbacView.EntityAlias entityAlias, final RbacView.Role role) { final var roleDef = rbacDef.findRbacRole(entityAlias, role); @@ -453,7 +466,7 @@ class RolesGrantsAndPermissionsGenerator { .collect(toSet()); } - private Set findIncomingSuperRolesForRole( + private Set findIncomingSuperRolesForRole( final RbacView.EntityAlias entityAlias, final RbacView.Role role) { final var roleDef = rbacDef.findRbacRole(entityAlias, role); @@ -462,7 +475,7 @@ class RolesGrantsAndPermissionsGenerator { .collect(toSet()); } - private Set findOutgoingSuperRolesForRole( + private Set findOutgoingSuperRolesForRole( final RbacView.EntityAlias entityAlias, final RbacView.Role role) { final var roleDef = rbacDef.findRbacRole(entityAlias, role); @@ -506,7 +519,7 @@ class RolesGrantsAndPermissionsGenerator { private void generateUpdateTrigger(final StringWriter plPgSql) { generateHeader(plPgSql, "update"); - if ( hasAnyUpdatableAndNullableEntityAliases() ) { + if ( hasAnyUpdatableAndNullableEntityAliases() || hasAnyConditionalGrants() ) { generateSimplifiedUpdateTriggerFunction(plPgSql); } else { generateUpdateTriggerFunction(plPgSql); diff --git a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md index 8014cdaf..3f45379b 100644 --- a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md +++ b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md @@ -87,7 +87,6 @@ role:anchorPerson:ADMIN ==> role:relation:ADMIN role:relation:ADMIN ==> role:relation:AGENT role:holderPerson:ADMIN ==> role:relation:AGENT role:relation:AGENT ==> role:relation:TENANT -role:holderPerson:ADMIN ==> role:relation:TENANT role:contact:ADMIN ==> role:relation:TENANT role:relation:TENANT ==> role:anchorPerson:REFERRER role:relation:TENANT ==> role:holderPerson:REFERRER diff --git a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql index ff890a59..ae783ff6 100644 --- a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql +++ b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql @@ -74,7 +74,6 @@ begin permissions => array['SELECT'], incomingSuperRoles => array[ hsOfficeContactADMIN(newContact), - hsOfficePersonADMIN(newHolderPerson), hsOfficeRelationAGENT(NEW)], outgoingSubRoles => array[ hsOfficeContactREFERRER(newContact), diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java index f474de0c..91a7965e 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java @@ -153,7 +153,6 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea // REPRESENTATIVE holder person -> (represented) anchor person "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:TENANT to role:hs_office_contact#fourthcontact:ADMIN by system and assume }", - "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:TENANT to role:hs_office_person#BesslerBert:ADMIN by system and assume }", null) ); -- 2.39.5 From 4f25bf14967f1a6027a6d0a982c49901e0388458 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Tue, 2 Apr 2024 10:09:28 +0200 Subject: [PATCH 15/29] WIP: rbac-generator-with-conditional-grants --- .../relation/HsOfficeRelationEntity.java | 10 ++- .../hsadminng/rbac/rbacdef/RbacView.java | 17 ++++- .../RbacViewMermaidFlowchartGenerator.java | 4 +- .../5033-hs-office-relation-rbac.md | 6 +- .../5033-hs-office-relation-rbac.sql | 63 +++++------------ ...ficeRelationRepositoryIntegrationTest.java | 67 ++++++++++++++++++- 6 files changed, 109 insertions(+), 58 deletions(-) diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java index 21c82852..a46ab2d9 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java @@ -104,18 +104,16 @@ public class HsOfficeRelationEntity implements RbacObject, Stringifyable { .createRole(OWNER, (with) -> { with.owningUser(CREATOR); with.incomingSuperRole(GLOBAL, ADMIN); - // TODO: if type=REPRESENTATIIVE - // with.incomingSuperRole("holderPerson", ADMIN); + with.incomingSuperRole("holderPerson", ADMIN).where("${REF}.type = 'REPRESENTATIVE'"); with.permission(DELETE); }) .createSubRole(ADMIN, (with) -> { - with.incomingSuperRole("anchorPerson", ADMIN); - // TODO: if type=REPRESENTATIIVE - // with.outgoingSuperRole("anchorPerson", OWNER); + with.incomingSuperRole("anchorPerson", ADMIN).where("${REF}.type <> 'REPRESENTATIVE'"); + with.outgoingSubRole("anchorPerson", OWNER).where("${REF}.type = 'REPRESENTATIVE'"); with.permission(UPDATE); }) .createSubRole(AGENT, (with) -> { - with.incomingSuperRole("holderPerson", ADMIN); + with.incomingSuperRole("holderPerson", ADMIN).where("${REF}.type <> 'REPRESENTATIVE'"); }) .createSubRole(TENANT, (with) -> { with.incomingSuperRole("contact", ADMIN); diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java index cb048455..a09b270b 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java @@ -496,10 +496,13 @@ public class RbacView { private final RbacPermissionDefinition permDef; private boolean assumed = true; private boolean toCreate = false; + private String sqlWhere; @Override public String toString() { - final var arrow = isAssumed() ? " --> " : " -- // --> "; + final var arrow = isConditional() + ? (isAssumed() ? " -- ?? --> " : " -- ?//? --> ") + : (isAssumed() ? " --> " : " -- // --> "); return switch (grantType()) { case ROLE_TO_USER -> userDef.toString() + arrow + subRoleDef.toString(); case ROLE_TO_ROLE -> superRoleDef + arrow + subRoleDef; @@ -546,6 +549,10 @@ public class RbacView { return assumed; } + boolean isConditional() { + return sqlWhere != null; + } + boolean isToCreate() { return toCreate; } @@ -567,8 +574,14 @@ public class RbacView { .orElse(false); } - public void unassumed() { + public RbacGrantDefinition unassumed() { this.assumed = false; + return this; + } + + public RbacGrantDefinition where(final String sqlWhere) { + this.sqlWhere = sqlWhere; + return this; } public enum GrantType { diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java index c6e775c9..4b6e1c14 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java @@ -109,7 +109,9 @@ public class RbacViewMermaidFlowchartGenerator { private String grantDef(final RbacView.RbacGrantDefinition grant) { final var arrow = (grant.isToCreate() ? " ==>" : " -.->") - + (grant.isAssumed() ? " " : "|XX| "); + + (grant.isConditional() + ? (grant.isAssumed() ? " |??| " : "|?XX?| ") + : (grant.isAssumed() ? " " : "|XX| ")); return switch (grant.grantType()) { case ROLE_TO_USER -> // TODO: other user types not implemented yet diff --git a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md index 3f45379b..be9f89b7 100644 --- a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md +++ b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md @@ -82,10 +82,12 @@ role:global:ADMIN -.-> role:contact:OWNER role:contact:OWNER -.-> role:contact:ADMIN role:contact:ADMIN -.-> role:contact:REFERRER role:global:ADMIN ==> role:relation:OWNER +role:holderPerson:ADMIN ==> |??| role:relation:OWNER role:relation:OWNER ==> role:relation:ADMIN -role:anchorPerson:ADMIN ==> role:relation:ADMIN +role:anchorPerson:ADMIN ==> |??| role:relation:ADMIN +role:relation:ADMIN ==> |??| role:anchorPerson:OWNER role:relation:ADMIN ==> role:relation:AGENT -role:holderPerson:ADMIN ==> role:relation:AGENT +role:holderPerson:ADMIN ==> |??| role:relation:AGENT role:relation:AGENT ==> role:relation:TENANT role:contact:ADMIN ==> role:relation:TENANT role:relation:TENANT ==> role:anchorPerson:REFERRER diff --git a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql index ae783ff6..aca2eb93 100644 --- a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql +++ b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql @@ -57,16 +57,12 @@ begin perform createRoleWithGrants( hsOfficeRelationADMIN(NEW), permissions => array['UPDATE'], - incomingSuperRoles => array[ - hsOfficePersonADMIN(newAnchorPerson), - hsOfficeRelationOWNER(NEW)] + incomingSuperRoles => array[hsOfficeRelationOWNER(NEW)] ); perform createRoleWithGrants( hsOfficeRelationAGENT(NEW), - incomingSuperRoles => array[ - hsOfficePersonADMIN(newHolderPerson), - hsOfficeRelationADMIN(NEW)] + incomingSuperRoles => array[hsOfficeRelationADMIN(NEW)] ); perform createRoleWithGrants( @@ -81,6 +77,19 @@ begin hsOfficePersonREFERRER(newHolderPerson)] ); + if NEW.type <> 'REPRESENTATIVE' then + call grantRoleToRole(hsOfficeRelationADMIN(NEW), hsOfficePersonADMIN(newAnchorPerson)); + end if; + if NEW.type <> 'REPRESENTATIVE' then + call grantRoleToRole(hsOfficeRelationAGENT(NEW), hsOfficePersonADMIN(newHolderPerson)); + end if; + if NEW.type = 'REPRESENTATIVE' then + call grantRoleToRole(hsOfficePersonOWNER(newAnchorPerson), hsOfficeRelationADMIN(NEW)); + end if; + if NEW.type = 'REPRESENTATIVE' then + call grantRoleToRole(hsOfficeRelationOWNER(NEW), hsOfficePersonADMIN(newHolderPerson)); + end if; + call leaveTriggerForObjectUuid(NEW.uuid); end; $$; @@ -117,48 +126,12 @@ create or replace procedure updateRbacRulesForHsOfficeRelation( NEW hs_office_relation ) language plpgsql as $$ - -declare - oldHolderPerson hs_office_person; - newHolderPerson hs_office_person; - oldAnchorPerson hs_office_person; - newAnchorPerson hs_office_person; - oldContact hs_office_contact; - newContact hs_office_contact; - begin - call enterTriggerForObjectUuid(NEW.uuid); - - SELECT * FROM hs_office_person WHERE uuid = OLD.holderUuid INTO oldHolderPerson; - assert oldHolderPerson.uuid is not null, format('oldHolderPerson must not be null for OLD.holderUuid = %s', OLD.holderUuid); - - SELECT * FROM hs_office_person WHERE uuid = NEW.holderUuid INTO newHolderPerson; - assert newHolderPerson.uuid is not null, format('newHolderPerson must not be null for NEW.holderUuid = %s', NEW.holderUuid); - - SELECT * FROM hs_office_person WHERE uuid = OLD.anchorUuid INTO oldAnchorPerson; - assert oldAnchorPerson.uuid is not null, format('oldAnchorPerson must not be null for OLD.anchorUuid = %s', OLD.anchorUuid); - - SELECT * FROM hs_office_person WHERE uuid = NEW.anchorUuid INTO newAnchorPerson; - assert newAnchorPerson.uuid is not null, format('newAnchorPerson must not be null for NEW.anchorUuid = %s', NEW.anchorUuid); - - SELECT * FROM hs_office_contact WHERE uuid = OLD.contactUuid INTO oldContact; - assert oldContact.uuid is not null, format('oldContact must not be null for OLD.contactUuid = %s', OLD.contactUuid); - - SELECT * FROM hs_office_contact WHERE uuid = NEW.contactUuid INTO newContact; - assert newContact.uuid is not null, format('newContact must not be null for NEW.contactUuid = %s', NEW.contactUuid); - - - if NEW.contactUuid <> OLD.contactUuid then - - call revokeRoleFromRole(hsOfficeRelationTENANT(OLD), hsOfficeContactADMIN(oldContact)); - call grantRoleToRole(hsOfficeRelationTENANT(NEW), hsOfficeContactADMIN(newContact)); - - call revokeRoleFromRole(hsOfficeContactREFERRER(oldContact), hsOfficeRelationTENANT(OLD)); - call grantRoleToRole(hsOfficeContactREFERRER(newContact), hsOfficeRelationTENANT(NEW)); + if NEW.contactUuid is distinct from OLD.contactUuid then + delete from rbacgrants g where g.grantedbytriggerof = OLD.uuid; + call buildRbacSystemForHsOfficeRelation(NEW); end if; - - call leaveTriggerForObjectUuid(NEW.uuid); end; $$; /* diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java index 91a7965e..2813bcf6 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java @@ -103,6 +103,69 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea final var initialRoleNames = distinctRoleNamesOf(rawRoleRepo.findAll()); final var initialGrantNames = distinctGrantDisplaysOf(rawGrantRepo.findAll()); + // when + attempt(em, () -> { + final var givenAnchorPerson = personRepo.findPersonByOptionalNameLike("Bessler").stream() + .filter(p -> p.getPersonType() == UNINCORPORATED_FIRM) + .findFirst().orElseThrow(); + final var givenHolderPerson = personRepo.findPersonByOptionalNameLike("Bert").stream() + .filter(p -> p.getPersonType() == NATURAL_PERSON) + .findFirst().orElseThrow(); + final var givenContact = contactRepo.findContactByOptionalLabelLike("fourth contact").stream() + .findFirst().orElseThrow(); + final var newRelation = HsOfficeRelationEntity.builder() + .anchor(givenAnchorPerson) + .holder(givenHolderPerson) + .type(HsOfficeRelationType.SUBSCRIBER) + .mark("dummy") + .contact(givenContact) + .build(); + return toCleanup(relationRepo.save(newRelation)); + }); + + // then + assertThat(distinctRoleNamesOf(rawRoleRepo.findAll())).containsExactlyInAnyOrder(Array.from( + initialRoleNames, + "hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:OWNER", + "hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:ADMIN", + "hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:AGENT", + "hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:TENANT")); + assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll())).containsExactlyInAnyOrder(Array.fromFormatted( + initialGrantNames, + // TODO: this grant should only be created for DEBITOR-Relationships, thus the RBAC DSL needs to support conditional grants + "{ grant perm:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:INSERT>hs_office_sepamandate to role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:ADMIN by system and assume }", + + "{ grant perm:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:DELETE to role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:OWNER by system and assume }", + "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:OWNER to role:global#global:ADMIN by system and assume }", + "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:OWNER to user:superuser-alex@hostsharing.net by hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:OWNER and assume }", + + "{ grant perm:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:UPDATE to role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:ADMIN by system and assume }", + "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:ADMIN to role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:OWNER by system and assume }", + "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:ADMIN to role:hs_office_person#ErbenBesslerMelBessler:ADMIN by system and assume }", + + "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:AGENT to role:hs_office_person#BesslerBert:ADMIN by system and assume }", + "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:AGENT to role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:ADMIN by system and assume }", + + "{ grant perm:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:SELECT to role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:TENANT by system and assume }", + "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:TENANT to role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:AGENT by system and assume }", + "{ grant role:hs_office_person#BesslerBert:REFERRER to role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:TENANT by system and assume }", + "{ grant role:hs_office_person#ErbenBesslerMelBessler:REFERRER to role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:TENANT by system and assume }", + "{ grant role:hs_office_contact#fourthcontact:REFERRER to role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:TENANT by system and assume }", + + // SUBSCRIBER holder person -> (represented) anchor person + "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:TENANT to role:hs_office_contact#fourthcontact:ADMIN by system and assume }", + + null) + ); + } + + @Test + public void createsAndGrantsRolesForTypeRepresentative() { + // given + context("superuser-alex@hostsharing.net"); + final var initialRoleNames = distinctRoleNamesOf(rawRoleRepo.findAll()); + final var initialGrantNames = distinctGrantDisplaysOf(rawGrantRepo.findAll()); + // when attempt(em, () -> { final var givenAnchorPerson = personRepo.findPersonByOptionalNameLike("Bessler").stream() @@ -140,9 +203,9 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea "{ grant perm:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:UPDATE to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN by system and assume }", "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:OWNER by system and assume }", - "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN to role:hs_office_person#ErbenBesslerMelBessler:ADMIN by system and assume }", + "{ grant role:hs_office_person#ErbenBesslerMelBessler:OWNER to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN by system and assume }", - "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:AGENT to role:hs_office_person#BesslerBert:ADMIN by system and assume }", + "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:OWNER to role:hs_office_person#BesslerBert:ADMIN by system and assume }", "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:AGENT to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN by system and assume }", "{ grant perm:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:SELECT to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:TENANT by system and assume }", -- 2.39.5 From b5ef54e83cef45b9f89100248fcb318e5ad4d4d3 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Wed, 3 Apr 2024 08:46:50 +0200 Subject: [PATCH 16/29] baseline with green tests --- .../relation/HsOfficeRelationEntity.java | 11 +-- .../hsadminng/rbac/rbacdef/RbacView.java | 1 - .../RolesGrantsAndPermissionsGenerator.java | 10 +-- .../5033-hs-office-relation-rbac.md | 7 +- .../5033-hs-office-relation-rbac.sql | 66 ++++++++++++----- .../5043-hs-office-partner-rbac.md | 3 +- .../5063-hs-office-debitor-rbac.md | 6 +- .../5073-hs-office-sepamandate-rbac.md | 3 +- .../5103-hs-office-membership-rbac.md | 3 +- .../5113-hs-office-coopshares-rbac.md | 3 +- .../5123-hs-office-coopassets-rbac.md | 3 +- ...fficeRelationControllerAcceptanceTest.java | 2 +- ...ficeRelationRepositoryIntegrationTest.java | 70 ++----------------- 13 files changed, 74 insertions(+), 114 deletions(-) diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java index a46ab2d9..8d6c6fe8 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java @@ -104,18 +104,21 @@ public class HsOfficeRelationEntity implements RbacObject, Stringifyable { .createRole(OWNER, (with) -> { with.owningUser(CREATOR); with.incomingSuperRole(GLOBAL, ADMIN); - with.incomingSuperRole("holderPerson", ADMIN).where("${REF}.type = 'REPRESENTATIVE'"); + // TODO: if type=REPRESENTATIIVE + // with.incomingSuperRole("holderPerson", ADMIN); with.permission(DELETE); }) .createSubRole(ADMIN, (with) -> { - with.incomingSuperRole("anchorPerson", ADMIN).where("${REF}.type <> 'REPRESENTATIVE'"); - with.outgoingSubRole("anchorPerson", OWNER).where("${REF}.type = 'REPRESENTATIVE'"); + with.incomingSuperRole("anchorPerson", ADMIN); + // TODO: if type=REPRESENTATIIVE + // with.outgoingSuperRole("anchorPerson", OWNER); with.permission(UPDATE); }) .createSubRole(AGENT, (with) -> { - with.incomingSuperRole("holderPerson", ADMIN).where("${REF}.type <> 'REPRESENTATIVE'"); + with.incomingSuperRole("holderPerson", ADMIN); }) .createSubRole(TENANT, (with) -> { + with.incomingSuperRole("holderPerson", ADMIN); with.incomingSuperRole("contact", ADMIN); with.outgoingSubRole("anchorPerson", REFERRER); with.outgoingSubRole("holderPerson", REFERRER); diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java index a09b270b..d6c2d3cc 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java @@ -14,7 +14,6 @@ import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity; import net.hostsharing.hsadminng.hs.office.sepamandate.HsOfficeSepaMandateEntity; import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject; -import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject; import net.hostsharing.hsadminng.test.cust.TestCustomerEntity; import net.hostsharing.hsadminng.test.dom.TestDomainEntity; import net.hostsharing.hsadminng.test.pac.TestPackageEntity; diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java index 07d70314..4c4ce134 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java @@ -301,11 +301,11 @@ class RolesGrantsAndPermissionsGenerator { .replace("${permRef}", createPerm(NEW, grantDef.getPermDef())) .replace("${superRoleRef}", roleRef(NEW, grantDef.getSuperRoleDef())); }; - if (grantDef.isConditional()) { - return "if " + grantDef.getOnlyInCaseOf() + " then\n" - + " " + grantSql + "\n" - + "end if;"; - } +// if (grantDef.isConditional()) { +// return "if " + grantDef.getOnlyInCaseOf() + " then\n" +// + " " + grantSql + "\n" +// + "end if;"; +// } return grantSql; } diff --git a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md index be9f89b7..8014cdaf 100644 --- a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md +++ b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md @@ -82,13 +82,12 @@ role:global:ADMIN -.-> role:contact:OWNER role:contact:OWNER -.-> role:contact:ADMIN role:contact:ADMIN -.-> role:contact:REFERRER role:global:ADMIN ==> role:relation:OWNER -role:holderPerson:ADMIN ==> |??| role:relation:OWNER role:relation:OWNER ==> role:relation:ADMIN -role:anchorPerson:ADMIN ==> |??| role:relation:ADMIN -role:relation:ADMIN ==> |??| role:anchorPerson:OWNER +role:anchorPerson:ADMIN ==> role:relation:ADMIN role:relation:ADMIN ==> role:relation:AGENT -role:holderPerson:ADMIN ==> |??| role:relation:AGENT +role:holderPerson:ADMIN ==> role:relation:AGENT role:relation:AGENT ==> role:relation:TENANT +role:holderPerson:ADMIN ==> role:relation:TENANT role:contact:ADMIN ==> role:relation:TENANT role:relation:TENANT ==> role:anchorPerson:REFERRER role:relation:TENANT ==> role:holderPerson:REFERRER diff --git a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql index aca2eb93..ff890a59 100644 --- a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql +++ b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql @@ -57,12 +57,16 @@ begin perform createRoleWithGrants( hsOfficeRelationADMIN(NEW), permissions => array['UPDATE'], - incomingSuperRoles => array[hsOfficeRelationOWNER(NEW)] + incomingSuperRoles => array[ + hsOfficePersonADMIN(newAnchorPerson), + hsOfficeRelationOWNER(NEW)] ); perform createRoleWithGrants( hsOfficeRelationAGENT(NEW), - incomingSuperRoles => array[hsOfficeRelationADMIN(NEW)] + incomingSuperRoles => array[ + hsOfficePersonADMIN(newHolderPerson), + hsOfficeRelationADMIN(NEW)] ); perform createRoleWithGrants( @@ -70,6 +74,7 @@ begin permissions => array['SELECT'], incomingSuperRoles => array[ hsOfficeContactADMIN(newContact), + hsOfficePersonADMIN(newHolderPerson), hsOfficeRelationAGENT(NEW)], outgoingSubRoles => array[ hsOfficeContactREFERRER(newContact), @@ -77,19 +82,6 @@ begin hsOfficePersonREFERRER(newHolderPerson)] ); - if NEW.type <> 'REPRESENTATIVE' then - call grantRoleToRole(hsOfficeRelationADMIN(NEW), hsOfficePersonADMIN(newAnchorPerson)); - end if; - if NEW.type <> 'REPRESENTATIVE' then - call grantRoleToRole(hsOfficeRelationAGENT(NEW), hsOfficePersonADMIN(newHolderPerson)); - end if; - if NEW.type = 'REPRESENTATIVE' then - call grantRoleToRole(hsOfficePersonOWNER(newAnchorPerson), hsOfficeRelationADMIN(NEW)); - end if; - if NEW.type = 'REPRESENTATIVE' then - call grantRoleToRole(hsOfficeRelationOWNER(NEW), hsOfficePersonADMIN(newHolderPerson)); - end if; - call leaveTriggerForObjectUuid(NEW.uuid); end; $$; @@ -126,12 +118,48 @@ create or replace procedure updateRbacRulesForHsOfficeRelation( NEW hs_office_relation ) language plpgsql as $$ -begin - if NEW.contactUuid is distinct from OLD.contactUuid then - delete from rbacgrants g where g.grantedbytriggerof = OLD.uuid; - call buildRbacSystemForHsOfficeRelation(NEW); +declare + oldHolderPerson hs_office_person; + newHolderPerson hs_office_person; + oldAnchorPerson hs_office_person; + newAnchorPerson hs_office_person; + oldContact hs_office_contact; + newContact hs_office_contact; + +begin + call enterTriggerForObjectUuid(NEW.uuid); + + SELECT * FROM hs_office_person WHERE uuid = OLD.holderUuid INTO oldHolderPerson; + assert oldHolderPerson.uuid is not null, format('oldHolderPerson must not be null for OLD.holderUuid = %s', OLD.holderUuid); + + SELECT * FROM hs_office_person WHERE uuid = NEW.holderUuid INTO newHolderPerson; + assert newHolderPerson.uuid is not null, format('newHolderPerson must not be null for NEW.holderUuid = %s', NEW.holderUuid); + + SELECT * FROM hs_office_person WHERE uuid = OLD.anchorUuid INTO oldAnchorPerson; + assert oldAnchorPerson.uuid is not null, format('oldAnchorPerson must not be null for OLD.anchorUuid = %s', OLD.anchorUuid); + + SELECT * FROM hs_office_person WHERE uuid = NEW.anchorUuid INTO newAnchorPerson; + assert newAnchorPerson.uuid is not null, format('newAnchorPerson must not be null for NEW.anchorUuid = %s', NEW.anchorUuid); + + SELECT * FROM hs_office_contact WHERE uuid = OLD.contactUuid INTO oldContact; + assert oldContact.uuid is not null, format('oldContact must not be null for OLD.contactUuid = %s', OLD.contactUuid); + + SELECT * FROM hs_office_contact WHERE uuid = NEW.contactUuid INTO newContact; + assert newContact.uuid is not null, format('newContact must not be null for NEW.contactUuid = %s', NEW.contactUuid); + + + if NEW.contactUuid <> OLD.contactUuid then + + call revokeRoleFromRole(hsOfficeRelationTENANT(OLD), hsOfficeContactADMIN(oldContact)); + call grantRoleToRole(hsOfficeRelationTENANT(NEW), hsOfficeContactADMIN(newContact)); + + call revokeRoleFromRole(hsOfficeContactREFERRER(oldContact), hsOfficeRelationTENANT(OLD)); + call grantRoleToRole(hsOfficeContactREFERRER(newContact), hsOfficeRelationTENANT(NEW)); + end if; + + call leaveTriggerForObjectUuid(NEW.uuid); end; $$; /* diff --git a/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.md b/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.md index 44154df0..a0caa074 100644 --- a/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.md +++ b/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.md @@ -97,13 +97,12 @@ role:global:ADMIN -.-> role:partnerRel.contact:OWNER role:partnerRel.contact:OWNER -.-> role:partnerRel.contact:ADMIN role:partnerRel.contact:ADMIN -.-> role:partnerRel.contact:REFERRER role:global:ADMIN -.-> role:partnerRel:OWNER -role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:OWNER role:partnerRel:OWNER -.-> role:partnerRel:ADMIN role:partnerRel.anchorPerson:ADMIN -.-> role:partnerRel:ADMIN -role:partnerRel:ADMIN -.-> role:partnerRel.anchorPerson:OWNER role:partnerRel:ADMIN -.-> role:partnerRel:AGENT role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:AGENT role:partnerRel:AGENT -.-> role:partnerRel:TENANT +role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:TENANT role:partnerRel.contact:ADMIN -.-> role:partnerRel:TENANT role:partnerRel:TENANT -.-> role:partnerRel.anchorPerson:REFERRER role:partnerRel:TENANT -.-> role:partnerRel.holderPerson:REFERRER diff --git a/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.md b/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.md index 084d163b..5c43e03d 100644 --- a/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.md +++ b/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.md @@ -150,13 +150,12 @@ role:global:ADMIN -.-> role:debitorRel.contact:OWNER role:debitorRel.contact:OWNER -.-> role:debitorRel.contact:ADMIN role:debitorRel.contact:ADMIN -.-> role:debitorRel.contact:REFERRER role:global:ADMIN -.-> role:debitorRel:OWNER -role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:OWNER role:debitorRel:OWNER -.-> role:debitorRel:ADMIN role:debitorRel.anchorPerson:ADMIN -.-> role:debitorRel:ADMIN -role:debitorRel:ADMIN -.-> role:debitorRel.anchorPerson:OWNER role:debitorRel:ADMIN -.-> role:debitorRel:AGENT role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:AGENT role:debitorRel:AGENT -.-> role:debitorRel:TENANT +role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:TENANT role:debitorRel.contact:ADMIN -.-> role:debitorRel:TENANT role:debitorRel:TENANT -.-> role:debitorRel.anchorPerson:REFERRER role:debitorRel:TENANT -.-> role:debitorRel.holderPerson:REFERRER @@ -176,13 +175,12 @@ role:global:ADMIN -.-> role:partnerRel.contact:OWNER role:partnerRel.contact:OWNER -.-> role:partnerRel.contact:ADMIN role:partnerRel.contact:ADMIN -.-> role:partnerRel.contact:REFERRER role:global:ADMIN -.-> role:partnerRel:OWNER -role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:OWNER role:partnerRel:OWNER -.-> role:partnerRel:ADMIN role:partnerRel.anchorPerson:ADMIN -.-> role:partnerRel:ADMIN -role:partnerRel:ADMIN -.-> role:partnerRel.anchorPerson:OWNER role:partnerRel:ADMIN -.-> role:partnerRel:AGENT role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:AGENT role:partnerRel:AGENT -.-> role:partnerRel:TENANT +role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:TENANT role:partnerRel.contact:ADMIN -.-> role:partnerRel:TENANT role:partnerRel:TENANT -.-> role:partnerRel.anchorPerson:REFERRER role:partnerRel:TENANT -.-> role:partnerRel.holderPerson:REFERRER diff --git a/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.md b/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.md index 3bd2102e..aa3059f9 100644 --- a/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.md +++ b/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.md @@ -109,13 +109,12 @@ role:global:ADMIN -.-> role:debitorRel.contact:OWNER role:debitorRel.contact:OWNER -.-> role:debitorRel.contact:ADMIN role:debitorRel.contact:ADMIN -.-> role:debitorRel.contact:REFERRER role:global:ADMIN -.-> role:debitorRel:OWNER -role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:OWNER role:debitorRel:OWNER -.-> role:debitorRel:ADMIN role:debitorRel.anchorPerson:ADMIN -.-> role:debitorRel:ADMIN -role:debitorRel:ADMIN -.-> role:debitorRel.anchorPerson:OWNER role:debitorRel:ADMIN -.-> role:debitorRel:AGENT role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:AGENT role:debitorRel:AGENT -.-> role:debitorRel:TENANT +role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:TENANT role:debitorRel.contact:ADMIN -.-> role:debitorRel:TENANT role:debitorRel:TENANT -.-> role:debitorRel.anchorPerson:REFERRER role:debitorRel:TENANT -.-> role:debitorRel.holderPerson:REFERRER 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 bf205df7..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 @@ -95,13 +95,12 @@ role:global:ADMIN -.-> role:partnerRel.contact:OWNER role:partnerRel.contact:OWNER -.-> role:partnerRel.contact:ADMIN role:partnerRel.contact:ADMIN -.-> role:partnerRel.contact:REFERRER role:global:ADMIN -.-> role:partnerRel:OWNER -role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:OWNER role:partnerRel:OWNER -.-> role:partnerRel:ADMIN role:partnerRel.anchorPerson:ADMIN -.-> role:partnerRel:ADMIN -role:partnerRel:ADMIN -.-> role:partnerRel.anchorPerson:OWNER role:partnerRel:ADMIN -.-> role:partnerRel:AGENT role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:AGENT role:partnerRel:AGENT -.-> role:partnerRel:TENANT +role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:TENANT role:partnerRel.contact:ADMIN -.-> role:partnerRel:TENANT role:partnerRel:TENANT -.-> role:partnerRel.anchorPerson:REFERRER role:partnerRel:TENANT -.-> role:partnerRel.holderPerson:REFERRER 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 e4d45686..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 @@ -96,13 +96,12 @@ role:global:ADMIN -.-> role:membership.partnerRel.contact:OWNER role:membership.partnerRel.contact:OWNER -.-> role:membership.partnerRel.contact:ADMIN role:membership.partnerRel.contact:ADMIN -.-> role:membership.partnerRel.contact:REFERRER role:global:ADMIN -.-> role:membership.partnerRel:OWNER -role:membership.partnerRel.holderPerson:ADMIN -.-> role:membership.partnerRel:OWNER role:membership.partnerRel:OWNER -.-> role:membership.partnerRel:ADMIN role:membership.partnerRel.anchorPerson:ADMIN -.-> role:membership.partnerRel:ADMIN -role:membership.partnerRel:ADMIN -.-> role:membership.partnerRel.anchorPerson:OWNER role:membership.partnerRel:ADMIN -.-> role:membership.partnerRel:AGENT role:membership.partnerRel.holderPerson:ADMIN -.-> role:membership.partnerRel:AGENT role:membership.partnerRel:AGENT -.-> role:membership.partnerRel:TENANT +role:membership.partnerRel.holderPerson:ADMIN -.-> role:membership.partnerRel:TENANT 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 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 2f6bc29d..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 @@ -96,13 +96,12 @@ role:global:ADMIN -.-> role:membership.partnerRel.contact:OWNER role:membership.partnerRel.contact:OWNER -.-> role:membership.partnerRel.contact:ADMIN role:membership.partnerRel.contact:ADMIN -.-> role:membership.partnerRel.contact:REFERRER role:global:ADMIN -.-> role:membership.partnerRel:OWNER -role:membership.partnerRel.holderPerson:ADMIN -.-> role:membership.partnerRel:OWNER role:membership.partnerRel:OWNER -.-> role:membership.partnerRel:ADMIN role:membership.partnerRel.anchorPerson:ADMIN -.-> role:membership.partnerRel:ADMIN -role:membership.partnerRel:ADMIN -.-> role:membership.partnerRel.anchorPerson:OWNER role:membership.partnerRel:ADMIN -.-> role:membership.partnerRel:AGENT role:membership.partnerRel.holderPerson:ADMIN -.-> role:membership.partnerRel:AGENT role:membership.partnerRel:AGENT -.-> role:membership.partnerRel:TENANT +role:membership.partnerRel.holderPerson:ADMIN -.-> role:membership.partnerRel:TENANT 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 diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationControllerAcceptanceTest.java index 78d64e6a..54218b67 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationControllerAcceptanceTest.java @@ -362,7 +362,7 @@ class HsOfficeRelationControllerAcceptanceTest extends ContextBasedTestWithClean assertThat(givenRelation.getContact().getLabel()).isEqualTo("seventh contact"); final var givenContact = contactRepo.findContactByOptionalLabelLike("fourth").get(0); - final var location = RestAssured // @formatter:off + RestAssured // @formatter:off .given() .header("current-user", "superuser-alex@hostsharing.net") .contentType(ContentType.JSON) diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java index 2813bcf6..becc29d9 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java @@ -103,69 +103,6 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea final var initialRoleNames = distinctRoleNamesOf(rawRoleRepo.findAll()); final var initialGrantNames = distinctGrantDisplaysOf(rawGrantRepo.findAll()); - // when - attempt(em, () -> { - final var givenAnchorPerson = personRepo.findPersonByOptionalNameLike("Bessler").stream() - .filter(p -> p.getPersonType() == UNINCORPORATED_FIRM) - .findFirst().orElseThrow(); - final var givenHolderPerson = personRepo.findPersonByOptionalNameLike("Bert").stream() - .filter(p -> p.getPersonType() == NATURAL_PERSON) - .findFirst().orElseThrow(); - final var givenContact = contactRepo.findContactByOptionalLabelLike("fourth contact").stream() - .findFirst().orElseThrow(); - final var newRelation = HsOfficeRelationEntity.builder() - .anchor(givenAnchorPerson) - .holder(givenHolderPerson) - .type(HsOfficeRelationType.SUBSCRIBER) - .mark("dummy") - .contact(givenContact) - .build(); - return toCleanup(relationRepo.save(newRelation)); - }); - - // then - assertThat(distinctRoleNamesOf(rawRoleRepo.findAll())).containsExactlyInAnyOrder(Array.from( - initialRoleNames, - "hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:OWNER", - "hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:ADMIN", - "hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:AGENT", - "hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:TENANT")); - assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll())).containsExactlyInAnyOrder(Array.fromFormatted( - initialGrantNames, - // TODO: this grant should only be created for DEBITOR-Relationships, thus the RBAC DSL needs to support conditional grants - "{ grant perm:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:INSERT>hs_office_sepamandate to role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:ADMIN by system and assume }", - - "{ grant perm:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:DELETE to role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:OWNER by system and assume }", - "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:OWNER to role:global#global:ADMIN by system and assume }", - "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:OWNER to user:superuser-alex@hostsharing.net by hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:OWNER and assume }", - - "{ grant perm:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:UPDATE to role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:ADMIN by system and assume }", - "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:ADMIN to role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:OWNER by system and assume }", - "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:ADMIN to role:hs_office_person#ErbenBesslerMelBessler:ADMIN by system and assume }", - - "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:AGENT to role:hs_office_person#BesslerBert:ADMIN by system and assume }", - "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:AGENT to role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:ADMIN by system and assume }", - - "{ grant perm:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:SELECT to role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:TENANT by system and assume }", - "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:TENANT to role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:AGENT by system and assume }", - "{ grant role:hs_office_person#BesslerBert:REFERRER to role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:TENANT by system and assume }", - "{ grant role:hs_office_person#ErbenBesslerMelBessler:REFERRER to role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:TENANT by system and assume }", - "{ grant role:hs_office_contact#fourthcontact:REFERRER to role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:TENANT by system and assume }", - - // SUBSCRIBER holder person -> (represented) anchor person - "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-SUBSCRIBER-BesslerBert:TENANT to role:hs_office_contact#fourthcontact:ADMIN by system and assume }", - - null) - ); - } - - @Test - public void createsAndGrantsRolesForTypeRepresentative() { - // given - context("superuser-alex@hostsharing.net"); - final var initialRoleNames = distinctRoleNamesOf(rawRoleRepo.findAll()); - final var initialGrantNames = distinctGrantDisplaysOf(rawGrantRepo.findAll()); - // when attempt(em, () -> { final var givenAnchorPerson = personRepo.findPersonByOptionalNameLike("Bessler").stream() @@ -203,9 +140,9 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea "{ grant perm:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:UPDATE to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN by system and assume }", "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:OWNER by system and assume }", - "{ grant role:hs_office_person#ErbenBesslerMelBessler:OWNER to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN by system and assume }", + "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN to role:hs_office_person#ErbenBesslerMelBessler:ADMIN by system and assume }", - "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:OWNER to role:hs_office_person#BesslerBert:ADMIN by system and assume }", + "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:AGENT to role:hs_office_person#BesslerBert:ADMIN by system and assume }", "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:AGENT to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN by system and assume }", "{ grant perm:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:SELECT to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:TENANT by system and assume }", @@ -216,6 +153,7 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea // REPRESENTATIVE holder person -> (represented) anchor person "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:TENANT to role:hs_office_contact#fourthcontact:ADMIN by system and assume }", + "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:TENANT to role:hs_office_person#BesslerBert:ADMIN by system and assume }", null) ); @@ -279,10 +217,10 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea context("superuser-alex@hostsharing.net"); final var givenRelation = givenSomeTemporaryRelationBessler( "Bert", "fifth contact"); + assertThatRelationActuallyInDatabase(givenRelation); assertThatRelationIsVisibleForUserWithRole( givenRelation, "hs_office_person#ErbenBesslerMelBessler:ADMIN"); - assertThatRelationActuallyInDatabase(givenRelation); context("superuser-alex@hostsharing.net"); final var givenContact = contactRepo.findContactByOptionalLabelLike("sixth contact").stream().findFirst().orElseThrow(); -- 2.39.5 From 92086d8634d25c9e30b385ad8f78f5db0a656d6e Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Wed, 3 Apr 2024 10:22:23 +0200 Subject: [PATCH 17/29] scribbled the DSL for switchOnColumn+inCaseOf --- .../office/debitor/HsOfficeDebitorEntity.java | 2 + .../office/partner/HsOfficePartnerEntity.java | 2 + .../relation/HsOfficeRelationEntity.java | 76 +++++++++++------- .../hsadminng/rbac/rbacdef/RbacView.java | 77 +++++++++++++++---- 4 files changed, 117 insertions(+), 40 deletions(-) diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java index 08c70f66..8b48e221 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java @@ -26,6 +26,7 @@ import static jakarta.persistence.CascadeType.PERSIST; import static jakarta.persistence.CascadeType.REFRESH; import static java.util.Optional.ofNullable; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Column.dependsOnColumn; +import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.ColumnValue.usingCase; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NOT_NULL; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NULLABLE; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.*; @@ -157,6 +158,7 @@ public class HsOfficeDebitorEntity implements RbacObject, Stringifyable { .toRole("global", ADMIN).grantPermission(INSERT) .importRootEntityAliasProxy("debitorRel", HsOfficeRelationEntity.class, + usingCase("DEBITOR"), directlyFetchedByDependsOnColumn(), dependsOnColumn("debitorRelUuid")) .createPermission(DELETE).grantedTo("debitorRel", OWNER) diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntity.java index 43b78fca..3c5f1983 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntity.java @@ -29,6 +29,7 @@ import java.util.UUID; import static jakarta.persistence.CascadeType.*; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Column.dependsOnColumn; +import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.ColumnValue.usingDefaultCase; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.*; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.SELECT; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.*; @@ -98,6 +99,7 @@ public class HsOfficePartnerEntity implements Stringifyable, RbacObject { .toRole("global", ADMIN).grantPermission(INSERT) .importRootEntityAliasProxy("partnerRel", HsOfficeRelationEntity.class, + usingDefaultCase(), directlyFetchedByDependsOnColumn(), dependsOnColumn("partnerRelUuid")) .createPermission(DELETE).grantedTo("partnerRel", ADMIN) diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java index 8d6c6fe8..2202e366 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java @@ -11,17 +11,17 @@ import net.hostsharing.hsadminng.stringify.Stringify; import net.hostsharing.hsadminng.stringify.Stringifyable; import jakarta.persistence.*; +import jakarta.persistence.Column; import java.io.IOException; import java.util.UUID; +import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.*; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Column.dependsOnColumn; -import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.GLOBAL; 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.RbacUserReference.UserRole.CREATOR; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.*; 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; @Entity @@ -101,31 +101,53 @@ public class HsOfficeRelationEntity implements RbacObject, Stringifyable { dependsOnColumn("contactUuid"), directlyFetchedByDependsOnColumn(), NOT_NULL) - .createRole(OWNER, (with) -> { - with.owningUser(CREATOR); - with.incomingSuperRole(GLOBAL, ADMIN); - // TODO: if type=REPRESENTATIIVE - // with.incomingSuperRole("holderPerson", ADMIN); - with.permission(DELETE); - }) - .createSubRole(ADMIN, (with) -> { - with.incomingSuperRole("anchorPerson", ADMIN); - // TODO: if type=REPRESENTATIIVE - // with.outgoingSuperRole("anchorPerson", OWNER); - with.permission(UPDATE); - }) - .createSubRole(AGENT, (with) -> { - with.incomingSuperRole("holderPerson", ADMIN); - }) - .createSubRole(TENANT, (with) -> { - with.incomingSuperRole("holderPerson", ADMIN); - with.incomingSuperRole("contact", ADMIN); - with.outgoingSubRole("anchorPerson", REFERRER); - with.outgoingSubRole("holderPerson", REFERRER); - with.outgoingSubRole("contact", REFERRER); - with.permission(SELECT); - }) - + .switchOnColumn("type", + inCaseOf("REPRESENTATIVE", then -> { + then.createRole(OWNER, (with) -> { + with.owningUser(CREATOR); + with.incomingSuperRole(GLOBAL, ADMIN); + with.incomingSuperRole("holderPerson", ADMIN); + with.permission(DELETE); + }) + .createSubRole(ADMIN, (with) -> { + with.incomingSuperRole("anchorPerson", ADMIN); + with.outgoingSubRole("anchorPerson", OWNER); + with.permission(UPDATE); + }) + .createSubRole(AGENT, (with) -> { + }) + .createSubRole(TENANT, (with) -> { + with.incomingSuperRole("holderPerson", ADMIN); + with.incomingSuperRole("contact", ADMIN); + with.outgoingSubRole("anchorPerson", REFERRER); + with.outgoingSubRole("holderPerson", REFERRER); + with.outgoingSubRole("contact", REFERRER); + with.permission(SELECT); + }); + }), + //FIXME: .inCaseOf("DEBITOR") + inOtherCases(then -> { + then.createRole(OWNER, (with) -> { + with.owningUser(CREATOR); + with.incomingSuperRole(GLOBAL, ADMIN); + with.permission(DELETE); + }) + .createSubRole(ADMIN, (with) -> { + with.incomingSuperRole("anchorPerson", ADMIN); + with.permission(UPDATE); + }) + .createSubRole(AGENT, (with) -> { + with.incomingSuperRole("holderPerson", ADMIN); + }) + .createSubRole(TENANT, (with) -> { + with.incomingSuperRole("holderPerson", ADMIN); + with.incomingSuperRole("contact", ADMIN); + with.outgoingSubRole("anchorPerson", REFERRER); + with.outgoingSubRole("holderPerson", REFERRER); + with.outgoingSubRole("contact", REFERRER); + with.permission(SELECT); + }); + })) .toRole("anchorPerson", ADMIN).grantPermission(INSERT); } diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java index d6c2d3cc..ab5e6b07 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java @@ -34,10 +34,10 @@ import static java.util.Optional.ofNullable; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NOT_NULL; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacUserReference.UserRole.CREATOR; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL.Part.AUTO_FETCH; -import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL.directlyFetchedByDependsOnColumn; import static org.apache.commons.lang3.StringUtils.uncapitalize; @Getter +// TODO.refa: rename to RbacDSL public class RbacView { public static final String GLOBAL = "global"; @@ -65,6 +65,15 @@ public class RbacView { private SQL orderBySqlExpression; private EntityAlias rootEntityAliasProxy; private RbacRoleDefinition previousRoleDef; + private final Map cases = new HashMap<>() { + @Override + public String put(final String key, final String value) { + if (containsKey(key)) { + throw new IllegalArgumentException("duplicate case: " + key); + } + return super.put(key, value); + } + }; /** Crates an RBAC definition template for the given entity class and defining the given alias. * @@ -277,6 +286,7 @@ public class RbacView { public RbacView importRootEntityAliasProxy( final String aliasName, final Class entityClass, + final ColumnValue forCase, final SQL fetchSql, final Column dependsOnColum) { if (rootEntityAliasProxy != null) { @@ -339,14 +349,6 @@ public class RbacView { return this; } - // TODO: remove once it's not used in HsOffice...Entity anymore - public RbacView importEntityAlias( - final String aliasName, final Class entityClass, - final Column dependsOnColum) { - importEntityAliasImpl(aliasName, entityClass, directlyFetchedByDependsOnColumn(), dependsOnColum, false, null); - return this; - } - private EntityAlias importEntityAliasImpl( final String aliasName, final Class entityClass, final SQL fetchSql, final Column dependsOnColum, boolean asSubEntity, final Nullable nullable) { @@ -397,6 +399,12 @@ public class RbacView { return this; } + public RbacView switchOnColumn(final String discriminatorColumName, final CaseDef... caseDefs) { + // FIXME: currently only the default case is executed + stream(caseDefs).filter(caseDef -> caseDef.val == null).findAny().orElseThrow().def.accept(this); + return this; + } + private void verifyVersionColumnExists() { if (stream(rootEntityAlias.entityClass.getDeclaredFields()) .noneMatch(f -> f.getAnnotation(Version.class) != null)) { @@ -480,6 +488,25 @@ public class RbacView { } + public static class CaseDef { + + private final String val; + private final Consumer def; + + public CaseDef(final String discriminatorColumnValue, final Consumer def) { + this.val = discriminatorColumnValue; + this.def = def; + } + } + + public static CaseDef inCaseOf(final String discriminatorColumnValue, final Consumer def) { + return new CaseDef(discriminatorColumnValue, def); + } + + public static CaseDef inOtherCases(final Consumer def) { + return new CaseDef(null, def); + } + public enum Nullable { NOT_NULL, // DEFAULT NULLABLE @@ -495,7 +522,8 @@ public class RbacView { private final RbacPermissionDefinition permDef; private boolean assumed = true; private boolean toCreate = false; - private String sqlWhere; + private String onlyInCaseOf; + private String exceptInCaseOf; @Override public String toString() { @@ -549,7 +577,7 @@ public class RbacView { } boolean isConditional() { - return sqlWhere != null; + return onlyInCaseOf != null; } boolean isToCreate() { @@ -578,8 +606,14 @@ public class RbacView { return this; } - public RbacGrantDefinition where(final String sqlWhere) { - this.sqlWhere = sqlWhere; + public RbacGrantDefinition onlyInCaseOf(final String caseName) { + this.onlyInCaseOf = caseName; + return this; + } + + + public RbacGrantDefinition exceptInCaseOf(final String caseName) { + this.exceptInCaseOf = caseName; return this; } @@ -1034,6 +1068,23 @@ public class RbacView { } } + public static class ColumnValue { + + public static ColumnValue usingDefaultCase() { + return new ColumnValue(null); + } + + public static ColumnValue usingCase(final String value) { + return new ColumnValue(value); + } + + public final String value; + + private ColumnValue(final String value) { + this.value = value; + } + } + private static class AliasNameMapper { private final RbacView importedRbacView; -- 2.39.5 From 001ab652c79ed99f1f1bfa77cd46224a17b3831f Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Thu, 4 Apr 2024 10:00:13 +0200 Subject: [PATCH 18/29] working version with conditional generation --- .../relation/HsOfficeRelationEntity.java | 6 +- .../rbac/rbacdef/ConditionGenerator.java | 75 ++++++++++++ .../hsadminng/rbac/rbacdef/RbacView.java | 111 ++++++++++-------- .../RbacViewMermaidFlowchartGenerator.java | 15 ++- .../RolesGrantsAndPermissionsGenerator.java | 32 ++++- .../5033-hs-office-relation-rbac-DEBITOR.md | 91 ++++++++++++++ ...-hs-office-relation-rbac-REPRESENTATIVE.md | 103 ++++++++++++++++ .../5033-hs-office-relation-rbac.md | 7 +- .../5033-hs-office-relation-rbac.sql | 91 ++++++-------- .../rbacdef/ConditionGeneratorUnitTest.java | 46 ++++++++ 10 files changed, 463 insertions(+), 114 deletions(-) create mode 100644 src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/ConditionGenerator.java create mode 100644 src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac-DEBITOR.md create mode 100644 src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac-REPRESENTATIVE.md create mode 100644 src/test/java/net/hostsharing/hsadminng/rbac/rbacdef/ConditionGeneratorUnitTest.java diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java index 2202e366..e18a8cd4 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java @@ -15,6 +15,8 @@ import jakarta.persistence.Column; import java.io.IOException; import java.util.UUID; +import static net.hostsharing.hsadminng.rbac.rbacdef.ConditionGenerator.CaseDef.inCaseOf; +import static net.hostsharing.hsadminng.rbac.rbacdef.ConditionGenerator.CaseDef.inOtherCases; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.*; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Column.dependsOnColumn; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NOT_NULL; @@ -110,11 +112,11 @@ public class HsOfficeRelationEntity implements RbacObject, Stringifyable { with.permission(DELETE); }) .createSubRole(ADMIN, (with) -> { - with.incomingSuperRole("anchorPerson", ADMIN); with.outgoingSubRole("anchorPerson", OWNER); with.permission(UPDATE); }) .createSubRole(AGENT, (with) -> { + with.incomingSuperRole("anchorPerson", ADMIN); }) .createSubRole(TENANT, (with) -> { with.incomingSuperRole("holderPerson", ADMIN); @@ -125,7 +127,7 @@ public class HsOfficeRelationEntity implements RbacObject, Stringifyable { with.permission(SELECT); }); }), - //FIXME: .inCaseOf("DEBITOR") + inCaseOf("DEBITOR", then -> {}), inOtherCases(then -> { then.createRole(OWNER, (with) -> { with.owningUser(CREATOR); diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/ConditionGenerator.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/ConditionGenerator.java new file mode 100644 index 00000000..0ea70b02 --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/ConditionGenerator.java @@ -0,0 +1,75 @@ +package net.hostsharing.hsadminng.rbac.rbacdef; + +import java.util.Objects; +import java.util.Set; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +import static java.lang.String.join; +import static java.util.Optional.ofNullable; + +public class ConditionGenerator { + + private final String discriminatorColumName; + private final Set allCases; + + public ConditionGenerator(final String discriminatorColumName, final Set allCases) { + this.discriminatorColumName = discriminatorColumName; + this.allCases = allCases; + } + + public String generatePlPgSql(final Set forCases) { + if (forCases.size() == 1) { + if (forCases.iterator().next().isDefaultCase()) { + final var nonDefaultCases = allCases.stream().filter(c -> !c.isDefaultCase()).map(c -> c.val).toList(); + if (nonDefaultCases.size() > 1) { + return discriminatorColumName + " not in ('" + join("', '", nonDefaultCases) + "')"; + } + return discriminatorColumName + " <> '" + nonDefaultCases.getFirst() + "'"; + } + return discriminatorColumName + " = '" + forCases.iterator().next().val + "'"; + } + return discriminatorColumName + " in ('" + forCases.stream().map(c -> c.val).collect(Collectors.joining("', '")) + "')"; + } + + + + public static class CaseDef { + + final String val; + final Consumer def; + + private CaseDef(final String discriminatorColumnValue, final Consumer def) { + this.val = discriminatorColumnValue; + this.def = def; + } + + + public static CaseDef inCaseOf(final String discriminatorColumnValue, final Consumer def) { + return new CaseDef(discriminatorColumnValue, def); + } + + public static CaseDef inOtherCases(final Consumer def) { + return new CaseDef(null, def); + } + + @Override + public int hashCode() { + return ofNullable(val).map(String::hashCode).orElse(0); + } + + @Override + public boolean equals(final Object other) { + if (this == other) + return true; + if (other == null || getClass() != other.getClass()) + return false; + final CaseDef caseDef = (CaseDef) other; + return Objects.equals(val, caseDef.val); + } + + boolean isDefaultCase() { + return val == null; + } + } +} diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java index ab5e6b07..d5a225c5 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java @@ -13,6 +13,7 @@ import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity; import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity; import net.hostsharing.hsadminng.hs.office.sepamandate.HsOfficeSepaMandateEntity; +import net.hostsharing.hsadminng.rbac.rbacdef.ConditionGenerator.CaseDef; import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject; import net.hostsharing.hsadminng.test.cust.TestCustomerEntity; import net.hostsharing.hsadminng.test.dom.TestDomainEntity; @@ -31,9 +32,12 @@ import java.util.stream.Stream; import static java.lang.reflect.Modifier.isStatic; import static java.util.Arrays.stream; import static java.util.Optional.ofNullable; +import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.ColumnValue.usingDefaultCase; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NOT_NULL; +import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacGrantDefinition.GrantType.PERM_TO_ROLE; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacUserReference.UserRole.CREATOR; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL.Part.AUTO_FETCH; +import static org.apache.commons.collections4.SetUtils.hashSet; import static org.apache.commons.lang3.StringUtils.uncapitalize; @Getter @@ -60,14 +64,17 @@ public class RbacView { }; private final Set updatableColumns = new LinkedHashSet<>(); private final Set grantDefs = new LinkedHashSet<>(); + private final Set allCases = new LinkedHashSet<>(); + private String discriminatorColumName; + private CaseDef processingCase; private SQL identityViewSqlQuery; private SQL orderBySqlExpression; private EntityAlias rootEntityAliasProxy; private RbacRoleDefinition previousRoleDef; - private final Map cases = new HashMap<>() { + private final Map cases = new LinkedHashMap<>() { @Override - public String put(final String key, final String value) { + public CaseDef put(final String key, final CaseDef value) { if (containsKey(key)) { throw new IllegalArgumentException("duplicate case: " + key); } @@ -247,7 +254,11 @@ public class RbacView { } private RbacPermissionDefinition createPermission(final EntityAlias entityAlias, final Permission permission) { - return new RbacPermissionDefinition(entityAlias, permission, null, true); + return permDefs.stream() + .filter(p -> p.permission == permission && p.entityAlias == entityAlias) + .findFirst() + // .map(g -> g.forCase(processingCase)) TODO: not implemented case dependent + .orElseGet(() -> new RbacPermissionDefinition(entityAlias, permission, null, true)); } public RbacView declarePlaceholderEntityAliases(final String... aliasNames) { @@ -292,7 +303,7 @@ public class RbacView { if (rootEntityAliasProxy != null) { throw new IllegalStateException("there is already an entityAliasProxy: " + rootEntityAliasProxy); } - rootEntityAliasProxy = importEntityAliasImpl(aliasName, entityClass, fetchSql, dependsOnColum, false, NOT_NULL); + rootEntityAliasProxy = importEntityAliasImpl(aliasName, entityClass, forCase, fetchSql, dependsOnColum, false, NOT_NULL); return this; } @@ -311,7 +322,7 @@ public class RbacView { public RbacView importSubEntityAlias( final String aliasName, final Class entityClass, final SQL fetchSql, final Column dependsOnColum) { - importEntityAliasImpl(aliasName, entityClass, fetchSql, dependsOnColum, true, NOT_NULL); + importEntityAliasImpl(aliasName, entityClass, usingDefaultCase(), fetchSql, dependsOnColum, true, NOT_NULL); return this; } @@ -345,17 +356,17 @@ public class RbacView { public RbacView importEntityAlias( final String aliasName, final Class entityClass, final Column dependsOnColum, final SQL fetchSql, final Nullable nullable) { - importEntityAliasImpl(aliasName, entityClass, fetchSql, dependsOnColum, false, nullable); + importEntityAliasImpl(aliasName, entityClass, usingDefaultCase(), fetchSql, dependsOnColum, false, nullable); return this; } private EntityAlias importEntityAliasImpl( - final String aliasName, final Class entityClass, + final String aliasName, final Class entityClass, final ColumnValue forCase, final SQL fetchSql, final Column dependsOnColum, boolean asSubEntity, final Nullable nullable) { final var entityAlias = new EntityAlias(aliasName, entityClass, fetchSql, dependsOnColum, asSubEntity, nullable); entityAliases.put(aliasName, entityAlias); try { - importAsAlias(aliasName, rbacDefinition(entityClass), asSubEntity); + importAsAlias(aliasName, rbacDefinition(entityClass), forCase, asSubEntity); } catch (final ReflectiveOperationException exc) { throw new RuntimeException("cannot import entity: " + entityClass, exc); } @@ -367,7 +378,7 @@ public class RbacView { return (RbacView) entityClass.getMethod("rbac").invoke(null); } - private RbacView importAsAlias(final String aliasName, final RbacView importedRbacView, final boolean asSubEntity) { + private RbacView importAsAlias(final String aliasName, final RbacView importedRbacView, final ColumnValue forCase, final boolean asSubEntity) { final var mapper = new AliasNameMapper(importedRbacView, aliasName, asSubEntity ? entityAliases.keySet() : null); importedRbacView.getEntityAliases().values().stream() @@ -382,7 +393,8 @@ public class RbacView { new RbacRoleDefinition(findEntityAlias(mapper.map(roleDef.entityAlias.aliasName)), roleDef.role); }); importedRbacView.getGrantDefs().forEach(grantDef -> { - if (grantDef.grantType() == RbacGrantDefinition.GrantType.ROLE_TO_ROLE) { + if ( grantDef.matchesCase(forCase) && + grantDef.grantType() == RbacGrantDefinition.GrantType.ROLE_TO_ROLE) { final var importedGrantDef = findOrCreateGrantDef( findRbacRole( mapper.map(grantDef.getSubRoleDef().entityAlias.aliasName), @@ -400,8 +412,15 @@ public class RbacView { } public RbacView switchOnColumn(final String discriminatorColumName, final CaseDef... caseDefs) { + this.discriminatorColumName = discriminatorColumName; + allCases.addAll(stream(caseDefs).toList()); + // FIXME: currently only the default case is executed - stream(caseDefs).filter(caseDef -> caseDef.val == null).findAny().orElseThrow().def.accept(this); + stream(caseDefs).forEach(caseDef -> { + this.processingCase = caseDef; + caseDef.def.accept(this); + this.processingCase = null; + }); return this; } @@ -463,6 +482,12 @@ public class RbacView { } public void generateWithBaseFileName(final String baseFileName) { + if (allCases.size() > 1) { + allCases.forEach(c -> { + final var fileName = baseFileName + (c.isDefaultCase() ? "" : "-" + c.val) + ".md"; + new RbacViewMermaidFlowchartGenerator(this, c).generateToMarkdownFile(Path.of(OUTPUT_BASEDIR, fileName)); + }); + } new RbacViewMermaidFlowchartGenerator(this).generateToMarkdownFile(Path.of(OUTPUT_BASEDIR, baseFileName + ".md")); new RbacViewPostgresGenerator(this).generateToChangeLog(Path.of(OUTPUT_BASEDIR, baseFileName + ".sql")); } @@ -488,25 +513,6 @@ public class RbacView { } - public static class CaseDef { - - private final String val; - private final Consumer def; - - public CaseDef(final String discriminatorColumnValue, final Consumer def) { - this.val = discriminatorColumnValue; - this.def = def; - } - } - - public static CaseDef inCaseOf(final String discriminatorColumnValue, final Consumer def) { - return new CaseDef(discriminatorColumnValue, def); - } - - public static CaseDef inOtherCases(final Consumer def) { - return new CaseDef(null, def); - } - public enum Nullable { NOT_NULL, // DEFAULT NULLABLE @@ -522,8 +528,7 @@ public class RbacView { private final RbacPermissionDefinition permDef; private boolean assumed = true; private boolean toCreate = false; - private String onlyInCaseOf; - private String exceptInCaseOf; + private Set forCases = new HashSet<>(); @Override public String toString() { @@ -537,11 +542,12 @@ public class RbacView { }; } - RbacGrantDefinition(final RbacRoleDefinition subRoleDef, final RbacRoleDefinition superRoleDef) { + RbacGrantDefinition(final RbacRoleDefinition subRoleDef, final RbacRoleDefinition superRoleDef, final CaseDef forCase) { this.userDef = null; this.subRoleDef = subRoleDef; this.superRoleDef = superRoleDef; this.permDef = null; + this.forCases = hashSet(forCase); register(this); } @@ -567,7 +573,7 @@ public class RbacView { @NotNull GrantType grantType() { - return permDef != null ? GrantType.PERM_TO_ROLE + return permDef != null ? PERM_TO_ROLE : userDef != null ? GrantType.ROLE_TO_USER : GrantType.ROLE_TO_ROLE; } @@ -576,8 +582,27 @@ public class RbacView { return assumed; } + + RbacGrantDefinition forCase(final CaseDef processingCase) { + forCases.add(processingCase); + return this; + } + boolean isConditional() { - return onlyInCaseOf != null; + return !forCases.isEmpty() && forCases.size() g.permDef == permDef && g.subRoleDef == roleDef) + .filter(g -> g.permDef == permDef && g.superRoleDef == roleDef) .findFirst() .orElseGet(() -> new RbacGrantDefinition(permDef, roleDef)); } @@ -851,7 +865,8 @@ public class RbacView { return grantDefs.stream() .filter(g -> g.subRoleDef == subRoleDefinition && g.superRoleDef == superRoleDefinition) .findFirst() - .orElseGet(() -> new RbacGrantDefinition(subRoleDefinition, superRoleDefinition)); + .map(g -> g.forCase(processingCase)) + .orElseGet(() -> new RbacGrantDefinition(subRoleDefinition, superRoleDefinition, processingCase)); } record EntityAlias(String aliasName, Class entityClass, SQL fetchSql, Column dependsOnColum, boolean isSubEntity, Nullable nullable) { diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java index 4b6e1c14..e4dedc25 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java @@ -1,6 +1,7 @@ package net.hostsharing.hsadminng.rbac.rbacdef; import lombok.SneakyThrows; +import net.hostsharing.hsadminng.rbac.rbacdef.ConditionGenerator.CaseDef; import org.apache.commons.lang3.StringUtils; import java.nio.file.*; @@ -15,10 +16,13 @@ public class RbacViewMermaidFlowchartGenerator { public static final String HOSTSHARING_DARK_BLUE = "#274d6e"; public static final String HOSTSHARING_LIGHT_BLUE = "#99bcdb"; private final RbacView rbacDef; + + private final CaseDef forCase; private final StringWriter flowchart = new StringWriter(); - public RbacViewMermaidFlowchartGenerator(final RbacView rbacDef) { + public RbacViewMermaidFlowchartGenerator(final RbacView rbacDef, final CaseDef forCase) { this.rbacDef = rbacDef; + this.forCase = forCase; flowchart.writeLn(""" %%{init:{'flowchart':{'htmlLabels':false}}}%% flowchart TB @@ -26,6 +30,10 @@ public class RbacViewMermaidFlowchartGenerator { renderEntitySubgraphs(); renderGrants(); } + + public RbacViewMermaidFlowchartGenerator(final RbacView rbacDef) { + this(rbacDef, null); + } private void renderEntitySubgraphs() { rbacDef.getEntityAliases().values().stream() .filter(entityAlias -> !rbacDef.isEntityAliasProxy(entityAlias)) @@ -99,6 +107,7 @@ public class RbacViewMermaidFlowchartGenerator { private void renderGrants(final RbacView.RbacGrantDefinition.GrantType grantType, final String comment) { final var grantsOfRequestedType = rbacDef.getGrantDefs().stream() .filter(g -> g.grantType() == grantType) + .filter(g -> g.matchesCase(forCase)) .toList(); if ( !grantsOfRequestedType.isEmpty()) { flowchart.ensureSingleEmptyLine(); @@ -109,9 +118,7 @@ public class RbacViewMermaidFlowchartGenerator { private String grantDef(final RbacView.RbacGrantDefinition grant) { final var arrow = (grant.isToCreate() ? " ==>" : " -.->") - + (grant.isConditional() - ? (grant.isAssumed() ? " |??| " : "|?XX?| ") - : (grant.isAssumed() ? " " : "|XX| ")); + + (grant.isAssumed() ? " " : "|XX| "); return switch (grant.grantType()) { case ROLE_TO_USER -> // TODO: other user types not implemented yet diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java index 4c4ce134..c755d1c5 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java @@ -1,11 +1,13 @@ package net.hostsharing.hsadminng.rbac.rbacdef; +import net.hostsharing.hsadminng.rbac.rbacdef.ConditionGenerator.CaseDef; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacGrantDefinition; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacPermissionDefinition; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Stream; import static java.util.Optional.ofNullable; @@ -189,7 +191,25 @@ class RolesGrantsAndPermissionsGenerator { createRolesWithGrantsSql(plPgSql, REFERRER); generateGrants(plPgSql, ROLE_TO_USER); + generateGrants(plPgSql, ROLE_TO_ROLE); + if (!rbacDef.getAllCases().isEmpty()) { + plPgSql.writeLn(); + final var ifOrElsIf = new AtomicReference<>("IF "); + rbacDef.getAllCases().forEach(caseDef -> { + if (caseDef.val != null) { + plPgSql.writeLn(ifOrElsIf + rbacDef.getDiscriminatorColumName() + " = '" + caseDef.val + "' THEN"); + } else { + plPgSql.writeLn("ELSE"); + } + plPgSql.indented(() -> { + generateGrants(plPgSql, ROLE_TO_ROLE, caseDef); + }); + ifOrElsIf.set("ELSIF "); + }); + plPgSql.writeLn("END IF;"); + } + generateGrants(plPgSql, PERM_TO_ROLE); } @@ -267,9 +287,19 @@ class RolesGrantsAndPermissionsGenerator { return isInsertPermissionGrant; } + private void generateGrants(final StringWriter plPgSql, final RbacGrantDefinition.GrantType grantType, final CaseDef caseDef) { + rbacGrants.stream() + .filter(g -> g.matchesCase(caseDef)) + .filter(g -> g.grantType() == grantType) + .map(this::generateGrant) + .sorted() + .forEach(text -> plPgSql.writeLn(text, with("ref", NEW.name()))); + } + private void generateGrants(final StringWriter plPgSql, final RbacGrantDefinition.GrantType grantType) { plPgSql.ensureSingleEmptyLine(); rbacGrants.stream() + .filter(g -> !g.isConditional()) .filter(g -> g.grantType() == grantType) .map(this::generateGrant) .sorted() @@ -302,7 +332,7 @@ class RolesGrantsAndPermissionsGenerator { .replace("${superRoleRef}", roleRef(NEW, grantDef.getSuperRoleDef())); }; // if (grantDef.isConditional()) { -// return "if " + grantDef.getOnlyInCaseOf() + " then\n" +// return "if " + grantDef.generateCondition() + " then\n" // + " " + grantSql + "\n" // + "end if;"; // } diff --git a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac-DEBITOR.md b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac-DEBITOR.md new file mode 100644 index 00000000..f3ffabdf --- /dev/null +++ b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac-DEBITOR.md @@ -0,0 +1,91 @@ +### rbac relation + +This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually. + +```mermaid +%%{init:{'flowchart':{'htmlLabels':false}}}%% +flowchart TB + +subgraph holderPerson["`**holderPerson**`"] + direction TB + style holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph holderPerson:roles[ ] + style holderPerson:roles fill:#99bcdb,stroke:white + + role:holderPerson:OWNER[[holderPerson:OWNER]] + role:holderPerson:ADMIN[[holderPerson:ADMIN]] + role:holderPerson:REFERRER[[holderPerson:REFERRER]] + end +end + +subgraph anchorPerson["`**anchorPerson**`"] + direction TB + style anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph anchorPerson:roles[ ] + style anchorPerson:roles fill:#99bcdb,stroke:white + + role:anchorPerson:OWNER[[anchorPerson:OWNER]] + role:anchorPerson:ADMIN[[anchorPerson:ADMIN]] + role:anchorPerson:REFERRER[[anchorPerson:REFERRER]] + end +end + +subgraph contact["`**contact**`"] + direction TB + style contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph contact:roles[ ] + style contact:roles fill:#99bcdb,stroke:white + + role:contact:OWNER[[contact:OWNER]] + role:contact:ADMIN[[contact:ADMIN]] + role:contact:REFERRER[[contact:REFERRER]] + end +end + +subgraph relation["`**relation**`"] + direction TB + style relation fill:#dd4901,stroke:#274d6e,stroke-width:8px + + subgraph relation:roles[ ] + style relation:roles fill:#dd4901,stroke:white + + role:relation:OWNER[[relation:OWNER]] + role:relation:ADMIN[[relation:ADMIN]] + role:relation:AGENT[[relation:AGENT]] + role:relation:TENANT[[relation:TENANT]] + end + + subgraph relation:permissions[ ] + style relation:permissions fill:#dd4901,stroke:white + + perm:relation:DELETE{{relation:DELETE}} + perm:relation:UPDATE{{relation:UPDATE}} + perm:relation:SELECT{{relation:SELECT}} + perm:relation:INSERT{{relation:INSERT}} + end +end + +%% granting roles to users +user:creator ==> role:relation:OWNER + +%% granting roles to roles +role:global:ADMIN -.-> role:anchorPerson:OWNER +role:anchorPerson:OWNER -.-> role:anchorPerson:ADMIN +role:anchorPerson:ADMIN -.-> role:anchorPerson:REFERRER +role:global:ADMIN -.-> role:holderPerson:OWNER +role:holderPerson:OWNER -.-> role:holderPerson:ADMIN +role:holderPerson:ADMIN -.-> role:holderPerson:REFERRER +role:global:ADMIN -.-> role:contact:OWNER +role:contact:OWNER -.-> role:contact:ADMIN +role:contact:ADMIN -.-> role:contact:REFERRER + +%% granting permissions to roles +role:relation:OWNER ==> perm:relation:DELETE +role:relation:ADMIN ==> perm:relation:UPDATE +role:relation:TENANT ==> perm:relation:SELECT +role:anchorPerson:ADMIN ==> perm:relation:INSERT + +``` diff --git a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac-REPRESENTATIVE.md b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac-REPRESENTATIVE.md new file mode 100644 index 00000000..067355a8 --- /dev/null +++ b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac-REPRESENTATIVE.md @@ -0,0 +1,103 @@ +### rbac relation + +This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually. + +```mermaid +%%{init:{'flowchart':{'htmlLabels':false}}}%% +flowchart TB + +subgraph holderPerson["`**holderPerson**`"] + direction TB + style holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph holderPerson:roles[ ] + style holderPerson:roles fill:#99bcdb,stroke:white + + role:holderPerson:OWNER[[holderPerson:OWNER]] + role:holderPerson:ADMIN[[holderPerson:ADMIN]] + role:holderPerson:REFERRER[[holderPerson:REFERRER]] + end +end + +subgraph anchorPerson["`**anchorPerson**`"] + direction TB + style anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph anchorPerson:roles[ ] + style anchorPerson:roles fill:#99bcdb,stroke:white + + role:anchorPerson:OWNER[[anchorPerson:OWNER]] + role:anchorPerson:ADMIN[[anchorPerson:ADMIN]] + role:anchorPerson:REFERRER[[anchorPerson:REFERRER]] + end +end + +subgraph contact["`**contact**`"] + direction TB + style contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px + + subgraph contact:roles[ ] + style contact:roles fill:#99bcdb,stroke:white + + role:contact:OWNER[[contact:OWNER]] + role:contact:ADMIN[[contact:ADMIN]] + role:contact:REFERRER[[contact:REFERRER]] + end +end + +subgraph relation["`**relation**`"] + direction TB + style relation fill:#dd4901,stroke:#274d6e,stroke-width:8px + + subgraph relation:roles[ ] + style relation:roles fill:#dd4901,stroke:white + + role:relation:OWNER[[relation:OWNER]] + role:relation:ADMIN[[relation:ADMIN]] + role:relation:AGENT[[relation:AGENT]] + role:relation:TENANT[[relation:TENANT]] + end + + subgraph relation:permissions[ ] + style relation:permissions fill:#dd4901,stroke:white + + perm:relation:DELETE{{relation:DELETE}} + perm:relation:UPDATE{{relation:UPDATE}} + perm:relation:SELECT{{relation:SELECT}} + perm:relation:INSERT{{relation:INSERT}} + end +end + +%% granting roles to users +user:creator ==> role:relation:OWNER + +%% granting roles to roles +role:global:ADMIN -.-> role:anchorPerson:OWNER +role:anchorPerson:OWNER -.-> role:anchorPerson:ADMIN +role:anchorPerson:ADMIN -.-> role:anchorPerson:REFERRER +role:global:ADMIN -.-> role:holderPerson:OWNER +role:holderPerson:OWNER -.-> role:holderPerson:ADMIN +role:holderPerson:ADMIN -.-> role:holderPerson:REFERRER +role:global:ADMIN -.-> role:contact:OWNER +role:contact:OWNER -.-> role:contact:ADMIN +role:contact:ADMIN -.-> role:contact:REFERRER +role:global:ADMIN ==> role:relation:OWNER +role:holderPerson:ADMIN ==> role:relation:OWNER +role:relation:OWNER ==> role:relation:ADMIN +role:relation:ADMIN ==> role:anchorPerson:OWNER +role:relation:ADMIN ==> role:relation:AGENT +role:anchorPerson:ADMIN ==> role:relation:AGENT +role:relation:AGENT ==> role:relation:TENANT +role:holderPerson:ADMIN ==> role:relation:TENANT +role:contact:ADMIN ==> role:relation:TENANT +role:relation:TENANT ==> role:anchorPerson:REFERRER +role:relation:TENANT ==> role:holderPerson:REFERRER +role:relation:TENANT ==> role:contact:REFERRER + +%% granting permissions to roles +role:relation:OWNER ==> perm:relation:DELETE +role:relation:ADMIN ==> perm:relation:UPDATE +role:relation:TENANT ==> perm:relation:SELECT +role:anchorPerson:ADMIN ==> perm:relation:INSERT + +``` diff --git a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md index 8014cdaf..b598df88 100644 --- a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md +++ b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md @@ -82,16 +82,19 @@ role:global:ADMIN -.-> role:contact:OWNER role:contact:OWNER -.-> role:contact:ADMIN role:contact:ADMIN -.-> role:contact:REFERRER role:global:ADMIN ==> role:relation:OWNER +role:holderPerson:ADMIN ==> role:relation:OWNER role:relation:OWNER ==> role:relation:ADMIN -role:anchorPerson:ADMIN ==> role:relation:ADMIN +role:relation:ADMIN ==> role:anchorPerson:OWNER role:relation:ADMIN ==> role:relation:AGENT -role:holderPerson:ADMIN ==> role:relation:AGENT +role:anchorPerson:ADMIN ==> role:relation:AGENT role:relation:AGENT ==> role:relation:TENANT role:holderPerson:ADMIN ==> role:relation:TENANT role:contact:ADMIN ==> role:relation:TENANT role:relation:TENANT ==> role:anchorPerson:REFERRER role:relation:TENANT ==> role:holderPerson:REFERRER role:relation:TENANT ==> role:contact:REFERRER +role:anchorPerson:ADMIN ==> role:relation:ADMIN +role:holderPerson:ADMIN ==> role:relation:AGENT %% granting permissions to roles role:relation:OWNER ==> perm:relation:DELETE diff --git a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql index ff890a59..50cf960e 100644 --- a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql +++ b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql @@ -50,38 +50,51 @@ begin perform createRoleWithGrants( hsOfficeRelationOWNER(NEW), permissions => array['DELETE'], - incomingSuperRoles => array[globalADMIN()], userUuids => array[currentUserUuid()] ); perform createRoleWithGrants( hsOfficeRelationADMIN(NEW), - permissions => array['UPDATE'], - incomingSuperRoles => array[ - hsOfficePersonADMIN(newAnchorPerson), - hsOfficeRelationOWNER(NEW)] + permissions => array['UPDATE'] ); perform createRoleWithGrants( - hsOfficeRelationAGENT(NEW), - incomingSuperRoles => array[ - hsOfficePersonADMIN(newHolderPerson), - hsOfficeRelationADMIN(NEW)] + hsOfficeRelationAGENT(NEW) ); perform createRoleWithGrants( hsOfficeRelationTENANT(NEW), - permissions => array['SELECT'], - incomingSuperRoles => array[ - hsOfficeContactADMIN(newContact), - hsOfficePersonADMIN(newHolderPerson), - hsOfficeRelationAGENT(NEW)], - outgoingSubRoles => array[ - hsOfficeContactREFERRER(newContact), - hsOfficePersonREFERRER(newAnchorPerson), - hsOfficePersonREFERRER(newHolderPerson)] + permissions => array['SELECT'] ); + IF type = 'REPRESENTATIVE' THEN + call grantRoleToRole(hsOfficeContactREFERRER(newContact), hsOfficeRelationTENANT(NEW)); + call grantRoleToRole(hsOfficePersonOWNER(newAnchorPerson), hsOfficeRelationADMIN(NEW)); + call grantRoleToRole(hsOfficePersonREFERRER(newAnchorPerson), hsOfficeRelationTENANT(NEW)); + call grantRoleToRole(hsOfficePersonREFERRER(newHolderPerson), hsOfficeRelationTENANT(NEW)); + call grantRoleToRole(hsOfficeRelationADMIN(NEW), hsOfficeRelationOWNER(NEW)); + call grantRoleToRole(hsOfficeRelationAGENT(NEW), hsOfficePersonADMIN(newAnchorPerson)); + call grantRoleToRole(hsOfficeRelationAGENT(NEW), hsOfficeRelationADMIN(NEW)); + call grantRoleToRole(hsOfficeRelationOWNER(NEW), globalAdmin()); + call grantRoleToRole(hsOfficeRelationOWNER(NEW), hsOfficePersonADMIN(newHolderPerson)); + call grantRoleToRole(hsOfficeRelationTENANT(NEW), hsOfficeContactADMIN(newContact)); + call grantRoleToRole(hsOfficeRelationTENANT(NEW), hsOfficePersonADMIN(newHolderPerson)); + call grantRoleToRole(hsOfficeRelationTENANT(NEW), hsOfficeRelationAGENT(NEW)); + ELSIF type = 'DEBITOR' THEN + ELSE + call grantRoleToRole(hsOfficeContactREFERRER(newContact), hsOfficeRelationTENANT(NEW)); + call grantRoleToRole(hsOfficePersonREFERRER(newAnchorPerson), hsOfficeRelationTENANT(NEW)); + call grantRoleToRole(hsOfficePersonREFERRER(newHolderPerson), hsOfficeRelationTENANT(NEW)); + call grantRoleToRole(hsOfficeRelationADMIN(NEW), hsOfficePersonADMIN(newAnchorPerson)); + call grantRoleToRole(hsOfficeRelationADMIN(NEW), hsOfficeRelationOWNER(NEW)); + call grantRoleToRole(hsOfficeRelationAGENT(NEW), hsOfficePersonADMIN(newHolderPerson)); + call grantRoleToRole(hsOfficeRelationAGENT(NEW), hsOfficeRelationADMIN(NEW)); + call grantRoleToRole(hsOfficeRelationOWNER(NEW), globalAdmin()); + call grantRoleToRole(hsOfficeRelationTENANT(NEW), hsOfficeContactADMIN(newContact)); + call grantRoleToRole(hsOfficeRelationTENANT(NEW), hsOfficePersonADMIN(newHolderPerson)); + call grantRoleToRole(hsOfficeRelationTENANT(NEW), hsOfficeRelationAGENT(NEW)); + END IF; + call leaveTriggerForObjectUuid(NEW.uuid); end; $$; @@ -118,48 +131,12 @@ create or replace procedure updateRbacRulesForHsOfficeRelation( NEW hs_office_relation ) language plpgsql as $$ - -declare - oldHolderPerson hs_office_person; - newHolderPerson hs_office_person; - oldAnchorPerson hs_office_person; - newAnchorPerson hs_office_person; - oldContact hs_office_contact; - newContact hs_office_contact; - begin - call enterTriggerForObjectUuid(NEW.uuid); - - SELECT * FROM hs_office_person WHERE uuid = OLD.holderUuid INTO oldHolderPerson; - assert oldHolderPerson.uuid is not null, format('oldHolderPerson must not be null for OLD.holderUuid = %s', OLD.holderUuid); - - SELECT * FROM hs_office_person WHERE uuid = NEW.holderUuid INTO newHolderPerson; - assert newHolderPerson.uuid is not null, format('newHolderPerson must not be null for NEW.holderUuid = %s', NEW.holderUuid); - - SELECT * FROM hs_office_person WHERE uuid = OLD.anchorUuid INTO oldAnchorPerson; - assert oldAnchorPerson.uuid is not null, format('oldAnchorPerson must not be null for OLD.anchorUuid = %s', OLD.anchorUuid); - - SELECT * FROM hs_office_person WHERE uuid = NEW.anchorUuid INTO newAnchorPerson; - assert newAnchorPerson.uuid is not null, format('newAnchorPerson must not be null for NEW.anchorUuid = %s', NEW.anchorUuid); - - SELECT * FROM hs_office_contact WHERE uuid = OLD.contactUuid INTO oldContact; - assert oldContact.uuid is not null, format('oldContact must not be null for OLD.contactUuid = %s', OLD.contactUuid); - - SELECT * FROM hs_office_contact WHERE uuid = NEW.contactUuid INTO newContact; - assert newContact.uuid is not null, format('newContact must not be null for NEW.contactUuid = %s', NEW.contactUuid); - - - if NEW.contactUuid <> OLD.contactUuid then - - call revokeRoleFromRole(hsOfficeRelationTENANT(OLD), hsOfficeContactADMIN(oldContact)); - call grantRoleToRole(hsOfficeRelationTENANT(NEW), hsOfficeContactADMIN(newContact)); - - call revokeRoleFromRole(hsOfficeContactREFERRER(oldContact), hsOfficeRelationTENANT(OLD)); - call grantRoleToRole(hsOfficeContactREFERRER(newContact), hsOfficeRelationTENANT(NEW)); + if NEW.contactUuid is distinct from OLD.contactUuid then + delete from rbacgrants g where g.grantedbytriggerof = OLD.uuid; + call buildRbacSystemForHsOfficeRelation(NEW); end if; - - call leaveTriggerForObjectUuid(NEW.uuid); end; $$; /* diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/rbacdef/ConditionGeneratorUnitTest.java b/src/test/java/net/hostsharing/hsadminng/rbac/rbacdef/ConditionGeneratorUnitTest.java new file mode 100644 index 00000000..030a496f --- /dev/null +++ b/src/test/java/net/hostsharing/hsadminng/rbac/rbacdef/ConditionGeneratorUnitTest.java @@ -0,0 +1,46 @@ +package net.hostsharing.hsadminng.rbac.rbacdef; + +import net.hostsharing.hsadminng.rbac.rbacdef.ConditionGenerator.CaseDef; +import org.junit.jupiter.api.Test; + +import java.util.function.Consumer; + +import static net.hostsharing.hsadminng.rbac.rbacdef.ConditionGenerator.CaseDef.inCaseOf; +import static net.hostsharing.hsadminng.rbac.rbacdef.ConditionGenerator.CaseDef.inOtherCases; +import static org.apache.commons.collections4.SetUtils.hashSet; +import static org.assertj.core.api.Assertions.assertThat; + +class ConditionGeneratorUnitTest { + + static final Consumer CONSUMER_FAKE = null; + static final CaseDef CASE_A = inCaseOf("A", CONSUMER_FAKE); + static final CaseDef CASE_B = inCaseOf("B", CONSUMER_FAKE); + static final CaseDef DEFAULT_CASE = inOtherCases(CONSUMER_FAKE); + + static final ConditionGenerator GENERATOR_WITH_A_B_AND_DEFAULT = + new ConditionGenerator("someCol", hashSet(CASE_A, CASE_B, DEFAULT_CASE)); + + @Test + void onlyCase_A_from_A_B_and_DEFAULT() { + assertThat(GENERATOR_WITH_A_B_AND_DEFAULT.generatePlPgSql(hashSet(CASE_A))) + .isEqualTo("someCol = 'A'"); + } + + @Test + void case_A_and_B_from_A_B_and_DEFAULT() { + assertThat(GENERATOR_WITH_A_B_AND_DEFAULT.generatePlPgSql(hashSet(CASE_A, CASE_B))) + .isEqualTo("someCol in ('A', 'B')"); + } + + @Test + void case_DEFAULT_from_A_B_and_DEFAULT() { + assertThat(GENERATOR_WITH_A_B_AND_DEFAULT.generatePlPgSql(hashSet(DEFAULT_CASE))) + .isEqualTo("someCol not in ('A', 'B')"); + } + + @Test + void case_A_and_DEFAULT_from_A_B_and_DEFAULT() { + assertThat(GENERATOR_WITH_A_B_AND_DEFAULT.generatePlPgSql(hashSet(CASE_A, DEFAULT_CASE))) + .isEqualTo("someCol <> 'B'"); + } +} -- 2.39.5 From c80dfc2fa8117cf39c2fa7f1455c0439b0273575 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Fri, 5 Apr 2024 09:54:39 +0200 Subject: [PATCH 19/29] cleaner version with conditional PostgreSQL generation (without DEBITOR-case) --- .../relation/HsOfficeRelationEntity.java | 6 +- .../rbac/rbacdef/ConditionGenerator.java | 75 ---------------- .../hsadminng/rbac/rbacdef/RbacView.java | 87 +++++++++++++++---- .../RolesGrantsAndPermissionsGenerator.java | 7 +- .../5033-hs-office-relation-rbac.sql | 38 ++++---- .../rbacdef/ConditionGeneratorUnitTest.java | 46 ---------- 6 files changed, 88 insertions(+), 171 deletions(-) delete mode 100644 src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/ConditionGenerator.java delete mode 100644 src/test/java/net/hostsharing/hsadminng/rbac/rbacdef/ConditionGeneratorUnitTest.java diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java index e18a8cd4..33a60f31 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java @@ -15,9 +15,9 @@ import jakarta.persistence.Column; import java.io.IOException; import java.util.UUID; -import static net.hostsharing.hsadminng.rbac.rbacdef.ConditionGenerator.CaseDef.inCaseOf; -import static net.hostsharing.hsadminng.rbac.rbacdef.ConditionGenerator.CaseDef.inOtherCases; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.*; +import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.CaseDef.inCaseOf; +import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.CaseDef.inOtherCases; 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.*; @@ -127,7 +127,7 @@ public class HsOfficeRelationEntity implements RbacObject, Stringifyable { with.permission(SELECT); }); }), - inCaseOf("DEBITOR", then -> {}), + // inCaseOf("DEBITOR", then -> {}), TODO.spec: needs to be defined inOtherCases(then -> { then.createRole(OWNER, (with) -> { with.owningUser(CREATOR); diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/ConditionGenerator.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/ConditionGenerator.java deleted file mode 100644 index 0ea70b02..00000000 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/ConditionGenerator.java +++ /dev/null @@ -1,75 +0,0 @@ -package net.hostsharing.hsadminng.rbac.rbacdef; - -import java.util.Objects; -import java.util.Set; -import java.util.function.Consumer; -import java.util.stream.Collectors; - -import static java.lang.String.join; -import static java.util.Optional.ofNullable; - -public class ConditionGenerator { - - private final String discriminatorColumName; - private final Set allCases; - - public ConditionGenerator(final String discriminatorColumName, final Set allCases) { - this.discriminatorColumName = discriminatorColumName; - this.allCases = allCases; - } - - public String generatePlPgSql(final Set forCases) { - if (forCases.size() == 1) { - if (forCases.iterator().next().isDefaultCase()) { - final var nonDefaultCases = allCases.stream().filter(c -> !c.isDefaultCase()).map(c -> c.val).toList(); - if (nonDefaultCases.size() > 1) { - return discriminatorColumName + " not in ('" + join("', '", nonDefaultCases) + "')"; - } - return discriminatorColumName + " <> '" + nonDefaultCases.getFirst() + "'"; - } - return discriminatorColumName + " = '" + forCases.iterator().next().val + "'"; - } - return discriminatorColumName + " in ('" + forCases.stream().map(c -> c.val).collect(Collectors.joining("', '")) + "')"; - } - - - - public static class CaseDef { - - final String val; - final Consumer def; - - private CaseDef(final String discriminatorColumnValue, final Consumer def) { - this.val = discriminatorColumnValue; - this.def = def; - } - - - public static CaseDef inCaseOf(final String discriminatorColumnValue, final Consumer def) { - return new CaseDef(discriminatorColumnValue, def); - } - - public static CaseDef inOtherCases(final Consumer def) { - return new CaseDef(null, def); - } - - @Override - public int hashCode() { - return ofNullable(val).map(String::hashCode).orElse(0); - } - - @Override - public boolean equals(final Object other) { - if (this == other) - return true; - if (other == null || getClass() != other.getClass()) - return false; - final CaseDef caseDef = (CaseDef) other; - return Objects.equals(val, caseDef.val); - } - - boolean isDefaultCase() { - return val == null; - } - } -} diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java index d5a225c5..171a3b64 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java @@ -13,7 +13,6 @@ import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity; import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity; import net.hostsharing.hsadminng.hs.office.sepamandate.HsOfficeSepaMandateEntity; -import net.hostsharing.hsadminng.rbac.rbacdef.ConditionGenerator.CaseDef; import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject; import net.hostsharing.hsadminng.test.cust.TestCustomerEntity; import net.hostsharing.hsadminng.test.dom.TestDomainEntity; @@ -27,6 +26,7 @@ import java.lang.reflect.Method; import java.nio.file.Path; import java.util.*; import java.util.function.Consumer; +import java.util.stream.Collectors; import java.util.stream.Stream; import static java.lang.reflect.Modifier.isStatic; @@ -483,9 +483,12 @@ public class RbacView { public void generateWithBaseFileName(final String baseFileName) { if (allCases.size() > 1) { - allCases.forEach(c -> { - final var fileName = baseFileName + (c.isDefaultCase() ? "" : "-" + c.val) + ".md"; - new RbacViewMermaidFlowchartGenerator(this, c).generateToMarkdownFile(Path.of(OUTPUT_BASEDIR, fileName)); + allCases.forEach(caseDef -> { + if ( caseDef.isDefaultCase() ) { // FIXME remove the condition + final var fileName = baseFileName + (caseDef.isDefaultCase() ? "" : "-" + caseDef.val) + ".md"; + new RbacViewMermaidFlowchartGenerator(this, caseDef) + .generateToMarkdownFile(Path.of(OUTPUT_BASEDIR, fileName)); + } }); } new RbacViewMermaidFlowchartGenerator(this).generateToMarkdownFile(Path.of(OUTPUT_BASEDIR, baseFileName + ".md")); @@ -532,14 +535,14 @@ public class RbacView { @Override public String toString() { - final var arrow = isConditional() - ? (isAssumed() ? " -- ?? --> " : " -- ?//? --> ") - : (isAssumed() ? " --> " : " -- // --> "); - return switch (grantType()) { + final var arrow = isAssumed() ? " --> " : " -- // --> "; + final var grant = switch (grantType()) { case ROLE_TO_USER -> userDef.toString() + arrow + subRoleDef.toString(); case ROLE_TO_ROLE -> superRoleDef + arrow + subRoleDef; case PERM_TO_ROLE -> superRoleDef + arrow + permDef; }; + final var condition = isConditional() ? (" " +forCases.stream().map(CaseDef::toString).collect(Collectors.joining("||"))) : ""; + return grant + condition; } RbacGrantDefinition(final RbacRoleDefinition subRoleDef, final RbacRoleDefinition superRoleDef, final CaseDef forCase) { @@ -547,7 +550,7 @@ public class RbacView { this.subRoleDef = subRoleDef; this.superRoleDef = superRoleDef; this.permDef = null; - this.forCases = hashSet(forCase); + this.forCases = forCase != null ? hashSet(forCase) : null; register(this); } @@ -589,20 +592,19 @@ public class RbacView { } boolean isConditional() { - return !forCases.isEmpty() && forCases.size() g.subRoleDef == subRoleDefinition && g.superRoleDef == superRoleDefinition) .findFirst() .map(g -> g.forCase(processingCase)) .orElseGet(() -> new RbacGrantDefinition(subRoleDefinition, superRoleDefinition, processingCase)); + return distinctGrantDef; } record EntityAlias(String aliasName, Class entityClass, SQL fetchSql, Column dependsOnColum, boolean isSubEntity, Nullable nullable) { @@ -1124,6 +1127,52 @@ public class RbacView { } } + public static class CaseDef { + + final String val; + final Consumer def; + + private CaseDef(final String discriminatorColumnValue, final Consumer def) { + this.val = discriminatorColumnValue; + this.def = def; + } + + + public static CaseDef inCaseOf(final String discriminatorColumnValue, final Consumer def) { + return new CaseDef(discriminatorColumnValue, def); + } + + public static CaseDef inOtherCases(final Consumer def) { + return new CaseDef(null, def); + } + + @Override + public int hashCode() { + return ofNullable(val).map(String::hashCode).orElse(0); + } + + @Override + public boolean equals(final Object other) { + if (this == other) + return true; + if (other == null || getClass() != other.getClass()) + return false; + final CaseDef caseDef = (CaseDef) other; + return Objects.equals(val, caseDef.val); + } + + boolean isDefaultCase() { + return val == null; + } + + @Override + public String toString() { + return isDefaultCase() + ? "inOtherCases" + : "inCaseOf:" + val; + } + } + private static void generateRbacView(final Class c) { final Method mainMethod = stream(c.getMethods()).filter( m -> isStatic(m.getModifiers()) && m.getName().equals("main") diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java index c755d1c5..91a312bf 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java @@ -1,6 +1,6 @@ package net.hostsharing.hsadminng.rbac.rbacdef; -import net.hostsharing.hsadminng.rbac.rbacdef.ConditionGenerator.CaseDef; +import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.CaseDef; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacGrantDefinition; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacPermissionDefinition; @@ -198,7 +198,7 @@ class RolesGrantsAndPermissionsGenerator { final var ifOrElsIf = new AtomicReference<>("IF "); rbacDef.getAllCases().forEach(caseDef -> { if (caseDef.val != null) { - plPgSql.writeLn(ifOrElsIf + rbacDef.getDiscriminatorColumName() + " = '" + caseDef.val + "' THEN"); + plPgSql.writeLn(ifOrElsIf + "NEW." + rbacDef.getDiscriminatorColumName() + " = '" + caseDef.val + "' THEN"); } else { plPgSql.writeLn("ELSE"); } @@ -401,11 +401,8 @@ class RolesGrantsAndPermissionsGenerator { .replace("${roleSuffix}", capitalize(role.name()))); generatePermissionsForRole(plPgSql, role); - generateIncomingSuperRolesForRole(plPgSql, role); - generateOutgoingSubRolesForRole(plPgSql, role); - generateUserGrantsForRole(plPgSql, role); plPgSql.chopTail(",\n"); diff --git a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql index 50cf960e..75adaeb4 100644 --- a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql +++ b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql @@ -50,49 +50,41 @@ begin perform createRoleWithGrants( hsOfficeRelationOWNER(NEW), permissions => array['DELETE'], + incomingSuperRoles => array[globalADMIN()], userUuids => array[currentUserUuid()] ); perform createRoleWithGrants( hsOfficeRelationADMIN(NEW), - permissions => array['UPDATE'] + permissions => array['UPDATE'], + incomingSuperRoles => array[hsOfficeRelationOWNER(NEW)] ); perform createRoleWithGrants( - hsOfficeRelationAGENT(NEW) + hsOfficeRelationAGENT(NEW), + incomingSuperRoles => array[hsOfficeRelationADMIN(NEW)] ); perform createRoleWithGrants( hsOfficeRelationTENANT(NEW), - permissions => array['SELECT'] + permissions => array['SELECT'], + incomingSuperRoles => array[ + hsOfficeContactADMIN(newContact), + hsOfficePersonADMIN(newHolderPerson), + hsOfficeRelationAGENT(NEW)], + outgoingSubRoles => array[ + hsOfficeContactREFERRER(newContact), + hsOfficePersonREFERRER(newAnchorPerson), + hsOfficePersonREFERRER(newHolderPerson)] ); - IF type = 'REPRESENTATIVE' THEN - call grantRoleToRole(hsOfficeContactREFERRER(newContact), hsOfficeRelationTENANT(NEW)); + IF NEW.type = 'REPRESENTATIVE' THEN call grantRoleToRole(hsOfficePersonOWNER(newAnchorPerson), hsOfficeRelationADMIN(NEW)); - call grantRoleToRole(hsOfficePersonREFERRER(newAnchorPerson), hsOfficeRelationTENANT(NEW)); - call grantRoleToRole(hsOfficePersonREFERRER(newHolderPerson), hsOfficeRelationTENANT(NEW)); - call grantRoleToRole(hsOfficeRelationADMIN(NEW), hsOfficeRelationOWNER(NEW)); call grantRoleToRole(hsOfficeRelationAGENT(NEW), hsOfficePersonADMIN(newAnchorPerson)); - call grantRoleToRole(hsOfficeRelationAGENT(NEW), hsOfficeRelationADMIN(NEW)); - call grantRoleToRole(hsOfficeRelationOWNER(NEW), globalAdmin()); call grantRoleToRole(hsOfficeRelationOWNER(NEW), hsOfficePersonADMIN(newHolderPerson)); - call grantRoleToRole(hsOfficeRelationTENANT(NEW), hsOfficeContactADMIN(newContact)); - call grantRoleToRole(hsOfficeRelationTENANT(NEW), hsOfficePersonADMIN(newHolderPerson)); - call grantRoleToRole(hsOfficeRelationTENANT(NEW), hsOfficeRelationAGENT(NEW)); - ELSIF type = 'DEBITOR' THEN ELSE - call grantRoleToRole(hsOfficeContactREFERRER(newContact), hsOfficeRelationTENANT(NEW)); - call grantRoleToRole(hsOfficePersonREFERRER(newAnchorPerson), hsOfficeRelationTENANT(NEW)); - call grantRoleToRole(hsOfficePersonREFERRER(newHolderPerson), hsOfficeRelationTENANT(NEW)); call grantRoleToRole(hsOfficeRelationADMIN(NEW), hsOfficePersonADMIN(newAnchorPerson)); - call grantRoleToRole(hsOfficeRelationADMIN(NEW), hsOfficeRelationOWNER(NEW)); call grantRoleToRole(hsOfficeRelationAGENT(NEW), hsOfficePersonADMIN(newHolderPerson)); - call grantRoleToRole(hsOfficeRelationAGENT(NEW), hsOfficeRelationADMIN(NEW)); - call grantRoleToRole(hsOfficeRelationOWNER(NEW), globalAdmin()); - call grantRoleToRole(hsOfficeRelationTENANT(NEW), hsOfficeContactADMIN(newContact)); - call grantRoleToRole(hsOfficeRelationTENANT(NEW), hsOfficePersonADMIN(newHolderPerson)); - call grantRoleToRole(hsOfficeRelationTENANT(NEW), hsOfficeRelationAGENT(NEW)); END IF; call leaveTriggerForObjectUuid(NEW.uuid); diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/rbacdef/ConditionGeneratorUnitTest.java b/src/test/java/net/hostsharing/hsadminng/rbac/rbacdef/ConditionGeneratorUnitTest.java deleted file mode 100644 index 030a496f..00000000 --- a/src/test/java/net/hostsharing/hsadminng/rbac/rbacdef/ConditionGeneratorUnitTest.java +++ /dev/null @@ -1,46 +0,0 @@ -package net.hostsharing.hsadminng.rbac.rbacdef; - -import net.hostsharing.hsadminng.rbac.rbacdef.ConditionGenerator.CaseDef; -import org.junit.jupiter.api.Test; - -import java.util.function.Consumer; - -import static net.hostsharing.hsadminng.rbac.rbacdef.ConditionGenerator.CaseDef.inCaseOf; -import static net.hostsharing.hsadminng.rbac.rbacdef.ConditionGenerator.CaseDef.inOtherCases; -import static org.apache.commons.collections4.SetUtils.hashSet; -import static org.assertj.core.api.Assertions.assertThat; - -class ConditionGeneratorUnitTest { - - static final Consumer CONSUMER_FAKE = null; - static final CaseDef CASE_A = inCaseOf("A", CONSUMER_FAKE); - static final CaseDef CASE_B = inCaseOf("B", CONSUMER_FAKE); - static final CaseDef DEFAULT_CASE = inOtherCases(CONSUMER_FAKE); - - static final ConditionGenerator GENERATOR_WITH_A_B_AND_DEFAULT = - new ConditionGenerator("someCol", hashSet(CASE_A, CASE_B, DEFAULT_CASE)); - - @Test - void onlyCase_A_from_A_B_and_DEFAULT() { - assertThat(GENERATOR_WITH_A_B_AND_DEFAULT.generatePlPgSql(hashSet(CASE_A))) - .isEqualTo("someCol = 'A'"); - } - - @Test - void case_A_and_B_from_A_B_and_DEFAULT() { - assertThat(GENERATOR_WITH_A_B_AND_DEFAULT.generatePlPgSql(hashSet(CASE_A, CASE_B))) - .isEqualTo("someCol in ('A', 'B')"); - } - - @Test - void case_DEFAULT_from_A_B_and_DEFAULT() { - assertThat(GENERATOR_WITH_A_B_AND_DEFAULT.generatePlPgSql(hashSet(DEFAULT_CASE))) - .isEqualTo("someCol not in ('A', 'B')"); - } - - @Test - void case_A_and_DEFAULT_from_A_B_and_DEFAULT() { - assertThat(GENERATOR_WITH_A_B_AND_DEFAULT.generatePlPgSql(hashSet(CASE_A, DEFAULT_CASE))) - .isEqualTo("someCol <> 'B'"); - } -} -- 2.39.5 From b9706ee4c34808a470d067abc2eccd426dbf3504 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Fri, 5 Apr 2024 12:10:30 +0200 Subject: [PATCH 20/29] properly generate imported conditional rbac rules (partner -> partnerRel usingDefaultCase) --- .../office/partner/HsOfficePartnerEntity.java | 8 +- .../relation/HsOfficeRelationEntity.java | 8 +- .../hsadminng/rbac/rbacdef/RbacView.java | 34 ++++--- .../RbacViewMermaidFlowchartGenerator.java | 36 +++++--- .../5033-hs-office-relation-rbac-DEBITOR.md | 91 ------------------- ...-hs-office-relation-rbac-REPRESENTATIVE.md | 1 - .../5033-hs-office-relation-rbac.md | 6 +- .../5033-hs-office-relation-rbac.sql | 3 +- .../5043-hs-office-partner-rbac.md | 11 +-- .../5043-hs-office-partner-rbac.sql | 18 ++-- .../5063-hs-office-debitor-rbac.md | 16 +--- .../5073-hs-office-sepamandate-rbac.md | 5 +- .../5103-hs-office-membership-rbac.md | 5 +- .../5113-hs-office-coopshares-rbac.md | 5 +- .../5123-hs-office-coopassets-rbac.md | 5 +- 15 files changed, 80 insertions(+), 172 deletions(-) delete mode 100644 src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac-DEBITOR.md diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntity.java index 3c5f1983..6b019f62 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntity.java @@ -102,16 +102,16 @@ public class HsOfficePartnerEntity implements Stringifyable, RbacObject { usingDefaultCase(), directlyFetchedByDependsOnColumn(), dependsOnColumn("partnerRelUuid")) - .createPermission(DELETE).grantedTo("partnerRel", ADMIN) - .createPermission(UPDATE).grantedTo("partnerRel", AGENT) + .createPermission(DELETE).grantedTo("partnerRel", OWNER) + .createPermission(UPDATE).grantedTo("partnerRel", ADMIN) .createPermission(SELECT).grantedTo("partnerRel", TENANT) .importSubEntityAlias("partnerDetails", HsOfficePartnerDetailsEntity.class, directlyFetchedByDependsOnColumn(), dependsOnColumn("detailsUuid")) - .createPermission("partnerDetails", DELETE).grantedTo("partnerRel", ADMIN) + .createPermission("partnerDetails", DELETE).grantedTo("partnerRel", OWNER) .createPermission("partnerDetails", UPDATE).grantedTo("partnerRel", AGENT) - .createPermission("partnerDetails", SELECT).grantedTo("partnerRel", AGENT); + .createPermission("partnerDetails", SELECT).grantedTo("partnerRel", AGENT); // not TENANT! } public static void main(String[] args) throws IOException { diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java index 33a60f31..1dbed5cc 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java @@ -119,7 +119,6 @@ public class HsOfficeRelationEntity implements RbacObject, Stringifyable { with.incomingSuperRole("anchorPerson", ADMIN); }) .createSubRole(TENANT, (with) -> { - with.incomingSuperRole("holderPerson", ADMIN); with.incomingSuperRole("contact", ADMIN); with.outgoingSubRole("anchorPerson", REFERRER); with.outgoingSubRole("holderPerson", REFERRER); @@ -132,17 +131,20 @@ public class HsOfficeRelationEntity implements RbacObject, Stringifyable { then.createRole(OWNER, (with) -> { with.owningUser(CREATOR); with.incomingSuperRole(GLOBAL, ADMIN); + with.incomingSuperRole("anchorPerson", ADMIN); with.permission(DELETE); }) .createSubRole(ADMIN, (with) -> { - with.incomingSuperRole("anchorPerson", ADMIN); with.permission(UPDATE); }) .createSubRole(AGENT, (with) -> { + // TODO.spec: we need relation:PROXY, to allow changing the relation contact. + // the alternative would be to move this to the relation:ADMIN role, + // but then the partner holder person could update the partner relation itself, + // see partner entity. with.incomingSuperRole("holderPerson", ADMIN); }) .createSubRole(TENANT, (with) -> { - with.incomingSuperRole("holderPerson", ADMIN); with.incomingSuperRole("contact", ADMIN); with.outgoingSubRole("anchorPerson", REFERRER); with.outgoingSubRole("holderPerson", REFERRER); diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java index 171a3b64..4e792861 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java @@ -393,8 +393,8 @@ public class RbacView { new RbacRoleDefinition(findEntityAlias(mapper.map(roleDef.entityAlias.aliasName)), roleDef.role); }); importedRbacView.getGrantDefs().forEach(grantDef -> { - if ( grantDef.matchesCase(forCase) && - grantDef.grantType() == RbacGrantDefinition.GrantType.ROLE_TO_ROLE) { + if ( grantDef.grantType() == RbacGrantDefinition.GrantType.ROLE_TO_ROLE && + grantDef.matchesCase(forCase) ) { final var importedGrantDef = findOrCreateGrantDef( findRbacRole( mapper.map(grantDef.getSubRoleDef().entityAlias.aliasName), @@ -484,14 +484,13 @@ public class RbacView { public void generateWithBaseFileName(final String baseFileName) { if (allCases.size() > 1) { allCases.forEach(caseDef -> { - if ( caseDef.isDefaultCase() ) { // FIXME remove the condition - final var fileName = baseFileName + (caseDef.isDefaultCase() ? "" : "-" + caseDef.val) + ".md"; - new RbacViewMermaidFlowchartGenerator(this, caseDef) - .generateToMarkdownFile(Path.of(OUTPUT_BASEDIR, fileName)); - } + final var fileName = baseFileName + (caseDef.isDefaultCase() ? "" : "-" + caseDef.val) + ".md"; + new RbacViewMermaidFlowchartGenerator(this, caseDef) + .generateToMarkdownFile(Path.of(OUTPUT_BASEDIR, fileName)); }); + } else { + new RbacViewMermaidFlowchartGenerator(this).generateToMarkdownFile(Path.of(OUTPUT_BASEDIR, baseFileName + ".md")); } - new RbacViewMermaidFlowchartGenerator(this).generateToMarkdownFile(Path.of(OUTPUT_BASEDIR, baseFileName + ".md")); new RbacViewPostgresGenerator(this).generateToChangeLog(Path.of(OUTPUT_BASEDIR, baseFileName + ".sql")); } @@ -541,7 +540,9 @@ public class RbacView { case ROLE_TO_ROLE -> superRoleDef + arrow + subRoleDef; case PERM_TO_ROLE -> superRoleDef + arrow + permDef; }; - final var condition = isConditional() ? (" " +forCases.stream().map(CaseDef::toString).collect(Collectors.joining("||"))) : ""; + final var condition = isConditional() + ? (" (" +forCases.stream().map(CaseDef::toString).collect(Collectors.joining("||")) + ")") + : ""; return grant + condition; } @@ -595,14 +596,19 @@ public class RbacView { return forCases != null && !forCases.isEmpty() && forCases.size() c.isCase(requestedCase)); + return noCasesDefined || generateForAllCases || isGrantedForRequestedCase; } boolean matchesCase(final CaseDef requestedCase) { final var noCasesDefined = forCases.isEmpty(); final var generateForAllCases = requestedCase == null; - final var isGrantedOnlyForDefaultCase = forCases.size() == 1 && forCases.iterator().next() == null; // FIXME: needed? final boolean isGrantedForRequestedCase = forCases.contains(requestedCase); return noCasesDefined || generateForAllCases || isGrantedForRequestedCase; } @@ -1171,6 +1177,10 @@ public class RbacView { ? "inOtherCases" : "inCaseOf:" + val; } + + public boolean isCase(final ColumnValue requestedCase) { + return Objects.equals(requestedCase.value, this.val); + } } private static void generateRbacView(final Class c) { diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java index e4dedc25..1f615ef3 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java @@ -1,7 +1,7 @@ package net.hostsharing.hsadminng.rbac.rbacdef; import lombok.SneakyThrows; -import net.hostsharing.hsadminng.rbac.rbacdef.ConditionGenerator.CaseDef; +import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.CaseDef; import org.apache.commons.lang3.StringUtils; import java.nio.file.*; @@ -107,7 +107,7 @@ public class RbacViewMermaidFlowchartGenerator { private void renderGrants(final RbacView.RbacGrantDefinition.GrantType grantType, final String comment) { final var grantsOfRequestedType = rbacDef.getGrantDefs().stream() .filter(g -> g.grantType() == grantType) - .filter(g -> g.matchesCase(forCase)) + .filter(this::isToBeRenderedInThisGraph) .toList(); if ( !grantsOfRequestedType.isEmpty()) { flowchart.ensureSingleEmptyLine(); @@ -116,10 +116,19 @@ public class RbacViewMermaidFlowchartGenerator { } } + private boolean isToBeRenderedInThisGraph(final RbacView.RbacGrantDefinition g) { + if ( g.grantType() != ROLE_TO_ROLE ) + return true; + if ( forCase == null && !g.isConditional() ) + return true; + final var isToBeRenderedInThisGraph = g.getForCases() == null || g.getForCases().contains(forCase); + return isToBeRenderedInThisGraph; + } + private String grantDef(final RbacView.RbacGrantDefinition grant) { final var arrow = (grant.isToCreate() ? " ==>" : " -.->") + (grant.isAssumed() ? " " : "|XX| "); - return switch (grant.grantType()) { + final var grantDef = switch (grant.grantType()) { case ROLE_TO_USER -> // TODO: other user types not implemented yet "user:creator" + arrow + roleId(grant.getSubRoleDef()); @@ -127,6 +136,7 @@ public class RbacViewMermaidFlowchartGenerator { roleId(grant.getSuperRoleDef()) + arrow + roleId(grant.getSubRoleDef()); case PERM_TO_ROLE -> roleId(grant.getSuperRoleDef()) + arrow + permId(grant.getPermDef()); }; + return grantDef; } private String permDef(final RbacView.RbacPermissionDefinition perm) { @@ -155,16 +165,16 @@ public class RbacViewMermaidFlowchartGenerator { Files.writeString( path, """ - ### rbac %{entityAlias} - - This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually. - - ```mermaid - %{flowchart} - ``` - """ - .replace("%{entityAlias}", rbacDef.getRootEntityAlias().aliasName()) - .replace("%{flowchart}", flowchart.toString()), + ### rbac %{entityAlias} + + This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually. + + ```mermaid + %{flowchart} + ``` + """ + .replace("%{entityAlias}", rbacDef.getRootEntityAlias().aliasName()) + .replace("%{flowchart}", flowchart.toString()), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); System.out.println("Markdown-File: " + path.toAbsolutePath()); } diff --git a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac-DEBITOR.md b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac-DEBITOR.md deleted file mode 100644 index f3ffabdf..00000000 --- a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac-DEBITOR.md +++ /dev/null @@ -1,91 +0,0 @@ -### rbac relation - -This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually. - -```mermaid -%%{init:{'flowchart':{'htmlLabels':false}}}%% -flowchart TB - -subgraph holderPerson["`**holderPerson**`"] - direction TB - style holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph holderPerson:roles[ ] - style holderPerson:roles fill:#99bcdb,stroke:white - - role:holderPerson:OWNER[[holderPerson:OWNER]] - role:holderPerson:ADMIN[[holderPerson:ADMIN]] - role:holderPerson:REFERRER[[holderPerson:REFERRER]] - end -end - -subgraph anchorPerson["`**anchorPerson**`"] - direction TB - style anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph anchorPerson:roles[ ] - style anchorPerson:roles fill:#99bcdb,stroke:white - - role:anchorPerson:OWNER[[anchorPerson:OWNER]] - role:anchorPerson:ADMIN[[anchorPerson:ADMIN]] - role:anchorPerson:REFERRER[[anchorPerson:REFERRER]] - end -end - -subgraph contact["`**contact**`"] - direction TB - style contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px - - subgraph contact:roles[ ] - style contact:roles fill:#99bcdb,stroke:white - - role:contact:OWNER[[contact:OWNER]] - role:contact:ADMIN[[contact:ADMIN]] - role:contact:REFERRER[[contact:REFERRER]] - end -end - -subgraph relation["`**relation**`"] - direction TB - style relation fill:#dd4901,stroke:#274d6e,stroke-width:8px - - subgraph relation:roles[ ] - style relation:roles fill:#dd4901,stroke:white - - role:relation:OWNER[[relation:OWNER]] - role:relation:ADMIN[[relation:ADMIN]] - role:relation:AGENT[[relation:AGENT]] - role:relation:TENANT[[relation:TENANT]] - end - - subgraph relation:permissions[ ] - style relation:permissions fill:#dd4901,stroke:white - - perm:relation:DELETE{{relation:DELETE}} - perm:relation:UPDATE{{relation:UPDATE}} - perm:relation:SELECT{{relation:SELECT}} - perm:relation:INSERT{{relation:INSERT}} - end -end - -%% granting roles to users -user:creator ==> role:relation:OWNER - -%% granting roles to roles -role:global:ADMIN -.-> role:anchorPerson:OWNER -role:anchorPerson:OWNER -.-> role:anchorPerson:ADMIN -role:anchorPerson:ADMIN -.-> role:anchorPerson:REFERRER -role:global:ADMIN -.-> role:holderPerson:OWNER -role:holderPerson:OWNER -.-> role:holderPerson:ADMIN -role:holderPerson:ADMIN -.-> role:holderPerson:REFERRER -role:global:ADMIN -.-> role:contact:OWNER -role:contact:OWNER -.-> role:contact:ADMIN -role:contact:ADMIN -.-> role:contact:REFERRER - -%% granting permissions to roles -role:relation:OWNER ==> perm:relation:DELETE -role:relation:ADMIN ==> perm:relation:UPDATE -role:relation:TENANT ==> perm:relation:SELECT -role:anchorPerson:ADMIN ==> perm:relation:INSERT - -``` diff --git a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac-REPRESENTATIVE.md b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac-REPRESENTATIVE.md index 067355a8..91a991a1 100644 --- a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac-REPRESENTATIVE.md +++ b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac-REPRESENTATIVE.md @@ -88,7 +88,6 @@ role:relation:ADMIN ==> role:anchorPerson:OWNER role:relation:ADMIN ==> role:relation:AGENT role:anchorPerson:ADMIN ==> role:relation:AGENT role:relation:AGENT ==> role:relation:TENANT -role:holderPerson:ADMIN ==> role:relation:TENANT role:contact:ADMIN ==> role:relation:TENANT role:relation:TENANT ==> role:anchorPerson:REFERRER role:relation:TENANT ==> role:holderPerson:REFERRER diff --git a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md index b598df88..d1efd785 100644 --- a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md +++ b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md @@ -82,18 +82,14 @@ role:global:ADMIN -.-> role:contact:OWNER role:contact:OWNER -.-> role:contact:ADMIN role:contact:ADMIN -.-> role:contact:REFERRER role:global:ADMIN ==> role:relation:OWNER -role:holderPerson:ADMIN ==> role:relation:OWNER role:relation:OWNER ==> role:relation:ADMIN -role:relation:ADMIN ==> role:anchorPerson:OWNER role:relation:ADMIN ==> role:relation:AGENT -role:anchorPerson:ADMIN ==> role:relation:AGENT role:relation:AGENT ==> role:relation:TENANT -role:holderPerson:ADMIN ==> role:relation:TENANT role:contact:ADMIN ==> role:relation:TENANT role:relation:TENANT ==> role:anchorPerson:REFERRER role:relation:TENANT ==> role:holderPerson:REFERRER role:relation:TENANT ==> role:contact:REFERRER -role:anchorPerson:ADMIN ==> role:relation:ADMIN +role:anchorPerson:ADMIN ==> role:relation:OWNER role:holderPerson:ADMIN ==> role:relation:AGENT %% granting permissions to roles diff --git a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql index 75adaeb4..15114d03 100644 --- a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql +++ b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql @@ -70,7 +70,6 @@ begin permissions => array['SELECT'], incomingSuperRoles => array[ hsOfficeContactADMIN(newContact), - hsOfficePersonADMIN(newHolderPerson), hsOfficeRelationAGENT(NEW)], outgoingSubRoles => array[ hsOfficeContactREFERRER(newContact), @@ -83,8 +82,8 @@ begin call grantRoleToRole(hsOfficeRelationAGENT(NEW), hsOfficePersonADMIN(newAnchorPerson)); call grantRoleToRole(hsOfficeRelationOWNER(NEW), hsOfficePersonADMIN(newHolderPerson)); ELSE - call grantRoleToRole(hsOfficeRelationADMIN(NEW), hsOfficePersonADMIN(newAnchorPerson)); call grantRoleToRole(hsOfficeRelationAGENT(NEW), hsOfficePersonADMIN(newHolderPerson)); + call grantRoleToRole(hsOfficeRelationOWNER(NEW), hsOfficePersonADMIN(newAnchorPerson)); END IF; call leaveTriggerForObjectUuid(NEW.uuid); diff --git a/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.md b/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.md index a0caa074..3522b5a3 100644 --- a/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.md +++ b/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.md @@ -98,22 +98,21 @@ role:partnerRel.contact:OWNER -.-> role:partnerRel.contact:ADMIN role:partnerRel.contact:ADMIN -.-> role:partnerRel.contact:REFERRER role:global:ADMIN -.-> role:partnerRel:OWNER role:partnerRel:OWNER -.-> role:partnerRel:ADMIN -role:partnerRel.anchorPerson:ADMIN -.-> role:partnerRel:ADMIN role:partnerRel:ADMIN -.-> role:partnerRel:AGENT -role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:AGENT role:partnerRel:AGENT -.-> role:partnerRel:TENANT -role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:TENANT 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.anchorPerson:ADMIN -.-> role:partnerRel:OWNER +role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:AGENT %% granting permissions to roles role:global:ADMIN ==> perm:partner:INSERT -role:partnerRel:ADMIN ==> perm:partner:DELETE -role:partnerRel:AGENT ==> perm:partner:UPDATE +role:partnerRel:OWNER ==> perm:partner:DELETE +role:partnerRel:ADMIN ==> perm:partner:UPDATE role:partnerRel:TENANT ==> perm:partner:SELECT -role:partnerRel:ADMIN ==> perm:partnerDetails:DELETE +role:partnerRel:OWNER ==> perm:partnerDetails:DELETE role:partnerRel:AGENT ==> perm:partnerDetails:UPDATE role:partnerRel:AGENT ==> perm:partnerDetails:SELECT diff --git a/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.sql b/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.sql index b5510d8c..7d263dbd 100644 --- a/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.sql +++ b/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.sql @@ -42,10 +42,10 @@ begin SELECT * FROM hs_office_partner_details WHERE uuid = NEW.detailsUuid INTO newPartnerDetails; assert newPartnerDetails.uuid is not null, format('newPartnerDetails must not be null for NEW.detailsUuid = %s', NEW.detailsUuid); - call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationADMIN(newPartnerRel)); + call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationOWNER(newPartnerRel)); call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationTENANT(newPartnerRel)); - call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationAGENT(newPartnerRel)); - call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'DELETE'), hsOfficeRelationADMIN(newPartnerRel)); + call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationADMIN(newPartnerRel)); + call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'DELETE'), hsOfficeRelationOWNER(newPartnerRel)); call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'SELECT'), hsOfficeRelationAGENT(newPartnerRel)); call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationAGENT(newPartnerRel)); @@ -110,17 +110,17 @@ begin if NEW.partnerRelUuid <> OLD.partnerRelUuid then - call revokePermissionFromRole(getPermissionId(OLD.uuid, 'DELETE'), hsOfficeRelationADMIN(oldPartnerRel)); - call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationADMIN(newPartnerRel)); + call revokePermissionFromRole(getPermissionId(OLD.uuid, 'DELETE'), hsOfficeRelationOWNER(oldPartnerRel)); + call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationOWNER(newPartnerRel)); - call revokePermissionFromRole(getPermissionId(OLD.uuid, 'UPDATE'), hsOfficeRelationAGENT(oldPartnerRel)); - call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationAGENT(newPartnerRel)); + call revokePermissionFromRole(getPermissionId(OLD.uuid, 'UPDATE'), hsOfficeRelationADMIN(oldPartnerRel)); + call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationADMIN(newPartnerRel)); call revokePermissionFromRole(getPermissionId(OLD.uuid, 'SELECT'), hsOfficeRelationTENANT(oldPartnerRel)); call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationTENANT(newPartnerRel)); - call revokePermissionFromRole(getPermissionId(oldPartnerDetails.uuid, 'DELETE'), hsOfficeRelationADMIN(oldPartnerRel)); - call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'DELETE'), hsOfficeRelationADMIN(newPartnerRel)); + call revokePermissionFromRole(getPermissionId(oldPartnerDetails.uuid, 'DELETE'), hsOfficeRelationOWNER(oldPartnerRel)); + call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'DELETE'), hsOfficeRelationOWNER(newPartnerRel)); call revokePermissionFromRole(getPermissionId(oldPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationAGENT(oldPartnerRel)); call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationAGENT(newPartnerRel)); diff --git a/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.md b/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.md index 5c43e03d..d6e546cf 100644 --- a/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.md +++ b/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.md @@ -149,17 +149,6 @@ role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel.holderPerson:REFERRER role:global:ADMIN -.-> role:debitorRel.contact:OWNER role:debitorRel.contact:OWNER -.-> role:debitorRel.contact:ADMIN role:debitorRel.contact:ADMIN -.-> role:debitorRel.contact:REFERRER -role:global:ADMIN -.-> role:debitorRel:OWNER -role:debitorRel:OWNER -.-> role:debitorRel:ADMIN -role:debitorRel.anchorPerson:ADMIN -.-> role:debitorRel:ADMIN -role:debitorRel:ADMIN -.-> role:debitorRel:AGENT -role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:AGENT -role:debitorRel:AGENT -.-> role:debitorRel:TENANT -role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:TENANT -role:debitorRel.contact:ADMIN -.-> role:debitorRel:TENANT -role:debitorRel:TENANT -.-> role:debitorRel.anchorPerson:REFERRER -role:debitorRel:TENANT -.-> role:debitorRel.holderPerson:REFERRER -role:debitorRel:TENANT -.-> role:debitorRel.contact:REFERRER role:global:ADMIN -.-> role:refundBankAccount:OWNER role:refundBankAccount:OWNER -.-> role:refundBankAccount:ADMIN role:refundBankAccount:ADMIN -.-> role:refundBankAccount:REFERRER @@ -176,15 +165,14 @@ role:partnerRel.contact:OWNER -.-> role:partnerRel.contact:ADMIN role:partnerRel.contact:ADMIN -.-> role:partnerRel.contact:REFERRER role:global:ADMIN -.-> role:partnerRel:OWNER role:partnerRel:OWNER -.-> role:partnerRel:ADMIN -role:partnerRel.anchorPerson:ADMIN -.-> role:partnerRel:ADMIN role:partnerRel:ADMIN -.-> role:partnerRel:AGENT -role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:AGENT role:partnerRel:AGENT -.-> role:partnerRel:TENANT -role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:TENANT 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.anchorPerson:ADMIN -.-> role:partnerRel:OWNER +role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:AGENT role:partnerRel:ADMIN ==> role:debitorRel:ADMIN role:partnerRel:AGENT ==> role:debitorRel:AGENT role:debitorRel:AGENT ==> role:partnerRel:TENANT diff --git a/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.md b/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.md index aa3059f9..e3528f7f 100644 --- a/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.md +++ b/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.md @@ -110,15 +110,14 @@ role:debitorRel.contact:OWNER -.-> role:debitorRel.contact:ADMIN role:debitorRel.contact:ADMIN -.-> role:debitorRel.contact:REFERRER role:global:ADMIN -.-> role:debitorRel:OWNER role:debitorRel:OWNER -.-> role:debitorRel:ADMIN -role:debitorRel.anchorPerson:ADMIN -.-> role:debitorRel:ADMIN role:debitorRel:ADMIN -.-> role:debitorRel:AGENT -role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:AGENT role:debitorRel:AGENT -.-> role:debitorRel:TENANT -role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:TENANT role:debitorRel.contact:ADMIN -.-> role:debitorRel:TENANT role:debitorRel:TENANT -.-> role:debitorRel.anchorPerson:REFERRER role:debitorRel:TENANT -.-> role:debitorRel.holderPerson:REFERRER role:debitorRel:TENANT -.-> role:debitorRel.contact:REFERRER +role:debitorRel.anchorPerson:ADMIN -.-> role:debitorRel:OWNER +role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:AGENT role:global:ADMIN -.-> role:bankAccount:OWNER role:bankAccount:OWNER -.-> role:bankAccount:ADMIN role:bankAccount:ADMIN -.-> role:bankAccount:REFERRER 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 3681b8e6..9e5752b8 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 @@ -96,15 +96,14 @@ role:partnerRel.contact:OWNER -.-> role:partnerRel.contact:ADMIN role:partnerRel.contact:ADMIN -.-> role:partnerRel.contact:REFERRER role:global:ADMIN -.-> role:partnerRel:OWNER role:partnerRel:OWNER -.-> role:partnerRel:ADMIN -role:partnerRel.anchorPerson:ADMIN -.-> role:partnerRel:ADMIN role:partnerRel:ADMIN -.-> role:partnerRel:AGENT -role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:AGENT role:partnerRel:AGENT -.-> role:partnerRel:TENANT -role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:TENANT 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.anchorPerson:ADMIN -.-> role:partnerRel:OWNER +role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:AGENT role:membership:OWNER ==> role:membership:ADMIN role:partnerRel:ADMIN ==> role:membership:ADMIN role:membership:ADMIN ==> role:membership:AGENT 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 26ff3d5c..b38ad4a0 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 @@ -97,15 +97,14 @@ role:membership.partnerRel.contact:OWNER -.-> role:membership.partnerRel.contact role:membership.partnerRel.contact:ADMIN -.-> role:membership.partnerRel.contact:REFERRER role:global:ADMIN -.-> role:membership.partnerRel:OWNER role:membership.partnerRel:OWNER -.-> role:membership.partnerRel:ADMIN -role:membership.partnerRel.anchorPerson:ADMIN -.-> role:membership.partnerRel:ADMIN role:membership.partnerRel:ADMIN -.-> role:membership.partnerRel:AGENT -role:membership.partnerRel.holderPerson:ADMIN -.-> role:membership.partnerRel:AGENT role:membership.partnerRel:AGENT -.-> role:membership.partnerRel:TENANT -role:membership.partnerRel.holderPerson:ADMIN -.-> role:membership.partnerRel:TENANT 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.anchorPerson:ADMIN -.-> role:membership.partnerRel:OWNER +role:membership.partnerRel.holderPerson:ADMIN -.-> role:membership.partnerRel:AGENT role:membership:OWNER -.-> role:membership:ADMIN role:membership.partnerRel:ADMIN -.-> role:membership:ADMIN role:membership:ADMIN -.-> role:membership:AGENT 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 d220a38c..77de3dc2 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 @@ -97,15 +97,14 @@ role:membership.partnerRel.contact:OWNER -.-> role:membership.partnerRel.contact role:membership.partnerRel.contact:ADMIN -.-> role:membership.partnerRel.contact:REFERRER role:global:ADMIN -.-> role:membership.partnerRel:OWNER role:membership.partnerRel:OWNER -.-> role:membership.partnerRel:ADMIN -role:membership.partnerRel.anchorPerson:ADMIN -.-> role:membership.partnerRel:ADMIN role:membership.partnerRel:ADMIN -.-> role:membership.partnerRel:AGENT -role:membership.partnerRel.holderPerson:ADMIN -.-> role:membership.partnerRel:AGENT role:membership.partnerRel:AGENT -.-> role:membership.partnerRel:TENANT -role:membership.partnerRel.holderPerson:ADMIN -.-> role:membership.partnerRel:TENANT 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.anchorPerson:ADMIN -.-> role:membership.partnerRel:OWNER +role:membership.partnerRel.holderPerson:ADMIN -.-> role:membership.partnerRel:AGENT role:membership:OWNER -.-> role:membership:ADMIN role:membership.partnerRel:ADMIN -.-> role:membership:ADMIN role:membership:ADMIN -.-> role:membership:AGENT -- 2.39.5 From a840f910bb80f55f9b1a3fe4f585fcb44a27b0c2 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Fri, 5 Apr 2024 14:49:32 +0200 Subject: [PATCH 21/29] add condition case to generated Markdown headline --- .../rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java | 5 +++-- .../5033-hs-office-relation-rbac-REPRESENTATIVE.md | 2 +- .../5-hs-office/503-relation/5033-hs-office-relation-rbac.md | 2 +- .../5-hs-office/504-partner/5043-hs-office-partner-rbac.md | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java index 1f615ef3..089f27ae 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java @@ -165,7 +165,7 @@ public class RbacViewMermaidFlowchartGenerator { Files.writeString( path, """ - ### rbac %{entityAlias} + ### rbac %{entityAlias} %{case} This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually. @@ -174,7 +174,8 @@ public class RbacViewMermaidFlowchartGenerator { ``` """ .replace("%{entityAlias}", rbacDef.getRootEntityAlias().aliasName()) - .replace("%{flowchart}", flowchart.toString()), + .replace("%{flowchart}", flowchart.toString()) + .replace("%{case}", forCase == null ? "" : (forCase.toString()) ), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); System.out.println("Markdown-File: " + path.toAbsolutePath()); } diff --git a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac-REPRESENTATIVE.md b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac-REPRESENTATIVE.md index 91a991a1..e5f608e8 100644 --- a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac-REPRESENTATIVE.md +++ b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac-REPRESENTATIVE.md @@ -1,4 +1,4 @@ -### rbac relation +### rbac relation inCaseOf:REPRESENTATIVE This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually. diff --git a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md index d1efd785..4ff19e79 100644 --- a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md +++ b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md @@ -1,4 +1,4 @@ -### rbac relation +### rbac relation inOtherCases This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually. diff --git a/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.md b/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.md index 3522b5a3..a8ff3960 100644 --- a/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.md +++ b/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.md @@ -1,4 +1,4 @@ -### rbac partner +### rbac partner This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually. -- 2.39.5 From cbd8c3e4ff1c85bab315e697515447a352c2429b Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Fri, 5 Apr 2024 18:22:52 +0200 Subject: [PATCH 22/29] amends tests according to changed rbac structure and some fixes, ImportOfficeData not yet working --- .../changelog/1-rbac/1051-rbac-user-grant.sql | 11 ++-- .../1-rbac/1057-rbac-role-builder.sql | 3 +- ...fficeDebitorRepositoryIntegrationTest.java | 3 +- .../hs/office/migration/ImportOfficeData.java | 43 ++++++------- ...fficePartnerRepositoryIntegrationTest.java | 62 +++++++++---------- ...ficeRelationRepositoryIntegrationTest.java | 16 ++--- 6 files changed, 65 insertions(+), 73 deletions(-) diff --git a/src/main/resources/db/changelog/1-rbac/1051-rbac-user-grant.sql b/src/main/resources/db/changelog/1-rbac/1051-rbac-user-grant.sql index a82865c8..17645ca3 100644 --- a/src/main/resources/db/changelog/1-rbac/1051-rbac-user-grant.sql +++ b/src/main/resources/db/changelog/1-rbac/1051-rbac-user-grant.sql @@ -20,19 +20,18 @@ begin return currentSubjectsUuids[1]; end; $$; -create or replace procedure grantRoleToUserUnchecked(grantedByRoleUuid uuid, roleUuid uuid, userUuid uuid, doAssume boolean = true) +create or replace procedure grantRoleToUserUnchecked(grantedByRoleUuid uuid, grantedRoleUuid uuid, userUuid uuid, doAssume boolean = true) language plpgsql as $$ begin perform assertReferenceType('grantingRoleUuid', grantedByRoleUuid, 'RbacRole'); - perform assertReferenceType('roleId (descendant)', roleUuid, 'RbacRole'); + perform assertReferenceType('roleId (descendant)', grantedRoleUuid, 'RbacRole'); perform assertReferenceType('userId (ascendant)', userUuid, 'RbacUser'); insert into RbacGrants (grantedByRoleUuid, ascendantUuid, descendantUuid, assumed) - values (grantedByRoleUuid, userUuid, roleUuid, doAssume); - -- TODO.spec: What should happen on multiple grants? What if options (doAssume) are not the same? - -- Most powerful or latest grant wins? What about managed? - -- on conflict do nothing; -- allow granting multiple times + values (grantedByRoleUuid, userUuid, grantedRoleUuid, doAssume) + -- TODO: check if grantedByRoleUuid+doAssume are the same, otherwise raise exception? + on conflict do nothing; -- allow granting multiple times end; $$; create or replace procedure grantRoleToUser(grantedByRoleUuid uuid, grantedRoleUuid uuid, userUuid uuid, doAssume boolean = true) diff --git a/src/main/resources/db/changelog/1-rbac/1057-rbac-role-builder.sql b/src/main/resources/db/changelog/1-rbac/1057-rbac-role-builder.sql index 57ba3cb7..1e9bd2bc 100644 --- a/src/main/resources/db/changelog/1-rbac/1057-rbac-role-builder.sql +++ b/src/main/resources/db/changelog/1-rbac/1057-rbac-role-builder.sql @@ -6,6 +6,7 @@ --changeset rbac-role-builder-create-role:1 endDelimiter:--// -- ----------------------------------------------------------------- +-- TODO: rename to defineRoleWithGrants because it does not complain if the role already exists create or replace function createRoleWithGrants( roleDescriptor RbacRoleDescriptor, permissions RbacOp[] = array[]::RbacOp[], @@ -28,7 +29,7 @@ declare userUuid uuid; userGrantsByRoleUuid uuid; begin - roleUuid := createRole(roleDescriptor); + roleUuid := coalesce(findRoleId(roleDescriptor), createRole(roleDescriptor)); foreach permission in array permissions loop diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java index 32f441af..3a4d4e16 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java @@ -186,13 +186,13 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean "{ grant perm:debitor#D-1000122:DELETE to role:relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER by system and assume }", "{ grant perm:relation#FirstGmbH-with-DEBITOR-FourtheG:DELETE to role:relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER by system and assume }", "{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER to role:global#global:ADMIN by system and assume }", + "{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER to role:person#FirstGmbH:ADMIN by system and assume }", "{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER to user:superuser-alex@hostsharing.net by relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER and assume }", // admin "{ grant perm:debitor#D-1000122:UPDATE to role:relation#FirstGmbH-with-DEBITOR-FourtheG:ADMIN by system and assume }", "{ grant perm:relation#FirstGmbH-with-DEBITOR-FourtheG:UPDATE to role:relation#FirstGmbH-with-DEBITOR-FourtheG:ADMIN by system and assume }", "{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:ADMIN to role:relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER by system and assume }", - "{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:ADMIN to role:person#FirstGmbH:ADMIN by system and assume }", "{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:ADMIN to role:relation#HostsharingeG-with-PARTNER-FirstGmbH:ADMIN by system and assume }", // agent @@ -208,7 +208,6 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean "{ grant role:person#FirstGmbH:REFERRER to role:relation#FirstGmbH-with-DEBITOR-FourtheG:TENANT by system and assume }", "{ grant role:person#FourtheG:REFERRER to role:relation#FirstGmbH-with-DEBITOR-FourtheG:TENANT by system and assume }", "{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:TENANT to role:contact#fourthcontact:ADMIN by system and assume }", - "{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:TENANT to role:person#FourtheG:ADMIN by system and assume }", "{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:TENANT to role:relation#FirstGmbH-with-DEBITOR-FourtheG:AGENT by system and assume }", null)); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java b/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java index 8da1f12f..14a41b66 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java @@ -292,29 +292,25 @@ public class ImportOfficeData extends ContextBasedTest { { 2000000=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='NP Mellies, Michael', contact='Herr Michael Mellies '), 2000001=rel(anchor='NP Mellies, Michael', type='DEBITOR', holder='NP Mellies, Michael', contact='Herr Michael Mellies '), - 2000002=rel(anchor='NP Mellies, Michael', type='DEBITOR', holder='NP Mellies, Michael', contact='Herr Michael Mellies '), - 2000003=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'), - 2000004=rel(anchor='LP JM GmbH', type='DEBITOR', holder='LP JM GmbH', contact='Frau Dr. Jenny Meyer-Billing , JM GmbH'), - 2000005=rel(anchor='LP JM GmbH', type='DEBITOR', holder='LP JM GmbH', contact='Frau Dr. Jenny Meyer-Billing , JM GmbH'), - 2000006=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='?? Test PS', contact='Petra Schmidt , Test PS'), - 2000007=rel(anchor='?? Test PS', type='DEBITOR', holder='?? Test PS', contact='Petra Schmidt , Test PS'), - 2000008=rel(anchor='?? Test PS', type='DEBITOR', holder='?? Test PS', contact='Petra Schmidt , Test PS'), - 2000009=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='null null, null'), - 2000010=rel(anchor='null null, null', type='DEBITOR'), - 2000011=rel(anchor='null null, null', type='DEBITOR'), - 2000012=rel(anchor='NP Mellies, Michael', type='OPERATIONS', holder='NP Mellies, Michael', contact='Herr Michael Mellies '), - 2000013=rel(anchor='NP Mellies, Michael', type='REPRESENTATIVE', holder='NP Mellies, Michael', contact='Herr Michael Mellies '), - 2000014=rel(anchor='LP JM GmbH', type='EX_PARTNER', holder='LP JM e.K.', contact='JM e.K.'), - 2000015=rel(anchor='LP JM GmbH', type='OPERATIONS', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'), - 2000016=rel(anchor='LP JM GmbH', type='VIP_CONTACT', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'), - 2000017=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='operations-announce', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'), - 2000018=rel(anchor='LP JM GmbH', type='REPRESENTATIVE', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'), - 2000019=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='members-announce', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'), - 2000020=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='customers-announce', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'), - 2000021=rel(anchor='LP JM GmbH', type='VIP_CONTACT', holder='LP JM GmbH', contact='Frau Tammy Meyer-VIP , JM GmbH'), - 2000022=rel(anchor='?? Test PS', type='OPERATIONS', holder='?? Test PS', contact='Petra Schmidt , Test PS'), - 2000023=rel(anchor='?? Test PS', type='REPRESENTATIVE', holder='?? Test PS', contact='Petra Schmidt , Test PS'), -2000024=rel(anchor='NP Mellies, Michael', type='SUBSCRIBER', mark='operations-announce', holder='NP Fanninga, Frauke', contact='Frau Frauke Fanninga ') + 2000002=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'), + 2000003=rel(anchor='LP JM GmbH', type='DEBITOR', holder='LP JM GmbH', contact='Frau Dr. Jenny Meyer-Billing , JM GmbH'), + 2000004=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='?? Test PS', contact='Petra Schmidt , Test PS'), + 2000005=rel(anchor='?? Test PS', type='DEBITOR', holder='?? Test PS', contact='Petra Schmidt , Test PS'), + 2000006=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='null null, null'), + 2000007=rel(anchor='null null, null', type='DEBITOR'), + 2000008=rel(anchor='NP Mellies, Michael', type='OPERATIONS', holder='NP Mellies, Michael', contact='Herr Michael Mellies '), + 2000009=rel(anchor='NP Mellies, Michael', type='REPRESENTATIVE', holder='NP Mellies, Michael', contact='Herr Michael Mellies '), + 2000010=rel(anchor='LP JM GmbH', type='EX_PARTNER', holder='LP JM e.K.', contact='JM e.K.'), + 2000011=rel(anchor='LP JM GmbH', type='OPERATIONS', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'), + 2000012=rel(anchor='LP JM GmbH', type='VIP_CONTACT', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'), + 2000013=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='operations-announce', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'), + 2000014=rel(anchor='LP JM GmbH', type='REPRESENTATIVE', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'), + 2000015=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='members-announce', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'), + 2000016=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='customers-announce', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'), + 2000017=rel(anchor='LP JM GmbH', type='VIP_CONTACT', holder='LP JM GmbH', contact='Frau Tammy Meyer-VIP , JM GmbH'), + 2000018=rel(anchor='?? Test PS', type='OPERATIONS', holder='?? Test PS', contact='Petra Schmidt , Test PS'), + 2000019=rel(anchor='?? Test PS', type='REPRESENTATIVE', holder='?? Test PS', contact='Petra Schmidt , Test PS'), + 2000020=rel(anchor='NP Mellies, Michael', type='SUBSCRIBER', mark='operations-announce', holder='NP Fanninga, Frauke', contact='Frau Frauke Fanninga ') } """); } @@ -721,7 +717,6 @@ public class ImportOfficeData extends ContextBasedTest { null, // will be set in contacts import null // will beset in contacts import ); - relations.put(relationId++, debitorRel); final var debitor = HsOfficeDebitorEntity.builder() .debitorNumberSuffix("00") diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepositoryIntegrationTest.java index 98bff812..c1d3fbc3 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepositoryIntegrationTest.java @@ -10,7 +10,6 @@ import net.hostsharing.hsadminng.hs.office.test.ContextBasedTestWithCleanup; import net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantRepository; import net.hostsharing.hsadminng.rbac.rbacrole.RawRbacObjectRepository; import net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleRepository; -import net.hostsharing.test.Array; import net.hostsharing.test.JpaAttempt; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Nested; @@ -25,13 +24,13 @@ import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; import jakarta.servlet.http.HttpServletRequest; import java.util.Arrays; -import java.util.HashSet; import java.util.List; +import java.util.Objects; import static net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantEntity.distinctGrantDisplaysOf; import static net.hostsharing.hsadminng.rbac.rbacrole.RawRbacObjectEntity.objectDisplaysOf; import static net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleEntity.distinctRoleNamesOf; -import static net.hostsharing.test.Array.fromFormatted; +import static net.hostsharing.test.Array.from; import static net.hostsharing.test.JpaAttempt.attempt; import static org.assertj.core.api.Assertions.assertThat; @@ -130,7 +129,7 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean }).assertSuccessful(); // then - assertThat(distinctRoleNamesOf(rawRoleRepo.findAll())).containsExactlyInAnyOrder(Array.from( + assertThat(distinctRoleNamesOf(rawRoleRepo.findAll())).containsExactlyInAnyOrder(from( initialRoleNames, "hs_office_relation#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler:OWNER", "hs_office_relation#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler:ADMIN", @@ -140,44 +139,43 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean .map(s -> s.replace("ErbenBesslerMelBessler", "EBess")) .map(s -> s.replace("fourthcontact", "4th")) .map(s -> s.replace("hs_office_", "")) - .containsExactlyInAnyOrder(distinct(fromFormatted( + .containsExactlyInAnyOrder(distinct(from( initialGrantNames, - "{ grant perm:relation#HostsharingeG-with-PARTNER-EBess:INSERT>sepamandate to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }", + "{ grant perm:relation#HostsharingeG-with-PARTNER-EBess:INSERT>sepamandate to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }", // permissions on partner - "{ grant perm:partner#P-20032:DELETE to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }", - "{ grant perm:partner#P-20032:UPDATE to role:relation#HostsharingeG-with-PARTNER-EBess:AGENT by system and assume }", - "{ grant perm:partner#P-20032:SELECT to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }", + "{ grant perm:partner#P-20032:DELETE to role:relation#HostsharingeG-with-PARTNER-EBess:OWNER by system and assume }", + "{ grant perm:partner#P-20032:UPDATE to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }", + "{ grant perm:partner#P-20032:SELECT to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }", // permissions on partner-details - "{ grant perm:partner_details#P-20032:DELETE to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }", - "{ grant perm:partner_details#P-20032:UPDATE to role:relation#HostsharingeG-with-PARTNER-EBess:AGENT by system and assume }", - "{ grant perm:partner_details#P-20032:SELECT to role:relation#HostsharingeG-with-PARTNER-EBess:AGENT by system and assume }", + "{ grant perm:partner_details#P-20032:DELETE to role:relation#HostsharingeG-with-PARTNER-EBess:OWNER by system and assume }", + "{ grant perm:partner_details#P-20032:UPDATE to role:relation#HostsharingeG-with-PARTNER-EBess:AGENT by system and assume }", + "{ grant perm:partner_details#P-20032:SELECT to role:relation#HostsharingeG-with-PARTNER-EBess:AGENT by system and assume }", // permissions on partner-relation - "{ grant perm:relation#HostsharingeG-with-PARTNER-EBess:DELETE to role:relation#HostsharingeG-with-PARTNER-EBess:OWNER by system and assume }", - "{ grant perm:relation#HostsharingeG-with-PARTNER-EBess:UPDATE to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }", - "{ grant perm:relation#HostsharingeG-with-PARTNER-EBess:SELECT to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }", + "{ grant perm:relation#HostsharingeG-with-PARTNER-EBess:DELETE to role:relation#HostsharingeG-with-PARTNER-EBess:OWNER by system and assume }", + "{ grant perm:relation#HostsharingeG-with-PARTNER-EBess:UPDATE to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }", + "{ grant perm:relation#HostsharingeG-with-PARTNER-EBess:SELECT to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }", // relation owner - "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:OWNER to role:global#global:ADMIN by system and assume }", - "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:OWNER to user:superuser-alex@hostsharing.net by relation#HostsharingeG-with-PARTNER-EBess:OWNER and assume }", + "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:OWNER to role:global#global:ADMIN by system and assume }", + "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:OWNER to user:superuser-alex@hostsharing.net by relation#HostsharingeG-with-PARTNER-EBess:OWNER and assume }", // relation admin - "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN to role:relation#HostsharingeG-with-PARTNER-EBess:OWNER by system and assume }", - "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN to role:person#HostsharingeG:ADMIN by system and assume }", + "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN to role:relation#HostsharingeG-with-PARTNER-EBess:OWNER by system and assume }", + "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:OWNER to role:person#HostsharingeG:ADMIN by system and assume }", // relation agent - "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:AGENT to role:person#EBess:ADMIN by system and assume }", - "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:AGENT to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }", + "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:AGENT to role:person#EBess:ADMIN by system and assume }", + "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:AGENT to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }", // relation tenant - "{ grant role:contact#4th:REFERRER to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }", - "{ grant role:person#EBess:REFERRER to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }", - "{ grant role:person#HostsharingeG:REFERRER to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }", - "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:TENANT to role:contact#4th:ADMIN by system and assume }", - "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:TENANT to role:person#EBess:ADMIN by system and assume }", - "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:TENANT to role:relation#HostsharingeG-with-PARTNER-EBess:AGENT by system and assume }", + "{ grant role:contact#4th:REFERRER to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }", + "{ grant role:person#EBess:REFERRER to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }", + "{ grant role:person#HostsharingeG:REFERRER to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }", + "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:TENANT to role:contact#4th:ADMIN by system and assume }", + "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:TENANT to role:relation#HostsharingeG-with-PARTNER-EBess:AGENT by system and assume }", null))); } @@ -411,9 +409,9 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean public void deletingAPartnerAlsoDeletesRelatedRolesAndGrants() { // given context("superuser-alex@hostsharing.net"); - final var initialObjects = Array.from(objectDisplaysOf(rawObjectRepo.findAll())); - final var initialRoleNames = Array.from(distinctRoleNamesOf(rawRoleRepo.findAll())); - final var initialGrantNames = Array.from(distinctGrantDisplaysOf(rawGrantRepo.findAll())); + final var initialObjects = from(objectDisplaysOf(rawObjectRepo.findAll())); + final var initialRoleNames = from(distinctRoleNamesOf(rawRoleRepo.findAll())); + final var initialGrantNames = from(distinctGrantDisplaysOf(rawGrantRepo.findAll())); final var givenPartner = givenSomeTemporaryHostsharingPartner(20034, "Erben Bessler", "twelfth"); // when @@ -499,8 +497,6 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean private String[] distinct(final String[] strings) { // TODO: alternatively cleanup all rbac objects in @AfterEach? - final var set = new HashSet(); - set.addAll(List.of(strings)); - return set.toArray(new String[0]); + return Arrays.stream(strings).filter(Objects::nonNull).distinct().toList().toArray(new String[0]); } } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java index becc29d9..bc8bfd40 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java @@ -5,6 +5,7 @@ import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository; import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRepository; import net.hostsharing.hsadminng.hs.office.test.ContextBasedTestWithCleanup; import net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantRepository; +import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantsDiagramService; import net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleRepository; import net.hostsharing.test.Array; import net.hostsharing.test.JpaAttempt; @@ -140,9 +141,10 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea "{ grant perm:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:UPDATE to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN by system and assume }", "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:OWNER by system and assume }", - "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN to role:hs_office_person#ErbenBesslerMelBessler:ADMIN by system and assume }", + "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:OWNER to role:hs_office_person#BesslerBert:ADMIN by system and assume }", + "{ grant role:hs_office_person#ErbenBesslerMelBessler:OWNER to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN by system and assume }", - "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:AGENT to role:hs_office_person#BesslerBert:ADMIN by system and assume }", + "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:AGENT to role:hs_office_person#ErbenBesslerMelBessler:ADMIN by system and assume }", "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:AGENT to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN by system and assume }", "{ grant perm:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:SELECT to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:TENANT by system and assume }", @@ -153,8 +155,6 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea // REPRESENTATIVE holder person -> (represented) anchor person "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:TENANT to role:hs_office_contact#fourthcontact:ADMIN by system and assume }", - "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:TENANT to role:hs_office_person#BesslerBert:ADMIN by system and assume }", - null) ); } @@ -249,19 +249,19 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea } @Test - public void holderAdmin_canNotUpdateRelatedRelation() { + public void relationAgent_canSelectButNotUpdateRelatedRelation() { // given context("superuser-alex@hostsharing.net"); final var givenRelation = givenSomeTemporaryRelationBessler( "Anita", "eighth"); assertThatRelationIsVisibleForUserWithRole( givenRelation, - "hs_office_person#BesslerAnita:ADMIN"); + "hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerAnita:AGENT"); assertThatRelationActuallyInDatabase(givenRelation); // when final var result = jpaAttempt.transacted(() -> { - context("superuser-alex@hostsharing.net", "hs_office_person#BesslerAnita:ADMIN"); + context("superuser-alex@hostsharing.net", "hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerAnita:AGENT"); givenRelation.setContact(null); return relationRepo.save(givenRelation); }); @@ -295,6 +295,8 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea } private void assertThatRelationActuallyInDatabase(final HsOfficeRelationEntity saved) { + generateRbacDiagramForCurrentSubjects(RbacGrantsDiagramService.Include.ALL_NON_TEST_ENTITY_RELATED); + generateRbacDiagramForObjectPermission(saved.getUuid(), "SELECT", "relation-select"); final var found = relationRepo.findByUuid(saved.getUuid()); assertThat(found).isNotEmpty().get().isNotSameAs(saved).usingRecursiveComparison().isEqualTo(saved); } -- 2.39.5 From 7559b8ced3f4570a0042df31d996443afb648162 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Sun, 7 Apr 2024 12:26:13 +0200 Subject: [PATCH 23/29] ignore self-representative relation in ImportOfficeData --- .../db/changelog/1-rbac/1050-rbac-base.sql | 24 -------------- .../hs/office/migration/ImportOfficeData.java | 32 +++++++++++++++---- 2 files changed, 26 insertions(+), 30 deletions(-) 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..2b3147c9 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 @@ -659,30 +659,6 @@ begin on conflict do nothing; -- allow granting multiple times end; $$; -create or replace procedure grantRoleToRoleIfNotNull(subRole RbacRoleDescriptor, superRole RbacRoleDescriptor, doAssume bool = true) - language plpgsql as $$ -declare - superRoleId uuid; - subRoleId uuid; -begin - if ( superRoleId is null ) then return; end if; - superRoleId := findRoleId(superRole); - if ( subRoleId is null ) then return; end if; - subRoleId := findRoleId(subRole); - - perform assertReferenceType('superRoleId (ascendant)', superRoleId, 'RbacRole'); - perform assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole'); - - if isGranted(subRoleId, superRoleId) then - call raiseDuplicateRoleGrantException(subRoleId, superRoleId); - end if; - - insert - into RbacGrants (grantedByTriggerOf, ascendantuuid, descendantUuid, assumed) - values (currentTriggerObjectUuid(), superRoleId, subRoleId, doAssume) - on conflict do nothing; -- allow granting multiple times -end; $$; - create or replace procedure revokeRoleFromRole(subRole RbacRoleDescriptor, superRole RbacRoleDescriptor) language plpgsql as $$ declare diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java b/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java index 14a41b66..7cbb0473 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java @@ -421,14 +421,33 @@ public class ImportOfficeData extends ContextBasedTest { } @Test - @Order(2009) + @Order(3001) + void removeSelfRepresentativeRelations() { + assumeThatWeAreImportingControlledTestData(); + + // this happens if a natural person is marked as 'contractual' for itself + final var idsToRemove = new HashSet(); + relations.forEach( (id, r) -> { + if (r.getHolder() == r.getAnchor() ) { + idsToRemove.add(id); + } + }); + + // remove self-representatives + idsToRemove.forEach(id -> { + System.out.println("removing self representative relation: " + relations.get(id).toString()); + relations.remove(id); + }); + } + + @Test + @Order(3002) void removeEmptyRelations() { assumeThatWeAreImportingControlledTestData(); // avoid a error when persisting the deliberately invalid partner entry #99 final var idsToRemove = new HashSet(); relations.forEach( (id, r) -> { - // such a record if (r.getContact() == null || r.getContact().getLabel() == null || r.getHolder() == null || r.getHolder().getPersonType() == null ) { idsToRemove.add(id); @@ -443,7 +462,7 @@ public class ImportOfficeData extends ContextBasedTest { } @Test - @Order(2002) + @Order(3003) void removeEmptyPartners() { assumeThatWeAreImportingControlledTestData(); @@ -467,7 +486,7 @@ public class ImportOfficeData extends ContextBasedTest { } @Test - @Order(2003) + @Order(3004) void removeEmptyDebitors() { assumeThatWeAreImportingControlledTestData(); @@ -486,7 +505,7 @@ public class ImportOfficeData extends ContextBasedTest { } @Test - @Order(3000) + @Order(9000) @Commit void persistEntities() { @@ -512,6 +531,7 @@ public class ImportOfficeData extends ContextBasedTest { relations.forEach(this::persist); }).assertSuccessful(); + System.out.println("persisting " + partners.size() + " partners"); jpaAttempt.transacted(() -> { context(rbacSuperuser); partners.forEach((id, partner) -> { @@ -529,7 +549,7 @@ public class ImportOfficeData extends ContextBasedTest { context(rbacSuperuser); debitors.forEach((id, debitor) -> { debitor.setDebitorRel(em.merge(debitor.getDebitorRel())); - em.persist(debitor); + persist(id, debitor); }); }).assertSuccessful(); -- 2.39.5 From f1bbc85ec62d53c57583997a8734daab91d28865 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Sun, 7 Apr 2024 12:37:44 +0200 Subject: [PATCH 24/29] amendmends after self-review --- .../office/debitor/HsOfficeDebitorEntity.java | 19 +++++++++++++++---- .../hsadminng/rbac/rbacdef/RbacView.java | 4 ++-- .../RolesGrantsAndPermissionsGenerator.java | 5 ----- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java index 8b48e221..509cb165 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java @@ -1,6 +1,10 @@ package net.hostsharing.hsadminng.hs.office.debitor; -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.bankaccount.HsOfficeBankAccountEntity; import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity; @@ -15,7 +19,13 @@ import org.hibernate.annotations.JoinFormula; import org.hibernate.annotations.NotFound; import org.hibernate.annotations.NotFoundAction; -import jakarta.persistence.*; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; import jakarta.validation.constraints.Pattern; import java.io.IOException; import java.util.UUID; @@ -26,7 +36,7 @@ import static jakarta.persistence.CascadeType.PERSIST; import static jakarta.persistence.CascadeType.REFRESH; import static java.util.Optional.ofNullable; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Column.dependsOnColumn; -import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.ColumnValue.usingCase; +import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.ColumnValue.usingDefaultCase; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NOT_NULL; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NULLABLE; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.*; @@ -158,7 +168,8 @@ public class HsOfficeDebitorEntity implements RbacObject, Stringifyable { .toRole("global", ADMIN).grantPermission(INSERT) .importRootEntityAliasProxy("debitorRel", HsOfficeRelationEntity.class, - usingCase("DEBITOR"), + // TODO.spec: do we need a distinct case for DEBITOR-Relation? + usingDefaultCase(), directlyFetchedByDependsOnColumn(), dependsOnColumn("debitorRelUuid")) .createPermission(DELETE).grantedTo("debitorRel", OWNER) diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java index 4e792861..90bddc20 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java @@ -257,7 +257,7 @@ public class RbacView { return permDefs.stream() .filter(p -> p.permission == permission && p.entityAlias == entityAlias) .findFirst() - // .map(g -> g.forCase(processingCase)) TODO: not implemented case dependent + // .map(g -> g.forCase(processingCase)) TODO.impl: not implemented case dependent .orElseGet(() -> new RbacPermissionDefinition(entityAlias, permission, null, true)); } @@ -415,7 +415,6 @@ public class RbacView { this.discriminatorColumName = discriminatorColumName; allCases.addAll(stream(caseDefs).toList()); - // FIXME: currently only the default case is executed stream(caseDefs).forEach(caseDef -> { this.processingCase = caseDef; caseDef.def.accept(this); @@ -1133,6 +1132,7 @@ public class RbacView { } } + // FIXME: subclass of ColumnValue public static class CaseDef { final String val; diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java index 91a312bf..38632e27 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java @@ -331,11 +331,6 @@ class RolesGrantsAndPermissionsGenerator { .replace("${permRef}", createPerm(NEW, grantDef.getPermDef())) .replace("${superRoleRef}", roleRef(NEW, grantDef.getSuperRoleDef())); }; -// if (grantDef.isConditional()) { -// return "if " + grantDef.generateCondition() + " then\n" -// + " " + grantSql + "\n" -// + "end if;"; -// } return grantSql; } -- 2.39.5 From d565099f3b5a69419baf782db4d11154a63545b9 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Sun, 7 Apr 2024 12:47:17 +0200 Subject: [PATCH 25/29] remove unnecessary method, which had no effect anyway --- .../hs/office/migration/ImportOfficeData.java | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java b/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java index 7cbb0473..a763804a 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java @@ -218,23 +218,6 @@ public class ImportOfficeData extends ContextBasedTest { } } - @Test - @Order(1021) - void buildDebitorRelations() { - debitors.forEach( (id, debitor) -> { - final var debitorRel = HsOfficeRelationEntity.builder() - .type(HsOfficeRelationType.DEBITOR) - .anchor(debitor.getPartner().getPartnerRel().getHolder()) - .holder(debitor.getPartner().getPartnerRel().getHolder()) // just 1 debitor/partner in legacy hsadmin - // FIXME .contact() - .build(); - if (debitorRel.getAnchor() != null && debitorRel.getHolder() != null && - debitorRel.getContact() != null ) { - relations.put(relationId++, debitorRel); - } - }); - } - @Test @Order(1029) void verifyContacts() { -- 2.39.5 From 25823342e7478ae224f7255e011b54b940ecc20b Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Sun, 7 Apr 2024 13:13:49 +0200 Subject: [PATCH 26/29] avoid extra space in headline of generated Markdown --- .../rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java index 089f27ae..96a956e5 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java @@ -165,7 +165,7 @@ public class RbacViewMermaidFlowchartGenerator { Files.writeString( path, """ - ### rbac %{entityAlias} %{case} + ### rbac %{entityAlias}%{case} This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually. @@ -175,7 +175,7 @@ public class RbacViewMermaidFlowchartGenerator { """ .replace("%{entityAlias}", rbacDef.getRootEntityAlias().aliasName()) .replace("%{flowchart}", flowchart.toString()) - .replace("%{case}", forCase == null ? "" : (forCase.toString()) ), + .replace("%{case}", forCase == null ? "" : " " + forCase), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); System.out.println("Markdown-File: " + path.toAbsolutePath()); } -- 2.39.5 From 1e6b19c33775ea77293b07709691f042df120bce Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Sun, 7 Apr 2024 13:17:39 +0200 Subject: [PATCH 27/29] re-generate RBAC diagrams --- .../504-partner/5043-hs-office-partner-rbac.md | 2 +- .../506-debitor/5063-hs-office-debitor-rbac.md | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.md b/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.md index a8ff3960..3522b5a3 100644 --- a/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.md +++ b/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.md @@ -1,4 +1,4 @@ -### rbac partner +### rbac partner This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually. diff --git a/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.md b/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.md index d6e546cf..57ce3e73 100644 --- a/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.md +++ b/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.md @@ -149,6 +149,16 @@ role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel.holderPerson:REFERRER role:global:ADMIN -.-> role:debitorRel.contact:OWNER role:debitorRel.contact:OWNER -.-> role:debitorRel.contact:ADMIN role:debitorRel.contact:ADMIN -.-> role:debitorRel.contact:REFERRER +role:global:ADMIN -.-> role:debitorRel:OWNER +role:debitorRel:OWNER -.-> role:debitorRel:ADMIN +role:debitorRel:ADMIN -.-> role:debitorRel:AGENT +role:debitorRel:AGENT -.-> role:debitorRel:TENANT +role:debitorRel.contact:ADMIN -.-> role:debitorRel:TENANT +role:debitorRel:TENANT -.-> role:debitorRel.anchorPerson:REFERRER +role:debitorRel:TENANT -.-> role:debitorRel.holderPerson:REFERRER +role:debitorRel:TENANT -.-> role:debitorRel.contact:REFERRER +role:debitorRel.anchorPerson:ADMIN -.-> role:debitorRel:OWNER +role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:AGENT role:global:ADMIN -.-> role:refundBankAccount:OWNER role:refundBankAccount:OWNER -.-> role:refundBankAccount:ADMIN role:refundBankAccount:ADMIN -.-> role:refundBankAccount:REFERRER -- 2.39.5 From 56f316ef80223e07fbd50075bd6408c2428cb6fd Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Sun, 7 Apr 2024 13:20:44 +0200 Subject: [PATCH 28/29] CaseDef extends ColumnValue --- .../hsadminng/rbac/rbacdef/RbacView.java | 30 ++++++------------- .../RolesGrantsAndPermissionsGenerator.java | 4 +-- 2 files changed, 11 insertions(+), 23 deletions(-) diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java index 90bddc20..d052b958 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java @@ -394,7 +394,7 @@ public class RbacView { }); importedRbacView.getGrantDefs().forEach(grantDef -> { if ( grantDef.grantType() == RbacGrantDefinition.GrantType.ROLE_TO_ROLE && - grantDef.matchesCase(forCase) ) { + (grantDef.forCases == null || grantDef.matchesCase(forCase)) ) { final var importedGrantDef = findOrCreateGrantDef( findRbacRole( mapper.map(grantDef.getSubRoleDef().entityAlias.aliasName), @@ -483,7 +483,7 @@ public class RbacView { public void generateWithBaseFileName(final String baseFileName) { if (allCases.size() > 1) { allCases.forEach(caseDef -> { - final var fileName = baseFileName + (caseDef.isDefaultCase() ? "" : "-" + caseDef.val) + ".md"; + final var fileName = baseFileName + (caseDef.isDefaultCase() ? "" : "-" + caseDef.value) + ".md"; new RbacViewMermaidFlowchartGenerator(this, caseDef) .generateToMarkdownFile(Path.of(OUTPUT_BASEDIR, fileName)); }); @@ -596,22 +596,12 @@ public class RbacView { } boolean matchesCase(final ColumnValue requestedCase) { - if (forCases == null) { - return true; - } final var noCasesDefined = forCases.isEmpty(); final var generateForAllCases = requestedCase == null; final boolean isGrantedForRequestedCase = forCases.stream().anyMatch(c -> c.isCase(requestedCase)); return noCasesDefined || generateForAllCases || isGrantedForRequestedCase; } - boolean matchesCase(final CaseDef requestedCase) { - final var noCasesDefined = forCases.isEmpty(); - final var generateForAllCases = requestedCase == null; - final boolean isGrantedForRequestedCase = forCases.contains(requestedCase); - return noCasesDefined || generateForAllCases || isGrantedForRequestedCase; - } - boolean isToCreate() { return toCreate; } @@ -1132,14 +1122,12 @@ public class RbacView { } } - // FIXME: subclass of ColumnValue - public static class CaseDef { + public static class CaseDef extends ColumnValue { - final String val; final Consumer def; private CaseDef(final String discriminatorColumnValue, final Consumer def) { - this.val = discriminatorColumnValue; + super(discriminatorColumnValue); this.def = def; } @@ -1154,7 +1142,7 @@ public class RbacView { @Override public int hashCode() { - return ofNullable(val).map(String::hashCode).orElse(0); + return ofNullable(value).map(String::hashCode).orElse(0); } @Override @@ -1164,22 +1152,22 @@ public class RbacView { if (other == null || getClass() != other.getClass()) return false; final CaseDef caseDef = (CaseDef) other; - return Objects.equals(val, caseDef.val); + return Objects.equals(value, caseDef.value); } boolean isDefaultCase() { - return val == null; + return value == null; } @Override public String toString() { return isDefaultCase() ? "inOtherCases" - : "inCaseOf:" + val; + : "inCaseOf:" + value; } public boolean isCase(final ColumnValue requestedCase) { - return Objects.equals(requestedCase.value, this.val); + return Objects.equals(requestedCase.value, this.value); } } diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java index 38632e27..2089d4d9 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java @@ -197,8 +197,8 @@ class RolesGrantsAndPermissionsGenerator { plPgSql.writeLn(); final var ifOrElsIf = new AtomicReference<>("IF "); rbacDef.getAllCases().forEach(caseDef -> { - if (caseDef.val != null) { - plPgSql.writeLn(ifOrElsIf + "NEW." + rbacDef.getDiscriminatorColumName() + " = '" + caseDef.val + "' THEN"); + if (caseDef.value != null) { + plPgSql.writeLn(ifOrElsIf + "NEW." + rbacDef.getDiscriminatorColumName() + " = '" + caseDef.value + "' THEN"); } else { plPgSql.writeLn("ELSE"); } -- 2.39.5 From 5051198e00e35d373a42859ef118b5c2cfd6556d Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Mon, 8 Apr 2024 08:38:31 +0200 Subject: [PATCH 29/29] always generate dynacmi RBAC to doc/temp with explicit name --- .../rbac/rbacgrant/RbacGrantsDiagramService.java | 2 +- .../HsOfficeRelationRepositoryIntegrationTest.java | 3 --- .../hs/office/test/ContextBasedTestWithCleanup.java | 8 +++----- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantsDiagramService.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantsDiagramService.java index 0cf30dca..f4dc2167 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantsDiagramService.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantsDiagramService.java @@ -209,7 +209,7 @@ public class RbacGrantsDiagramService { } - class LimitedHashSet extends HashSet { + static class LimitedHashSet extends HashSet { @Override public boolean add(final T t) { diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java index bc8bfd40..77342f0d 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java @@ -5,7 +5,6 @@ import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository; import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRepository; import net.hostsharing.hsadminng.hs.office.test.ContextBasedTestWithCleanup; import net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantRepository; -import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantsDiagramService; import net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleRepository; import net.hostsharing.test.Array; import net.hostsharing.test.JpaAttempt; @@ -295,8 +294,6 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea } private void assertThatRelationActuallyInDatabase(final HsOfficeRelationEntity saved) { - generateRbacDiagramForCurrentSubjects(RbacGrantsDiagramService.Include.ALL_NON_TEST_ENTITY_RELATED); - generateRbacDiagramForObjectPermission(saved.getUuid(), "SELECT", "relation-select"); final var found = relationRepo.findByUuid(saved.getUuid()); assertThat(found).isNotEmpty().get().isNotSameAs(saved).usingRecursiveComparison().isEqualTo(saved); } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/test/ContextBasedTestWithCleanup.java b/src/test/java/net/hostsharing/hsadminng/hs/office/test/ContextBasedTestWithCleanup.java index fc0b81c3..64feda26 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/test/ContextBasedTestWithCleanup.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/test/ContextBasedTestWithCleanup.java @@ -17,7 +17,6 @@ import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.Repository; import jakarta.persistence.*; -import java.lang.reflect.Method; import java.util.*; import static java.lang.System.out; @@ -272,12 +271,11 @@ public abstract class ContextBasedTestWithCleanup extends ContextBasedTest { /** * Generates a diagram of the RBAC-Grants to the current subjects (user or assumed roles). */ - protected void generateRbacDiagramForCurrentSubjects(final EnumSet include) { - final var title = testInfo.getTestMethod().map(Method::getName).orElseThrow(); + protected void generateRbacDiagramForCurrentSubjects(final EnumSet include, final String name) { RbacGrantsDiagramService.writeToFile( - title, + name, diagramService.allGrantsToCurrentUser(include), - "doc/" + title + ".md" + "doc/temp/" + name + ".md" ); } -- 2.39.5