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)); }