Compare commits

..

No commits in common. "ecc91592b0482fef98f63408f6dc5d005071d281" and "4c6b7beb2d903f23bd110b5642b32400b9050290" have entirely different histories.

7 changed files with 132 additions and 158 deletions

View File

@ -397,7 +397,6 @@ 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[])
returns uuid[]
language plpgsql as $$
@ -669,26 +668,6 @@ begin
end if;
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:--//
-- ----------------------------------------------------------------------------

View File

@ -74,7 +74,6 @@ begin
return roleDescriptor('%2$s', entity.uuid, 'tenant');
end; $f$;
-- TODO: remove guest role
create or replace function %1$sGuest(entity %2$s)
returns RbacRoleDescriptor
language plpgsql
@ -83,14 +82,6 @@ begin
return roleDescriptor('%2$s', entity.uuid, 'guest');
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);
execute sql;
end; $$;

View File

@ -7,6 +7,13 @@ 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:--//
-- ----------------------------------------------------------------------------
@ -28,40 +35,70 @@ begin
if TG_OP = 'INSERT' then
-- Permissions and Grants for Partner
-- === ATTENTION: code generated from related Mermaid flowchart: ===
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(
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'),
getRoleId(hsOfficePartnerOwner(NEW), 'fail'),
createPermissions(NEW.detailsUuid, array ['*'])
);
call grantPermissionsToRole(
getRoleId(hsOfficeRelationshipAdmin(newPartnerRole), 'fail'),
getRoleId(hsOfficePartnerAdmin(NEW), 'fail'),
createPermissions(NEW.detailsUuid, array ['edit'])
);
call grantPermissionsToRole(
-- Yes, here hsOfficePartnerAGENT is used, not hsOfficeRelationshipTENANT.
-- Do NOT grant view permission on partner-details to hsOfficeRelationshipTENANT!
-- Yes, here hsOfficePartnerAGENT is used, not hsOfficePartnerTENANT.
-- Do NOT grant view permission on partner-details to hsOfficePartnerTENANT!
-- Otherwise package-admins etc. would be able to read the data.
getRoleId(hsOfficeRelationshipAgent(newPartnerRole), 'fail'),
getRoleId(hsOfficePartnerAgent(NEW), 'fail'),
createPermissions(NEW.detailsUuid, array ['view'])
);
@ -71,47 +108,14 @@ begin
if OLD.partnerRoleUuid <> NEW.partnerRoleUuid then
select * from hs_office_relationship as r where r.uuid = OLD.partnerRoleUuid into oldPartnerRole;
-- Revoke all Permissions from old partner relationship
-- TODO: introduce call revokeAllPermissionsOnDescendantFromAllRolesOfAscendant(OLD, oldPartnerRole);
delete from rbacGrants where descendantUuid==OLD.uuid and ascendantUuid==OLD.partnerRoleUuid;
call revokeRoleFromRole(hsOfficeRelationshipTenant(oldPartnerRole), hsOfficePartnerAdmin(OLD));
call grantRoleToRole(hsOfficeRelationshipTenant(newPartnerRole), hsOfficePartnerAdmin(NEW));
-- Grants for Partner
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(hsOfficePartnerAgent(OLD), hsOfficeRelationshipAdmin(oldPartnerRole));
call grantRoleToRole(hsOfficePartnerAgent(NEW), hsOfficeRelationshipAdmin(newPartnerRole));
call revokeRoleFromRole(hsOfficeRelationshipGuest(oldPartnerRole), hsOfficePartnerTenant(OLD));
call grantRoleToRole(hsOfficeRelationshipGuest(newPartnerRole), hsOfficePartnerTenant(NEW));
end if;
else

View File

