From 368da1cc95548fd3bc27c2dbdfbdcd024d84e84b Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Mon, 17 Oct 2022 08:14:09 +0200 Subject: [PATCH] add hs-office-membership RBAC rules (yet without mainDebitor update) --- .../303-hs-office-membership-rbac.md | 71 ++++++++ .../303-hs-office-membership-rbac.sql | 157 ++++++++++++++++++ 2 files changed, 228 insertions(+) create mode 100644 src/main/resources/db/changelog/303-hs-office-membership-rbac.md create mode 100644 src/main/resources/db/changelog/303-hs-office-membership-rbac.sql 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 new file mode 100644 index 00000000..3ba354a1 --- /dev/null +++ b/src/main/resources/db/changelog/303-hs-office-membership-rbac.md @@ -0,0 +1,71 @@ +### hs_office_membership RBAC + +```mermaid +flowchart TB + +subgraph global + style global fill:#eee + + role:global.admin[global.admin] +end + +subgraph hsOfficeDebitor + direction TB + style hsOfficeDebitor fill:#eee + + role:hsOfficeDebitor.owner[debitor.owner] + --> role:hsOfficeDebitor.admin[debitor.admin] + --> role:hsOfficeDebitor.tenant[debitor.tenant] + --> role:hsOfficeDebitor.guest[debitor.guest] +end + +subgraph hsOfficePartner + direction TB + style hsOfficePartner fill:#eee + + role:hsOfficePartner.owner[partner.admin] + --> role:hsOfficePartner.admin[partner.admin] + --> role:hsOfficePartner.agent[partner.agent] + --> role:hsOfficePartner.tenant[partner.tenant] + --> role:hsOfficePartner.guest[partner.guest] +end + +subgraph hsOfficeMembership + + role:hsOfficeMembership.owner[membership.owner] + %% permissions + role:hsOfficeMembership.owner --> perm:hsOfficeMembership.*{{membership.*}} + %% incoming + role:global.admin ---> role:hsOfficeMembership.owner + + role:hsOfficeMembership.admin[membership.admin] + %% permissions + role:hsOfficeMembership.admin --> perm:hsOfficeMembership.edit{{membership.edit}} + %% incoming + role:hsOfficeMembership.owner ---> role:hsOfficeMembership.admin + + role:hsOfficeMembership.agent[membership.agent] + %% incoming + role:hsOfficeMembership.admin ---> role:hsOfficeMembership.agent + role:hsOfficePartner.admin --> role:hsOfficeMembership.agent + role:hsOfficeDebitor.admin --> role:hsOfficeMembership.agent + %% outgoing + role:hsOfficeMembership.agent --> role:hsOfficePartner.tenant + role:hsOfficeMembership.admin --> role:hsOfficeDebitor.tenant + + role:hsOfficeMembership.tenant[membership.tenant] + %% incoming + role:hsOfficeMembership.agent --> role:hsOfficeMembership.tenant + %% outgoing + role:hsOfficeMembership.tenant --> role:hsOfficePartner.guest + role:hsOfficeMembership.tenant --> role:hsOfficeDebitor.guest + + role:hsOfficeMembership.guest[membership.guest] + %% permissions + role:hsOfficeMembership.guest --> perm:hsOfficeMembership.view{{membership.view}} + %% incoming + role:hsOfficeMembership.tenant --> role:hsOfficeMembership.guest +end + + +``` 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 new file mode 100644 index 00000000..97b1f27f --- /dev/null +++ b/src/main/resources/db/changelog/303-hs-office-membership-rbac.sql @@ -0,0 +1,157 @@ +--liquibase formatted sql + +-- ============================================================================ +--changeset hs-office-membership-rbac-OBJECT:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- +call generateRelatedRbacObject('hs_office_membership'); +--// + + +-- ============================================================================ +--changeset hs-office-membership-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- +call generateRbacRoleDescriptors('hsOfficeMembership', 'hs_office_membership'); +--// + + +-- ============================================================================ +--changeset hs-office-membership-rbac-ROLES-CREATION:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- + +/* + Creates and updates the roles and their assignments for membership entities. + */ + +create or replace function hsOfficeMembershipRbacRolesTrigger() + returns trigger + language plpgsql + strict as $$ +declare + newHsOfficePartner hs_office_partner; + newHsOfficeDebitor hs_office_debitor; +begin + + select * from hs_office_partner as p where p.uuid = NEW.partnerUuid into newHsOfficePartner; + select * from hs_office_debitor as c where c.uuid = NEW.mainDebitorUuid into newHsOfficeDebitor; + + if TG_OP = 'INSERT' then + + -- === ATTENTION: code generated from related Mermaid flowchart: === + + perform createRoleWithGrants( + hsOfficeMembershipOwner(NEW), + permissions => array['*'], + incomingSuperRoles => array[globalAdmin()] + ); + + perform createRoleWithGrants( + hsOfficeMembershipAdmin(NEW), + permissions => array['edit'], + incomingSuperRoles => array[hsOfficeMembershipOwner(NEW)], + outgoingSubRoles => array[hsOfficeDebitorTenant(newHsOfficeDebitor)] + ); + + perform createRoleWithGrants( + hsOfficeMembershipAgent(NEW), + incomingSuperRoles => array[hsOfficeMembershipAdmin(NEW), hsOfficePartnerAdmin(newHsOfficePartner), hsOfficeDebitorAdmin(newHsOfficeDebitor)], + outgoingSubRoles => array[hsOfficePartnerTenant(newHsOfficePartner)] + ); + + perform createRoleWithGrants( + hsOfficeMembershipTenant(NEW), + incomingSuperRoles => array[hsOfficeMembershipAgent(NEW)], + outgoingSubRoles => array[hsOfficePartnerGuest(newHsOfficePartner), hsOfficeDebitorGuest(newHsOfficeDebitor)] + ); + + perform createRoleWithGrants( + hsOfficeMembershipGuest(NEW), + permissions => array['view'], + incomingSuperRoles => array[hsOfficeMembershipTenant(NEW)] + ); + + -- === END of code generated from Mermaid flowchart. === + + 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 createRbacRolesForHsOfficeMembership_Trigger + after insert + on hs_office_membership + for each row +execute procedure hsOfficeMembershipRbacRolesTrigger(); +--// + + +-- ============================================================================ +--changeset hs-office-membership-rbac-IDENTITY-VIEW:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- +call generateRbacIdentityView('hs_office_membership', idNameExpression => $idName$ + (select idName from hs_office_partner_iv p where p.uuid = target.partnerUuid) + $idName$); +--// + + +-- ============================================================================ +--changeset hs-office-membership-rbac-RESTRICTED-VIEW:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- +call generateRbacRestrictedView('hs_office_membership', + orderby => 'target.reference', + columnUpdates => $updates$ + validity = new.validity, + reasonForTermination = new.reasonForTermination + $updates$); +--// + + +-- ============================================================================ +--changeset hs-office-membership-rbac-NEW-Membership:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- +/* + Creates a global permission for new-membership and assigns it to the hostsharing admins role. + */ +do language plpgsql $$ + declare + addCustomerPermissions uuid[]; + globalObjectUuid uuid; + globalAdminRoleUuid uuid ; + begin + call defineContext('granting global new-membership permission to global admin role', null, null, null); + + globalAdminRoleUuid := findRoleId(globalAdmin()); + globalObjectUuid := (select uuid from global); + addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-membership']); + call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions); + end; +$$; + +/** + Used by the trigger to prevent the add-customer to current user respectively assumed roles. + */ +create or replace function addHsOfficeMembershipNotAllowedForCurrentSubjects() + returns trigger + language PLPGSQL +as $$ +begin + raise exception '[403] new-membership 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_membership_insert_trigger + before insert + on hs_office_membership + for each row + -- TODO.spec: who is allowed to create new memberships + when ( not hasAssumedRole() ) +execute procedure addHsOfficeMembershipNotAllowedForCurrentSubjects(); +--// +