remove partner roles and amend grants accordingly

This commit is contained in:
Michael Hoennig 2024-02-08 13:28:13 +01:00
parent 4c6b7beb2d
commit 3261e92b2c
6 changed files with 133 additions and 107 deletions

View File

@ -397,6 +397,7 @@ select exists(
); );
$$; $$;
-- TODO: the array parameter and thus the array return value is only used in toPermissionUuids, simplify to non-arrays
create or replace function createPermissions(forObjectUuid uuid, permitOps RbacOp[]) create or replace function createPermissions(forObjectUuid uuid, permitOps RbacOp[])
returns uuid[] returns uuid[]
language plpgsql as $$ language plpgsql as $$
@ -668,6 +669,26 @@ begin
end if; end if;
end; $$; end; $$;
create or replace procedure revokePermissionFromRole(permission RbacRoleDescriptor, superRole RbacRoleDescriptor)
language plpgsql as $$
declare
superRoleId uuid;
subRoleId uuid;
begin
superRoleId := findRoleId(superRole);
subRoleId := findRoleId(subRole);
perform assertReferenceType('superRoleId (ascendant)', superRoleId, 'RbacRole');
perform assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole');
if (isGranted(superRoleId, subRoleId)) then
delete from RbacGrants where ascendantUuid = superRoleId and descendantUuid = subRoleId;
else
raise exception 'cannot revoke role % (%) from % (% because it is not granted',
subRole, subRoleId, superRole, superRoleId;
end if;
end; $$;
-- ============================================================================ -- ============================================================================
--changeset rbac-base-QUERY-ACCESSIBLE-OBJECT-UUIDS:1 endDelimiter:--// --changeset rbac-base-QUERY-ACCESSIBLE-OBJECT-UUIDS:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------

View File

@ -74,6 +74,7 @@ begin
return roleDescriptor('%2$s', entity.uuid, 'tenant'); return roleDescriptor('%2$s', entity.uuid, 'tenant');
end; $f$; end; $f$;
-- TODO: remove guest role
create or replace function %1$sGuest(entity %2$s) create or replace function %1$sGuest(entity %2$s)
returns RbacRoleDescriptor returns RbacRoleDescriptor
language plpgsql language plpgsql
@ -82,6 +83,14 @@ begin
return roleDescriptor('%2$s', entity.uuid, 'guest'); return roleDescriptor('%2$s', entity.uuid, 'guest');
end; $f$; end; $f$;
create or replace function %1$sReferrer(entity %2$s)
returns RbacRoleDescriptor
language plpgsql
strict as $f$
begin
return roleDescriptor('%2$s', entity.uuid, 'referrer');
end; $f$;
$sql$, prefix, targetTable); $sql$, prefix, targetTable);
execute sql; execute sql;
end; $$; end; $$;

View File