@ -3,24 +3,9 @@
```mermaid
flowchart TB
subgraph partnerRelationship[hsOfficeRelationship:PARTNER]
direction TB
style partnerRelationship fill:#eee
subgraph bank[ ]
style bank fill:#fff
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
direction TB
style refundBankAccount fill:#eee
@ -29,7 +14,28 @@ subgraph internal[ ]
--> role:refundBankAccount.admin[bankAccount.admin]
--> role:refundBankAccount.referrer[bankAccount.referrer]
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]
direction TB
@ -50,7 +56,7 @@ subgraph internal[ ]
role:debitorRelationship.admin[debitorRelationship.admin]
%% permissions
==> perm:debitor.edit{{debitor.edit}}
==> perm:debitor.edit{{debitorRelationship.edit}}
%% incoming
role:partnerRelationship.admin ==> role:debitorRelationship.admin
%% outgoing

View File

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

View File

@ -27,13 +27,11 @@ create or replace function hsOfficeMembershipRbacRolesTrigger()
language plpgsql
strict as $$
declare
newHsOfficePartner hs_office_partner;
newHsOfficePartnerRel hs_office_relationship;
newHsOfficeDebitor hs_office_debitor;
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_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;
if TG_OP = 'INSERT' then
@ -54,20 +52,20 @@ begin
perform createRoleWithGrants(
hsOfficeMembershipAgent(NEW),
incomingSuperRoles => array[hsOfficeMembershipAdmin(NEW), hsOfficeRelationshipAdmin(newHsOfficePartnerRel), hsOfficeDebitorAdmin(newHsOfficeDebitor)],
outgoingSubRoles => array[hsOfficeRelationshipTenant(newHsOfficePartnerRel), hsOfficeDebitorTenant(newHsOfficeDebitor)]
incomingSuperRoles => array[hsOfficeMembershipAdmin(NEW), hsOfficePartnerAdmin(newHsOfficePartner), hsOfficeDebitorAdmin(newHsOfficeDebitor)],
outgoingSubRoles => array[hsOfficePartnerTenant(newHsOfficePartner), hsOfficeDebitorTenant(newHsOfficeDebitor)]
);
perform createRoleWithGrants(
hsOfficeMembershipTenant(NEW),
incomingSuperRoles => array[hsOfficeMembershipAgent(NEW), hsOfficeRelationshipAgent(newHsOfficePartnerRel), hsOfficeDebitorAgent(newHsOfficeDebitor)],
outgoingSubRoles => array[hsOfficeRelationshipGuest(newHsOfficePartnerRel), hsOfficeDebitorGuest(newHsOfficeDebitor)]
incomingSuperRoles => array[hsOfficeMembershipAgent(NEW), hsOfficePartnerAgent(newHsOfficePartner), hsOfficeDebitorAgent(newHsOfficeDebitor)],
outgoingSubRoles => array[hsOfficePartnerGuest(newHsOfficePartner), hsOfficeDebitorGuest(newHsOfficeDebitor)]
);
perform createRoleWithGrants(
hsOfficeMembershipGuest(NEW),
permissions => array['view'],
incomingSuperRoles => array[hsOfficeMembershipTenant(NEW), hsOfficeRelationshipTenant(newHsOfficePartnerRel), hsOfficeDebitorTenant(newHsOfficeDebitor)]
incomingSuperRoles => array[hsOfficeMembershipTenant(NEW), hsOfficePartnerTenant(newHsOfficePartner), hsOfficeDebitorTenant(newHsOfficeDebitor)]
);
-- === END of code generated from Mermaid flowchart. ===

View File

@ -181,26 +181,26 @@ public class ImportOfficeData extends ContextBasedTest {
// no contacts yet => mostly null values
assertThat(toFormattedString(partners)).isEqualToIgnoringWhitespace("""
{
17=partner(P-10017: null null, null),
20=partner(P-10020: null null, null),
22=partner(P-11022: null null, null),
99=partner(P-19999: null null, null)
17=partner(null null, null),
20=partner(null null, null),
22=partner(null null, null),
99=partner(null null, null)
}
""");
assertThat(toFormattedString(contacts)).isEqualTo("{}");
assertThat(toFormattedString(debitors)).isEqualToIgnoringWhitespace("""
{
17=debitor(D-1001700: P-10017, mih),
20=debitor(D-1002000: P-10020, xyz),
22=debitor(D-1102200: P-11022, xxx),
99=debitor(D-1999900: P-19999, zzz)
17=debitor(D-1001700: null null, null: mih),
20=debitor(D-1002000: null null, null: xyz),
22=debitor(D-1102200: null null, null: xxx),
99=debitor(D-1999900: null null, null: zzz)
}
""");
assertThat(toFormattedString(memberships)).isEqualToIgnoringWhitespace("""
{
17=Membership(M-1001700, P-10017, D-1001700, [2000-12-06,), NONE),
20=Membership(M-1002000, P-10020, D-1002000, [2000-12-06,2016-01-01), UNKNOWN),
22=Membership(M-1102200, P-11022, D-1102200, [2021-04-01,), NONE)
17=Membership(M-1001700, null null, null, D-1001700, [2000-12-06,), NONE),
20=Membership(M-1002000, null null, null, D-1002000, [2000-12-06,2016-01-01), UNKNOWN),
22=Membership(M-1102200, null null, null, D-1102200, [2021-04-01,), NONE)
}
""");
}
@ -224,10 +224,10 @@ public class ImportOfficeData extends ContextBasedTest {
assertThat(toFormattedString(partners)).isEqualToIgnoringWhitespace("""
{
17=partner(P-10017: NP Mellies, Michael, Herr Michael Mellies ),
20=partner(P-10020: LP JM GmbH, Herr Philip Meyer-Contract , JM GmbH),
22=partner(P-11022: ?? Test PS, Petra Schmidt , Test PS),
99=partner(P-19999: null null, null)
17=partner(NP Mellies, Michael: Herr Michael Mellies ),
20=partner(LP JM GmbH: Herr Philip Meyer-Contract , JM GmbH),
22=partner(?? Test PS: Petra Schmidt , Test PS),
99=partner(null null, null)
}
""");
assertThat(toFormattedString(contacts)).isEqualToIgnoringWhitespace("""
@ -257,17 +257,17 @@ public class ImportOfficeData extends ContextBasedTest {
""");
assertThat(toFormattedString(debitors)).isEqualToIgnoringWhitespace("""
{
17=debitor(D-1001700: P-10017, mih),
20=debitor(D-1002000: P-10020, xyz),
22=debitor(D-1102200: P-11022, xxx),
99=debitor(D-1999900: P-19999, zzz)
17=debitor(D-1001700: NP Mellies, Michael: mih),
20=debitor(D-1002000: LP JM GmbH: xyz),
22=debitor(D-1102200: ?? Test PS: xxx),
99=debitor(D-1999900: null null, null: zzz)
}
""");
assertThat(toFormattedString(memberships)).isEqualToIgnoringWhitespace("""
{
17=Membership(M-1001700, P-10017, D-1001700, [2000-12-06,), NONE),
20=Membership(M-1002000, P-10020, D-1002000, [2000-12-06,2016-01-01), UNKNOWN),
22=Membership(M-1102200, P-11022, D-1102200, [2021-04-01,), NONE)
17=Membership(M-1001700, NP Mellies, Michael, D-1001700, [2000-12-06,), NONE),
20=Membership(M-1002000, LP JM GmbH, D-1002000, [2000-12-06,2016-01-01), UNKNOWN),
22=Membership(M-1102200, ?? Test PS, D-1102200, [2021-04-01,), NONE)
}
""");
assertThat(toFormattedString(relationships)).isEqualToIgnoringWhitespace("""
@ -313,9 +313,9 @@ public class ImportOfficeData extends ContextBasedTest {
assertThat(toFormattedString(bankAccounts)).isEqualToIgnoringWhitespace("""
{
234234=bankAccount(DE37500105177419788228: holder='Michael Mellies', bic='INGDDEFFXXX'),
235600=bankAccount(DE02300209000106531065: holder='JM e.K.', bic='CMCIDEDD'),
235662=bankAccount(DE49500105174516484892: holder='JM GmbH', bic='INGDDEFFXXX')
234234=bankAccount(holder='Michael Mellies', iban='DE37500105177419788228', bic='INGDDEFFXXX'),
235600=bankAccount(holder='JM e.K.', iban='DE02300209000106531065', bic='CMCIDEDD'),
235662=bankAccount(holder='JM GmbH', iban='DE49500105174516484892', bic='INGDDEFFXXX')
}
""");
assertThat(toFormattedString(sepaMandates)).isEqualToIgnoringWhitespace("""