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 new file mode 100644 index 00000000..4093eb2d --- /dev/null +++ b/src/main/resources/db/changelog/313-hs-office-coopshares-rbac.md @@ -0,0 +1,29 @@ +### hs_office_coopSharesTransaction RBAC + +```mermaid +flowchart TB + +subgraph hsOfficeMembership + 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 +end + +subgraph hsOfficeCoopSharesTransaction + + role:hsOfficeMembership.admin + --> perm:hsOfficeCoopSharesTransaction.create{{coopSharesTx.create}} + + role:hsOfficeMembership.agent + --> perm:hsOfficeCoopSharesTransaction.view{{coopSharesTx.view}} +end + + +``` 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 new file mode 100644 index 00000000..d6afcfc8 --- /dev/null +++ b/src/main/resources/db/changelog/313-hs-office-coopshares-rbac.sql @@ -0,0 +1,124 @@ +--liquibase formatted sql + +-- ============================================================================ +--changeset hs-office-coopSharesTransaction-rbac-OBJECT:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- +call generateRelatedRbacObject('hs_office_coopSharesTransaction'); +--// + + +-- ============================================================================ +--changeset hs-office-coopSharesTransaction-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- +call generateRbacRoleDescriptors('hsOfficeCoopSharesTransaction', 'hs_office_coopSharesTransaction'); +--// + + +-- ============================================================================ +--changeset hs-office-coopSharesTransaction-rbac-ROLES-CREATION:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- + +/* + Creates and updates the permissions for coopSharesTransaction entities. + */ + +create or replace function hsOfficeCoopSharesTransactionRbacRolesTrigger() + returns trigger + language plpgsql + strict as $$ +declare + newHsOfficeMembership hs_office_membership; +begin + + select * from hs_office_membership as p where p.uuid = NEW.membershipUuid into newHsOfficeMembership; + + 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(hsOfficeMembershipTenant(newHsOfficeMembership), 'fail'), + createPermissions(NEW.uuid, array ['view']) + ); + + else + raise exception 'invalid usage of TRIGGER'; + end if; + + 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 + for each row +execute procedure hsOfficeCoopSharesTransactionRbacRolesTrigger(); +--// + + +-- ============================================================================ +--changeset hs-office-coopSharesTransaction-rbac-IDENTITY-VIEW:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- +call generateRbacIdentityView('hs_office_coopSharesTransaction', + idNameExpression => '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. + */ +do language plpgsql $$ + declare + addCustomerPermissions uuid[]; + globalObjectUuid uuid; + globalAdminRoleUuid uuid ; + begin + call defineContext('granting global new-coopSharesTransaction permission to global admin role', null, null, null); + + globalAdminRoleUuid := findRoleId(globalAdmin()); + globalObjectUuid := (select uuid from global); + addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-coopsharestransaction']); + call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions); + end; +$$; + +/** + Used by the trigger to prevent the add-customer to current user respectively assumed roles. + */ +create or replace function addHsOfficeCoopSharesTransactionNotAllowedForCurrentSubjects() + returns trigger + language PLPGSQL +as $$ +begin + raise exception '[403] new-coopsharestransaction not permitted for %', + array_to_string(currentSubjects(), ';', 'null'); +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 + for each row + when ( not hasAssumedRole() ) +execute procedure addHsOfficeCoopSharesTransactionNotAllowedForCurrentSubjects(); +--// + diff --git a/src/main/resources/db/changelog/318-hs-office-coopshares-test-data.sql b/src/main/resources/db/changelog/318-hs-office-coopshares-test-data.sql new file mode 100644 index 00000000..3948272d --- /dev/null +++ b/src/main/resources/db/changelog/318-hs-office-coopshares-test-data.sql @@ -0,0 +1,44 @@ +--liquibase formatted sql + + +-- ============================================================================ +--changeset hs-office-coopSharesTransaction-TEST-DATA-GENERATOR:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- + +/* + Creates a single coopSharesTransaction test record. + */ +create or replace procedure createHsOfficeCoopSharesTransactionTestData(givenMembershipNumber numeric) + language plpgsql as $$ +declare + currentTask varchar; + membership hs_office_membership; +begin + currentTask = 'creating coopSharesTransaction test-data ' || givenMembershipNumber; + execute format('set local hsadminng.currentTask to %L', currentTask); + + call defineContext(currentTask); + select m.uuid from hs_office_membership m where m.memberNumber = givenMembershipNumber into membership; + + raise notice 'creating test coopSharesTransaction: %', givenMembershipNumber; + insert + into hs_office_coopsharestransaction(uuid, membershipuuid, transactiontype, valuedate, sharecount, reference, comment) + values + (uuid_generate_v4(), membership.uuid, 'SUBSCRIPTION', '2010-03-15', 2, 'ref '||givenMembershipNumber||'-1', 'initial subscription'), + (uuid_generate_v4(), membership.uuid, 'SUBSCRIPTION', '2021-09-01', 24, 'ref '||givenMembershipNumber||'-2', 'subsscibing more'), + (uuid_generate_v4(), membership.uuid, 'CANCELLATION', '2022-10-20', 12, 'ref '||givenMembershipNumber||'-3', 'cancelling some'); +end; $$; +--// + + +-- ============================================================================ +--changeset hs-office-coopSharesTransaction-TEST-DATA-GENERATION:1 –context=dev,tc endDelimiter:--// +-- ---------------------------------------------------------------------------- + +do language plpgsql $$ + begin + call createHsOfficeCoopSharesTransactionTestData(10001); + call createHsOfficeCoopSharesTransactionTestData(10002); + call createHsOfficeCoopSharesTransactionTestData(10003); + end; +$$; diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index e0345a10..c082e609 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -99,3 +99,7 @@ databaseChangeLog: file: db/changelog/308-hs-office-membership-test-data.sql - include: file: db/changelog/310-hs-office-coopshares.sql + - include: + file: db/changelog/313-hs-office-coopshares-rbac.sql + - include: + file: db/changelog/318-hs-office-coopshares-test-data.sql