@ -7,13 +7,6 @@ call generateRelatedRbacObject('hs_office_partner');
--// --//
-- ============================================================================
--changeset hs-office-partner-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRoleDescriptors('hsOfficePartner', 'hs_office_partner');
--//
-- ============================================================================ -- ============================================================================
--changeset hs-office-partner-rbac-ROLES-CREATION:1 endDelimiter:--// --changeset hs-office-partner-rbac-ROLES-CREATION:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
@ -35,70 +28,40 @@ begin
if TG_OP = 'INSERT' then if TG_OP = 'INSERT' then
-- === ATTENTION: code generated from related Mermaid flowchart: === -- Permissions and Grants for Partner
perform createRoleWithGrants(
hsOfficePartnerOwner(NEW),
permissions => array['*'],
incomingSuperRoles => array[globalAdmin()],
outgoingSubRoles => array[
hsOfficeRelationshipOwner(newPartnerRole)]
);
perform createRoleWithGrants(
hsOfficePartnerAdmin(NEW),
permissions => array['edit'],
incomingSuperRoles => array[
hsOfficePartnerOwner(NEW)],
outgoingSubRoles => array[
hsOfficeRelationshipAdmin(newPartnerRole)]
);
perform createRoleWithGrants(
hsOfficePartnerAgent(NEW),
incomingSuperRoles => array[
hsOfficePartnerAdmin(NEW),
hsOfficeRelationshipAgent(newPartnerRole)]
);
perform createRoleWithGrants(
hsOfficePartnerTenant(NEW),
incomingSuperRoles => array[
hsOfficePartnerAgent(NEW)],
outgoingSubRoles => array[
hsOfficeRelationshipTenant(newPartnerRole)]
);
perform createRoleWithGrants(
hsOfficePartnerGuest(NEW),
permissions => array['view'],
incomingSuperRoles => array[hsOfficePartnerTenant(NEW)]
);
-- === END of code generated from Mermaid flowchart. ===
-- Each partner-details entity belong exactly to one partner entity
-- and it makes little sense just to delegate partner-details roles.
-- Therefore, we did not model partner-details roles,
-- but instead just assign extra permissions to existing partner-roles.
--Attention: Cannot be in partner-details because of insert order (partner is not in database yet)
call grantPermissionsToRole( call grantPermissionsToRole(
getRoleId(hsOfficePartnerOwner(NEW), 'fail'), getRoleId(hsOfficeRelationshipOwner(newPartnerRole), 'fail'),
createPermissions(NEW.uuid, array ['*'])
);
call grantPermissionsToRole(
getRoleId(hsOfficeRelationshipAdmin(newPartnerRole), 'fail'),
createPermissions(NEW.uuid, array ['edit'])
);
call grantPermissionsToRole(
getRoleId(hsOfficeRelationshipTenant(newPartnerRole), 'fail'),
createPermissions(NEW.uuid, array ['view'])
);
-- Permissions and Grants for PartnerDetails
call grantPermissionsToRole(
getRoleId(hsOfficeRelationshipOwner(newPartnerRole), 'fail'),
createPermissions(NEW.detailsUuid, array ['*']) createPermissions(NEW.detailsUuid, array ['*'])
); );
call grantPermissionsToRole( call grantPermissionsToRole(
getRoleId(hsOfficePartnerAdmin(NEW), 'fail'), getRoleId(hsOfficeRelationshipAdmin(newPartnerRole), 'fail'),
createPermissions(NEW.detailsUuid, array ['edit']) createPermissions(NEW.detailsUuid, array ['edit'])
); );
call grantPermissionsToRole( call grantPermissionsToRole(
-- Yes, here hsOfficePartnerAGENT is used, not hsOfficePartnerTENANT. -- Yes, here hsOfficePartnerAGENT is used, not hsOfficeRelationshipTENANT.
-- Do NOT grant view permission on partner-details to hsOfficePartnerTENANT! -- Do NOT grant view permission on partner-details to hsOfficeRelationshipTENANT!
-- Otherwise package-admins etc. would be able to read the data. -- Otherwise package-admins etc. would be able to read the data.
getRoleId(hsOfficePartnerAgent(NEW), 'fail'), getRoleId(hsOfficeRelationshipAgent(newPartnerRole), 'fail'),
createPermissions(NEW.detailsUuid, array ['view']) createPermissions(NEW.detailsUuid, array ['view'])
); );
@ -108,14 +71,47 @@ begin
if OLD.partnerRoleUuid <> NEW.partnerRoleUuid then if OLD.partnerRoleUuid <> NEW.partnerRoleUuid then
select * from hs_office_relationship as r where r.uuid = OLD.partnerRoleUuid into oldPartnerRole; select * from hs_office_relationship as r where r.uuid = OLD.partnerRoleUuid into oldPartnerRole;
call revokeRoleFromRole(hsOfficeRelationshipTenant(oldPartnerRole), hsOfficePartnerAdmin(OLD)); -- Revoke all Permissions from old partner relationship
call grantRoleToRole(hsOfficeRelationshipTenant(newPartnerRole), hsOfficePartnerAdmin(NEW)); -- TODO: introduce call revokeAllPermissionsOnDescendantFromAllRolesOfAscendant(OLD, oldPartnerRole);
delete from rbacGrants where descendantUuid==OLD.uuid and ascendantUuid==OLD.partnerRoleUuid;
call revokeRoleFromRole(hsOfficePartnerAgent(OLD), hsOfficeRelationshipAdmin(oldPartnerRole)); -- Grants for Partner
call grantRoleToRole(hsOfficePartnerAgent(NEW), hsOfficeRelationshipAdmin(newPartnerRole));
call grantPermissionsToRole(
getRoleId(hsOfficeRelationshipOwner(newPartnerRole), 'fail'),
array[findPermissionId(NEW.uuid, '*')]
);
call grantPermissionsToRole(
getRoleId(hsOfficeRelationshipAdmin(newPartnerRole), 'fail'),
array[findPermissionId(NEW.uuid, 'edit')]
);
call grantPermissionsToRole(
getRoleId(hsOfficeRelationshipTenant(newPartnerRole), 'fail'),
array[findPermissionId(NEW.uuid, 'view')]
);
-- Grants for PartnerDetails
call grantPermissionsToRole(
getRoleId(hsOfficeRelationshipOwner(newPartnerRole), 'fail'),
array[findPermissionId(NEW.detailsUuid, '*')]
);
call grantPermissionsToRole(
getRoleId(hsOfficeRelationshipAdmin(newPartnerRole), 'fail'),
array[findPermissionId(NEW.detailsUuid, array ['edit'])]
);
call grantPermissionsToRole(
-- Yes, here hsOfficePartnerAGENT is used, not hsOfficePartnerTENANT.
-- Do NOT grant view permission on partner-details to hsOfficeRelationshipTENANT!
-- Otherwise package-admins etc. would be able to read the data.
getRoleId(hsOfficeRelationshipAgent(newPartnerRole), 'fail'),
array[findPermissionId(NEW.detailsUuid, 'view')]
);
call revokeRoleFromRole(hsOfficeRelationshipGuest(oldPartnerRole), hsOfficePartnerTenant(OLD));
call grantRoleToRole(hsOfficeRelationshipGuest(newPartnerRole), hsOfficePartnerTenant(NEW));
end if; end if;
else else

