From 59c41a176ec18e1cf367a22751b1ea7d3684691a Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Thu, 28 Mar 2024 15:42:38 +0100 Subject: [PATCH] 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)); }