View File

@ -3,8 +3,23 @@
```mermaid ```mermaid
flowchart TB flowchart TB
subgraph bank[ ] subgraph partnerRelationship[hsOfficeRelationship:PARTNER]
style bank fill:#fff direction TB
style partnerRelationship fill:#eee
role:partnerRelationship.owner[relationship.owner]
--> role:partnerRelationship.admin[relationship.admin]
--> role:partnerRelationship.agent[relationship.agent]
--> role:partnerRelationship.tenant[relationship.tenant]
partnerPersonAdmin>e.g. partnerPerson.admin] --> role:partnerRelationship.agent
otherPersonAdmin>e.g. operationalPerson.admin] --> role:partnerRelationship.tenant
role:partnerRelationship.tenant --> partnerPersonReferrer>e.g. partnerPerson.referrer]
end
subgraph internal[ ]
direction TB
style internal fill:#fff
subgraph refundBankAccount subgraph refundBankAccount
direction TB direction TB
@ -14,28 +29,7 @@ subgraph bank[ ]
--> role:refundBankAccount.admin[bankAccount.admin] --> role:refundBankAccount.admin[bankAccount.admin]
--> role:refundBankAccount.referrer[bankAccount.referrer] --> role:refundBankAccount.referrer[bankAccount.referrer]
end end
end
subgraph partner[ ]
style partner fill:#fff
subgraph partnerRelationship[hsOfficeRelationship:PARTNER]
direction TB
style partnerRelationship fill:#eee
role:partnerRelationship.owner[relationship.owner]
--> role:partnerRelationship.admin[relationship.admin]
--> role:partnerRelationship.agent[relationship.agent]
--> role:partnerRelationship.tenant[relationship.tenant]
partnerPerson[e.g. partnerPerson.admin] --> role:partnerRelationship.agent
otherPerson[e.g. operationalPerson.admin] --> role:partnerRelationship.tenant
end
end
subgraph internal[ ]
direction TB
style internal fill:#fff
subgraph debitorRelationship[hsOfficeRelationship:DEBITOR] subgraph debitorRelationship[hsOfficeRelationship:DEBITOR]
direction TB direction TB
@ -56,7 +50,7 @@ subgraph internal[ ]
role:debitorRelationship.admin[debitorRelationship.admin] role:debitorRelationship.admin[debitorRelationship.admin]
%% permissions %% permissions
==> perm:debitor.edit{{debitorRelationship.edit}} ==> perm:debitor.edit{{debitor.edit}}
%% incoming %% incoming
role:partnerRelationship.admin ==> role:debitorRelationship.admin role:partnerRelationship.admin ==> role:debitorRelationship.admin
%% outgoing %% outgoing

View File

@ -30,6 +30,8 @@ declare
hsOfficeDebitorTenant RbacRoleDescriptor; hsOfficeDebitorTenant RbacRoleDescriptor;
oldPartner hs_office_partner; oldPartner hs_office_partner;
newPartner hs_office_partner; newPartner hs_office_partner;
oldPartnerRel hs_office_relationship;
newPartnerRel hs_office_relationship;
oldContact hs_office_contact; oldContact hs_office_contact;
newContact hs_office_contact; newContact hs_office_contact;
newBankAccount hs_office_bankaccount; newBankAccount hs_office_bankaccount;
@ -39,10 +41,11 @@ begin
hsOfficeDebitorTenant := hsOfficeDebitorTenant(NEW); hsOfficeDebitorTenant := hsOfficeDebitorTenant(NEW);
select * from hs_office_partner as p where p.uuid = NEW.partnerUuid into newPartner; select * from hs_office_partner as p where p.uuid = NEW.partnerUuid into newPartner;
select * from hs_office_relationship as r where r.relType = 'PARTNER' and r.relHolderUuid = NEW.partnerUuid into newPartnerRel;
select * from hs_office_contact as c where c.uuid = NEW.billingContactUuid into newContact; select * from hs_office_contact as c where c.uuid = NEW.billingContactUuid into newContact;
select * from hs_office_bankaccount as b where b.uuid = NEW.refundBankAccountUuid into newBankAccount; select * from hs_office_bankaccount as b where b.uuid = NEW.refundBankAccountUuid into newBankAccount;
if TG_OP = 'INSERT' then
if TG_OP = 'INSERT' then
perform createRoleWithGrants( perform createRoleWithGrants(
hsOfficeDebitorOwner(NEW), hsOfficeDebitorOwner(NEW),
@ -62,7 +65,7 @@ begin
hsOfficeDebitorAgent(NEW), hsOfficeDebitorAgent(NEW),
incomingSuperRoles => array[ incomingSuperRoles => array[
hsOfficeDebitorAdmin(NEW), hsOfficeDebitorAdmin(NEW),
hsOfficePartnerAdmin(newPartner), hsOfficeRelationshipAdmin(newPartnerRel),
hsOfficeContactAdmin(newContact)], hsOfficeContactAdmin(newContact)],
outgoingSubRoles => array[ outgoingSubRoles => array[
hsOfficeBankAccountTenant(newBankaccount)] hsOfficeBankAccountTenant(newBankaccount)]
@ -72,10 +75,10 @@ begin
hsOfficeDebitorTenant(NEW), hsOfficeDebitorTenant(NEW),
incomingSuperRoles => array[ incomingSuperRoles => array[
hsOfficeDebitorAgent(NEW), hsOfficeDebitorAgent(NEW),
hsOfficePartnerAgent(newPartner), hsOfficeRelationshipAgent(newPartnerRel),
hsOfficeBankAccountAdmin(newBankaccount)], hsOfficeBankAccountAdmin(newBankaccount)],
outgoingSubRoles => array[ outgoingSubRoles => array[
hsOfficePartnerTenant(newPartner), hsOfficeRelationshipTenant(newPartnerRel),
hsOfficeContactGuest(newContact), hsOfficeContactGuest(newContact),
hsOfficeBankAccountGuest(newBankaccount)] hsOfficeBankAccountGuest(newBankaccount)]
); );
@ -91,15 +94,16 @@ begin
if OLD.partnerUuid <> NEW.partnerUuid then if OLD.partnerUuid <> NEW.partnerUuid then
select * from hs_office_partner as p where p.uuid = OLD.partnerUuid into oldPartner; select * from hs_office_partner as p where p.uuid = OLD.partnerUuid into oldPartner;
select * from hs_office_relationship as r where r.uuid = OLD.partnerUuid into oldPartnerRel;
call revokeRoleFromRole(hsOfficeDebitorAgent(OLD), hsOfficePartnerAdmin(oldPartner)); call revokeRoleFromRole(hsOfficeDebitorAgent(OLD), hsOfficeRelationshipAdmin(oldPartnerRel));
call grantRoleToRole(hsOfficeDebitorAgent(NEW), hsOfficePartnerAdmin(newPartner)); call grantRoleToRole(hsOfficeDebitorAgent(NEW), hsOfficeRelationshipAdmin(oldPartnerRel));
call revokeRoleFromRole(hsOfficeDebitorTenant(OLD), hsOfficePartnerAgent(oldPartner)); call revokeRoleFromRole(hsOfficeDebitorTenant(OLD), hsOfficeRelationshipAgent(oldPartnerRel));
call grantRoleToRole(hsOfficeDebitorTenant(NEW), hsOfficePartnerAgent(newPartner)); call grantRoleToRole(hsOfficeDebitorTenant(NEW), hsOfficeRelationshipAgent(newPartner));
call revokeRoleFromRole(hsOfficePartnerTenant(oldPartner), hsOfficeDebitorTenant(OLD)); call revokeRoleFromRole(hsOfficeRelationshipTenant(oldPartnerRel), hsOfficeDebitorTenant(OLD));
call grantRoleToRole(hsOfficePartnerTenant(newPartner), hsOfficeDebitorTenant(NEW)); call grantRoleToRole(hsOfficeRelationshipTenant(newPartnerRel), hsOfficeDebitorTenant(NEW));
end if; end if;
if OLD.billingContactUuid <> NEW.billingContactUuid then if OLD.billingContactUuid <> NEW.billingContactUuid then

View File

@ -27,11 +27,13 @@ create or replace function hsOfficeMembershipRbacRolesTrigger()
language plpgsql language plpgsql
strict as $$ strict as $$
declare declare
newHsOfficePartner hs_office_partner; newHsOfficePartner hs_office_partner;
newHsOfficeDebitor hs_office_debitor; newHsOfficePartnerRel hs_office_relationship;
newHsOfficeDebitor hs_office_debitor;
begin begin
select * from hs_office_partner as p where p.uuid = NEW.partnerUuid into newHsOfficePartner; select * from hs_office_partner as p where p.uuid = NEW.partnerUuid into newHsOfficePartner;
select * from hs_office_relationship as r where r.relType = 'PARTNER' and r.relHolderUuid = NEW.partnerUuid into newHsOfficePartnerRel;
select * from hs_office_debitor as c where c.uuid = NEW.mainDebitorUuid into newHsOfficeDebitor; select * from hs_office_debitor as c where c.uuid = NEW.mainDebitorUuid into newHsOfficeDebitor;
if TG_OP = 'INSERT' then if TG_OP = 'INSERT' then
@ -52,20 +54,20 @@ begin
perform createRoleWithGrants( perform createRoleWithGrants(
hsOfficeMembershipAgent(NEW), hsOfficeMembershipAgent(NEW),
incomingSuperRoles => array[hsOfficeMembershipAdmin(NEW), hsOfficePartnerAdmin(newHsOfficePartner), hsOfficeDebitorAdmin(newHsOfficeDebitor)], incomingSuperRoles => array[hsOfficeMembershipAdmin(NEW), hsOfficeRelationshipAdmin(newHsOfficePartnerRel), hsOfficeDebitorAdmin(newHsOfficeDebitor)],
outgoingSubRoles => array[hsOfficePartnerTenant(newHsOfficePartner), hsOfficeDebitorTenant(newHsOfficeDebitor)] outgoingSubRoles => array[hsOfficeRelationshipTenant(newHsOfficePartnerRel), hsOfficeDebitorTenant(newHsOfficeDebitor)]
); );
perform createRoleWithGrants( perform createRoleWithGrants(
hsOfficeMembershipTenant(NEW), hsOfficeMembershipTenant(NEW),
incomingSuperRoles => array[hsOfficeMembershipAgent(NEW), hsOfficePartnerAgent(newHsOfficePartner), hsOfficeDebitorAgent(newHsOfficeDebitor)], incomingSuperRoles => array[hsOfficeMembershipAgent(NEW), hsOfficeRelationshipAgent(newHsOfficePartnerRel), hsOfficeDebitorAgent(newHsOfficeDebitor)],
outgoingSubRoles => array[hsOfficePartnerGuest(newHsOfficePartner), hsOfficeDebitorGuest(newHsOfficeDebitor)] outgoingSubRoles => array[hsOfficeRelationshipGuest(newHsOfficePartnerRel), hsOfficeDebitorGuest(newHsOfficeDebitor)]
); );
perform createRoleWithGrants( perform createRoleWithGrants(
hsOfficeMembershipGuest(NEW), hsOfficeMembershipGuest(NEW),
permissions => array['view'], permissions => array['view'],
incomingSuperRoles => array[hsOfficeMembershipTenant(NEW), hsOfficePartnerTenant(newHsOfficePartner), hsOfficeDebitorTenant(newHsOfficeDebitor)] incomingSuperRoles => array[hsOfficeMembershipTenant(NEW), hsOfficeRelationshipTenant(newHsOfficePartnerRel), hsOfficeDebitorTenant(newHsOfficeDebitor)]
); );
-- === END of code generated from Mermaid flowchart. === -- === END of code generated from Mermaid flowchart. ===