1
0

move Parter+Debitor person+contact to related Relationsship (#20)

Co-authored-by: Michael Hoennig <michael@hoennig.de>
Reviewed-on: https://dev.hostsharing.net/hostsharing/hs.hsadmin.ng/pulls/20
Reviewed-by: Timotheus Pokorra <timotheus.pokorra@hostsharing.net>
This commit is contained in:
Michael Hoennig
2024-03-28 12:15:13 +01:00
parent 4572c6bda0
commit d3ca2b7e23
117 changed files with 3995 additions and 5287 deletions

View File

@@ -3,7 +3,7 @@
-- ============================================================================
-- NUMERIC-HASH-FUNCTIONS
--changeset hash:1 endDelimiter:--//
--changeset numeric-hash-functions:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
create function bigIntHash(text) returns bigint as $$

View File

@@ -26,7 +26,7 @@ create or replace procedure defineContext(
currentTask varchar(96),
currentRequest text = null,
currentUser varchar(63) = null,
assumedRoles varchar(256) = null
assumedRoles varchar(1023) = null
)
language plpgsql as $$
begin
@@ -43,7 +43,7 @@ begin
execute format('set local hsadminng.currentUser to %L', currentUser);
assumedRoles := coalesce(assumedRoles, '');
assert length(assumedRoles) <= 256, FORMAT('assumedRoles must not be longer than 256 characters: "%s"', assumedRoles);
assert length(assumedRoles) <= 1023, FORMAT('assumedRoles must not be longer than 1023 characters: "%s"', assumedRoles);
execute format('set local hsadminng.assumedRoles to %L', assumedRoles);
call contextDefined(currentTask, currentRequest, currentUser, assumedRoles);
@@ -87,11 +87,11 @@ end; $$;
Raises exception if not set.
*/
create or replace function currentRequest()
returns varchar(512)
returns text
stable -- leakproof
language plpgsql as $$
declare
currentRequest varchar(512);
currentRequest text;
begin
begin
currentRequest := current_setting('hsadminng.currentRequest');
@@ -135,22 +135,11 @@ end; $$;
or empty array, if not set.
*/
create or replace function assumedRoles()
returns varchar(63)[]
returns varchar(1023)[]
stable -- leakproof
language plpgsql as $$
declare
currentSubject varchar(63);
begin
begin
currentSubject := current_setting('hsadminng.assumedRoles');
exception
when others then
return array []::varchar[];
end;
if (currentSubject = '') then
return array []::varchar[];
end if;
return string_to_array(currentSubject, ';');
return string_to_array(current_setting('hsadminng.assumedRoles', true), ';');
end; $$;
create or replace function cleanIdentifier(rawIdentifier varchar)
@@ -219,17 +208,17 @@ begin
end ; $$;
create or replace function currentSubjects()
returns varchar(63)[]
returns varchar(1023)[]
stable -- leakproof
language plpgsql as $$
declare
assumedRoles varchar(63)[];
assumedRoles varchar(1023)[];
begin
assumedRoles := assumedRoles();
if array_length(assumedRoles, 1) > 0 then
return assumedRoles();
return assumedRoles;
else
return array [currentUser()]::varchar(63)[];
return array [currentUser()]::varchar(1023)[];
end if;
end; $$;

View File

@@ -27,9 +27,9 @@ create table tx_context
txId bigint not null,
txTimestamp timestamp not null,
currentUser varchar(63) not null, -- not the uuid, because users can be deleted
assumedRoles varchar(256) not null, -- not the uuids, because roles can be deleted
assumedRoles varchar(1023) not null, -- not the uuids, because roles can be deleted
currentTask varchar(96) not null,
currentRequest text not null
currentRequest text not null
);
create index on tx_context using brin (txTimestamp);

View File

@@ -63,6 +63,7 @@ create or replace view rbacgrants_ev as
x.grantedByRoleUuid,
x.ascendantUuid as ascendantUuid,
x.descendantUuid as descendantUuid,
x.op as permOp, x.optablename as permOpTableName,
x.assumed
from (
select g.uuid as grantUuid,
@@ -74,13 +75,17 @@ create or replace view rbacgrants_ev as
'role ' || aro.objectTable || '#' || findIdNameByObjectUuid(aro.objectTable, aro.uuid) || '.' || ar.roletype
) as ascendingIdName,
aro.objectTable, aro.uuid,
coalesce(
'role ' || dro.objectTable || '#' || findIdNameByObjectUuid(dro.objectTable, dro.uuid) || '.' || dr.roletype,
'perm ' || dp.op || ' on ' || dpo.objecttable || '#' || findIdNameByObjectUuid(dpo.objectTable, dpo.uuid)
( case
when dro is not null
then ('role ' || dro.objectTable || '#' || findIdNameByObjectUuid(dro.objectTable, dro.uuid) || '.' || dr.roletype)
when dp.op = 'INSERT'
then 'perm ' || dp.op || ' into ' || dp.opTableName || ' with ' || dpo.objecttable || '#' || findIdNameByObjectUuid(dpo.objectTable, dpo.uuid)
else 'perm ' || dp.op || ' on ' || dpo.objecttable || '#' || findIdNameByObjectUuid(dpo.objectTable, dpo.uuid)
end
) as descendingIdName,
dro.objectTable, dro.uuid
from rbacgrants as g
dro.objectTable, dro.uuid,
dp.op, dp.optablename
from rbacgrants as g
left outer join rbacrole as ar on ar.uuid = g.ascendantUuid
left outer join rbacobject as aro on aro.uuid = ar.objectuuid

View File

@@ -86,16 +86,14 @@ execute procedure insertTriggerForTestCustomer_tf();
do language plpgsql $$
declare
row global;
permissionUuid uuid;
roleUuid uuid;
begin
call defineContext('create INSERT INTO test_customer permissions for the related global rows');
FOR row IN SELECT * FROM global
LOOP
roleUuid := findRoleId(globalAdmin());
permissionUuid := createPermission(row.uuid, 'INSERT', 'test_customer');
call grantPermissionToRole(permissionUuid, roleUuid);
call grantPermissionToRole(
createPermission(row.uuid, 'INSERT', 'test_customer'),
globalAdmin());
END LOOP;
END;
$$;

View File

@@ -151,16 +151,14 @@ execute procedure updateTriggerForTestPackage_tf();
do language plpgsql $$
declare
row test_customer;
permissionUuid uuid;
roleUuid uuid;
begin
call defineContext('create INSERT INTO test_package permissions for the related test_customer rows');
FOR row IN SELECT * FROM test_customer
LOOP
roleUuid := findRoleId(testCustomerAdmin(row));
permissionUuid := createPermission(row.uuid, 'INSERT', 'test_package');
call grantPermissionToRole(permissionUuid, roleUuid);
call grantPermissionToRole(
createPermission(row.uuid, 'INSERT', 'test_package'),
testCustomerAdmin(row));
END LOOP;
END;
$$;

View File

@@ -150,16 +150,14 @@ execute procedure updateTriggerForTestDomain_tf();
do language plpgsql $$
declare
row test_package;
permissionUuid uuid;
roleUuid uuid;
begin
call defineContext('create INSERT INTO test_domain permissions for the related test_package rows');
FOR row IN SELECT * FROM test_package
LOOP
roleUuid := findRoleId(testPackageAdmin(row));
permissionUuid := createPermission(row.uuid, 'INSERT', 'test_domain');
call grantPermissionToRole(permissionUuid, roleUuid);
call grantPermissionToRole(
createPermission(row.uuid, 'INSERT', 'test_domain'),
testPackageAdmin(row));
END LOOP;
END;
$$;

View File

@@ -1,126 +0,0 @@
--liquibase formatted sql
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
-- ============================================================================
--changeset hs-office-contact-rbac-OBJECT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRelatedRbacObject('hs_office_contact');
--//
-- ============================================================================
--changeset hs-office-contact-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRoleDescriptors('hsOfficeContact', 'hs_office_contact');
--//
-- ============================================================================
--changeset hs-office-contact-rbac-insert-trigger:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
*/
create or replace procedure buildRbacSystemForHsOfficeContact(
NEW hs_office_contact
)
language plpgsql as $$
declare
begin
call enterTriggerForObjectUuid(NEW.uuid);
perform createRoleWithGrants(
hsOfficeContactOwner(NEW),
permissions => array['DELETE'],
incomingSuperRoles => array[globalAdmin()],
userUuids => array[currentUserUuid()]
);
perform createRoleWithGrants(
hsOfficeContactAdmin(NEW),
permissions => array['UPDATE'],
incomingSuperRoles => array[hsOfficeContactOwner(NEW)]
);
perform createRoleWithGrants(
hsOfficeContactReferrer(NEW),
permissions => array['SELECT'],
incomingSuperRoles => array[hsOfficeContactAdmin(NEW)]
);
call leaveTriggerForObjectUuid(NEW.uuid);
end; $$;
/*
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_contact row.
*/
create or replace function insertTriggerForHsOfficeContact_tf()
returns trigger
language plpgsql
strict as $$
begin
call buildRbacSystemForHsOfficeContact(NEW);
return NEW;
end; $$;
create trigger insertTriggerForHsOfficeContact_tg
after insert on hs_office_contact
for each row
execute procedure insertTriggerForHsOfficeContact_tf();
--//
-- ============================================================================
--changeset hs-office-contact-rbac-INSERT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/**
Checks if the user or assumed roles are allowed to insert a row to hs_office_contact,
where only global-admin has that permission.
*/
create or replace function hs_office_contact_insert_permission_missing_tf()
returns trigger
language plpgsql as $$
begin
raise exception '[403] insert into hs_office_contact not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids();
end; $$;
create trigger hs_office_contact_insert_permission_check_tg
before insert on hs_office_contact
for each row
when ( not isGlobalAdmin() )
execute procedure hs_office_contact_insert_permission_missing_tf();
--//
-- ============================================================================
--changeset hs-office-contact-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('hs_office_contact',
$idName$
label
$idName$);
--//
-- ============================================================================
--changeset hs-office-contact-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRestrictedView('hs_office_contact',
$orderBy$
label
$orderBy$,
$updates$
label = new.label,
postalAddress = new.postalAddress,
emailAddresses = new.emailAddresses,
phoneNumbers = new.phoneNumbers
$updates$);
--//

View File

@@ -24,6 +24,7 @@ subgraph contact["`**contact**`"]
perm:contact:DELETE{{contact:DELETE}}
perm:contact:UPDATE{{contact:UPDATE}}
perm:contact:SELECT{{contact:SELECT}}
perm:contact:INSERT{{contact:INSERT}}
end
end
@@ -39,5 +40,6 @@ role:contact:admin ==> role:contact:referrer
role:contact:owner ==> perm:contact:DELETE
role:contact:admin ==> perm:contact:UPDATE
role:contact:referrer ==> perm:contact:SELECT
role:global:guest ==> perm:contact:INSERT
```

View File

@@ -1,4 +1,6 @@
--liquibase formatted sql
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
-- ============================================================================
--changeset hs-office-contact-rbac-OBJECT:1 endDelimiter:--//
@@ -15,127 +17,130 @@ call generateRbacRoleDescriptors('hsOfficeContact', 'hs_office_contact');
-- ============================================================================
--changeset hs-office-contact-rbac-ROLES-CREATION:1 endDelimiter:--//
--changeset hs-office-contact-rbac-insert-trigger:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates the roles and their assignments for a new contact for the AFTER INSERT TRIGGER.
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
*/
create or replace function createRbacRolesForHsOfficeContact()
create or replace procedure buildRbacSystemForHsOfficeContact(
NEW hs_office_contact
)
language plpgsql as $$
declare
begin
call enterTriggerForObjectUuid(NEW.uuid);
perform createRoleWithGrants(
hsOfficeContactOwner(NEW),
permissions => array['DELETE'],
incomingSuperRoles => array[globalAdmin()],
userUuids => array[currentUserUuid()]
);
perform createRoleWithGrants(
hsOfficeContactAdmin(NEW),
permissions => array['UPDATE'],
incomingSuperRoles => array[hsOfficeContactOwner(NEW)]
);
perform createRoleWithGrants(
hsOfficeContactReferrer(NEW),
permissions => array['SELECT'],
incomingSuperRoles => array[hsOfficeContactAdmin(NEW)]
);
call leaveTriggerForObjectUuid(NEW.uuid);
end; $$;
/*
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_contact row.
*/
create or replace function insertTriggerForHsOfficeContact_tf()
returns trigger
language plpgsql
strict as $$
begin
if TG_OP <> 'INSERT' then
raise exception 'invalid usage of TRIGGER AFTER INSERT';
end if;
perform createRoleWithGrants(
hsOfficeContactOwner(NEW),
permissions => array['DELETE'],
incomingSuperRoles => array[globalAdmin()],
userUuids => array[currentUserUuid()],
grantedByRole => globalAdmin()
);
perform createRoleWithGrants(
hsOfficeContactAdmin(NEW),
permissions => array['UPDATE'],
incomingSuperRoles => array[hsOfficeContactOwner(NEW)]
);
perform createRoleWithGrants(
hsOfficeContactTenant(NEW),
incomingSuperRoles => array[hsOfficeContactAdmin(NEW)]
);
perform createRoleWithGrants(
hsOfficeContactGuest(NEW),
permissions => array['SELECT'],
incomingSuperRoles => array[hsOfficeContactTenant(NEW)]
);
call buildRbacSystemForHsOfficeContact(NEW);
return NEW;
end; $$;
/*
An AFTER INSERT TRIGGER which creates the role structure for a new customer.
*/
create trigger createRbacRolesForHsOfficeContact_Trigger
after insert
on hs_office_contact
create trigger insertTriggerForHsOfficeContact_tg
after insert on hs_office_contact
for each row
execute procedure createRbacRolesForHsOfficeContact();
execute procedure insertTriggerForHsOfficeContact_tf();
--//
-- ============================================================================
--changeset hs-office-contact-rbac-INSERT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates INSERT INTO hs_office_contact permissions for the related global rows.
*/
do language plpgsql $$
declare
row global;
begin
call defineContext('create INSERT INTO hs_office_contact permissions for the related global rows');
FOR row IN SELECT * FROM global
LOOP
call grantPermissionToRole(
createPermission(row.uuid, 'INSERT', 'hs_office_contact'),
globalGuest());
END LOOP;
END;
$$;
/**
Adds hs_office_contact INSERT permission to specified role of new global rows.
*/
create or replace function hs_office_contact_global_insert_tf()
returns trigger
language plpgsql
strict as $$
begin
call grantPermissionToRole(
createPermission(NEW.uuid, 'INSERT', 'hs_office_contact'),
globalGuest());
return NEW;
end; $$;
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
create trigger z_hs_office_contact_global_insert_tg
after insert on global
for each row
execute procedure hs_office_contact_global_insert_tf();
--//
-- ============================================================================
--changeset hs-office-contact-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('hs_office_contact', $idName$
target.label
call generateRbacIdentityViewFromProjection('hs_office_contact',
$idName$
label
$idName$);
--//
-- ============================================================================
--changeset hs-office-contact-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRestrictedView('hs_office_contact', 'target.label',
call generateRbacRestrictedView('hs_office_contact',
$orderBy$
label
$orderBy$,
$updates$
label = new.label,
postalAddress = new.postalAddress,
emailAddresses = new.emailAddresses,
phoneNumbers = new.phoneNumbers
$updates$);
--/
-- ============================================================================
--changeset hs-office-contact-rbac-NEW-CONTACT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates a global permission for new-contact and assigns it to the hostsharing admins role.
*/
do language plpgsql $$
declare
addCustomerPermissions uuid[];
globalObjectUuid uuid;
globalAdminRoleUuid uuid;
begin
call defineContext('granting global new-contact permission to global admin role', null, null, null);
globalAdminRoleUuid := findRoleId(globalAdmin());
globalObjectUuid := (select uuid from global);
addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-contact']);
call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions);
end;
$$;
/**
Used by the trigger to prevent the add-customer to current user respectively assumed roles.
*/
create or replace function addHsOfficeContactNotAllowedForCurrentSubjects()
returns trigger
language PLPGSQL
as $$
begin
raise exception '[403] new-contact 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_contact_insert_trigger
before insert
on hs_office_contact
for each row
-- TODO.spec: who is allowed to create new contacts
when ( not hasAssumedRole() )
execute procedure addHsOfficeContactNotAllowedForCurrentSubjects();
--//

View File

@@ -22,7 +22,6 @@ create table if not exists hs_office_person
givenName varchar(48),
familyName varchar(48)
);
--//
-- ============================================================================

View File

@@ -1,126 +0,0 @@
--liquibase formatted sql
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
-- ============================================================================
--changeset hs-office-person-rbac-OBJECT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRelatedRbacObject('hs_office_person');
--//
-- ============================================================================
--changeset hs-office-person-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRoleDescriptors('hsOfficePerson', 'hs_office_person');
--//
-- ============================================================================
--changeset hs-office-person-rbac-insert-trigger:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
*/
create or replace procedure buildRbacSystemForHsOfficePerson(
NEW hs_office_person
)
language plpgsql as $$
declare
begin
call enterTriggerForObjectUuid(NEW.uuid);
perform createRoleWithGrants(
hsOfficePersonOwner(NEW),
permissions => array['DELETE'],
incomingSuperRoles => array[globalAdmin()],
userUuids => array[currentUserUuid()]
);
perform createRoleWithGrants(
hsOfficePersonAdmin(NEW),
permissions => array['UPDATE'],
incomingSuperRoles => array[hsOfficePersonOwner(NEW)]
);
perform createRoleWithGrants(
hsOfficePersonReferrer(NEW),
permissions => array['SELECT'],
incomingSuperRoles => array[hsOfficePersonAdmin(NEW)]
);
call leaveTriggerForObjectUuid(NEW.uuid);
end; $$;
/*
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_person row.
*/
create or replace function insertTriggerForHsOfficePerson_tf()
returns trigger
language plpgsql
strict as $$
begin
call buildRbacSystemForHsOfficePerson(NEW);
return NEW;
end; $$;
create trigger insertTriggerForHsOfficePerson_tg
after insert on hs_office_person
for each row
execute procedure insertTriggerForHsOfficePerson_tf();
--//
-- ============================================================================
--changeset hs-office-person-rbac-INSERT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/**
Checks if the user or assumed roles are allowed to insert a row to hs_office_person,
where only global-admin has that permission.
*/
create or replace function hs_office_person_insert_permission_missing_tf()
returns trigger
language plpgsql as $$
begin
raise exception '[403] insert into hs_office_person not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids();
end; $$;
create trigger hs_office_person_insert_permission_check_tg
before insert on hs_office_person
for each row
when ( not isGlobalAdmin() )
execute procedure hs_office_person_insert_permission_missing_tf();
--//
-- ============================================================================
--changeset hs-office-person-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('hs_office_person',
$idName$
concat(tradeName, familyName, givenName)
$idName$);
--//
-- ============================================================================
--changeset hs-office-person-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRestrictedView('hs_office_person',
$orderBy$
concat(tradeName, familyName, givenName)
$orderBy$,
$updates$
personType = new.personType,
tradeName = new.tradeName,
givenName = new.givenName,
familyName = new.familyName
$updates$);
--//

View File

@@ -21,6 +21,7 @@ subgraph person["`**person**`"]
subgraph person:permissions[ ]
style person:permissions fill:#dd4901,stroke:white
perm:person:INSERT{{person:INSERT}}
perm:person:DELETE{{person:DELETE}}
perm:person:UPDATE{{person:UPDATE}}
perm:person:SELECT{{person:SELECT}}
@@ -36,6 +37,7 @@ role:person:owner ==> role:person:admin
role:person:admin ==> role:person:referrer
%% granting permissions to roles
role:global:guest ==> perm:person:INSERT
role:person:owner ==> perm:person:DELETE
role:person:admin ==> perm:person:UPDATE
role:person:referrer ==> perm:person:SELECT

View File

@@ -1,4 +1,6 @@
--liquibase formatted sql
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
-- ============================================================================
--changeset hs-office-person-rbac-OBJECT:1 endDelimiter:--//
@@ -15,74 +17,125 @@ call generateRbacRoleDescriptors('hsOfficePerson', 'hs_office_person');
-- ============================================================================
--changeset hs-office-person-rbac-ROLES-CREATION:1 endDelimiter:--//
--changeset hs-office-person-rbac-insert-trigger:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates the roles and their assignments for a new person for the AFTER INSERT TRIGGER.
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
*/
create or replace function createRbacRolesForHsOfficePerson()
create or replace procedure buildRbacSystemForHsOfficePerson(
NEW hs_office_person
)
language plpgsql as $$
declare
begin
call enterTriggerForObjectUuid(NEW.uuid);
perform createRoleWithGrants(
hsOfficePersonOwner(NEW),
permissions => array['DELETE'],
incomingSuperRoles => array[globalAdmin()],
userUuids => array[currentUserUuid()]
);
perform createRoleWithGrants(
hsOfficePersonAdmin(NEW),
permissions => array['UPDATE'],
incomingSuperRoles => array[hsOfficePersonOwner(NEW)]
);
perform createRoleWithGrants(
hsOfficePersonReferrer(NEW),
permissions => array['SELECT'],
incomingSuperRoles => array[hsOfficePersonAdmin(NEW)]
);
call leaveTriggerForObjectUuid(NEW.uuid);
end; $$;
/*
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_person row.
*/
create or replace function insertTriggerForHsOfficePerson_tf()
returns trigger
language plpgsql
strict as $$
begin
if TG_OP <> 'INSERT' then
raise exception 'invalid usage of TRIGGER AFTER INSERT';
end if;
perform createRoleWithGrants(
hsOfficePersonOwner(NEW),
permissions => array['DELETE'],
incomingSuperRoles => array[globalAdmin()],
userUuids => array[currentUserUuid()],
grantedByRole => globalAdmin()
);
-- TODO: who is admin? the person itself? is it allowed for the person itself or a representative to update the data?
perform createRoleWithGrants(
hsOfficePersonAdmin(NEW),
permissions => array['UPDATE'],
incomingSuperRoles => array[hsOfficePersonOwner(NEW)]
);
perform createRoleWithGrants(
hsOfficePersonTenant(NEW),
incomingSuperRoles => array[hsOfficePersonAdmin(NEW)]
);
perform createRoleWithGrants(
hsOfficePersonGuest(NEW),
permissions => array['SELECT'],
incomingSuperRoles => array[hsOfficePersonTenant(NEW)]
);
call buildRbacSystemForHsOfficePerson(NEW);
return NEW;
end; $$;
/*
An AFTER INSERT TRIGGER which creates the role structure for a new customer.
*/
create trigger createRbacRolesForHsOfficePerson_Trigger
after insert
on hs_office_person
create trigger insertTriggerForHsOfficePerson_tg
after insert on hs_office_person
for each row
execute procedure createRbacRolesForHsOfficePerson();
execute procedure insertTriggerForHsOfficePerson_tf();
--//
-- ============================================================================
--changeset hs-office-person-rbac-INSERT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates INSERT INTO hs_office_person permissions for the related global rows.
*/
do language plpgsql $$
declare
row global;
begin
call defineContext('create INSERT INTO hs_office_person permissions for the related global rows');
FOR row IN SELECT * FROM global
LOOP
call grantPermissionToRole(
createPermission(row.uuid, 'INSERT', 'hs_office_person'),
globalGuest());
END LOOP;
END;
$$;
/**
Adds hs_office_person INSERT permission to specified role of new global rows.
*/
create or replace function hs_office_person_global_insert_tf()
returns trigger
language plpgsql
strict as $$
begin
call grantPermissionToRole(
createPermission(NEW.uuid, 'INSERT', 'hs_office_person'),
globalGuest());
return NEW;
end; $$;
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
create trigger z_hs_office_person_global_insert_tg
after insert on global
for each row
execute procedure hs_office_person_global_insert_tf();
--//
-- ============================================================================
--changeset hs-office-person-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('hs_office_person', $idName$
concat(target.tradeName, target.familyName, target.givenName)
call generateRbacIdentityViewFromProjection('hs_office_person',
$idName$
concat(tradeName, familyName, givenName)
$idName$);
--//
-- ============================================================================
--changeset hs-office-person-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRestrictedView('hs_office_person', 'concat(target.tradeName, target.familyName, target.givenName)',
call generateRbacRestrictedView('hs_office_person',
$orderBy$
concat(tradeName, familyName, givenName)
$orderBy$,
$updates$
personType = new.personType,
tradeName = new.tradeName,
@@ -91,49 +144,3 @@ call generateRbacRestrictedView('hs_office_person', 'concat(target.tradeName, ta
$updates$);
--//
-- ============================================================================
--changeset hs-office-person-rbac-NEW-PERSON:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates a global permission for new-person and assigns it to the hostsharing admins role.
*/
do language plpgsql $$
declare
addCustomerPermissions uuid[];
globalObjectUuid uuid;
globalAdminRoleUuid uuid ;
begin
call defineContext('granting global new-person permission to global admin role', null, null, null);
globalAdminRoleUuid := findRoleId(globalAdmin());
globalObjectUuid := (select uuid from global);
addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-person']);
call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions);
end;
$$;
/**
Used by the trigger to prevent the add-customer to current user respectively assumed roles.
*/
create or replace function addHsOfficePersonNotAllowedForCurrentSubjects()
returns trigger
language PLPGSQL
as $$
begin
raise exception '[403] new-person 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_person_insert_trigger
before insert
on hs_office_person
for each row
-- TODO.spec: who is allowed to create new persons
when ( not hasAssumedRole() )
execute procedure addHsOfficePersonNotAllowedForCurrentSubjects();
--//

View File

@@ -28,7 +28,7 @@ begin
call defineContext(currentTask, null, emailAddr);
execute format('set local hsadminng.currentTask to %L', currentTask);
raise notice 'creating test person: %', fullName;
raise notice 'creating test person: % by %', fullName, emailAddr;
insert
into hs_office_person (persontype, tradename, givenname, familyname)
values (newPersonType, newTradeName, newGivenName, newFamilyName);
@@ -67,9 +67,10 @@ do language plpgsql $$
call createHsOfficePersonTestData('NP', null, 'Fouler', 'Ellie');
call createHsOfficePersonTestData('LP', 'Second e.K.', 'Smith', 'Peter');
call createHsOfficePersonTestData('IF', 'Third OHG');
call createHsOfficePersonTestData('IF', 'Fourth eG');
call createHsOfficePersonTestData('LP', 'Fourth eG');
call createHsOfficePersonTestData('UF', 'Erben Bessler', 'Mel', 'Bessler');
call createHsOfficePersonTestData('NP', null, 'Bessler', 'Anita');
call createHsOfficePersonTestData('NP', null, 'Bessler', 'Bert');
call createHsOfficePersonTestData('NP', null, 'Winkler', 'Paul');
end;
$$;

View File

@@ -1,100 +0,0 @@
### rbac relation
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
```mermaid
%%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB
subgraph holderPerson["`**holderPerson**`"]
direction TB
style holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph holderPerson:roles[ ]
style holderPerson:roles fill:#99bcdb,stroke:white
role:holderPerson:owner[[holderPerson:owner]]
role:holderPerson:admin[[holderPerson:admin]]
role:holderPerson:referrer[[holderPerson:referrer]]
end
end
subgraph anchorPerson["`**anchorPerson**`"]
direction TB
style anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph anchorPerson:roles[ ]
style anchorPerson:roles fill:#99bcdb,stroke:white
role:anchorPerson:owner[[anchorPerson:owner]]
role:anchorPerson:admin[[anchorPerson:admin]]
role:anchorPerson:referrer[[anchorPerson:referrer]]
end
end
subgraph contact["`**contact**`"]
direction TB
style contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph contact:roles[ ]
style contact:roles fill:#99bcdb,stroke:white
role:contact:owner[[contact:owner]]
role:contact:admin[[contact:admin]]
role:contact:referrer[[contact:referrer]]
end
end
subgraph relation["`**relation**`"]
direction TB
style relation fill:#dd4901,stroke:#274d6e,stroke-width:8px
subgraph relation:roles[ ]
style relation:roles fill:#dd4901,stroke:white
role:relation:owner[[relation:owner]]
role:relation:admin[[relation:admin]]
role:relation:agent[[relation:agent]]
role:relation:tenant[[relation:tenant]]
end
subgraph relation:permissions[ ]
style relation:permissions fill:#dd4901,stroke:white
perm:relation:DELETE{{relation:DELETE}}
perm:relation:UPDATE{{relation:UPDATE}}
perm:relation:SELECT{{relation:SELECT}}
end
end
%% granting roles to users
user:creator ==> role:relation:owner
%% granting roles to roles
role:global:admin -.-> role:anchorPerson:owner
role:anchorPerson:owner -.-> role:anchorPerson:admin
role:anchorPerson:admin -.-> role:anchorPerson:referrer
role:global:admin -.-> role:holderPerson:owner
role:holderPerson:owner -.-> role:holderPerson:admin
role:holderPerson:admin -.-> role:holderPerson:referrer
role:global:admin -.-> role:contact:owner
role:contact:owner -.-> role:contact:admin
role:contact:admin -.-> role:contact:referrer
role:global:admin ==> role:relation:owner
role:relation:owner ==> role:relation:admin
role:anchorPerson:admin ==> role:relation:admin
role:relation:admin ==> role:relation:agent
role:holderPerson:admin ==> role:relation:agent
role:relation:agent ==> role:relation:tenant
role:holderPerson:admin ==> role:relation:tenant
role:contact:admin ==> role:relation:tenant
role:relation:tenant ==> role:anchorPerson:referrer
role:relation:tenant ==> role:holderPerson:referrer
role:relation:tenant ==> role:contact:referrer
%% granting permissions to roles
role:relation:owner ==> perm:relation:DELETE
role:relation:admin ==> perm:relation:UPDATE
role:relation:tenant ==> perm:relation:SELECT
```

View File

@@ -1,191 +0,0 @@
--liquibase formatted sql
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
-- ============================================================================
--changeset hs-office-relation-rbac-OBJECT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRelatedRbacObject('hs_office_relation');
--//
-- ============================================================================
--changeset hs-office-relation-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRoleDescriptors('hsOfficeRelation', 'hs_office_relation');
--//
-- ============================================================================
--changeset hs-office-relation-rbac-insert-trigger:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
*/
create or replace procedure buildRbacSystemForHsOfficeRelation(
NEW hs_office_relation
)
language plpgsql as $$
declare
newHolderPerson hs_office_person;
newAnchorPerson hs_office_person;
newContact hs_office_contact;
begin
call enterTriggerForObjectUuid(NEW.uuid);
SELECT * FROM hs_office_person WHERE uuid = NEW.holderUuid INTO newHolderPerson;
SELECT * FROM hs_office_person WHERE uuid = NEW.anchorUuid INTO newAnchorPerson;
SELECT * FROM hs_office_contact WHERE uuid = NEW.contactUuid INTO newContact;
perform createRoleWithGrants(
hsOfficeRelationOwner(NEW),
permissions => array['DELETE'],
incomingSuperRoles => array[globalAdmin()],
userUuids => array[currentUserUuid()]
);
perform createRoleWithGrants(
hsOfficeRelationAdmin(NEW),
permissions => array['UPDATE'],
incomingSuperRoles => array[
hsOfficePersonAdmin(newAnchorPerson),
hsOfficeRelationOwner(NEW)]
);
perform createRoleWithGrants(
hsOfficeRelationAgent(NEW),
incomingSuperRoles => array[
hsOfficePersonAdmin(newHolderPerson),
hsOfficeRelationAdmin(NEW)]
);
perform createRoleWithGrants(
hsOfficeRelationTenant(NEW),
permissions => array['SELECT'],
incomingSuperRoles => array[
hsOfficeContactAdmin(newContact),
hsOfficePersonAdmin(newHolderPerson),
hsOfficeRelationAgent(NEW)],
outgoingSubRoles => array[
hsOfficeContactReferrer(newContact),
hsOfficePersonReferrer(newAnchorPerson),
hsOfficePersonReferrer(newHolderPerson)]
);
call leaveTriggerForObjectUuid(NEW.uuid);
end; $$;
/*
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_relation row.
*/
create or replace function insertTriggerForHsOfficeRelation_tf()
returns trigger
language plpgsql
strict as $$
begin
call buildRbacSystemForHsOfficeRelation(NEW);
return NEW;
end; $$;
create trigger insertTriggerForHsOfficeRelation_tg
after insert on hs_office_relation
for each row
execute procedure insertTriggerForHsOfficeRelation_tf();
--//
-- ============================================================================
--changeset hs-office-relation-rbac-update-trigger:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Called from the AFTER UPDATE TRIGGER to re-wire the grants.
*/
create or replace procedure updateRbacRulesForHsOfficeRelation(
OLD hs_office_relation,
NEW hs_office_relation
)
language plpgsql as $$
begin
if NEW.contactUuid is distinct from OLD.contactUuid then
delete from rbacgrants g where g.grantedbytriggerof = OLD.uuid;
call buildRbacSystemForHsOfficeRelation(NEW);
end if;
end; $$;
/*
AFTER INSERT TRIGGER to re-wire the grant structure for a new hs_office_relation row.
*/
create or replace function updateTriggerForHsOfficeRelation_tf()
returns trigger
language plpgsql
strict as $$
begin
call updateRbacRulesForHsOfficeRelation(OLD, NEW);
return NEW;
end; $$;
create trigger updateTriggerForHsOfficeRelation_tg
after update on hs_office_relation
for each row
execute procedure updateTriggerForHsOfficeRelation_tf();
--//
-- ============================================================================
--changeset hs-office-relation-rbac-INSERT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/**
Checks if the user or assumed roles are allowed to insert a row to hs_office_relation,
where only global-admin has that permission.
*/
create or replace function hs_office_relation_insert_permission_missing_tf()
returns trigger
language plpgsql as $$
begin
raise exception '[403] insert into hs_office_relation not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids();
end; $$;
create trigger hs_office_relation_insert_permission_check_tg
before insert on hs_office_relation
for each row
when ( not isGlobalAdmin() )
execute procedure hs_office_relation_insert_permission_missing_tf();
--//
-- ============================================================================
--changeset hs-office-relation-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('hs_office_relation',
$idName$
(select idName from hs_office_person_iv p where p.uuid = anchorUuid)
|| '-with-' || target.type || '-'
|| (select idName from hs_office_person_iv p where p.uuid = holderUuid)
$idName$);
--//
-- ============================================================================
--changeset hs-office-relation-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRestrictedView('hs_office_relation',
$orderBy$
(select idName from hs_office_person_iv p where p.uuid = target.holderUuid)
$orderBy$,
$updates$
contactUuid = new.contactUuid
$updates$);
--//

View File

@@ -1,44 +1,102 @@
### hs_office_relation RBAC
### rbac relation
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
```mermaid
%%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB
subgraph global
style global fill:#eee
role:global.admin[global.admin]
end
subgraph hsOfficeContact
subgraph holderPerson["`**holderPerson**`"]
direction TB
style hsOfficeContact fill:#eee
role:hsOfficeContact.admin[contact.admin]
--> role:hsOfficeContact.tenant[contact.tenant]
--> role:hsOfficeContact.guest[contact.guest]
style holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph holderPerson:roles[ ]
style holderPerson:roles fill:#99bcdb,stroke:white
role:holderPerson:owner[[holderPerson:owner]]
role:holderPerson:admin[[holderPerson:admin]]
role:holderPerson:referrer[[holderPerson:referrer]]
end
end
subgraph hsOfficePerson
subgraph anchorPerson["`**anchorPerson**`"]
direction TB
style hsOfficePerson fill:#eee
role:hsOfficePerson.admin[person.admin]
--> role:hsOfficePerson.tenant[person.tenant]
--> role:hsOfficePerson.guest[person.guest]
style anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph anchorPerson:roles[ ]
style anchorPerson:roles fill:#99bcdb,stroke:white
role:anchorPerson:owner[[anchorPerson:owner]]
role:anchorPerson:admin[[anchorPerson:admin]]
role:anchorPerson:referrer[[anchorPerson:referrer]]
end
end
subgraph hsOfficeRelation
subgraph contact["`**contact**`"]
direction TB
style contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
role:hsOfficePerson#anchor.admin[person#anchor.admin]
--- role:hsOfficePerson.admin
role:hsOfficeRelation.owner[relation.owner]
%% permissions
role:hsOfficeRelation.owner --> perm:hsOfficeRelation.*{{relation.*}}
%% incoming
role:global.admin ---> role:hsOfficeRelation.owner
role:hsOfficePersonAdmin#anchor.admin
subgraph contact:roles[ ]
style contact:roles fill:#99bcdb,stroke:white
role:contact:owner[[contact:owner]]
role:contact:admin[[contact:admin]]
role:contact:referrer[[contact:referrer]]
end
end
subgraph relation["`**relation**`"]
direction TB
style relation fill:#dd4901,stroke:#274d6e,stroke-width:8px
subgraph relation:roles[ ]
style relation:roles fill:#dd4901,stroke:white
role:relation:owner[[relation:owner]]
role:relation:admin[[relation:admin]]
role:relation:agent[[relation:agent]]
role:relation:tenant[[relation:tenant]]
end
subgraph relation:permissions[ ]
style relation:permissions fill:#dd4901,stroke:white
perm:relation:DELETE{{relation:DELETE}}
perm:relation:UPDATE{{relation:UPDATE}}
perm:relation:SELECT{{relation:SELECT}}
perm:relation:INSERT{{relation:INSERT}}
end
end
%% granting roles to users
user:creator ==> role:relation:owner
%% granting roles to roles
role:global:admin -.-> role:anchorPerson:owner
role:anchorPerson:owner -.-> role:anchorPerson:admin
role:anchorPerson:admin -.-> role:anchorPerson:referrer
role:global:admin -.-> role:holderPerson:owner
role:holderPerson:owner -.-> role:holderPerson:admin
role:holderPerson:admin -.-> role:holderPerson:referrer
role:global:admin -.-> role:contact:owner
role:contact:owner -.-> role:contact:admin
role:contact:admin -.-> role:contact:referrer
role:global:admin ==> role:relation:owner
role:relation:owner ==> role:relation:admin
role:anchorPerson:admin ==> role:relation:admin
role:relation:admin ==> role:relation:agent
role:holderPerson:admin ==> role:relation:agent
role:relation:agent ==> role:relation:tenant
role:holderPerson:admin ==> role:relation:tenant
role:contact:admin ==> role:relation:tenant
role:relation:tenant ==> role:anchorPerson:referrer
role:relation:tenant ==> role:holderPerson:referrer
role:relation:tenant ==> role:contact:referrer
%% granting permissions to roles
role:relation:owner ==> perm:relation:DELETE
role:relation:admin ==> perm:relation:UPDATE
role:relation:tenant ==> perm:relation:SELECT
role:anchorPerson:admin ==> perm:relation:INSERT
```

View File

@@ -1,4 +1,6 @@
--liquibase formatted sql
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
-- ============================================================================
--changeset hs-office-relation-rbac-OBJECT:1 endDelimiter:--//
@@ -15,178 +17,255 @@ call generateRbacRoleDescriptors('hsOfficeRelation', 'hs_office_relation');
-- ============================================================================
--changeset hs-office-relation-rbac-ROLES-CREATION:1 endDelimiter:--//
--changeset hs-office-relation-rbac-insert-trigger:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates and updates the roles and their assignments for relation entities.
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
*/
create or replace function hsOfficeRelationRbacRolesTrigger()
returns trigger
language plpgsql
strict as $$
create or replace procedure buildRbacSystemForHsOfficeRelation(
NEW hs_office_relation
)
language plpgsql as $$
declare
hsOfficeRelationTenant RbacRoleDescriptor;
newAnchor hs_office_person;
newHolder hs_office_person;
oldContact hs_office_contact;
newContact hs_office_contact;
newHolderPerson hs_office_person;
newAnchorPerson hs_office_person;
newContact hs_office_contact;
begin
call enterTriggerForObjectUuid(NEW.uuid);
hsOfficeRelationTenant := hsOfficeRelationTenant(NEW);
SELECT * FROM hs_office_person WHERE uuid = NEW.holderUuid INTO newHolderPerson;
assert newHolderPerson.uuid is not null, format('newHolderPerson must not be null for NEW.holderUuid = %s', NEW.holderUuid);
select * from hs_office_person as p where p.uuid = NEW.anchorUuid into newAnchor;
select * from hs_office_person as p where p.uuid = NEW.holderUuid into newHolder;
select * from hs_office_contact as c where c.uuid = NEW.contactUuid into newContact;
SELECT * FROM hs_office_person WHERE uuid = NEW.anchorUuid INTO newAnchorPerson;
assert newAnchorPerson.uuid is not null, format('newAnchorPerson must not be null for NEW.anchorUuid = %s', NEW.anchorUuid);
if TG_OP = 'INSERT' then
SELECT * FROM hs_office_contact WHERE uuid = NEW.contactUuid INTO newContact;
assert newContact.uuid is not null, format('newContact must not be null for NEW.contactUuid = %s', NEW.contactUuid);
perform createRoleWithGrants(
hsOfficeRelationOwner(NEW),
permissions => array['DELETE'],
incomingSuperRoles => array[
globalAdmin(),
hsOfficePersonAdmin(newAnchor)]
);
perform createRoleWithGrants(
hsOfficeRelationAdmin(NEW),
permissions => array['UPDATE'],
incomingSuperRoles => array[hsOfficeRelationOwner(NEW)]
);
perform createRoleWithGrants(
hsOfficeRelationOwner(NEW),
permissions => array['DELETE'],
incomingSuperRoles => array[globalAdmin()],
userUuids => array[currentUserUuid()]
);
-- the tenant role for those related users who can view the data
perform createRoleWithGrants(
hsOfficeRelationTenant,
permissions => array['SELECT'],
incomingSuperRoles => array[
hsOfficeRelationAdmin(NEW),
hsOfficePersonAdmin(newAnchor),
hsOfficePersonAdmin(newHolder),
hsOfficeContactAdmin(newContact)],
outgoingSubRoles => array[
hsOfficePersonTenant(newAnchor),
hsOfficePersonTenant(newHolder),
hsOfficeContactTenant(newContact)]
);
perform createRoleWithGrants(
hsOfficeRelationAdmin(NEW),
permissions => array['UPDATE'],
incomingSuperRoles => array[
hsOfficePersonAdmin(newAnchorPerson),
hsOfficeRelationOwner(NEW)]
);
-- anchor and holder admin roles need each others tenant role
-- to be able to see the joined relation
-- TODO: this can probably be avoided through agent+guest roles
call grantRoleToRole(hsOfficePersonTenant(newAnchor), hsOfficePersonAdmin(newHolder));
call grantRoleToRole(hsOfficePersonTenant(newHolder), hsOfficePersonAdmin(newAnchor));
call grantRoleToRoleIfNotNull(hsOfficePersonTenant(newHolder), hsOfficeContactAdmin(newContact));
perform createRoleWithGrants(
hsOfficeRelationAgent(NEW),
incomingSuperRoles => array[
hsOfficePersonAdmin(newHolderPerson),
hsOfficeRelationAdmin(NEW)]
);
elsif TG_OP = 'UPDATE' then
if OLD.contactUuid <> NEW.contactUuid then
-- nothing but the contact can be updated,
-- in other cases, a new relation needs to be created and the old updated
select * from hs_office_contact as c where c.uuid = OLD.contactUuid into oldContact;
call revokeRoleFromRole( hsOfficeRelationTenant, hsOfficeContactAdmin(oldContact) );
call grantRoleToRole( hsOfficeRelationTenant, hsOfficeContactAdmin(newContact) );
call revokeRoleFromRole( hsOfficeContactTenant(oldContact), hsOfficeRelationTenant );
call grantRoleToRole( hsOfficeContactTenant(newContact), hsOfficeRelationTenant );
end if;
else
raise exception 'invalid usage of TRIGGER';
end if;
perform createRoleWithGrants(
hsOfficeRelationTenant(NEW),
permissions => array['SELECT'],
incomingSuperRoles => array[
hsOfficeContactAdmin(newContact),
hsOfficePersonAdmin(newHolderPerson),
hsOfficeRelationAgent(NEW)],
outgoingSubRoles => array[
hsOfficeContactReferrer(newContact),
hsOfficePersonReferrer(newAnchorPerson),
hsOfficePersonReferrer(newHolderPerson)]
);
call leaveTriggerForObjectUuid(NEW.uuid);
return NEW;
end; $$;
/*
An AFTER INSERT TRIGGER which creates the role structure for a new customer.
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_relation row.
*/
create trigger createRbacRolesForHsOfficeRelation_Trigger
after insert
on hs_office_relation
for each row
execute procedure hsOfficeRelationRbacRolesTrigger();
/*
An AFTER UPDATE TRIGGER which updates the role structure of a customer.
*/
create trigger updateRbacRolesForHsOfficeRelation_Trigger
after update
on hs_office_relation
create or replace function insertTriggerForHsOfficeRelation_tf()
returns trigger
language plpgsql
strict as $$
begin
call buildRbacSystemForHsOfficeRelation(NEW);
return NEW;
end; $$;
create trigger insertTriggerForHsOfficeRelation_tg
after insert on hs_office_relation
for each row
execute procedure hsOfficeRelationRbacRolesTrigger();
execute procedure insertTriggerForHsOfficeRelation_tf();
--//
-- ============================================================================
--changeset hs-office-relation-rbac-IDENTITY-VIEW:1 endDelimiter:--//
--changeset hs-office-relation-rbac-update-trigger:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('hs_office_relation', $idName$
(select idName from hs_office_person_iv p where p.uuid = target.anchorUuid)
|| '-with-' || target.type || '-' ||
(select idName from hs_office_person_iv p where p.uuid = target.holderUuid)
$idName$);
/*
Called from the AFTER UPDATE TRIGGER to re-wire the grants.
*/
create or replace procedure updateRbacRulesForHsOfficeRelation(
OLD hs_office_relation,
NEW hs_office_relation
)
language plpgsql as $$
declare
oldHolderPerson hs_office_person;
newHolderPerson hs_office_person;
oldAnchorPerson hs_office_person;
newAnchorPerson hs_office_person;
oldContact hs_office_contact;
newContact hs_office_contact;
begin
call enterTriggerForObjectUuid(NEW.uuid);
SELECT * FROM hs_office_person WHERE uuid = OLD.holderUuid INTO oldHolderPerson;
assert oldHolderPerson.uuid is not null, format('oldHolderPerson must not be null for OLD.holderUuid = %s', OLD.holderUuid);
SELECT * FROM hs_office_person WHERE uuid = NEW.holderUuid INTO newHolderPerson;
assert newHolderPerson.uuid is not null, format('newHolderPerson must not be null for NEW.holderUuid = %s', NEW.holderUuid);
SELECT * FROM hs_office_person WHERE uuid = OLD.anchorUuid INTO oldAnchorPerson;
assert oldAnchorPerson.uuid is not null, format('oldAnchorPerson must not be null for OLD.anchorUuid = %s', OLD.anchorUuid);
SELECT * FROM hs_office_person WHERE uuid = NEW.anchorUuid INTO newAnchorPerson;
assert newAnchorPerson.uuid is not null, format('newAnchorPerson must not be null for NEW.anchorUuid = %s', NEW.anchorUuid);
SELECT * FROM hs_office_contact WHERE uuid = OLD.contactUuid INTO oldContact;
assert oldContact.uuid is not null, format('oldContact must not be null for OLD.contactUuid = %s', OLD.contactUuid);
SELECT * FROM hs_office_contact WHERE uuid = NEW.contactUuid INTO newContact;
assert newContact.uuid is not null, format('newContact must not be null for NEW.contactUuid = %s', NEW.contactUuid);
if NEW.contactUuid <> OLD.contactUuid then
call revokeRoleFromRole(hsOfficeRelationTenant(OLD), hsOfficeContactAdmin(oldContact));
call grantRoleToRole(hsOfficeRelationTenant(NEW), hsOfficeContactAdmin(newContact));
call revokeRoleFromRole(hsOfficeContactReferrer(oldContact), hsOfficeRelationTenant(OLD));
call grantRoleToRole(hsOfficeContactReferrer(newContact), hsOfficeRelationTenant(NEW));
end if;
call leaveTriggerForObjectUuid(NEW.uuid);
end; $$;
/*
AFTER INSERT TRIGGER to re-wire the grant structure for a new hs_office_relation row.
*/
create or replace function updateTriggerForHsOfficeRelation_tf()
returns trigger
language plpgsql
strict as $$
begin
call updateRbacRulesForHsOfficeRelation(OLD, NEW);
return NEW;
end; $$;
create trigger updateTriggerForHsOfficeRelation_tg
after update on hs_office_relation
for each row
execute procedure updateTriggerForHsOfficeRelation_tf();
--//
-- ============================================================================
--changeset hs-office-relation-rbac-INSERT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates INSERT INTO hs_office_relation permissions for the related hs_office_person rows.
*/
do language plpgsql $$
declare
row hs_office_person;
begin
call defineContext('create INSERT INTO hs_office_relation permissions for the related hs_office_person rows');
FOR row IN SELECT * FROM hs_office_person
LOOP
call grantPermissionToRole(
createPermission(row.uuid, 'INSERT', 'hs_office_relation'),
hsOfficePersonAdmin(row));
END LOOP;
END;
$$;
/**
Adds hs_office_relation INSERT permission to specified role of new hs_office_person rows.
*/
create or replace function hs_office_relation_hs_office_person_insert_tf()
returns trigger
language plpgsql
strict as $$
begin
call grantPermissionToRole(
createPermission(NEW.uuid, 'INSERT', 'hs_office_relation'),
hsOfficePersonAdmin(NEW));
return NEW;
end; $$;
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
create trigger z_hs_office_relation_hs_office_person_insert_tg
after insert on hs_office_person
for each row
execute procedure hs_office_relation_hs_office_person_insert_tf();
/**
Checks if the user or assumed roles are allowed to insert a row to hs_office_relation,
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_relation_insert_permission_missing_tf()
returns trigger
language plpgsql as $$
begin
raise exception '[403] insert into hs_office_relation not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids();
end; $$;
create trigger hs_office_relation_insert_permission_check_tg
before insert on hs_office_relation
for each row
when ( not hasInsertPermission(NEW.anchorUuid, 'INSERT', 'hs_office_relation') )
execute procedure hs_office_relation_insert_permission_missing_tf();
--//
-- ============================================================================
--changeset hs-office-relation-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('hs_office_relation',
$idName$
(select idName from hs_office_person_iv p where p.uuid = anchorUuid)
|| '-with-' || target.type || '-'
|| (select idName from hs_office_person_iv p where p.uuid = holderUuid)
$idName$);
--//
-- ============================================================================
--changeset hs-office-relation-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRestrictedView('hs_office_relation',
'(select idName from hs_office_person_iv p where p.uuid = target.holderUuid)',
$orderBy$
(select idName from hs_office_person_iv p where p.uuid = target.holderUuid)
$orderBy$,
$updates$
contactUuid = new.contactUuid
$updates$);
--//
-- TODO: exception if one tries to amend any other column
-- ============================================================================
--changeset hs-office-relation-rbac-NEW-RELATHIONSHIP:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates a global permission for new-relation and assigns it to the hostsharing admins role.
*/
do language plpgsql $$
declare
addCustomerPermissions uuid[];
globalObjectUuid uuid;
globalAdminRoleUuid uuid ;
begin
call defineContext('granting global new-relation permission to global admin role', null, null, null);
globalAdminRoleUuid := findRoleId(globalAdmin());
globalObjectUuid := (select uuid from global);
addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-relation']);
call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions);
end;
$$;
/**
Used by the trigger to prevent the add-customer to current user respectively assumed roles.
*/
create or replace function addHsOfficeRelationNotAllowedForCurrentSubjects()
returns trigger
language PLPGSQL
as $$
begin
raise exception '[403] new-relation 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_relation_insert_trigger
before insert
on hs_office_relation
for each row
-- TODO.spec: who is allowed to create new relations
when ( not hasAssumedRole() )
execute procedure addHsOfficeRelationNotAllowedForCurrentSubjects();
--//

View File

@@ -11,7 +11,7 @@
create or replace procedure createHsOfficeRelationTestData(
holderPersonName varchar,
relationType HsOfficeRelationType,
anchorPersonTradeName varchar,
anchorPersonName varchar,
contactLabel varchar,
mark varchar default null)
language plpgsql as $$
@@ -23,24 +23,28 @@ declare
contact hs_office_contact;
begin
idName := cleanIdentifier( anchorPersonTradeName || '-' || holderPersonName);
idName := cleanIdentifier( anchorPersonName || '-' || holderPersonName);
currentTask := 'creating relation test-data ' || idName;
call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global.admin');
execute format('set local hsadminng.currentTask to %L', currentTask);
select p.* from hs_office_person p where p.tradeName = anchorPersonTradeName into anchorPerson;
select p.*
into anchorPerson
from hs_office_person p
where p.tradeName = anchorPersonName or p.familyName = anchorPersonName;
if anchorPerson is null then
raise exception 'anchorPerson "%" not found', anchorPersonTradeName;
raise exception 'anchorPerson "%" not found', anchorPersonName;
end if;
select p.* from hs_office_person p
where p.tradeName = holderPersonName or p.familyName = holderPersonName
into holderPerson;
select p.*
into holderPerson
from hs_office_person p
where p.tradeName = holderPersonName or p.familyName = holderPersonName;
if holderPerson is null then
raise exception 'holderPerson "%" not found', holderPersonName;
end if;
select c.* from hs_office_contact c where c.label = contactLabel into contact;
select c.* into contact from hs_office_contact c where c.label = contactLabel;
if contact is null then
raise exception 'contact "%" not found', contactLabel;
end if;
@@ -87,17 +91,22 @@ do language plpgsql $$
begin
call createHsOfficeRelationTestData('First GmbH', 'PARTNER', 'Hostsharing eG', 'first contact');
call createHsOfficeRelationTestData('Firby', 'REPRESENTATIVE', 'First GmbH', 'first contact');
call createHsOfficeRelationTestData('First GmbH', 'DEBITOR', 'First GmbH', 'first contact');
call createHsOfficeRelationTestData('Second e.K.', 'PARTNER', 'Hostsharing eG', 'second contact');
call createHsOfficeRelationTestData('Smith', 'REPRESENTATIVE', 'Second e.K.', 'second contact');
call createHsOfficeRelationTestData('Second e.K.', 'DEBITOR', 'Second e.K.', 'second contact');
call createHsOfficeRelationTestData('Third OHG', 'PARTNER', 'Hostsharing eG', 'third contact');
call createHsOfficeRelationTestData('Tucker', 'REPRESENTATIVE', 'Third OHG', 'third contact');
call createHsOfficeRelationTestData('Third OHG', 'DEBITOR', 'Third OHG', 'third contact');
call createHsOfficeRelationTestData('Fourth eG', 'PARTNER', 'Hostsharing eG', 'fourth contact');
call createHsOfficeRelationTestData('Fouler', 'REPRESENTATIVE', 'Third OHG', 'third contact');
call createHsOfficeRelationTestData('Third OHG', 'DEBITOR', 'Third OHG', 'third contact');
call createHsOfficeRelationTestData('Smith', 'PARTNER', 'Hostsharing eG', 'sixth contact');
call createHsOfficeRelationTestData('Smith', 'DEBITOR', 'Smith', 'third contact');
call createHsOfficeRelationTestData('Smith', 'SUBSCRIBER', 'Third OHG', 'third contact', 'members-announce');
end;
$$;

View File

@@ -33,23 +33,20 @@ create table hs_office_partner
(
uuid uuid unique references RbacObject (uuid) initially deferred,
partnerNumber numeric(5) unique not null,
partnerRelUuid uuid not null references hs_office_relation(uuid), -- TODO: delete in after delete trigger
personUuid uuid not null references hs_office_person(uuid), -- TODO: remove, replaced by partnerRelUuid
contactUuid uuid not null references hs_office_contact(uuid), -- TODO: remove, replaced by partnerRelUuid
partnerRelUuid uuid not null references hs_office_relation(uuid), -- deleted in after delete trigger
detailsUuid uuid not null references hs_office_partner_details(uuid) -- deleted in after delete trigger
);
--//
-- ============================================================================
--changeset hs-office-partner-DELETE-DETAILS-TRIGGER:1 endDelimiter:--//
--changeset hs-office-partner-DELETE-DEPENDENTS-TRIGGER:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/**
Trigger function to delete related details of a partner to delete.
*/
create or replace function deleteHsOfficeDetailsOnPartnerDelete()
create or replace function deleteHsOfficeDependentsOnPartnerDelete()
returns trigger
language PLPGSQL
as $$
@@ -61,17 +58,24 @@ begin
if counter = 0 then
raise exception 'partner details % could not be deleted', OLD.detailsUuid;
end if;
DELETE FROM hs_office_relation r WHERE r.uuid = OLD.partnerRelUuid;
GET DIAGNOSTICS counter = ROW_COUNT;
if counter = 0 then
raise exception 'partner relation % could not be deleted', OLD.partnerRelUuid;
end if;
RETURN OLD;
end; $$;
/**
Triggers deletion of related details of a partner to delete.
Triggers deletion of related rows of a partner to delete.
*/
create trigger hs_office_partner_delete_details_trigger
create trigger hs_office_partner_delete_dependents_trigger
after delete
on hs_office_partner
for each row
execute procedure deleteHsOfficeDetailsOnPartnerDelete();
execute procedure deleteHsOfficeDependentsOnPartnerDelete();
-- ============================================================================
--changeset hs-office-partner-MAIN-TABLE-JOURNAL:1 endDelimiter:--//

View File

@@ -1,158 +0,0 @@
### rbac partner
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
```mermaid
%%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB
subgraph partnerRel.contact["`**partnerRel.contact**`"]
direction TB
style partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.contact:roles[ ]
style partnerRel.contact:roles fill:#99bcdb,stroke:white
role:partnerRel.contact:owner[[partnerRel.contact:owner]]
role:partnerRel.contact:admin[[partnerRel.contact:admin]]
role:partnerRel.contact:referrer[[partnerRel.contact:referrer]]
end
end
subgraph partner["`**partner**`"]
direction TB
style partner fill:#dd4901,stroke:#274d6e,stroke-width:8px
subgraph partner:permissions[ ]
style partner:permissions fill:#dd4901,stroke:white
perm:partner:INSERT{{partner:INSERT}}
perm:partner:DELETE{{partner:DELETE}}
perm:partner:UPDATE{{partner:UPDATE}}
perm:partner:SELECT{{partner:SELECT}}
end
subgraph partnerRel["`**partnerRel**`"]
direction TB
style partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.contact["`**partnerRel.contact**`"]
direction TB
style partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.contact:roles[ ]
style partnerRel.contact:roles fill:#99bcdb,stroke:white
role:partnerRel.contact:owner[[partnerRel.contact:owner]]
role:partnerRel.contact:admin[[partnerRel.contact:admin]]
role:partnerRel.contact:referrer[[partnerRel.contact:referrer]]
end
end
subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"]
direction TB
style partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.anchorPerson:roles[ ]
style partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:partnerRel.anchorPerson:owner[[partnerRel.anchorPerson:owner]]
role:partnerRel.anchorPerson:admin[[partnerRel.anchorPerson:admin]]
role:partnerRel.anchorPerson:referrer[[partnerRel.anchorPerson:referrer]]
end
end
subgraph partnerRel.holderPerson["`**partnerRel.holderPerson**`"]
direction TB
style partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.holderPerson:roles[ ]
style partnerRel.holderPerson:roles fill:#99bcdb,stroke:white
role:partnerRel.holderPerson:owner[[partnerRel.holderPerson:owner]]
role:partnerRel.holderPerson:admin[[partnerRel.holderPerson:admin]]
role:partnerRel.holderPerson:referrer[[partnerRel.holderPerson:referrer]]
end
end
subgraph partnerRel:roles[ ]
style partnerRel:roles fill:#99bcdb,stroke:white
role:partnerRel:owner[[partnerRel:owner]]
role:partnerRel:admin[[partnerRel:admin]]
role:partnerRel:agent[[partnerRel:agent]]
role:partnerRel:tenant[[partnerRel:tenant]]
end
end
end
subgraph partnerDetails["`**partnerDetails**`"]
direction TB
style partnerDetails fill:#feb28c,stroke:#274d6e,stroke-width:8px
subgraph partnerDetails:permissions[ ]
style partnerDetails:permissions fill:#feb28c,stroke:white
perm:partnerDetails:DELETE{{partnerDetails:DELETE}}
perm:partnerDetails:UPDATE{{partnerDetails:UPDATE}}
perm:partnerDetails:SELECT{{partnerDetails:SELECT}}
end
end
subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"]
direction TB
style partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.anchorPerson:roles[ ]
style partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:partnerRel.anchorPerson:owner[[partnerRel.anchorPerson:owner]]
role:partnerRel.anchorPerson:admin[[partnerRel.anchorPerson:admin]]
role:partnerRel.anchorPerson:referrer[[partnerRel.anchorPerson:referrer]]
end
end
subgraph partnerRel.holderPerson["`**partnerRel.holderPerson**`"]
direction TB
style partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.holderPerson:roles[ ]
style partnerRel.holderPerson:roles fill:#99bcdb,stroke:white
role:partnerRel.holderPerson:owner[[partnerRel.holderPerson:owner]]
role:partnerRel.holderPerson:admin[[partnerRel.holderPerson:admin]]
role:partnerRel.holderPerson:referrer[[partnerRel.holderPerson:referrer]]
end
end
%% granting roles to roles
role:global:admin -.-> role:partnerRel.anchorPerson:owner
role:partnerRel.anchorPerson:owner -.-> role:partnerRel.anchorPerson:admin
role:partnerRel.anchorPerson:admin -.-> role:partnerRel.anchorPerson:referrer
role:global:admin -.-> role:partnerRel.holderPerson:owner
role:partnerRel.holderPerson:owner -.-> role:partnerRel.holderPerson:admin
role:partnerRel.holderPerson:admin -.-> role:partnerRel.holderPerson:referrer
role:global:admin -.-> role:partnerRel.contact:owner
role:partnerRel.contact:owner -.-> role:partnerRel.contact:admin
role:partnerRel.contact:admin -.-> role:partnerRel.contact:referrer
role:global:admin -.-> role:partnerRel:owner
role:partnerRel:owner -.-> role:partnerRel:admin
role:partnerRel.anchorPerson:admin -.-> role:partnerRel:admin
role:partnerRel:admin -.-> role:partnerRel:agent
role:partnerRel.holderPerson:admin -.-> role:partnerRel:agent
role:partnerRel:agent -.-> role:partnerRel:tenant
role:partnerRel.holderPerson:admin -.-> role:partnerRel:tenant
role:partnerRel.contact:admin -.-> role:partnerRel:tenant
role:partnerRel:tenant -.-> role:partnerRel.anchorPerson:referrer
role:partnerRel:tenant -.-> role:partnerRel.holderPerson:referrer
role:partnerRel:tenant -.-> role:partnerRel.contact:referrer
%% granting permissions to roles
role:global:admin ==> perm:partner:INSERT
role:partnerRel:admin ==> perm:partner:DELETE
role:partnerRel:agent ==> perm:partner:UPDATE
role:partnerRel:tenant ==> perm:partner:SELECT
role:partnerRel:admin ==> perm:partnerDetails:DELETE
role:partnerRel:agent ==> perm:partnerDetails:UPDATE
role:partnerRel:agent ==> perm:partnerDetails:SELECT
```

View File

@@ -1,248 +0,0 @@
--liquibase formatted sql
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
-- ============================================================================
--changeset hs-office-partner-rbac-OBJECT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
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-insert-trigger:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
*/
create or replace procedure buildRbacSystemForHsOfficePartner(
NEW hs_office_partner
)
language plpgsql as $$
declare
newPartnerRel hs_office_relation;
newPartnerDetails hs_office_partner_details;
begin
call enterTriggerForObjectUuid(NEW.uuid);
SELECT * FROM hs_office_relation WHERE uuid = NEW.partnerRelUuid INTO newPartnerRel;
assert newPartnerRel.uuid is not null, format('newPartnerRel must not be null for NEW.partnerRelUuid = %s', NEW.partnerRelUuid);
SELECT * FROM hs_office_partner_details WHERE uuid = NEW.detailsUuid INTO newPartnerDetails;
assert newPartnerDetails.uuid is not null, format('newPartnerDetails must not be null for NEW.detailsUuid = %s', NEW.detailsUuid);
call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationAdmin(newPartnerRel));
call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationTenant(newPartnerRel));
call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationAgent(newPartnerRel));
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'DELETE'), hsOfficeRelationAdmin(newPartnerRel));
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'SELECT'), hsOfficeRelationAgent(newPartnerRel));
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationAgent(newPartnerRel));
call leaveTriggerForObjectUuid(NEW.uuid);
end; $$;
/*
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_partner row.
*/
create or replace function insertTriggerForHsOfficePartner_tf()
returns trigger
language plpgsql
strict as $$
begin
call buildRbacSystemForHsOfficePartner(NEW);
return NEW;
end; $$;
create trigger insertTriggerForHsOfficePartner_tg
after insert on hs_office_partner
for each row
execute procedure insertTriggerForHsOfficePartner_tf();
--//
-- ============================================================================
--changeset hs-office-partner-rbac-update-trigger:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Called from the AFTER UPDATE TRIGGER to re-wire the grants.
*/
create or replace procedure updateRbacRulesForHsOfficePartner(
OLD hs_office_partner,
NEW hs_office_partner
)
language plpgsql as $$
declare
oldPartnerRel hs_office_relation;
newPartnerRel hs_office_relation;
oldPartnerDetails hs_office_partner_details;
newPartnerDetails hs_office_partner_details;
begin
call enterTriggerForObjectUuid(NEW.uuid);
SELECT * FROM hs_office_relation WHERE uuid = OLD.partnerRelUuid INTO oldPartnerRel;
assert oldPartnerRel.uuid is not null, format('oldPartnerRel must not be null for OLD.partnerRelUuid = %s', OLD.partnerRelUuid);
SELECT * FROM hs_office_relation WHERE uuid = NEW.partnerRelUuid INTO newPartnerRel;
assert newPartnerRel.uuid is not null, format('newPartnerRel must not be null for NEW.partnerRelUuid = %s', NEW.partnerRelUuid);
SELECT * FROM hs_office_partner_details WHERE uuid = OLD.detailsUuid INTO oldPartnerDetails;
assert oldPartnerDetails.uuid is not null, format('oldPartnerDetails must not be null for OLD.detailsUuid = %s', OLD.detailsUuid);
SELECT * FROM hs_office_partner_details WHERE uuid = NEW.detailsUuid INTO newPartnerDetails;
assert newPartnerDetails.uuid is not null, format('newPartnerDetails must not be null for NEW.detailsUuid = %s', NEW.detailsUuid);
if NEW.partnerRelUuid <> OLD.partnerRelUuid then
call revokePermissionFromRole(getPermissionId(OLD.uuid, 'DELETE'), hsOfficeRelationAdmin(oldPartnerRel));
call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationAdmin(newPartnerRel));
call revokePermissionFromRole(getPermissionId(OLD.uuid, 'UPDATE'), hsOfficeRelationAgent(oldPartnerRel));
call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationAgent(newPartnerRel));
call revokePermissionFromRole(getPermissionId(OLD.uuid, 'SELECT'), hsOfficeRelationTenant(oldPartnerRel));
call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationTenant(newPartnerRel));
call revokePermissionFromRole(getPermissionId(oldPartnerDetails.uuid, 'DELETE'), hsOfficeRelationAdmin(oldPartnerRel));
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'DELETE'), hsOfficeRelationAdmin(newPartnerRel));
call revokePermissionFromRole(getPermissionId(oldPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationAgent(oldPartnerRel));
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationAgent(newPartnerRel));
call revokePermissionFromRole(getPermissionId(oldPartnerDetails.uuid, 'SELECT'), hsOfficeRelationAgent(oldPartnerRel));
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'SELECT'), hsOfficeRelationAgent(newPartnerRel));
end if;
call leaveTriggerForObjectUuid(NEW.uuid);
end; $$;
/*
AFTER INSERT TRIGGER to re-wire the grant structure for a new hs_office_partner row.
*/
create or replace function updateTriggerForHsOfficePartner_tf()
returns trigger
language plpgsql
strict as $$
begin
call updateRbacRulesForHsOfficePartner(OLD, NEW);
return NEW;
end; $$;
create trigger updateTriggerForHsOfficePartner_tg
after update on hs_office_partner
for each row
execute procedure updateTriggerForHsOfficePartner_tf();
--//
-- ============================================================================
--changeset hs-office-partner-rbac-INSERT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates INSERT INTO hs_office_partner permissions for the related global rows.
*/
do language plpgsql $$
declare
row global;
permissionUuid uuid;
roleUuid uuid;
begin
call defineContext('create INSERT INTO hs_office_partner permissions for the related global rows');
FOR row IN SELECT * FROM global
LOOP
roleUuid := findRoleId(globalAdmin());
permissionUuid := createPermission(row.uuid, 'INSERT', 'hs_office_partner');
call grantPermissionToRole(permissionUuid, roleUuid);
END LOOP;
END;
$$;
/**
Adds hs_office_partner INSERT permission to specified role of new global rows.
*/
create or replace function hs_office_partner_global_insert_tf()
returns trigger
language plpgsql
strict as $$
begin
call grantPermissionToRole(
createPermission(NEW.uuid, 'INSERT', 'hs_office_partner'),
globalAdmin());
return NEW;
end; $$;
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
create trigger z_hs_office_partner_global_insert_tg
after insert on global
for each row
execute procedure hs_office_partner_global_insert_tf();
/**
Checks if the user or assumed roles are allowed to insert a row to hs_office_partner,
where only global-admin has that permission.
*/
create or replace function hs_office_partner_insert_permission_missing_tf()
returns trigger
language plpgsql as $$
begin
raise exception '[403] insert into hs_office_partner not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids();
end; $$;
create trigger hs_office_partner_insert_permission_check_tg
before insert on hs_office_partner
for each row
when ( not isGlobalAdmin() )
execute procedure hs_office_partner_insert_permission_missing_tf();
--//
-- ============================================================================
--changeset hs-office-partner-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromQuery('hs_office_partner',
$idName$
SELECT partner.partnerNumber
|| ':' || (SELECT idName FROM hs_office_person_iv p WHERE p.uuid = partner.personUuid)
|| '-' || (SELECT idName FROM hs_office_contact_iv c WHERE c.uuid = partner.contactUuid)
FROM hs_office_partner AS partner
$idName$);
--//
-- ============================================================================
--changeset hs-office-partner-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRestrictedView('hs_office_partner',
$orderBy$
SELECT partner.partnerNumber
|| ':' || (SELECT idName FROM hs_office_person_iv p WHERE p.uuid = partner.personUuid)
|| '-' || (SELECT idName FROM hs_office_contact_iv c WHERE c.uuid = partner.contactUuid)
FROM hs_office_partner AS partner
$orderBy$,
$updates$
partnerRelUuid = new.partnerRelUuid,
personUuid = new.personUuid,
contactUuid = new.contactUuid
$updates$);
--//

View File

@@ -1,78 +1,158 @@
### hs_office_partner RBAC
### rbac partner
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
```mermaid
%%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB
subgraph global
style global fill:#eee
role:global.admin[global.admin]
end
subgraph hsOfficeContact
subgraph partnerRel.contact["`**partnerRel.contact**`"]
direction TB
style hsOfficeContact fill:#eee
role:hsOfficeContact.admin[contact.admin]
--> role:hsOfficeContact.tenant[contact.tenant]
--> role:hsOfficeContact.guest[contact.guest]
style partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.contact:roles[ ]
style partnerRel.contact:roles fill:#99bcdb,stroke:white
role:partnerRel.contact:owner[[partnerRel.contact:owner]]
role:partnerRel.contact:admin[[partnerRel.contact:admin]]
role:partnerRel.contact:referrer[[partnerRel.contact:referrer]]
end
end
subgraph hsOfficePerson
subgraph partner["`**partner**`"]
direction TB
style hsOfficePerson fill:#eee
role:hsOfficePerson.admin[person.admin]
--> role:hsOfficePerson.tenant[person.tenant]
--> role:hsOfficePerson.guest[person.guest]
style partner fill:#dd4901,stroke:#274d6e,stroke-width:8px
subgraph partner:permissions[ ]
style partner:permissions fill:#dd4901,stroke:white
perm:partner:INSERT{{partner:INSERT}}
perm:partner:DELETE{{partner:DELETE}}
perm:partner:UPDATE{{partner:UPDATE}}
perm:partner:SELECT{{partner:SELECT}}
end
subgraph partnerRel["`**partnerRel**`"]
direction TB
style partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.contact["`**partnerRel.contact**`"]
direction TB
style partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.contact:roles[ ]
style partnerRel.contact:roles fill:#99bcdb,stroke:white
role:partnerRel.contact:owner[[partnerRel.contact:owner]]
role:partnerRel.contact:admin[[partnerRel.contact:admin]]
role:partnerRel.contact:referrer[[partnerRel.contact:referrer]]
end
end
subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"]
direction TB
style partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.anchorPerson:roles[ ]
style partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:partnerRel.anchorPerson:owner[[partnerRel.anchorPerson:owner]]
role:partnerRel.anchorPerson:admin[[partnerRel.anchorPerson:admin]]
role:partnerRel.anchorPerson:referrer[[partnerRel.anchorPerson:referrer]]
end
end
subgraph partnerRel.holderPerson["`**partnerRel.holderPerson**`"]
direction TB
style partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.holderPerson:roles[ ]
style partnerRel.holderPerson:roles fill:#99bcdb,stroke:white
role:partnerRel.holderPerson:owner[[partnerRel.holderPerson:owner]]
role:partnerRel.holderPerson:admin[[partnerRel.holderPerson:admin]]
role:partnerRel.holderPerson:referrer[[partnerRel.holderPerson:referrer]]
end
end
subgraph partnerRel:roles[ ]
style partnerRel:roles fill:#99bcdb,stroke:white
role:partnerRel:owner[[partnerRel:owner]]
role:partnerRel:admin[[partnerRel:admin]]
role:partnerRel:agent[[partnerRel:agent]]
role:partnerRel:tenant[[partnerRel:tenant]]
end
end
end
subgraph hsOfficePartnerDetails
subgraph partnerDetails["`**partnerDetails**`"]
direction TB
perm:hsOfficePartnerDetails.*{{partner.*}}
perm:hsOfficePartnerDetails.edit{{partner.edit}}
perm:hsOfficePartnerDetails.view{{partner.view}}
style partnerDetails fill:#feb28c,stroke:#274d6e,stroke-width:8px
subgraph partnerDetails:permissions[ ]
style partnerDetails:permissions fill:#feb28c,stroke:white
perm:partnerDetails:DELETE{{partnerDetails:DELETE}}
perm:partnerDetails:UPDATE{{partnerDetails:UPDATE}}
perm:partnerDetails:SELECT{{partnerDetails:SELECT}}
end
end
subgraph hsOfficePartner
role:hsOfficePartner.owner[partner.owner]
%% permissions
role:hsOfficePartner.owner --> perm:hsOfficePartner.*{{partner.*}}
role:hsOfficePartner.owner --> perm:hsOfficePartnerDetails.*{{partner.*}}
%% incoming
role:global.admin ---> role:hsOfficePartner.owner
role:hsOfficePartner.admin[partner.admin]
%% permissions
role:hsOfficePartner.admin --> perm:hsOfficePartner.edit{{partner.edit}}
role:hsOfficePartner.admin --> perm:hsOfficePartnerDetails.edit{{partner.edit}}
%% incoming
role:hsOfficePartner.owner ---> role:hsOfficePartner.admin
%% outgoing
role:hsOfficePartner.admin --> role:hsOfficePerson.tenant
role:hsOfficePartner.admin --> role:hsOfficeContact.tenant
role:hsOfficePartner.agent[partner.agent]
%% permissions
role:hsOfficePartner.agent --> perm:hsOfficePartnerDetails.view{{partner.view}}
%% incoming
role:hsOfficePartner.admin ---> role:hsOfficePartner.agent
role:hsOfficePerson.admin --> role:hsOfficePartner.agent
role:hsOfficeContact.admin --> role:hsOfficePartner.agent
role:hsOfficePartner.tenant[partner.tenant]
%% incoming
role:hsOfficePartner.agent --> role:hsOfficePartner.tenant
%% outgoing
role:hsOfficePartner.tenant --> role:hsOfficePerson.guest
role:hsOfficePartner.tenant --> role:hsOfficeContact.guest
subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"]
direction TB
style partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
role:hsOfficePartner.guest[partner.guest]
%% permissions
role:hsOfficePartner.guest --> perm:hsOfficePartner.view{{partner.view}}
%% incoming
role:hsOfficePartner.tenant --> role:hsOfficePartner.guest
subgraph partnerRel.anchorPerson:roles[ ]
style partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:partnerRel.anchorPerson:owner[[partnerRel.anchorPerson:owner]]
role:partnerRel.anchorPerson:admin[[partnerRel.anchorPerson:admin]]
role:partnerRel.anchorPerson:referrer[[partnerRel.anchorPerson:referrer]]
end
end
subgraph partnerRel.holderPerson["`**partnerRel.holderPerson**`"]
direction TB
style partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.holderPerson:roles[ ]
style partnerRel.holderPerson:roles fill:#99bcdb,stroke:white
role:partnerRel.holderPerson:owner[[partnerRel.holderPerson:owner]]
role:partnerRel.holderPerson:admin[[partnerRel.holderPerson:admin]]
role:partnerRel.holderPerson:referrer[[partnerRel.holderPerson:referrer]]
end
end
%% granting roles to roles
role:global:admin -.-> role:partnerRel.anchorPerson:owner
role:partnerRel.anchorPerson:owner -.-> role:partnerRel.anchorPerson:admin
role:partnerRel.anchorPerson:admin -.-> role:partnerRel.anchorPerson:referrer
role:global:admin -.-> role:partnerRel.holderPerson:owner
role:partnerRel.holderPerson:owner -.-> role:partnerRel.holderPerson:admin
role:partnerRel.holderPerson:admin -.-> role:partnerRel.holderPerson:referrer
role:global:admin -.-> role:partnerRel.contact:owner
role:partnerRel.contact:owner -.-> role:partnerRel.contact:admin
role:partnerRel.contact:admin -.-> role:partnerRel.contact:referrer
role:global:admin -.-> role:partnerRel:owner
role:partnerRel:owner -.-> role:partnerRel:admin
role:partnerRel.anchorPerson:admin -.-> role:partnerRel:admin
role:partnerRel:admin -.-> role:partnerRel:agent
role:partnerRel.holderPerson:admin -.-> role:partnerRel:agent
role:partnerRel:agent -.-> role:partnerRel:tenant
role:partnerRel.holderPerson:admin -.-> role:partnerRel:tenant
role:partnerRel.contact:admin -.-> role:partnerRel:tenant
role:partnerRel:tenant -.-> role:partnerRel.anchorPerson:referrer
role:partnerRel:tenant -.-> role:partnerRel.holderPerson:referrer
role:partnerRel:tenant -.-> role:partnerRel.contact:referrer
%% granting permissions to roles
role:global:admin ==> perm:partner:INSERT
role:partnerRel:admin ==> perm:partner:DELETE
role:partnerRel:agent ==> perm:partner:UPDATE
role:partnerRel:tenant ==> perm:partner:SELECT
role:partnerRel:admin ==> perm:partnerDetails:DELETE
role:partnerRel:agent ==> perm:partnerDetails:UPDATE
role:partnerRel:agent ==> perm:partnerDetails:SELECT
```

View File

@@ -1,4 +1,6 @@
--liquibase formatted sql
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
-- ============================================================================
--changeset hs-office-partner-rbac-OBJECT:1 endDelimiter:--//
@@ -15,242 +17,222 @@ call generateRbacRoleDescriptors('hsOfficePartner', 'hs_office_partner');
-- ============================================================================
--changeset hs-office-partner-rbac-ROLES-CREATION:1 endDelimiter:--//
--changeset hs-office-partner-rbac-insert-trigger:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates and updates the roles and their assignments for partner entities.
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
*/
create or replace function hsOfficePartnerRbacRolesTrigger()
returns trigger
language plpgsql
strict as $$
create or replace procedure buildRbacSystemForHsOfficePartner(
NEW hs_office_partner
)
language plpgsql as $$
declare
oldPartnerRel hs_office_relation;
newPartnerRel hs_office_relation;
newPartnerRel hs_office_relation;
newPartnerDetails hs_office_partner_details;
oldPerson hs_office_person;
newPerson hs_office_person;
oldContact hs_office_contact;
newContact hs_office_contact;
begin
call enterTriggerForObjectUuid(NEW.uuid);
select * from hs_office_relation as r where r.uuid = NEW.partnerReluuid into newPartnerRel;
select * from hs_office_person as p where p.uuid = NEW.personUuid into newPerson;
select * from hs_office_contact as c where c.uuid = NEW.contactUuid into newContact;
SELECT * FROM hs_office_relation WHERE uuid = NEW.partnerRelUuid INTO newPartnerRel;
assert newPartnerRel.uuid is not null, format('newPartnerRel must not be null for NEW.partnerRelUuid = %s', NEW.partnerRelUuid);
if TG_OP = 'INSERT' then
SELECT * FROM hs_office_partner_details WHERE uuid = NEW.detailsUuid INTO newPartnerDetails;
assert newPartnerDetails.uuid is not null, format('newPartnerDetails must not be null for NEW.detailsUuid = %s', NEW.detailsUuid);
-- === ATTENTION: code generated from related Mermaid flowchart: ===
perform createRoleWithGrants(
hsOfficePartnerOwner(NEW),
permissions => array['DELETE'],
incomingSuperRoles => array[globalAdmin()]
);
perform createRoleWithGrants(
hsOfficePartnerAdmin(NEW),
permissions => array['UPDATE'],
incomingSuperRoles => array[
hsOfficePartnerOwner(NEW)],
outgoingSubRoles => array[
hsOfficeRelationTenant(newPartnerRel),
hsOfficePersonTenant(newPerson),
hsOfficeContactTenant(newContact)]
);
perform createRoleWithGrants(
hsOfficePartnerAgent(NEW),
incomingSuperRoles => array[
hsOfficePartnerAdmin(NEW),
hsOfficeRelationAdmin(newPartnerRel),
hsOfficePersonAdmin(newPerson),
hsOfficeContactAdmin(newContact)]
);
perform createRoleWithGrants(
hsOfficePartnerTenant(NEW),
incomingSuperRoles => array[
hsOfficePartnerAgent(NEW)],
outgoingSubRoles => array[
hsOfficeRelationTenant(newPartnerRel),
hsOfficePersonGuest(newPerson),
hsOfficeContactGuest(newContact)]
);
perform createRoleWithGrants(
hsOfficePartnerGuest(NEW),
permissions => array['SELECT'],
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(hsOfficePartnerOwner(NEW)),
createPermissions(NEW.detailsUuid, array ['DELETE'])
);
call grantPermissionsToRole(
getRoleId(hsOfficePartnerAdmin(NEW)),
createPermissions(NEW.detailsUuid, array ['UPDATE'])
);
call grantPermissionsToRole(
-- 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(hsOfficePartnerAgent(NEW)),
createPermissions(NEW.detailsUuid, array ['SELECT'])
);
elsif TG_OP = 'UPDATE' then
if OLD.partnerRelUuid <> NEW.partnerRelUuid then
select * from hs_office_relation as r where r.uuid = OLD.partnerRelUuid into oldPartnerRel;
call revokeRoleFromRole(hsOfficeRelationTenant(oldPartnerRel), hsOfficePartnerAdmin(OLD));
call grantRoleToRole(hsOfficeRelationTenant(newPartnerRel), hsOfficePartnerAdmin(NEW));
call revokeRoleFromRole(hsOfficePartnerAgent(OLD), hsOfficeRelationAdmin(oldPartnerRel));
call grantRoleToRole(hsOfficePartnerAgent(NEW), hsOfficeRelationAdmin(newPartnerRel));
call revokeRoleFromRole(hsOfficeRelationGuest(oldPartnerRel), hsOfficePartnerTenant(OLD));
call grantRoleToRole(hsOfficeRelationGuest(newPartnerRel), hsOfficePartnerTenant(NEW));
end if;
if OLD.personUuid <> NEW.personUuid then
select * from hs_office_person as p where p.uuid = OLD.personUuid into oldPerson;
call revokeRoleFromRole(hsOfficePersonTenant(oldPerson), hsOfficePartnerAdmin(OLD));
call grantRoleToRole(hsOfficePersonTenant(newPerson), hsOfficePartnerAdmin(NEW));
call revokeRoleFromRole(hsOfficePartnerAgent(OLD), hsOfficePersonAdmin(oldPerson));
call grantRoleToRole(hsOfficePartnerAgent(NEW), hsOfficePersonAdmin(newPerson));
call revokeRoleFromRole(hsOfficePersonGuest(oldPerson), hsOfficePartnerTenant(OLD));
call grantRoleToRole(hsOfficePersonGuest(newPerson), hsOfficePartnerTenant(NEW));
end if;
if OLD.contactUuid <> NEW.contactUuid then
select * from hs_office_contact as c where c.uuid = OLD.contactUuid into oldContact;
call revokeRoleFromRole(hsOfficeContactTenant(oldContact), hsOfficePartnerAdmin(OLD));
call grantRoleToRole(hsOfficeContactTenant(newContact), hsOfficePartnerAdmin(NEW));
call revokeRoleFromRole(hsOfficePartnerAgent(OLD), hsOfficeContactAdmin(oldContact));
call grantRoleToRole(hsOfficePartnerAgent(NEW), hsOfficeContactAdmin(newContact));
call revokeRoleFromRole(hsOfficeContactGuest(oldContact), hsOfficePartnerTenant(OLD));
call grantRoleToRole(hsOfficeContactGuest(newContact), hsOfficePartnerTenant(NEW));
end if;
else
raise exception 'invalid usage of TRIGGER';
end if;
call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationAdmin(newPartnerRel));
call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationTenant(newPartnerRel));
call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationAgent(newPartnerRel));
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'DELETE'), hsOfficeRelationAdmin(newPartnerRel));
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'SELECT'), hsOfficeRelationAgent(newPartnerRel));
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationAgent(newPartnerRel));
call leaveTriggerForObjectUuid(NEW.uuid);
return NEW;
end; $$;
/*
An AFTER INSERT TRIGGER which creates the role structure for a new customer.
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_partner row.
*/
create trigger createRbacRolesForHsOfficePartner_Trigger
after insert
on hs_office_partner
for each row
execute procedure hsOfficePartnerRbacRolesTrigger();
/*
An AFTER UPDATE TRIGGER which updates the role structure of a customer.
*/
create trigger updateRbacRolesForHsOfficePartner_Trigger
after update
on hs_office_partner
create or replace function insertTriggerForHsOfficePartner_tf()
returns trigger
language plpgsql
strict as $$
begin
call buildRbacSystemForHsOfficePartner(NEW);
return NEW;
end; $$;
create trigger insertTriggerForHsOfficePartner_tg
after insert on hs_office_partner
for each row
execute procedure hsOfficePartnerRbacRolesTrigger();
execute procedure insertTriggerForHsOfficePartner_tf();
--//
-- ============================================================================
--changeset hs-office-partner-rbac-IDENTITY-VIEW:1 endDelimiter:--//
--changeset hs-office-partner-rbac-update-trigger:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('hs_office_partner', $idName$
partnerNumber || ':' ||
(select idName from hs_office_person_iv p where p.uuid = target.personuuid)
|| '-' ||
(select idName from hs_office_contact_iv c where c.uuid = target.contactuuid)
$idName$);
/*
Called from the AFTER UPDATE TRIGGER to re-wire the grants.
*/
create or replace procedure updateRbacRulesForHsOfficePartner(
OLD hs_office_partner,
NEW hs_office_partner
)
language plpgsql as $$
declare
oldPartnerRel hs_office_relation;
newPartnerRel hs_office_relation;
oldPartnerDetails hs_office_partner_details;
newPartnerDetails hs_office_partner_details;
begin
call enterTriggerForObjectUuid(NEW.uuid);
SELECT * FROM hs_office_relation WHERE uuid = OLD.partnerRelUuid INTO oldPartnerRel;
assert oldPartnerRel.uuid is not null, format('oldPartnerRel must not be null for OLD.partnerRelUuid = %s', OLD.partnerRelUuid);
SELECT * FROM hs_office_relation WHERE uuid = NEW.partnerRelUuid INTO newPartnerRel;
assert newPartnerRel.uuid is not null, format('newPartnerRel must not be null for NEW.partnerRelUuid = %s', NEW.partnerRelUuid);
SELECT * FROM hs_office_partner_details WHERE uuid = OLD.detailsUuid INTO oldPartnerDetails;
assert oldPartnerDetails.uuid is not null, format('oldPartnerDetails must not be null for OLD.detailsUuid = %s', OLD.detailsUuid);
SELECT * FROM hs_office_partner_details WHERE uuid = NEW.detailsUuid INTO newPartnerDetails;
assert newPartnerDetails.uuid is not null, format('newPartnerDetails must not be null for NEW.detailsUuid = %s', NEW.detailsUuid);
if NEW.partnerRelUuid <> OLD.partnerRelUuid then
call revokePermissionFromRole(getPermissionId(OLD.uuid, 'DELETE'), hsOfficeRelationAdmin(oldPartnerRel));
call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationAdmin(newPartnerRel));
call revokePermissionFromRole(getPermissionId(OLD.uuid, 'UPDATE'), hsOfficeRelationAgent(oldPartnerRel));
call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationAgent(newPartnerRel));
call revokePermissionFromRole(getPermissionId(OLD.uuid, 'SELECT'), hsOfficeRelationTenant(oldPartnerRel));
call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationTenant(newPartnerRel));
call revokePermissionFromRole(getPermissionId(oldPartnerDetails.uuid, 'DELETE'), hsOfficeRelationAdmin(oldPartnerRel));
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'DELETE'), hsOfficeRelationAdmin(newPartnerRel));
call revokePermissionFromRole(getPermissionId(oldPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationAgent(oldPartnerRel));
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationAgent(newPartnerRel));
call revokePermissionFromRole(getPermissionId(oldPartnerDetails.uuid, 'SELECT'), hsOfficeRelationAgent(oldPartnerRel));
call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'SELECT'), hsOfficeRelationAgent(newPartnerRel));
end if;
call leaveTriggerForObjectUuid(NEW.uuid);
end; $$;
/*
AFTER INSERT TRIGGER to re-wire the grant structure for a new hs_office_partner row.
*/
create or replace function updateTriggerForHsOfficePartner_tf()
returns trigger
language plpgsql
strict as $$
begin
call updateRbacRulesForHsOfficePartner(OLD, NEW);
return NEW;
end; $$;
create trigger updateTriggerForHsOfficePartner_tg
after update on hs_office_partner
for each row
execute procedure updateTriggerForHsOfficePartner_tf();
--//
-- ============================================================================
--changeset hs-office-partner-rbac-INSERT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates INSERT INTO hs_office_partner permissions for the related global rows.
*/
do language plpgsql $$
declare
row global;
begin
call defineContext('create INSERT INTO hs_office_partner permissions for the related global rows');
FOR row IN SELECT * FROM global
LOOP
call grantPermissionToRole(
createPermission(row.uuid, 'INSERT', 'hs_office_partner'),
globalAdmin());
END LOOP;
END;
$$;
/**
Adds hs_office_partner INSERT permission to specified role of new global rows.
*/
create or replace function hs_office_partner_global_insert_tf()
returns trigger
language plpgsql
strict as $$
begin
call grantPermissionToRole(
createPermission(NEW.uuid, 'INSERT', 'hs_office_partner'),
globalAdmin());
return NEW;
end; $$;
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
create trigger z_hs_office_partner_global_insert_tg
after insert on global
for each row
execute procedure hs_office_partner_global_insert_tf();
/**
Checks if the user or assumed roles are allowed to insert a row to hs_office_partner,
where only global-admin has that permission.
*/
create or replace function hs_office_partner_insert_permission_missing_tf()
returns trigger
language plpgsql as $$
begin
raise exception '[403] insert into hs_office_partner not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids();
end; $$;
create trigger hs_office_partner_insert_permission_check_tg
before insert on hs_office_partner
for each row
when ( not isGlobalAdmin() )
execute procedure hs_office_partner_insert_permission_missing_tf();
--//
-- ============================================================================
--changeset hs-office-partner-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('hs_office_partner',
$idName$
'P-' || partnerNumber
$idName$);
--//
-- ============================================================================
--changeset hs-office-partner-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRestrictedView('hs_office_partner',
'(select idName from hs_office_person_iv p where p.uuid = target.personUuid)',
$orderBy$
'P-' || partnerNumber
$orderBy$,
$updates$
partnerRelUuid = new.partnerRelUuid,
personUuid = new.personUuid,
contactUuid = new.contactUuid
partnerRelUuid = new.partnerRelUuid
$updates$);
--//
-- ============================================================================
--changeset hs-office-partner-rbac-NEW-PARTNER:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates a global permission for new-partner and assigns it to the Hostsharing admins role.
*/
do language plpgsql $$
declare
addCustomerPermissions uuid[];
globalObjectUuid uuid;
globalAdminRoleUuid uuid ;
begin
call defineContext('granting global new-partner permission to global admin role', null, null, null);
globalAdminRoleUuid := findRoleId(globalAdmin());
globalObjectUuid := (select uuid from global);
addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-partner']);
call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions);
end;
$$;
/**
Used by the trigger to prevent the add-customer to current user respectively assumed roles.
*/
create or replace function addHsOfficePartnerNotAllowedForCurrentSubjects()
returns trigger
language PLPGSQL
as $$
begin
raise exception '[403] new-partner 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_partner_insert_trigger
before insert
on hs_office_partner
for each row
-- TODO.spec: who is allowed to create new partners
when ( not hasAssumedRole() )
execute procedure addHsOfficePartnerNotAllowedForCurrentSubjects();
--//

View File

@@ -1,136 +0,0 @@
### rbac partnerDetails
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
```mermaid
%%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB
subgraph partnerRel.contact["`**partnerRel.contact**`"]
direction TB
style partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.contact:roles[ ]
style partnerRel.contact:roles fill:#99bcdb,stroke:white
role:partnerRel.contact:owner[[partnerRel.contact:owner]]
role:partnerRel.contact:admin[[partnerRel.contact:admin]]
role:partnerRel.contact:referrer[[partnerRel.contact:referrer]]
end
end
subgraph partnerDetails["`**partnerDetails**`"]
direction TB
style partnerDetails fill:#dd4901,stroke:#274d6e,stroke-width:8px
subgraph partnerDetails:permissions[ ]
style partnerDetails:permissions fill:#dd4901,stroke:white
perm:partnerDetails:INSERT{{partnerDetails:INSERT}}
end
subgraph partnerRel["`**partnerRel**`"]
direction TB
style partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.contact["`**partnerRel.contact**`"]
direction TB
style partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.contact:roles[ ]
style partnerRel.contact:roles fill:#99bcdb,stroke:white
role:partnerRel.contact:owner[[partnerRel.contact:owner]]
role:partnerRel.contact:admin[[partnerRel.contact:admin]]
role:partnerRel.contact:referrer[[partnerRel.contact:referrer]]
end
end
subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"]
direction TB
style partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.anchorPerson:roles[ ]
style partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:partnerRel.anchorPerson:owner[[partnerRel.anchorPerson:owner]]
role:partnerRel.anchorPerson:admin[[partnerRel.anchorPerson:admin]]
role:partnerRel.anchorPerson:referrer[[partnerRel.anchorPerson:referrer]]
end
end
subgraph partnerRel.holderPerson["`**partnerRel.holderPerson**`"]
direction TB
style partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.holderPerson:roles[ ]
style partnerRel.holderPerson:roles fill:#99bcdb,stroke:white
role:partnerRel.holderPerson:owner[[partnerRel.holderPerson:owner]]
role:partnerRel.holderPerson:admin[[partnerRel.holderPerson:admin]]
role:partnerRel.holderPerson:referrer[[partnerRel.holderPerson:referrer]]
end
end
subgraph partnerRel:roles[ ]
style partnerRel:roles fill:#99bcdb,stroke:white
role:partnerRel:owner[[partnerRel:owner]]
role:partnerRel:admin[[partnerRel:admin]]
role:partnerRel:agent[[partnerRel:agent]]
role:partnerRel:tenant[[partnerRel:tenant]]
end
end
end
subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"]
direction TB
style partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.anchorPerson:roles[ ]
style partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:partnerRel.anchorPerson:owner[[partnerRel.anchorPerson:owner]]
role:partnerRel.anchorPerson:admin[[partnerRel.anchorPerson:admin]]
role:partnerRel.anchorPerson:referrer[[partnerRel.anchorPerson:referrer]]
end
end
subgraph partnerRel.holderPerson["`**partnerRel.holderPerson**`"]
direction TB
style partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.holderPerson:roles[ ]
style partnerRel.holderPerson:roles fill:#99bcdb,stroke:white
role:partnerRel.holderPerson:owner[[partnerRel.holderPerson:owner]]
role:partnerRel.holderPerson:admin[[partnerRel.holderPerson:admin]]
role:partnerRel.holderPerson:referrer[[partnerRel.holderPerson:referrer]]
end
end
%% granting roles to roles
role:global:admin -.-> role:partnerRel.anchorPerson:owner
role:partnerRel.anchorPerson:owner -.-> role:partnerRel.anchorPerson:admin
role:partnerRel.anchorPerson:admin -.-> role:partnerRel.anchorPerson:referrer
role:global:admin -.-> role:partnerRel.holderPerson:owner
role:partnerRel.holderPerson:owner -.-> role:partnerRel.holderPerson:admin
role:partnerRel.holderPerson:admin -.-> role:partnerRel.holderPerson:referrer
role:global:admin -.-> role:partnerRel.contact:owner
role:partnerRel.contact:owner -.-> role:partnerRel.contact:admin
role:partnerRel.contact:admin -.-> role:partnerRel.contact:referrer
role:global:admin -.-> role:partnerRel:owner
role:partnerRel:owner -.-> role:partnerRel:admin
role:partnerRel.anchorPerson:admin -.-> role:partnerRel:admin
role:partnerRel:admin -.-> role:partnerRel:agent
role:partnerRel.holderPerson:admin -.-> role:partnerRel:agent
role:partnerRel:agent -.-> role:partnerRel:tenant
role:partnerRel.holderPerson:admin -.-> role:partnerRel:tenant
role:partnerRel.contact:admin -.-> role:partnerRel:tenant
role:partnerRel:tenant -.-> role:partnerRel.anchorPerson:referrer
role:partnerRel:tenant -.-> role:partnerRel.holderPerson:referrer
role:partnerRel:tenant -.-> role:partnerRel.contact:referrer
%% granting permissions to roles
role:global:admin ==> perm:partnerDetails:INSERT
```

View File

@@ -1,164 +0,0 @@
--liquibase formatted sql
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
-- ============================================================================
--changeset hs-office-partner-details-rbac-OBJECT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRelatedRbacObject('hs_office_partner_details');
--//
-- ============================================================================
--changeset hs-office-partner-details-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRoleDescriptors('hsOfficePartnerDetails', 'hs_office_partner_details');
--//
-- ============================================================================
--changeset hs-office-partner-details-rbac-insert-trigger:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
*/
create or replace procedure buildRbacSystemForHsOfficePartnerDetails(
NEW hs_office_partner_details
)
language plpgsql as $$
declare
newPartnerRel hs_office_relation;
begin
call enterTriggerForObjectUuid(NEW.uuid);
SELECT partnerRel.*
FROM hs_office_relation AS partnerRel
JOIN hs_office_partner AS partner
ON partner.detailsUuid = NEW.uuid
WHERE partnerRel.uuid = partner.partnerRelUuid
INTO newPartnerRel;
assert newPartnerRel.uuid is not null, format('newPartnerRel must not be null for NEW.partnerRelUuid = %s', NEW.partnerRelUuid);
call leaveTriggerForObjectUuid(NEW.uuid);
end; $$;
/*
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_partner_details row.
*/
create or replace function insertTriggerForHsOfficePartnerDetails_tf()
returns trigger
language plpgsql
strict as $$
begin
call buildRbacSystemForHsOfficePartnerDetails(NEW);
return NEW;
end; $$;
create trigger insertTriggerForHsOfficePartnerDetails_tg
after insert on hs_office_partner_details
for each row
execute procedure insertTriggerForHsOfficePartnerDetails_tf();
--//
-- ============================================================================
--changeset hs-office-partner-details-rbac-INSERT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates INSERT INTO hs_office_partner_details permissions for the related global rows.
*/
do language plpgsql $$
declare
row global;
permissionUuid uuid;
roleUuid uuid;
begin
call defineContext('create INSERT INTO hs_office_partner_details permissions for the related global rows');
FOR row IN SELECT * FROM global
LOOP
roleUuid := findRoleId(globalAdmin());
permissionUuid := createPermission(row.uuid, 'INSERT', 'hs_office_partner_details');
call grantPermissionToRole(permissionUuid, roleUuid);
END LOOP;
END;
$$;
/**
Adds hs_office_partner_details INSERT permission to specified role of new global rows.
*/
create or replace function hs_office_partner_details_global_insert_tf()
returns trigger
language plpgsql
strict as $$
begin
call grantPermissionToRole(
createPermission(NEW.uuid, 'INSERT', 'hs_office_partner_details'),
globalAdmin());
return NEW;
end; $$;
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
create trigger z_hs_office_partner_details_global_insert_tg
after insert on global
for each row
execute procedure hs_office_partner_details_global_insert_tf();
/**
Checks if the user or assumed roles are allowed to insert a row to hs_office_partner_details,
where only global-admin has that permission.
*/
create or replace function hs_office_partner_details_insert_permission_missing_tf()
returns trigger
language plpgsql as $$
begin
raise exception '[403] insert into hs_office_partner_details not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids();
end; $$;
create trigger hs_office_partner_details_insert_permission_check_tg
before insert on hs_office_partner_details
for each row
when ( not isGlobalAdmin() )
execute procedure hs_office_partner_details_insert_permission_missing_tf();
--//
-- ============================================================================
--changeset hs-office-partner-details-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromQuery('hs_office_partner_details',
$idName$
SELECT partner_iv.idName || '-details'
FROM hs_office_partner_details AS partnerDetails
JOIN hs_office_partner partner ON partner.detailsUuid = partnerDetails.uuid
JOIN hs_office_partner_iv partner_iv ON partner_iv.uuid = partner.uuid
$idName$);
--//
-- ============================================================================
--changeset hs-office-partner-details-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRestrictedView('hs_office_partner_details',
$orderBy$
SELECT partner_iv.idName || '-details'
FROM hs_office_partner_details AS partnerDetails
JOIN hs_office_partner partner ON partner.detailsUuid = partnerDetails.uuid
JOIN hs_office_partner_iv partner_iv ON partner_iv.uuid = partner.uuid
$orderBy$,
$updates$
registrationOffice = new.registrationOffice,
registrationNumber = new.registrationNumber,
birthPlace = new.birthPlace,
birthName = new.birthName,
birthday = new.birthday,
dateOfDeath = new.dateOfDeath
$updates$);
--//

View File

@@ -0,0 +1,23 @@
### rbac partnerDetails
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
```mermaid
%%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB
subgraph partnerDetails["`**partnerDetails**`"]
direction TB
style partnerDetails fill:#dd4901,stroke:#274d6e,stroke-width:8px
subgraph partnerDetails:permissions[ ]
style partnerDetails:permissions fill:#dd4901,stroke:white
perm:partnerDetails:INSERT{{partnerDetails:INSERT}}
end
end
%% granting permissions to roles
role:global:admin ==> perm:partnerDetails:INSERT
```

View File

@@ -1,4 +1,6 @@
--liquibase formatted sql
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
-- ============================================================================
--changeset hs-office-partner-details-rbac-OBJECT:1 endDelimiter:--//
@@ -8,76 +10,141 @@ call generateRelatedRbacObject('hs_office_partner_details');
-- ============================================================================
--changeset hs-office-partner-details-rbac-IDENTITY-VIEW:1 endDelimiter:--//
--changeset hs-office-partner-details-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('hs_office_partner_details', $idName$
(select idName || '-details' from hs_office_partner_iv partner_iv
join hs_office_partner partner on (partner_iv.uuid = partner.uuid)
where partner.detailsUuid = target.uuid)
$idName$);
call generateRbacRoleDescriptors('hsOfficePartnerDetails', 'hs_office_partner_details');
--//
-- ============================================================================
--changeset hs-office-partner-details-rbac-insert-trigger:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
*/
create or replace procedure buildRbacSystemForHsOfficePartnerDetails(
NEW hs_office_partner_details
)
language plpgsql as $$
declare
begin
call enterTriggerForObjectUuid(NEW.uuid);
call leaveTriggerForObjectUuid(NEW.uuid);
end; $$;
/*
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_partner_details row.
*/
create or replace function insertTriggerForHsOfficePartnerDetails_tf()
returns trigger
language plpgsql
strict as $$
begin
call buildRbacSystemForHsOfficePartnerDetails(NEW);
return NEW;
end; $$;
create trigger insertTriggerForHsOfficePartnerDetails_tg
after insert on hs_office_partner_details
for each row
execute procedure insertTriggerForHsOfficePartnerDetails_tf();
--//
-- ============================================================================
--changeset hs-office-partner-details-rbac-INSERT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates INSERT INTO hs_office_partner_details permissions for the related global rows.
*/
do language plpgsql $$
declare
row global;
begin
call defineContext('create INSERT INTO hs_office_partner_details permissions for the related global rows');
FOR row IN SELECT * FROM global
LOOP
call grantPermissionToRole(
createPermission(row.uuid, 'INSERT', 'hs_office_partner_details'),
globalAdmin());
END LOOP;
END;
$$;
/**
Adds hs_office_partner_details INSERT permission to specified role of new global rows.
*/
create or replace function hs_office_partner_details_global_insert_tf()
returns trigger
language plpgsql
strict as $$
begin
call grantPermissionToRole(
createPermission(NEW.uuid, 'INSERT', 'hs_office_partner_details'),
globalAdmin());
return NEW;
end; $$;
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
create trigger z_hs_office_partner_details_global_insert_tg
after insert on global
for each row
execute procedure hs_office_partner_details_global_insert_tf();
/**
Checks if the user or assumed roles are allowed to insert a row to hs_office_partner_details,
where only global-admin has that permission.
*/
create or replace function hs_office_partner_details_insert_permission_missing_tf()
returns trigger
language plpgsql as $$
begin
raise exception '[403] insert into hs_office_partner_details not allowed for current subjects % (%) assumed by user % (%)',
currentSubjects(), currentSubjectsUuids(), currentUser(), currentUserUuid();
end; $$;
create trigger hs_office_partner_details_insert_permission_check_tg
before insert on hs_office_partner_details
for each row
when ( not isGlobalAdmin() )
execute procedure hs_office_partner_details_insert_permission_missing_tf();
--//
-- ============================================================================
--changeset hs-office-partner-details-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromQuery('hs_office_partner_details',
$idName$
SELECT partnerDetails.uuid as uuid, partner_iv.idName || '-details' as idName
FROM hs_office_partner_details AS partnerDetails
JOIN hs_office_partner partner ON partner.detailsUuid = partnerDetails.uuid
JOIN hs_office_partner_iv partner_iv ON partner_iv.uuid = partner.uuid
$idName$);
--//
-- ============================================================================
--changeset hs-office-partner-details-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRestrictedView('hs_office_partner_details',
'target.uuid', -- no specific order required
$orderBy$
uuid
$orderBy$,
$updates$
registrationOffice = new.registrationOffice,
registrationNumber = new.registrationNumber,
birthPlace = new.birthPlace,
birthName = new.birthName,
birthday = new.birthday,
dateOfDeath = new.dateOfDeath
birthPlace = new.birthPlace,
birthName = new.birthName,
birthday = new.birthday,
dateOfDeath = new.dateOfDeath
$updates$);
--//
-- ============================================================================
--changeset hs-office-partner-details-rbac-NEW-PARTNER-DETAILS:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates a global permission for new-partner-details and assigns it to the hostsharing admins role.
*/
do language plpgsql $$
declare
addCustomerPermissions uuid[];
globalObjectUuid uuid;
globalAdminRoleUuid uuid ;
begin
call defineContext('granting global new-partner-details permission to global admin role', null, null, null);
globalAdminRoleUuid := findRoleId(globalAdmin());
globalObjectUuid := (select uuid from global);
addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-partner-details']);
call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions);
end;
$$;
-- TODO.refa: the code below could be moved to a generator, maybe even the code above.
-- Additionally, the code below is not neccesary for all entities, specifiy when it is!
/**
Used by the trigger to prevent the add-partner-details to current user respectively assumed roles.
*/
create or replace function addHsOfficePartnerDetailsNotAllowedForCurrentSubjects()
returns trigger
language PLPGSQL
as $$
begin
raise exception '[403] new-partner-details not permitted for %',
array_to_string(currentSubjects(), ';', 'null');
end; $$;
/**
Checks if the user or assumed roles are allowed to create new partner-details.
*/
create trigger hs_office_partner_details_insert_trigger
before insert
on hs_office_partner_details
for each row
when ( not hasAssumedRole() )
execute procedure addHsOfficePartnerDetailsNotAllowedForCurrentSubjects();
--//

View File

@@ -9,18 +9,17 @@
Creates a single partner test record.
*/
create or replace procedure createHsOfficePartnerTestData(
mandantTradeName varchar,
partnerNumber numeric(5),
mandantTradeName varchar,
newPartnerNumber numeric(5),
partnerPersonName varchar,
contactLabel varchar )
contactLabel varchar )
language plpgsql as $$
declare
currentTask varchar;
idName varchar;
mandantPerson hs_office_person;
partnerRel hs_office_relation;
partnerRel hs_office_relation;
relatedPerson hs_office_person;
relatedContact hs_office_contact;
relatedDetailsUuid uuid;
begin
idName := cleanIdentifier( partnerPersonName|| '-' || contactLabel);
@@ -38,9 +37,6 @@ begin
select p.* from hs_office_person p
where p.tradeName = partnerPersonName or p.familyName = partnerPersonName
into relatedPerson;
select c.* from hs_office_contact c
where c.label = contactLabel
into relatedContact;
select r.* from hs_office_relation r
where r.type = 'PARTNER'
@@ -53,7 +49,6 @@ begin
raise notice 'creating test partner: %', idName;
raise notice '- using partnerRel (%): %', partnerRel.uuid, partnerRel;
raise notice '- using person (%): %', relatedPerson.uuid, relatedPerson;
raise notice '- using contact (%): %', relatedContact.uuid, relatedContact;
if relatedPerson.persontype = 'NP' then
insert
@@ -68,8 +63,8 @@ begin
end if;
insert
into hs_office_partner (uuid, partnerNumber, partnerRelUuid, personuuid, contactuuid, detailsUuid)
values (uuid_generate_v4(), partnerNumber, partnerRel.uuid, relatedPerson.uuid, relatedContact.uuid, relatedDetailsUuid);
into hs_office_partner (uuid, partnerNumber, partnerRelUuid, detailsUuid)
values (uuid_generate_v4(), newPartnerNumber, partnerRel.uuid, relatedDetailsUuid);
end; $$;
--//

View File

@@ -1,43 +0,0 @@
### rbac bankAccount
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
```mermaid
%%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB
subgraph bankAccount["`**bankAccount**`"]
direction TB
style bankAccount fill:#dd4901,stroke:#274d6e,stroke-width:8px
subgraph bankAccount:roles[ ]
style bankAccount:roles fill:#dd4901,stroke:white
role:bankAccount:owner[[bankAccount:owner]]
role:bankAccount:admin[[bankAccount:admin]]
role:bankAccount:referrer[[bankAccount:referrer]]
end
subgraph bankAccount:permissions[ ]
style bankAccount:permissions fill:#dd4901,stroke:white
perm:bankAccount:DELETE{{bankAccount:DELETE}}
perm:bankAccount:UPDATE{{bankAccount:UPDATE}}
perm:bankAccount:SELECT{{bankAccount:SELECT}}
end
end
%% granting roles to users
user:creator ==> role:bankAccount:owner
%% granting roles to roles
role:global:admin ==> role:bankAccount:owner
role:bankAccount:owner ==> role:bankAccount:admin
role:bankAccount:admin ==> role:bankAccount:referrer
%% granting permissions to roles
role:bankAccount:owner ==> perm:bankAccount:DELETE
role:bankAccount:admin ==> perm:bankAccount:UPDATE
role:bankAccount:referrer ==> perm:bankAccount:SELECT
```

View File

@@ -1,125 +0,0 @@
--liquibase formatted sql
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
-- ============================================================================
--changeset hs-office-bankaccount-rbac-OBJECT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRelatedRbacObject('hs_office_bankaccount');
--//
-- ============================================================================
--changeset hs-office-bankaccount-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRoleDescriptors('hsOfficeBankAccount', 'hs_office_bankaccount');
--//
-- ============================================================================
--changeset hs-office-bankaccount-rbac-insert-trigger:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
*/
create or replace procedure buildRbacSystemForHsOfficeBankAccount(
NEW hs_office_bankaccount
)
language plpgsql as $$
declare
begin
call enterTriggerForObjectUuid(NEW.uuid);
perform createRoleWithGrants(
hsOfficeBankAccountOwner(NEW),
permissions => array['DELETE'],
incomingSuperRoles => array[globalAdmin()],
userUuids => array[currentUserUuid()]
);
perform createRoleWithGrants(
hsOfficeBankAccountAdmin(NEW),
permissions => array['UPDATE'],
incomingSuperRoles => array[hsOfficeBankAccountOwner(NEW)]
);
perform createRoleWithGrants(
hsOfficeBankAccountReferrer(NEW),
permissions => array['SELECT'],
incomingSuperRoles => array[hsOfficeBankAccountAdmin(NEW)]
);
call leaveTriggerForObjectUuid(NEW.uuid);
end; $$;
/*
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_bankaccount row.
*/
create or replace function insertTriggerForHsOfficeBankAccount_tf()
returns trigger
language plpgsql
strict as $$
begin
call buildRbacSystemForHsOfficeBankAccount(NEW);
return NEW;
end; $$;
create trigger insertTriggerForHsOfficeBankAccount_tg
after insert on hs_office_bankaccount
for each row
execute procedure insertTriggerForHsOfficeBankAccount_tf();
--//
-- ============================================================================
--changeset hs-office-bankaccount-rbac-INSERT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/**
Checks if the user or assumed roles are allowed to insert a row to hs_office_bankaccount,
where only global-admin has that permission.
*/
create or replace function hs_office_bankaccount_insert_permission_missing_tf()
returns trigger
language plpgsql as $$
begin
raise exception '[403] insert into hs_office_bankaccount not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids();
end; $$;
create trigger hs_office_bankaccount_insert_permission_check_tg
before insert on hs_office_bankaccount
for each row
when ( not isGlobalAdmin() )
execute procedure hs_office_bankaccount_insert_permission_missing_tf();
--//
-- ============================================================================
--changeset hs-office-bankaccount-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('hs_office_bankaccount',
$idName$
iban || ':' || holder
$idName$);
--//
-- ============================================================================
--changeset hs-office-bankaccount-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRestrictedView('hs_office_bankaccount',
$orderBy$
iban || ':' || holder
$orderBy$,
$updates$
holder = new.holder,
iban = new.iban,
bic = new.bic
$updates$);
--//

View File

@@ -1,40 +1,45 @@
### hs_office_bankaccount RBAC Roles
### rbac bankAccount
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
```mermaid
%%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB
subgraph global
style global fill: lightgray
role:global.admin[global.admin]
end
subgraph hsOfficeBankAccount
subgraph bankAccount["`**bankAccount**`"]
direction TB
style hsOfficeBankAccount fill: lightgreen
user:hsOfficeBankAccount.creator([bankAccount.creator])
style bankAccount fill:#dd4901,stroke:#274d6e,stroke-width:8px
role:hsOfficeBankAccount.owner[[bankAccount.owner]]
%% permissions
role:hsOfficeBankAccount.owner --> perm:hsOfficeBankAccount.*{{hsOfficeBankAccount.delete}}
%% incoming
role:global.admin --> role:hsOfficeBankAccount.owner
user:hsOfficeBankAccount.creator ---> role:hsOfficeBankAccount.owner
role:hsOfficeBankAccount.admin[[bankAccount.admin]]
%% incoming
role:hsOfficeBankAccount.owner ---> role:hsOfficeBankAccount.admin
role:hsOfficeBankAccount.tenant[[bankAccount.tenant]]
%% incoming
role:hsOfficeBankAccount.admin ---> role:hsOfficeBankAccount.tenant
role:hsOfficeBankAccount.guest[[bankAccount.guest]]
%% permissions
role:hsOfficeBankAccount.guest --> perm:hsOfficeBankAccount.view{{hsOfficeBankAccount.view}}
%% incoming
role:hsOfficeBankAccount.tenant ---> role:hsOfficeBankAccount.guest
subgraph bankAccount:roles[ ]
style bankAccount:roles fill:#dd4901,stroke:white
role:bankAccount:owner[[bankAccount:owner]]
role:bankAccount:admin[[bankAccount:admin]]
role:bankAccount:referrer[[bankAccount:referrer]]
end
subgraph bankAccount:permissions[ ]
style bankAccount:permissions fill:#dd4901,stroke:white
perm:bankAccount:INSERT{{bankAccount:INSERT}}
perm:bankAccount:DELETE{{bankAccount:DELETE}}
perm:bankAccount:UPDATE{{bankAccount:UPDATE}}
perm:bankAccount:SELECT{{bankAccount:SELECT}}
end
end
```
%% granting roles to users
user:creator ==> role:bankAccount:owner
%% granting roles to roles
role:global:admin ==> role:bankAccount:owner
role:bankAccount:owner ==> role:bankAccount:admin
role:bankAccount:admin ==> role:bankAccount:referrer
%% granting permissions to roles
role:global:guest ==> perm:bankAccount:INSERT
role:bankAccount:owner ==> perm:bankAccount:DELETE
role:bankAccount:admin ==> perm:bankAccount:UPDATE
role:bankAccount:referrer ==> perm:bankAccount:SELECT
```

View File

@@ -1,4 +1,6 @@
--liquibase formatted sql
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
-- ============================================================================
--changeset hs-office-bankaccount-rbac-OBJECT:1 endDelimiter:--//
@@ -15,125 +17,129 @@ call generateRbacRoleDescriptors('hsOfficeBankAccount', 'hs_office_bankaccount')
-- ============================================================================
--changeset hs-office-bankaccount-rbac-ROLES-CREATION:1 endDelimiter:--//
--changeset hs-office-bankaccount-rbac-insert-trigger:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates the roles and their assignments for a new bankaccount for the AFTER INSERT TRIGGER.
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
*/
create or replace function createRbacRolesForHsOfficeBankAccount()
create or replace procedure buildRbacSystemForHsOfficeBankAccount(
NEW hs_office_bankaccount
)
language plpgsql as $$
declare
begin
call enterTriggerForObjectUuid(NEW.uuid);
perform createRoleWithGrants(
hsOfficeBankAccountOwner(NEW),
permissions => array['DELETE'],
incomingSuperRoles => array[globalAdmin()],
userUuids => array[currentUserUuid()]
);
perform createRoleWithGrants(
hsOfficeBankAccountAdmin(NEW),
permissions => array['UPDATE'],
incomingSuperRoles => array[hsOfficeBankAccountOwner(NEW)]
);
perform createRoleWithGrants(
hsOfficeBankAccountReferrer(NEW),
permissions => array['SELECT'],
incomingSuperRoles => array[hsOfficeBankAccountAdmin(NEW)]
);
call leaveTriggerForObjectUuid(NEW.uuid);
end; $$;
/*
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_bankaccount row.
*/
create or replace function insertTriggerForHsOfficeBankAccount_tf()
returns trigger
language plpgsql
strict as $$
begin
if TG_OP <> 'INSERT' then
raise exception 'invalid usage of TRIGGER AFTER INSERT';
end if;
perform createRoleWithGrants(
hsOfficeBankAccountOwner(NEW),
permissions => array['DELETE'],
incomingSuperRoles => array[globalAdmin()],
userUuids => array[currentUserUuid()],
grantedByRole => globalAdmin()
);
perform createRoleWithGrants(
hsOfficeBankAccountAdmin(NEW),
incomingSuperRoles => array[hsOfficeBankAccountOwner(NEW)]
);
perform createRoleWithGrants(
hsOfficeBankAccountTenant(NEW),
incomingSuperRoles => array[hsOfficeBankAccountAdmin(NEW)]
);
perform createRoleWithGrants(
hsOfficeBankAccountGuest(NEW),
permissions => array['SELECT'],
incomingSuperRoles => array[hsOfficeBankAccountTenant(NEW)]
);
call buildRbacSystemForHsOfficeBankAccount(NEW);
return NEW;
end; $$;
/*
An AFTER INSERT TRIGGER which creates the role structure for a new customer.
*/
create trigger createRbacRolesForHsOfficeBankAccount_Trigger
after insert
on hs_office_bankaccount
create trigger insertTriggerForHsOfficeBankAccount_tg
after insert on hs_office_bankaccount
for each row
execute procedure createRbacRolesForHsOfficeBankAccount();
execute procedure insertTriggerForHsOfficeBankAccount_tf();
--//
-- ============================================================================
--changeset hs-office-bankaccount-rbac-INSERT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates INSERT INTO hs_office_bankaccount permissions for the related global rows.
*/
do language plpgsql $$
declare
row global;
begin
call defineContext('create INSERT INTO hs_office_bankaccount permissions for the related global rows');
FOR row IN SELECT * FROM global
LOOP
call grantPermissionToRole(
createPermission(row.uuid, 'INSERT', 'hs_office_bankaccount'),
globalGuest());
END LOOP;
END;
$$;
/**
Adds hs_office_bankaccount INSERT permission to specified role of new global rows.
*/
create or replace function hs_office_bankaccount_global_insert_tf()
returns trigger
language plpgsql
strict as $$
begin
call grantPermissionToRole(
createPermission(NEW.uuid, 'INSERT', 'hs_office_bankaccount'),
globalGuest());
return NEW;
end; $$;
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
create trigger z_hs_office_bankaccount_global_insert_tg
after insert on global
for each row
execute procedure hs_office_bankaccount_global_insert_tf();
--//
-- ============================================================================
--changeset hs-office-bankaccount-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('hs_office_bankaccount', $idName$
target.holder
call generateRbacIdentityViewFromProjection('hs_office_bankaccount',
$idName$
iban
$idName$);
--//
-- ============================================================================
--changeset hs-office-bankaccount-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRestrictedView('hs_office_bankaccount', 'target.holder',
call generateRbacRestrictedView('hs_office_bankaccount',
$orderBy$
iban
$orderBy$,
$updates$
holder = new.holder,
iban = new.iban,
bic = new.bic
$updates$);
--/
-- ============================================================================
--changeset hs-office-bankaccount-rbac-NEW-BANKACCOUNT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates a global permission for new-bankaccount and assigns it to the hostsharing admins role.
*/
do language plpgsql $$
declare
addCustomerPermissions uuid[];
globalObjectUuid uuid;
globalAdminRoleUuid uuid ;
begin
call defineContext('granting global new-bankaccount permission to global admin role', null, null, null);
globalAdminRoleUuid := findRoleId(globalAdmin());
globalObjectUuid := (select uuid from global);
addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-bankaccount']);
call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions);
end;
$$;
/**
Used by the trigger to prevent the add-customer to current user respectively assumed roles.
*/
create or replace function addHsOfficeBankAccountNotAllowedForCurrentSubjects()
returns trigger
language PLPGSQL
as $$
begin
raise exception '[403] new-bankaccount 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_bankaccount_insert_trigger
before insert
on hs_office_bankaccount
for each row
-- TODO.spec: who is allowed to create new bankaccounts
when ( not hasAssumedRole() )
execute procedure addHsOfficeBankAccountNotAllowedForCurrentSubjects();
--//

View File

@@ -1,178 +0,0 @@
### rbac sepaMandate
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
```mermaid
%%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB
subgraph bankAccount["`**bankAccount**`"]
direction TB
style bankAccount fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph bankAccount:roles[ ]
style bankAccount:roles fill:#99bcdb,stroke:white
role:bankAccount:owner[[bankAccount:owner]]
role:bankAccount:admin[[bankAccount:admin]]
role:bankAccount:referrer[[bankAccount:referrer]]
end
end
subgraph debitorRel.contact["`**debitorRel.contact**`"]
direction TB
style debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.contact:roles[ ]
style debitorRel.contact:roles fill:#99bcdb,stroke:white
role:debitorRel.contact:owner[[debitorRel.contact:owner]]
role:debitorRel.contact:admin[[debitorRel.contact:admin]]
role:debitorRel.contact:referrer[[debitorRel.contact:referrer]]
end
end
subgraph debitorRel.anchorPerson["`**debitorRel.anchorPerson**`"]
direction TB
style debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.anchorPerson:roles[ ]
style debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:debitorRel.anchorPerson:owner[[debitorRel.anchorPerson:owner]]
role:debitorRel.anchorPerson:admin[[debitorRel.anchorPerson:admin]]
role:debitorRel.anchorPerson:referrer[[debitorRel.anchorPerson:referrer]]
end
end
subgraph debitorRel.holderPerson["`**debitorRel.holderPerson**`"]
direction TB
style debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.holderPerson:roles[ ]
style debitorRel.holderPerson:roles fill:#99bcdb,stroke:white
role:debitorRel.holderPerson:owner[[debitorRel.holderPerson:owner]]
role:debitorRel.holderPerson:admin[[debitorRel.holderPerson:admin]]
role:debitorRel.holderPerson:referrer[[debitorRel.holderPerson:referrer]]
end
end
subgraph sepaMandate["`**sepaMandate**`"]
direction TB
style sepaMandate fill:#dd4901,stroke:#274d6e,stroke-width:8px
subgraph sepaMandate:roles[ ]
style sepaMandate:roles fill:#dd4901,stroke:white
role:sepaMandate:owner[[sepaMandate:owner]]
role:sepaMandate:admin[[sepaMandate:admin]]
role:sepaMandate:agent[[sepaMandate:agent]]
role:sepaMandate:referrer[[sepaMandate:referrer]]
end
subgraph sepaMandate:permissions[ ]
style sepaMandate:permissions fill:#dd4901,stroke:white
perm:sepaMandate:DELETE{{sepaMandate:DELETE}}
perm:sepaMandate:UPDATE{{sepaMandate:UPDATE}}
perm:sepaMandate:SELECT{{sepaMandate:SELECT}}
end
end
subgraph debitorRel["`**debitorRel**`"]
direction TB
style debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.contact["`**debitorRel.contact**`"]
direction TB
style debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.contact:roles[ ]
style debitorRel.contact:roles fill:#99bcdb,stroke:white
role:debitorRel.contact:owner[[debitorRel.contact:owner]]
role:debitorRel.contact:admin[[debitorRel.contact:admin]]
role:debitorRel.contact:referrer[[debitorRel.contact:referrer]]
end
end
subgraph debitorRel.anchorPerson["`**debitorRel.anchorPerson**`"]
direction TB
style debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.anchorPerson:roles[ ]
style debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:debitorRel.anchorPerson:owner[[debitorRel.anchorPerson:owner]]
role:debitorRel.anchorPerson:admin[[debitorRel.anchorPerson:admin]]
role:debitorRel.anchorPerson:referrer[[debitorRel.anchorPerson:referrer]]
end
end
subgraph debitorRel.holderPerson["`**debitorRel.holderPerson**`"]
direction TB
style debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.holderPerson:roles[ ]
style debitorRel.holderPerson:roles fill:#99bcdb,stroke:white
role:debitorRel.holderPerson:owner[[debitorRel.holderPerson:owner]]
role:debitorRel.holderPerson:admin[[debitorRel.holderPerson:admin]]
role:debitorRel.holderPerson:referrer[[debitorRel.holderPerson:referrer]]
end
end
subgraph debitorRel:roles[ ]
style debitorRel:roles fill:#99bcdb,stroke:white
role:debitorRel:owner[[debitorRel:owner]]
role:debitorRel:admin[[debitorRel:admin]]
role:debitorRel:agent[[debitorRel:agent]]
role:debitorRel:tenant[[debitorRel:tenant]]
end
end
%% granting roles to users
user:creator ==> role:sepaMandate:owner
%% granting roles to roles
role:global:admin -.-> role:debitorRel.anchorPerson:owner
role:debitorRel.anchorPerson:owner -.-> role:debitorRel.anchorPerson:admin
role:debitorRel.anchorPerson:admin -.-> role:debitorRel.anchorPerson:referrer
role:global:admin -.-> role:debitorRel.holderPerson:owner
role:debitorRel.holderPerson:owner -.-> role:debitorRel.holderPerson:admin
role:debitorRel.holderPerson:admin -.-> role:debitorRel.holderPerson:referrer
role:global:admin -.-> role:debitorRel.contact:owner
role:debitorRel.contact:owner -.-> role:debitorRel.contact:admin
role:debitorRel.contact:admin -.-> role:debitorRel.contact:referrer
role:global:admin -.-> role:debitorRel:owner
role:debitorRel:owner -.-> role:debitorRel:admin
role:debitorRel.anchorPerson:admin -.-> role:debitorRel:admin
role:debitorRel:admin -.-> role:debitorRel:agent
role:debitorRel.holderPerson:admin -.-> role:debitorRel:agent
role:debitorRel:agent -.-> role:debitorRel:tenant
role:debitorRel.holderPerson:admin -.-> role:debitorRel:tenant
role:debitorRel.contact:admin -.-> role:debitorRel:tenant
role:debitorRel:tenant -.-> role:debitorRel.anchorPerson:referrer
role:debitorRel:tenant -.-> role:debitorRel.holderPerson:referrer
role:debitorRel:tenant -.-> role:debitorRel.contact:referrer
role:global:admin -.-> role:bankAccount:owner
role:bankAccount:owner -.-> role:bankAccount:admin
role:bankAccount:admin -.-> role:bankAccount:referrer
role:global:admin ==> role:sepaMandate:owner
role:sepaMandate:owner ==> role:sepaMandate:admin
role:sepaMandate:admin ==> role:sepaMandate:agent
role:sepaMandate:agent ==> role:bankAccount:referrer
role:sepaMandate:agent ==> role:debitorRel:agent
role:sepaMandate:agent ==> role:sepaMandate:referrer
role:bankAccount:admin ==> role:sepaMandate:referrer
role:debitorRel:agent ==> role:sepaMandate:referrer
role:sepaMandate:referrer ==> role:debitorRel:tenant
%% granting permissions to roles
role:sepaMandate:owner ==> perm:sepaMandate:DELETE
role:sepaMandate:admin ==> perm:sepaMandate:UPDATE
role:sepaMandate:referrer ==> perm:sepaMandate:SELECT
```

View File

@@ -1,143 +0,0 @@
--liquibase formatted sql
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
-- ============================================================================
--changeset hs-office-sepamandate-rbac-OBJECT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRelatedRbacObject('hs_office_sepamandate');
--//
-- ============================================================================
--changeset hs-office-sepamandate-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRoleDescriptors('hsOfficeSepaMandate', 'hs_office_sepamandate');
--//
-- ============================================================================
--changeset hs-office-sepamandate-rbac-insert-trigger:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
*/
create or replace procedure buildRbacSystemForHsOfficeSepaMandate(
NEW hs_office_sepamandate
)
language plpgsql as $$
declare
newBankAccount hs_office_bankaccount;
newDebitorRel hs_office_relation;
begin
call enterTriggerForObjectUuid(NEW.uuid);
SELECT * FROM hs_office_bankaccount WHERE uuid = NEW.bankAccountUuid INTO newBankAccount;
SELECT * FROM hs_office_relation WHERE uuid = NEW.debitorRelUuid INTO newDebitorRel;
perform createRoleWithGrants(
hsOfficeSepaMandateOwner(NEW),
permissions => array['DELETE'],
incomingSuperRoles => array[globalAdmin()],
userUuids => array[currentUserUuid()]
);
perform createRoleWithGrants(
hsOfficeSepaMandateAdmin(NEW),
permissions => array['UPDATE'],
incomingSuperRoles => array[hsOfficeSepaMandateOwner(NEW)]
);
perform createRoleWithGrants(
hsOfficeSepaMandateAgent(NEW),
incomingSuperRoles => array[hsOfficeSepaMandateAdmin(NEW)],
outgoingSubRoles => array[
hsOfficeBankAccountReferrer(newBankAccount),
hsOfficeRelationAgent(newDebitorRel)]
);
perform createRoleWithGrants(
hsOfficeSepaMandateReferrer(NEW),
permissions => array['SELECT'],
incomingSuperRoles => array[
hsOfficeBankAccountAdmin(newBankAccount),
hsOfficeRelationAgent(newDebitorRel),
hsOfficeSepaMandateAgent(NEW)],
outgoingSubRoles => array[hsOfficeRelationTenant(newDebitorRel)]
);
call leaveTriggerForObjectUuid(NEW.uuid);
end; $$;
/*
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_sepamandate row.
*/
create or replace function insertTriggerForHsOfficeSepaMandate_tf()
returns trigger
language plpgsql
strict as $$
begin
call buildRbacSystemForHsOfficeSepaMandate(NEW);
return NEW;
end; $$;
create trigger insertTriggerForHsOfficeSepaMandate_tg
after insert on hs_office_sepamandate
for each row
execute procedure insertTriggerForHsOfficeSepaMandate_tf();
--//
-- ============================================================================
--changeset hs-office-sepamandate-rbac-INSERT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/**
Checks if the user or assumed roles are allowed to insert a row to hs_office_sepamandate,
where only global-admin has that permission.
*/
create or replace function hs_office_sepamandate_insert_permission_missing_tf()
returns trigger
language plpgsql as $$
begin
raise exception '[403] insert into hs_office_sepamandate not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids();
end; $$;
create trigger hs_office_sepamandate_insert_permission_check_tg
before insert on hs_office_sepamandate
for each row
when ( not isGlobalAdmin() )
execute procedure hs_office_sepamandate_insert_permission_missing_tf();
--//
-- ============================================================================
--changeset hs-office-sepamandate-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('hs_office_sepamandate',
$idName$
concat(tradeName, familyName, givenName)
$idName$);
--//
-- ============================================================================
--changeset hs-office-sepamandate-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRestrictedView('hs_office_sepamandate',
$orderBy$
concat(tradeName, familyName, givenName)
$orderBy$,
$updates$
reference = new.reference,
agreement = new.agreement,
validity = new.validity
$updates$);
--//

View File

@@ -1,71 +1,180 @@
### hs_office_sepaMandate RBAC
### rbac sepaMandate
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
```mermaid
%%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB
subgraph global
style global fill:#eee
role:global.admin[global.admin]
end
subgraph hsOfficeBankAccount
subgraph bankAccount["`**bankAccount**`"]
direction TB
style hsOfficeBankAccount fill:#eee
role:hsOfficeBankAccount.owner[bankAccount.owner]
--> role:hsOfficeBankAccount.admin[bankAccount.admin]
--> role:hsOfficeBankAccount.tenant[bankAccount.tenant]
--> role:hsOfficeBankAccount.guest[bankAccount.guest]
style bankAccount fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph bankAccount:roles[ ]
style bankAccount:roles fill:#99bcdb,stroke:white
role:bankAccount:owner[[bankAccount:owner]]
role:bankAccount:admin[[bankAccount:admin]]
role:bankAccount:referrer[[bankAccount:referrer]]
end
end
subgraph hsOfficeDebitor
subgraph debitorRel.contact["`**debitorRel.contact**`"]
direction TB
style hsOfficeDebitor fill:#eee
role:hsOfficeDebitor.owner[debitor.admin]
--> role:hsOfficeDebitor.admin[debitor.admin]
--> role:hsOfficeDebitor.agent[debitor.agent]
--> role:hsOfficeDebitor.tenant[debitor.tenant]
--> role:hsOfficeDebitor.guest[debitor.guest]
style debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.contact:roles[ ]
style debitorRel.contact:roles fill:#99bcdb,stroke:white
role:debitorRel.contact:owner[[debitorRel.contact:owner]]
role:debitorRel.contact:admin[[debitorRel.contact:admin]]
role:debitorRel.contact:referrer[[debitorRel.contact:referrer]]
end
end
subgraph hsOfficeSepaMandate
role:hsOfficeSepaMandate.owner[sepaMandate.owner]
%% permissions
role:hsOfficeSepaMandate.owner --> perm:hsOfficeSepaMandate.*{{sepaMandate.*}}
%% incoming
role:global.admin ---> role:hsOfficeSepaMandate.owner
role:hsOfficeSepaMandate.admin[sepaMandate.admin]
%% permissions
role:hsOfficeSepaMandate.admin --> perm:hsOfficeSepaMandate.edit{{sepaMandate.edit}}
%% incoming
role:hsOfficeSepaMandate.owner ---> role:hsOfficeSepaMandate.admin
role:hsOfficeSepaMandate.agent[sepaMandate.agent]
%% incoming
role:hsOfficeSepaMandate.admin ---> role:hsOfficeSepaMandate.agent
role:hsOfficeDebitor.admin --> role:hsOfficeSepaMandate.agent
role:hsOfficeBankAccount.admin --> role:hsOfficeSepaMandate.agent
%% outgoing
role:hsOfficeSepaMandate.agent --> role:hsOfficeDebitor.tenant
role:hsOfficeSepaMandate.admin --> role:hsOfficeBankAccount.tenant
role:hsOfficeSepaMandate.tenant[sepaMandate.tenant]
%% incoming
role:hsOfficeSepaMandate.agent --> role:hsOfficeSepaMandate.tenant
%% outgoing
role:hsOfficeSepaMandate.tenant --> role:hsOfficeDebitor.guest
role:hsOfficeSepaMandate.tenant --> role:hsOfficeBankAccount.guest
subgraph debitorRel.anchorPerson["`**debitorRel.anchorPerson**`"]
direction TB
style debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
role:hsOfficeSepaMandate.guest[sepaMandate.guest]
%% permissions
role:hsOfficeSepaMandate.guest --> perm:hsOfficeSepaMandate.view{{sepaMandate.view}}
%% incoming
role:hsOfficeSepaMandate.tenant --> role:hsOfficeSepaMandate.guest
subgraph debitorRel.anchorPerson:roles[ ]
style debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:debitorRel.anchorPerson:owner[[debitorRel.anchorPerson:owner]]
role:debitorRel.anchorPerson:admin[[debitorRel.anchorPerson:admin]]
role:debitorRel.anchorPerson:referrer[[debitorRel.anchorPerson:referrer]]
end
end
subgraph debitorRel.holderPerson["`**debitorRel.holderPerson**`"]
direction TB
style debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.holderPerson:roles[ ]
style debitorRel.holderPerson:roles fill:#99bcdb,stroke:white
role:debitorRel.holderPerson:owner[[debitorRel.holderPerson:owner]]
role:debitorRel.holderPerson:admin[[debitorRel.holderPerson:admin]]
role:debitorRel.holderPerson:referrer[[debitorRel.holderPerson:referrer]]
end
end
subgraph sepaMandate["`**sepaMandate**`"]
direction TB
style sepaMandate fill:#dd4901,stroke:#274d6e,stroke-width:8px
subgraph sepaMandate:roles[ ]
style sepaMandate:roles fill:#dd4901,stroke:white
role:sepaMandate:owner[[sepaMandate:owner]]
role:sepaMandate:admin[[sepaMandate:admin]]
role:sepaMandate:agent[[sepaMandate:agent]]
role:sepaMandate:referrer[[sepaMandate:referrer]]
end
subgraph sepaMandate:permissions[ ]
style sepaMandate:permissions fill:#dd4901,stroke:white
perm:sepaMandate:DELETE{{sepaMandate:DELETE}}
perm:sepaMandate:UPDATE{{sepaMandate:UPDATE}}
perm:sepaMandate:SELECT{{sepaMandate:SELECT}}
perm:sepaMandate:INSERT{{sepaMandate:INSERT}}
end
end
subgraph debitorRel["`**debitorRel**`"]
direction TB
style debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.contact["`**debitorRel.contact**`"]
direction TB
style debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.contact:roles[ ]
style debitorRel.contact:roles fill:#99bcdb,stroke:white
role:debitorRel.contact:owner[[debitorRel.contact:owner]]
role:debitorRel.contact:admin[[debitorRel.contact:admin]]
role:debitorRel.contact:referrer[[debitorRel.contact:referrer]]
end
end
subgraph debitorRel.anchorPerson["`**debitorRel.anchorPerson**`"]
direction TB
style debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.anchorPerson:roles[ ]
style debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:debitorRel.anchorPerson:owner[[debitorRel.anchorPerson:owner]]
role:debitorRel.anchorPerson:admin[[debitorRel.anchorPerson:admin]]
role:debitorRel.anchorPerson:referrer[[debitorRel.anchorPerson:referrer]]
end
end
subgraph debitorRel.holderPerson["`**debitorRel.holderPerson**`"]
direction TB
style debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.holderPerson:roles[ ]
style debitorRel.holderPerson:roles fill:#99bcdb,stroke:white
role:debitorRel.holderPerson:owner[[debitorRel.holderPerson:owner]]
role:debitorRel.holderPerson:admin[[debitorRel.holderPerson:admin]]
role:debitorRel.holderPerson:referrer[[debitorRel.holderPerson:referrer]]
end
end
subgraph debitorRel:roles[ ]
style debitorRel:roles fill:#99bcdb,stroke:white
role:debitorRel:owner[[debitorRel:owner]]
role:debitorRel:admin[[debitorRel:admin]]
role:debitorRel:agent[[debitorRel:agent]]
role:debitorRel:tenant[[debitorRel:tenant]]
end
end
%% granting roles to users
user:creator ==> role:sepaMandate:owner
%% granting roles to roles
role:global:admin -.-> role:debitorRel.anchorPerson:owner
role:debitorRel.anchorPerson:owner -.-> role:debitorRel.anchorPerson:admin
role:debitorRel.anchorPerson:admin -.-> role:debitorRel.anchorPerson:referrer
role:global:admin -.-> role:debitorRel.holderPerson:owner
role:debitorRel.holderPerson:owner -.-> role:debitorRel.holderPerson:admin
role:debitorRel.holderPerson:admin -.-> role:debitorRel.holderPerson:referrer
role:global:admin -.-> role:debitorRel.contact:owner
role:debitorRel.contact:owner -.-> role:debitorRel.contact:admin
role:debitorRel.contact:admin -.-> role:debitorRel.contact:referrer
role:global:admin -.-> role:debitorRel:owner
role:debitorRel:owner -.-> role:debitorRel:admin
role:debitorRel.anchorPerson:admin -.-> role:debitorRel:admin
role:debitorRel:admin -.-> role:debitorRel:agent
role:debitorRel.holderPerson:admin -.-> role:debitorRel:agent
role:debitorRel:agent -.-> role:debitorRel:tenant
role:debitorRel.holderPerson:admin -.-> role:debitorRel:tenant
role:debitorRel.contact:admin -.-> role:debitorRel:tenant
role:debitorRel:tenant -.-> role:debitorRel.anchorPerson:referrer
role:debitorRel:tenant -.-> role:debitorRel.holderPerson:referrer
role:debitorRel:tenant -.-> role:debitorRel.contact:referrer
role:global:admin -.-> role:bankAccount:owner
role:bankAccount:owner -.-> role:bankAccount:admin
role:bankAccount:admin -.-> role:bankAccount:referrer
role:global:admin ==> role:sepaMandate:owner
role:sepaMandate:owner ==> role:sepaMandate:admin
role:sepaMandate:admin ==> role:sepaMandate:agent
role:sepaMandate:agent ==> role:bankAccount:referrer
role:sepaMandate:agent ==> role:debitorRel:agent
role:sepaMandate:agent ==> role:sepaMandate:referrer
role:bankAccount:admin ==> role:sepaMandate:referrer
role:debitorRel:agent ==> role:sepaMandate:referrer
role:sepaMandate:referrer ==> role:debitorRel:tenant
%% granting permissions to roles
role:sepaMandate:owner ==> perm:sepaMandate:DELETE
role:sepaMandate:admin ==> perm:sepaMandate:UPDATE
role:sepaMandate:referrer ==> perm:sepaMandate:SELECT
role:debitorRel:admin ==> perm:sepaMandate:INSERT
```

View File

@@ -1,4 +1,6 @@
--liquibase formatted sql
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
-- ============================================================================
--changeset hs-office-sepamandate-rbac-OBJECT:1 endDelimiter:--//
@@ -15,144 +17,191 @@ call generateRbacRoleDescriptors('hsOfficeSepaMandate', 'hs_office_sepamandate')
-- ============================================================================
--changeset hs-office-sepamandate-rbac-ROLES-CREATION:1 endDelimiter:--//
--changeset hs-office-sepamandate-rbac-insert-trigger:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates and updates the roles and their assignments for sepaMandate entities.
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
*/
create or replace function hsOfficeSepaMandateRbacRolesTrigger()
returns trigger
language plpgsql
strict as $$
create or replace procedure buildRbacSystemForHsOfficeSepaMandate(
NEW hs_office_sepamandate
)
language plpgsql as $$
declare
newHsOfficeDebitor hs_office_debitor;
newHsOfficeBankAccount hs_office_bankAccount;
newBankAccount hs_office_bankaccount;
newDebitorRel hs_office_relation;
begin
call enterTriggerForObjectUuid(NEW.uuid);
select * from hs_office_debitor as p where p.uuid = NEW.debitorUuid into newHsOfficeDebitor;
select * from hs_office_bankAccount as c where c.uuid = NEW.bankAccountUuid into newHsOfficeBankAccount;
SELECT * FROM hs_office_bankaccount WHERE uuid = NEW.bankAccountUuid INTO newBankAccount;
assert newBankAccount.uuid is not null, format('newBankAccount must not be null for NEW.bankAccountUuid = %s', NEW.bankAccountUuid);
if TG_OP = 'INSERT' then
SELECT debitorRel.*
FROM hs_office_relation debitorRel
JOIN hs_office_debitor debitor ON debitor.debitorRelUuid = debitorRel.uuid
WHERE debitor.uuid = NEW.debitorUuid
INTO newDebitorRel;
assert newDebitorRel.uuid is not null, format('newDebitorRel must not be null for NEW.debitorUuid = %s', NEW.debitorUuid);
-- === ATTENTION: code generated from related Mermaid flowchart: ===
perform createRoleWithGrants(
hsOfficeSepaMandateOwner(NEW),
permissions => array['DELETE'],
incomingSuperRoles => array[globalAdmin()]
);
perform createRoleWithGrants(
hsOfficeSepaMandateOwner(NEW),
permissions => array['DELETE'],
incomingSuperRoles => array[globalAdmin()],
userUuids => array[currentUserUuid()]
);
perform createRoleWithGrants(
hsOfficeSepaMandateAdmin(NEW),
permissions => array['UPDATE'],
incomingSuperRoles => array[hsOfficeSepaMandateOwner(NEW)],
outgoingSubRoles => array[hsOfficeBankAccountTenant(newHsOfficeBankAccount)]
);
perform createRoleWithGrants(
hsOfficeSepaMandateAdmin(NEW),
permissions => array['UPDATE'],
incomingSuperRoles => array[hsOfficeSepaMandateOwner(NEW)]
);
perform createRoleWithGrants(
hsOfficeSepaMandateAgent(NEW),
incomingSuperRoles => array[hsOfficeSepaMandateAdmin(NEW), hsOfficeDebitorAdmin(newHsOfficeDebitor), hsOfficeBankAccountAdmin(newHsOfficeBankAccount)],
outgoingSubRoles => array[hsOfficeDebitorTenant(newHsOfficeDebitor)]
);
perform createRoleWithGrants(
hsOfficeSepaMandateAgent(NEW),
incomingSuperRoles => array[hsOfficeSepaMandateAdmin(NEW)],
outgoingSubRoles => array[
hsOfficeBankAccountReferrer(newBankAccount),
hsOfficeRelationAgent(newDebitorRel)]
);
perform createRoleWithGrants(
hsOfficeSepaMandateTenant(NEW),
incomingSuperRoles => array[hsOfficeSepaMandateAgent(NEW)],
outgoingSubRoles => array[hsOfficeDebitorGuest(newHsOfficeDebitor), hsOfficeBankAccountGuest(newHsOfficeBankAccount)]
);
perform createRoleWithGrants(
hsOfficeSepaMandateGuest(NEW),
permissions => array['SELECT'],
incomingSuperRoles => array[hsOfficeSepaMandateTenant(NEW)]
);
-- === END of code generated from Mermaid flowchart. ===
else
raise exception 'invalid usage of TRIGGER';
end if;
perform createRoleWithGrants(
hsOfficeSepaMandateReferrer(NEW),
permissions => array['SELECT'],
incomingSuperRoles => array[
hsOfficeBankAccountAdmin(newBankAccount),
hsOfficeRelationAgent(newDebitorRel),
hsOfficeSepaMandateAgent(NEW)],
outgoingSubRoles => array[hsOfficeRelationTenant(newDebitorRel)]
);
call leaveTriggerForObjectUuid(NEW.uuid);
return NEW;
end; $$;
/*
An AFTER INSERT TRIGGER which creates the role structure for a new customer.
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_sepamandate row.
*/
create trigger createRbacRolesForHsOfficeSepaMandate_Trigger
after insert
on hs_office_sepamandate
create or replace function insertTriggerForHsOfficeSepaMandate_tf()
returns trigger
language plpgsql
strict as $$
begin
call buildRbacSystemForHsOfficeSepaMandate(NEW);
return NEW;
end; $$;
create trigger insertTriggerForHsOfficeSepaMandate_tg
after insert on hs_office_sepamandate
for each row
execute procedure hsOfficeSepaMandateRbacRolesTrigger();
execute procedure insertTriggerForHsOfficeSepaMandate_tf();
--//
-- ============================================================================
--changeset hs-office-sepamandate-rbac-IDENTITY-VIEW:1 endDelimiter:--//
--changeset hs-office-sepamandate-rbac-INSERT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('hs_office_sepamandate', 'target.reference');
/*
Creates INSERT INTO hs_office_sepamandate permissions for the related hs_office_relation rows.
*/
do language plpgsql $$
declare
row hs_office_relation;
begin
call defineContext('create INSERT INTO hs_office_sepamandate permissions for the related hs_office_relation rows');
FOR row IN SELECT * FROM hs_office_relation
LOOP
call grantPermissionToRole(
createPermission(row.uuid, 'INSERT', 'hs_office_sepamandate'),
hsOfficeRelationAdmin(row));
END LOOP;
END;
$$;
/**
Adds hs_office_sepamandate INSERT permission to specified role of new hs_office_relation rows.
*/
create or replace function hs_office_sepamandate_hs_office_relation_insert_tf()
returns trigger
language plpgsql
strict as $$
begin
call grantPermissionToRole(
createPermission(NEW.uuid, 'INSERT', 'hs_office_sepamandate'),
hsOfficeRelationAdmin(NEW));
return NEW;
end; $$;
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
create trigger z_hs_office_sepamandate_hs_office_relation_insert_tg
after insert on hs_office_relation
for each row
execute procedure hs_office_sepamandate_hs_office_relation_insert_tf();
/**
Checks if the user or assumed roles are allowed to insert a row to hs_office_sepamandate,
where the check is performed by an indirect role.
An indirect role is a role which depends on an object uuid which is not a direct foreign key
of the source entity, but needs to be fetched via joined tables.
*/
create or replace function hs_office_sepamandate_insert_permission_check_tf()
returns trigger
language plpgsql as $$
declare
superRoleObjectUuid uuid;
begin
superRoleObjectUuid := (SELECT debitorRel.uuid
FROM hs_office_relation debitorRel
JOIN hs_office_debitor debitor ON debitor.debitorRelUuid = debitorRel.uuid
WHERE debitor.uuid = NEW.debitorUuid
);
assert superRoleObjectUuid is not null, 'superRoleObjectUuid must not be null';
if ( not hasInsertPermission(superRoleObjectUuid, 'INSERT', 'hs_office_sepamandate') ) then
raise exception
'[403] insert into hs_office_sepamandate not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids();
end if;
return NEW;
end; $$;
create trigger hs_office_sepamandate_insert_permission_check_tg
before insert on hs_office_sepamandate
for each row
execute procedure hs_office_sepamandate_insert_permission_check_tf();
--//
-- ============================================================================
--changeset hs-office-sepamandate-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromQuery('hs_office_sepamandate',
$idName$
select sm.uuid as uuid, ba.iban || '-' || sm.validity as idName
from hs_office_sepamandate sm
join hs_office_bankaccount ba on ba.uuid = sm.bankAccountUuid
$idName$);
--//
-- ============================================================================
--changeset hs-office-sepamandate-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRestrictedView('hs_office_sepamandate',
orderby => 'target.reference',
columnUpdates => $updates$
$orderBy$
validity
$orderBy$,
$updates$
reference = new.reference,
agreement = new.agreement,
validity = new.validity
$updates$);
--//
-- ============================================================================
--changeset hs-office-sepamandate-rbac-NEW-SepaMandate:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates a global permission for new-sepaMandate and assigns it to the hostsharing admins role.
*/
do language plpgsql $$
declare
addCustomerPermissions uuid[];
globalObjectUuid uuid;
globalAdminRoleUuid uuid ;
begin
call defineContext('granting global new-sepaMandate permission to global admin role', null, null, null);
globalAdminRoleUuid := findRoleId(globalAdmin());
globalObjectUuid := (select uuid from global);
addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-sepamandate']);
call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions);
end;
$$;
/**
Used by the trigger to prevent the add-customer to current user respectively assumed roles.
*/
create or replace function addHsOfficeSepaMandateNotAllowedForCurrentSubjects()
returns trigger
language PLPGSQL
as $$
begin
raise exception '[403] new-sepaMandate 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_sepamandate_insert_trigger
before insert
on hs_office_sepamandate
for each row
-- TODO.spec: who is allowed to create new sepaMandates
when ( not hasAssumedRole() )
execute procedure addHsOfficeSepaMandateNotAllowedForCurrentSubjects();
--//

View File

@@ -8,31 +8,36 @@
/*
Creates a single sepaMandate test record.
*/
create or replace procedure createHsOfficeSepaMandateTestData( tradeNameAndHolderName varchar )
create or replace procedure createHsOfficeSepaMandateTestData(
forPartnerNumber numeric(5),
forDebitorSuffix numeric(2),
forIban varchar,
withReference varchar)
language plpgsql as $$
declare
currentTask varchar;
idName varchar;
relatedDebitor hs_office_debitor;
relatedBankAccount hs_office_bankAccount;
begin
idName := cleanIdentifier( tradeNameAndHolderName);
currentTask := 'creating SEPA-mandate test-data ' || idName;
currentTask := 'creating SEPA-mandate test-data ' || forPartnerNumber::text || forDebitorSuffix::text;
call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global.admin');
execute format('set local hsadminng.currentTask to %L', currentTask);
select debitor.* from hs_office_debitor debitor
join hs_office_partner parter on parter.uuid = debitor.partnerUuid
join hs_office_person person on person.uuid = parter.personUuid
where person.tradeName = tradeNameAndHolderName into relatedDebitor;
select c.* from hs_office_bankAccount c where c.holder = tradeNameAndHolderName into relatedBankAccount;
select debitor.* into relatedDebitor
from hs_office_debitor debitor
join hs_office_relation debitorRel on debitorRel.uuid = debitor.debitorRelUuid
join hs_office_relation partnerRel on partnerRel.holderUuid = debitorRel.anchorUuid
join hs_office_partner partner on partner.partnerRelUuid = partnerRel.uuid
where partner.partnerNumber = forPartnerNumber and debitor.debitorNumberSuffix = forDebitorSuffix;
select b.* into relatedBankAccount
from hs_office_bankAccount b where b.iban = forIban;
raise notice 'creating test SEPA-mandate: %', idName;
raise notice 'creating test SEPA-mandate: %', forPartnerNumber::text || forDebitorSuffix::text;
raise notice '- using debitor (%): %', relatedDebitor.uuid, relatedDebitor;
raise notice '- using bankAccount (%): %', relatedBankAccount.uuid, relatedBankAccount;
insert
into hs_office_sepamandate (uuid, debitoruuid, bankAccountuuid, reference, agreement, validity)
values (uuid_generate_v4(), relatedDebitor.uuid, relatedBankAccount.uuid, 'ref'||idName, '20220930', daterange('20221001' , '20261231', '[]'));
values (uuid_generate_v4(), relatedDebitor.uuid, relatedBankAccount.uuid, withReference, '20220930', daterange('20221001' , '20261231', '[]'));
end; $$;
--//
@@ -43,9 +48,9 @@ end; $$;
do language plpgsql $$
begin
call createHsOfficeSepaMandateTestData('First GmbH');
call createHsOfficeSepaMandateTestData('Second e.K.');
call createHsOfficeSepaMandateTestData('Third OHG');
call createHsOfficeSepaMandateTestData(10001, 11, 'DE02120300000000202051', 'ref-10001-11');
call createHsOfficeSepaMandateTestData(10002, 12, 'DE02100500000054540402', 'ref-10002-12');
call createHsOfficeSepaMandateTestData(10003, 13, 'DE02300209000106531065', 'ref-10003-13');
end;
$$;
--//

View File

@@ -7,10 +7,9 @@
create table hs_office_debitor
(
uuid uuid unique references RbacObject (uuid) initially deferred,
partnerUuid uuid not null references hs_office_partner(uuid),
billable boolean not null default true,
debitorNumberSuffix numeric(2) not null,
billingContactUuid uuid not null references hs_office_contact(uuid),
debitorRelUuid uuid not null references hs_office_relation(uuid),
billable boolean not null default true,
vatId varchar(24), -- TODO.spec: here or in person?
vatCountryCode varchar(2),
vatBusiness boolean not null,
@@ -20,11 +19,43 @@ create table hs_office_debitor
constraint check_default_prefix check (
defaultPrefix::text ~ '^([a-z]{3}|al0|bh1|c4s|f3k|k8i|l3d|mh1|o13|p2m|s80|t4w)$'
)
-- TODO.impl: SEPA-mandate
);
--//
-- ============================================================================
--changeset hs-office-debitor-DELETE-DEPENDENTS-TRIGGER:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/**
Trigger function to delete related rows of a debitor to delete.
*/
create or replace function deleteHsOfficeDependentsOnDebitorDelete()
returns trigger
language PLPGSQL
as $$
declare
counter integer;
begin
DELETE FROM hs_office_relation r WHERE r.uuid = OLD.debitorRelUuid;
GET DIAGNOSTICS counter = ROW_COUNT;
if counter = 0 then
raise exception 'debitor relation % could not be deleted', OLD.debitorRelUuid;
end if;
RETURN OLD;
end; $$;
/**
Triggers deletion of related details of a debitor to delete.
*/
create trigger hs_office_debitor_delete_dependents_trigger
after delete
on hs_office_debitor
for each row
execute procedure deleteHsOfficeDependentsOnDebitorDelete();
-- ============================================================================
--changeset hs-office-debitor-MAIN-TABLE-JOURNAL:1 endDelimiter:--//
-- ----------------------------------------------------------------------------

View File

@@ -1,275 +0,0 @@
### rbac debitor
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
```mermaid
%%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB
subgraph debitorRel.anchorPerson["`**debitorRel.anchorPerson**`"]
direction TB
style debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.anchorPerson:roles[ ]
style debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:debitorRel.anchorPerson:owner[[debitorRel.anchorPerson:owner]]
role:debitorRel.anchorPerson:admin[[debitorRel.anchorPerson:admin]]
role:debitorRel.anchorPerson:referrer[[debitorRel.anchorPerson:referrer]]
end
end
subgraph debitorRel.holderPerson["`**debitorRel.holderPerson**`"]
direction TB
style debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.holderPerson:roles[ ]
style debitorRel.holderPerson:roles fill:#99bcdb,stroke:white
role:debitorRel.holderPerson:owner[[debitorRel.holderPerson:owner]]
role:debitorRel.holderPerson:admin[[debitorRel.holderPerson:admin]]
role:debitorRel.holderPerson:referrer[[debitorRel.holderPerson:referrer]]
end
end
subgraph partnerRel.holderPerson["`**partnerRel.holderPerson**`"]
direction TB
style partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.holderPerson:roles[ ]
style partnerRel.holderPerson:roles fill:#99bcdb,stroke:white
role:partnerRel.holderPerson:owner[[partnerRel.holderPerson:owner]]
role:partnerRel.holderPerson:admin[[partnerRel.holderPerson:admin]]
role:partnerRel.holderPerson:referrer[[partnerRel.holderPerson:referrer]]
end
end
subgraph debitor["`**debitor**`"]
direction TB
style debitor fill:#dd4901,stroke:#274d6e,stroke-width:8px
subgraph debitor:permissions[ ]
style debitor:permissions fill:#dd4901,stroke:white
perm:debitor:INSERT{{debitor:INSERT}}
perm:debitor:DELETE{{debitor:DELETE}}
perm:debitor:UPDATE{{debitor:UPDATE}}
perm:debitor:SELECT{{debitor:SELECT}}
end
subgraph debitorRel["`**debitorRel**`"]
direction TB
style debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.anchorPerson["`**debitorRel.anchorPerson**`"]
direction TB
style debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.anchorPerson:roles[ ]
style debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:debitorRel.anchorPerson:owner[[debitorRel.anchorPerson:owner]]
role:debitorRel.anchorPerson:admin[[debitorRel.anchorPerson:admin]]
role:debitorRel.anchorPerson:referrer[[debitorRel.anchorPerson:referrer]]
end
end
subgraph debitorRel.holderPerson["`**debitorRel.holderPerson**`"]
direction TB
style debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.holderPerson:roles[ ]
style debitorRel.holderPerson:roles fill:#99bcdb,stroke:white
role:debitorRel.holderPerson:owner[[debitorRel.holderPerson:owner]]
role:debitorRel.holderPerson:admin[[debitorRel.holderPerson:admin]]
role:debitorRel.holderPerson:referrer[[debitorRel.holderPerson:referrer]]
end
end
subgraph debitorRel.contact["`**debitorRel.contact**`"]
direction TB
style debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.contact:roles[ ]
style debitorRel.contact:roles fill:#99bcdb,stroke:white
role:debitorRel.contact:owner[[debitorRel.contact:owner]]
role:debitorRel.contact:admin[[debitorRel.contact:admin]]
role:debitorRel.contact:referrer[[debitorRel.contact:referrer]]
end
end
subgraph debitorRel:roles[ ]
style debitorRel:roles fill:#99bcdb,stroke:white
role:debitorRel:owner[[debitorRel:owner]]
role:debitorRel:admin[[debitorRel:admin]]
role:debitorRel:agent[[debitorRel:agent]]
role:debitorRel:tenant[[debitorRel:tenant]]
end
end
end
subgraph partnerRel["`**partnerRel**`"]
direction TB
style partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.holderPerson["`**partnerRel.holderPerson**`"]
direction TB
style partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.holderPerson:roles[ ]
style partnerRel.holderPerson:roles fill:#99bcdb,stroke:white
role:partnerRel.holderPerson:owner[[partnerRel.holderPerson:owner]]
role:partnerRel.holderPerson:admin[[partnerRel.holderPerson:admin]]
role:partnerRel.holderPerson:referrer[[partnerRel.holderPerson:referrer]]
end
end
subgraph partnerRel.contact["`**partnerRel.contact**`"]
direction TB
style partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.contact:roles[ ]
style partnerRel.contact:roles fill:#99bcdb,stroke:white
role:partnerRel.contact:owner[[partnerRel.contact:owner]]
role:partnerRel.contact:admin[[partnerRel.contact:admin]]
role:partnerRel.contact:referrer[[partnerRel.contact:referrer]]
end
end
subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"]
direction TB
style partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.anchorPerson:roles[ ]
style partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:partnerRel.anchorPerson:owner[[partnerRel.anchorPerson:owner]]
role:partnerRel.anchorPerson:admin[[partnerRel.anchorPerson:admin]]
role:partnerRel.anchorPerson:referrer[[partnerRel.anchorPerson:referrer]]
end
end
subgraph partnerRel:roles[ ]
style partnerRel:roles fill:#99bcdb,stroke:white
role:partnerRel:owner[[partnerRel:owner]]
role:partnerRel:admin[[partnerRel:admin]]
role:partnerRel:agent[[partnerRel:agent]]
role:partnerRel:tenant[[partnerRel:tenant]]
end
end
subgraph partnerRel.contact["`**partnerRel.contact**`"]
direction TB
style partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.contact:roles[ ]
style partnerRel.contact:roles fill:#99bcdb,stroke:white
role:partnerRel.contact:owner[[partnerRel.contact:owner]]
role:partnerRel.contact:admin[[partnerRel.contact:admin]]
role:partnerRel.contact:referrer[[partnerRel.contact:referrer]]
end
end
subgraph debitorRel.contact["`**debitorRel.contact**`"]
direction TB
style debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.contact:roles[ ]
style debitorRel.contact:roles fill:#99bcdb,stroke:white
role:debitorRel.contact:owner[[debitorRel.contact:owner]]
role:debitorRel.contact:admin[[debitorRel.contact:admin]]
role:debitorRel.contact:referrer[[debitorRel.contact:referrer]]
end
end
subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"]
direction TB
style partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.anchorPerson:roles[ ]
style partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:partnerRel.anchorPerson:owner[[partnerRel.anchorPerson:owner]]
role:partnerRel.anchorPerson:admin[[partnerRel.anchorPerson:admin]]
role:partnerRel.anchorPerson:referrer[[partnerRel.anchorPerson:referrer]]
end
end
subgraph refundBankAccount["`**refundBankAccount**`"]
direction TB
style refundBankAccount fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph refundBankAccount:roles[ ]
style refundBankAccount:roles fill:#99bcdb,stroke:white
role:refundBankAccount:owner[[refundBankAccount:owner]]
role:refundBankAccount:admin[[refundBankAccount:admin]]
role:refundBankAccount:referrer[[refundBankAccount:referrer]]
end
end
%% granting roles to roles
role:global:admin -.-> role:debitorRel.anchorPerson:owner
role:debitorRel.anchorPerson:owner -.-> role:debitorRel.anchorPerson:admin
role:debitorRel.anchorPerson:admin -.-> role:debitorRel.anchorPerson:referrer
role:global:admin -.-> role:debitorRel.holderPerson:owner
role:debitorRel.holderPerson:owner -.-> role:debitorRel.holderPerson:admin
role:debitorRel.holderPerson:admin -.-> role:debitorRel.holderPerson:referrer
role:global:admin -.-> role:debitorRel.contact:owner
role:debitorRel.contact:owner -.-> role:debitorRel.contact:admin
role:debitorRel.contact:admin -.-> role:debitorRel.contact:referrer
role:global:admin -.-> role:debitorRel:owner
role:debitorRel:owner -.-> role:debitorRel:admin
role:debitorRel.anchorPerson:admin -.-> role:debitorRel:admin
role:debitorRel:admin -.-> role:debitorRel:agent
role:debitorRel.holderPerson:admin -.-> role:debitorRel:agent
role:debitorRel:agent -.-> role:debitorRel:tenant
role:debitorRel.holderPerson:admin -.-> role:debitorRel:tenant
role:debitorRel.contact:admin -.-> role:debitorRel:tenant
role:debitorRel:tenant -.-> role:debitorRel.anchorPerson:referrer
role:debitorRel:tenant -.-> role:debitorRel.holderPerson:referrer
role:debitorRel:tenant -.-> role:debitorRel.contact:referrer
role:global:admin -.-> role:refundBankAccount:owner
role:refundBankAccount:owner -.-> role:refundBankAccount:admin
role:refundBankAccount:admin -.-> role:refundBankAccount:referrer
role:refundBankAccount:admin ==> role:debitorRel:agent
role:debitorRel:agent ==> role:refundBankAccount:referrer
role:global:admin -.-> role:partnerRel.anchorPerson:owner
role:partnerRel.anchorPerson:owner -.-> role:partnerRel.anchorPerson:admin
role:partnerRel.anchorPerson:admin -.-> role:partnerRel.anchorPerson:referrer
role:global:admin -.-> role:partnerRel.holderPerson:owner
role:partnerRel.holderPerson:owner -.-> role:partnerRel.holderPerson:admin
role:partnerRel.holderPerson:admin -.-> role:partnerRel.holderPerson:referrer
role:global:admin -.-> role:partnerRel.contact:owner
role:partnerRel.contact:owner -.-> role:partnerRel.contact:admin
role:partnerRel.contact:admin -.-> role:partnerRel.contact:referrer
role:global:admin -.-> role:partnerRel:owner
role:partnerRel:owner -.-> role:partnerRel:admin
role:partnerRel.anchorPerson:admin -.-> role:partnerRel:admin
role:partnerRel:admin -.-> role:partnerRel:agent
role:partnerRel.holderPerson:admin -.-> role:partnerRel:agent
role:partnerRel:agent -.-> role:partnerRel:tenant
role:partnerRel.holderPerson:admin -.-> role:partnerRel:tenant
role:partnerRel.contact:admin -.-> role:partnerRel:tenant
role:partnerRel:tenant -.-> role:partnerRel.anchorPerson:referrer
role:partnerRel:tenant -.-> role:partnerRel.holderPerson:referrer
role:partnerRel:tenant -.-> role:partnerRel.contact:referrer
role:partnerRel:admin ==> role:debitorRel:admin
role:partnerRel:agent ==> role:debitorRel:agent
role:debitorRel:agent ==> role:partnerRel:tenant
%% granting permissions to roles
role:global:admin ==> perm:debitor:INSERT
role:debitorRel:owner ==> perm:debitor:DELETE
role:debitorRel:admin ==> perm:debitor:UPDATE
role:debitorRel:tenant ==> perm:debitor:SELECT
```

View File

@@ -1,231 +0,0 @@
--liquibase formatted sql
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
-- ============================================================================
--changeset hs-office-debitor-rbac-OBJECT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRelatedRbacObject('hs_office_debitor');
--//
-- ============================================================================
--changeset hs-office-debitor-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRoleDescriptors('hsOfficeDebitor', 'hs_office_debitor');
--//
-- ============================================================================
--changeset hs-office-debitor-rbac-insert-trigger:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
*/
create or replace procedure buildRbacSystemForHsOfficeDebitor(
NEW hs_office_debitor
)
language plpgsql as $$
declare
newPartnerRel hs_office_relation;
newDebitorRel hs_office_relation;
newRefundBankAccount hs_office_bankaccount;
begin
call enterTriggerForObjectUuid(NEW.uuid);
SELECT * FROM hs_office_relation WHERE uuid = NEW.partnerRelUuid INTO newPartnerRel;
SELECT * FROM hs_office_relation WHERE uuid = NEW.debitorRelUuid INTO newDebitorRel;
assert newDebitorRel.uuid is not null, format('newDebitorRel must not be null for NEW.debitorRelUuid = %s', NEW.debitorRelUuid);
SELECT * FROM hs_office_bankaccount WHERE uuid = NEW.refundBankAccountUuid INTO newRefundBankAccount;
call grantRoleToRole(hsOfficeBankAccountReferrer(newRefundBankAccount), hsOfficeRelationAgent(newDebitorRel));
call grantRoleToRole(hsOfficeRelationAdmin(newDebitorRel), hsOfficeRelationAdmin(newPartnerRel));
call grantRoleToRole(hsOfficeRelationAgent(newDebitorRel), hsOfficeBankAccountAdmin(newRefundBankAccount));
call grantRoleToRole(hsOfficeRelationAgent(newDebitorRel), hsOfficeRelationAgent(newPartnerRel));
call grantRoleToRole(hsOfficeRelationTenant(newPartnerRel), hsOfficeRelationAgent(newDebitorRel));
call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationOwner(newDebitorRel));
call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationTenant(newDebitorRel));
call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationAdmin(newDebitorRel));
call leaveTriggerForObjectUuid(NEW.uuid);
end; $$;
/*
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_debitor row.
*/
create or replace function insertTriggerForHsOfficeDebitor_tf()
returns trigger
language plpgsql
strict as $$
begin
call buildRbacSystemForHsOfficeDebitor(NEW);
return NEW;
end; $$;
create trigger insertTriggerForHsOfficeDebitor_tg
after insert on hs_office_debitor
for each row
execute procedure insertTriggerForHsOfficeDebitor_tf();
--//
-- ============================================================================
--changeset hs-office-debitor-rbac-update-trigger:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Called from the AFTER UPDATE TRIGGER to re-wire the grants.
*/
create or replace procedure updateRbacRulesForHsOfficeDebitor(
OLD hs_office_debitor,
NEW hs_office_debitor
)
language plpgsql as $$
begin
if NEW.refundBankAccountUuid is distinct from OLD.refundBankAccountUuid then
delete from rbacgrants g where g.grantedbytriggerof = OLD.uuid;
call buildRbacSystemForHsOfficeDebitor(NEW);
end if;
end; $$;
/*
AFTER INSERT TRIGGER to re-wire the grant structure for a new hs_office_debitor row.
*/
create or replace function updateTriggerForHsOfficeDebitor_tf()
returns trigger
language plpgsql
strict as $$
begin
call updateRbacRulesForHsOfficeDebitor(OLD, NEW);
return NEW;
end; $$;
create trigger updateTriggerForHsOfficeDebitor_tg
after update on hs_office_debitor
for each row
execute procedure updateTriggerForHsOfficeDebitor_tf();
--//
-- ============================================================================
--changeset hs-office-debitor-rbac-INSERT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates INSERT INTO hs_office_debitor permissions for the related global rows.
*/
do language plpgsql $$
declare
row global;
permissionUuid uuid;
roleUuid uuid;
begin
call defineContext('create INSERT INTO hs_office_debitor permissions for the related global rows');
FOR row IN SELECT * FROM global
LOOP
roleUuid := findRoleId(globalAdmin());
permissionUuid := createPermission(row.uuid, 'INSERT', 'hs_office_debitor');
call grantPermissionToRole(permissionUuid, roleUuid);
END LOOP;
END;
$$;
/**
Adds hs_office_debitor INSERT permission to specified role of new global rows.
*/
create or replace function hs_office_debitor_global_insert_tf()
returns trigger
language plpgsql
strict as $$
begin
call grantPermissionToRole(
createPermission(NEW.uuid, 'INSERT', 'hs_office_debitor'),
globalAdmin());
return NEW;
end; $$;
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
create trigger z_hs_office_debitor_global_insert_tg
after insert on global
for each row
execute procedure hs_office_debitor_global_insert_tf();
/**
Checks if the user or assumed roles are allowed to insert a row to hs_office_debitor,
where only global-admin has that permission.
*/
create or replace function hs_office_debitor_insert_permission_missing_tf()
returns trigger
language plpgsql as $$
begin
raise exception '[403] insert into hs_office_debitor not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids();
end; $$;
create trigger hs_office_debitor_insert_permission_check_tg
before insert on hs_office_debitor
for each row
when ( not isGlobalAdmin() )
execute procedure hs_office_debitor_insert_permission_missing_tf();
--//
-- ============================================================================
--changeset hs-office-debitor-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromQuery('hs_office_debitor',
$idName$
SELECT debitor.uuid,
'D-' || (SELECT partner.partnerNumber
FROM hs_office_partner partner
JOIN hs_office_relation partnerRel
ON partnerRel.uuid = partner.partnerRelUUid AND partnerRel.type = 'PARTNER'
JOIN hs_office_relation debitorRel
ON debitorRel.anchorUuid = partnerRel.holderUuid AND partnerRel.type = 'DEBITOR'
WHERE debitorRel.uuid = debitor.debitorRelUuid)
|| to_char(debitorNumberSuffix, 'fm00')
from hs_office_debitor as debitor
$idName$);
--//
-- ============================================================================
--changeset hs-office-debitor-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRestrictedView('hs_office_debitor',
$orderBy$
SELECT debitor.uuid,
'D-' || (SELECT partner.partnerNumber
FROM hs_office_partner partner
JOIN hs_office_relation partnerRel
ON partnerRel.uuid = partner.partnerRelUUid AND partnerRel.type = 'PARTNER'
JOIN hs_office_relation debitorRel
ON debitorRel.anchorUuid = partnerRel.holderUuid AND partnerRel.type = 'DEBITOR'
WHERE debitorRel.uuid = debitor.debitorRelUuid)
|| to_char(debitorNumberSuffix, 'fm00')
from hs_office_debitor as debitor
$orderBy$,
$updates$
debitorRel = new.debitorRel,
billable = new.billable,
debitorUuid = new.debitorUuid,
refundBankAccountUuid = new.refundBankAccountUuid,
vatId = new.vatId,
vatCountryCode = new.vatCountryCode,
vatBusiness = new.vatBusiness,
vatReverseCharge = new.vatReverseCharge,
defaultPrefix = new.defaultPrefix
$updates$);
--//

View File

@@ -1,250 +1,275 @@
### hs_office_debitor RBAC Roles
### rbac debitor
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
```mermaid
%%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB
subgraph global
style global fill:#eee
role:global.admin[global.admin]
end
subgraph debitorRel.anchorPerson["`**debitorRel.anchorPerson**`"]
direction TB
style debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph office
style office fill:#eee
subgraph sepa
subgraph bankaccount
style bankaccount fill: #e9f7ef
user:hsOfficeBankAccount.creator([bankaccount.creator])
role:hsOfficeBankAccount.owner[bankaccount.owner]
%% permissions
role:hsOfficeBankAccount.owner --> perm:hsOfficeBankAccount.*{{bankaccount.*}}
%% incoming
role:global.admin --> role:hsOfficeBankAccount.owner
user:hsOfficeBankAccount.creator ---> role:hsOfficeBankAccount.owner
role:hsOfficeBankAccount.admin[bankaccount.admin]
%% permissions
role:hsOfficeBankAccount.admin --> perm:hsOfficeBankAccount.edit{{bankaccount.edit}}
%% incoming
role:hsOfficeBankAccount.owner ---> role:hsOfficeBankAccount.admin
role:hsOfficeBankAccount.tenant[bankaccount.tenant]
%% incoming
role:hsOfficeBankAccount.admin ---> role:hsOfficeBankAccount.tenant
role:hsOfficeBankAccount.guest[bankaccount.guest]
%% permissions
role:hsOfficeBankAccount.guest --> perm:hsOfficeBankAccount.view{{bankaccount.view}}
%% incoming
role:hsOfficeBankAccount.tenant ---> role:hsOfficeBankAccount.guest
end
subgraph hsOfficeSepaMandate
end
end
subgraph contact
style contact fill: #e9f7ef
user:hsOfficeContact.creator([contact.creator])
role:hsOfficeContact.owner[contact.owner]
%% permissions
role:hsOfficeContact.owner --> perm:hsOfficeContact.*{{contact.*}}
%% incoming
role:global.admin --> role:hsOfficeContact.owner
user:hsOfficeContact.creator ---> role:hsOfficeContact.owner
role:hsOfficeContact.admin[contact.admin]
%% permissions
role:hsOfficeContact.admin ---> perm:hsOfficeContact.edit{{contact.edit}}
%% incoming
role:hsOfficeContact.owner ---> role:hsOfficeContact.admin
role:hsOfficeContact.tenant[contact.tenant]
%% incoming
role:hsOfficeContact.admin ----> role:hsOfficeContact.tenant
role:hsOfficeContact.guest[contact.guest]
%% permissions
role:hsOfficeContact.guest --> perm:hsOfficeContact.view{{contact.view}}
%% incoming
role:hsOfficeContact.tenant ---> role:hsOfficeContact.guest
end
subgraph partner-person
subgraph person
style person fill: #e9f7ef
user:hsOfficePerson.creator([personcreator])
role:hsOfficePerson.owner[person.owner]
%% permissions
role:hsOfficePerson.owner --> perm:hsOfficePerson.*{{person.*}}
%% incoming
user:hsOfficePerson.creator ---> role:hsOfficePerson.owner
role:global.admin --> role:hsOfficePerson.owner
role:hsOfficePerson.admin[person.admin]
%% permissions
role:hsOfficePerson.admin --> perm:hsOfficePerson.edit{{person.edit}}
%% incoming
role:hsOfficePerson.owner ---> role:hsOfficePerson.admin
role:hsOfficePerson.tenant[person.tenant]
%% incoming
role:hsOfficePerson.admin -----> role:hsOfficePerson.tenant
role:hsOfficePerson.guest[person.guest]
%% permissions
role:hsOfficePerson.guest --> perm:hsOfficePerson.edit{{person.view}}
%% incoming
role:hsOfficePerson.tenant ---> role:hsOfficePerson.guest
end
subgraph partner
role:hsOfficePartner.owner[partner.owner]
%% permissions
role:hsOfficePartner.owner --> perm:hsOfficePartner.*{{partner.*}}
%% incoming
role:global.admin ---> role:hsOfficePartner.owner
role:hsOfficePartner.admin[partner.admin]
%% permissions
role:hsOfficePartner.admin --> perm:hsOfficePartner.edit{{partner.edit}}
%% incoming
role:hsOfficePartner.owner ---> role:hsOfficePartner.admin
%% outgoing
role:hsOfficePartner.admin --> role:hsOfficePerson.tenant
role:hsOfficePartner.admin --> role:hsOfficeContact.tenant
role:hsOfficePartner.agent[partner.agent]
%% incoming
role:hsOfficePartner.admin --> role:hsOfficePartner.agent
role:hsOfficePerson.admin --> role:hsOfficePartner.agent
role:hsOfficeContact.admin --> role:hsOfficePartner.agent
role:hsOfficePartner.tenant[partner.tenant]
%% incoming
role:hsOfficePartner.agent ---> role:hsOfficePartner.tenant
%% outgoing
role:hsOfficePartner.tenant --> role:hsOfficePerson.guest
role:hsOfficePartner.tenant --> role:hsOfficeContact.guest
role:hsOfficePartner.guest[partner.guest]
%% permissions
role:hsOfficePartner.guest --> perm:hsOfficePartner.view{{partner.view}}
%% incoming
role:hsOfficePartner.tenant ---> role:hsOfficePartner.guest
end
end
subgraph debitor
style debitor stroke-width:6px
user:hsOfficeDebitor.creator([debitor.creator])
%% created by role
user:hsOfficeDebitor.creator --> role:hsOfficePartner.agent
role:hsOfficeDebitor.owner[debitor.owner]
%% permissions
role:hsOfficeDebitor.owner --> perm:hsOfficeDebitor.*{{debitor.*}}
%% incoming
user:hsOfficeDebitor.creator --> role:hsOfficeDebitor.owner
role:global.admin --> role:hsOfficeDebitor.owner
role:hsOfficeDebitor.admin[debitor.admin]
%% permissions
role:hsOfficeDebitor.admin --> perm:hsOfficeDebitor.edit{{debitor.edit}}
%% incoming
role:hsOfficeDebitor.owner ---> role:hsOfficeDebitor.admin
role:hsOfficeDebitor.agent[debitor.agent]
%% incoming
role:hsOfficeDebitor.admin ---> role:hsOfficeDebitor.agent
role:hsOfficePartner.admin --> role:hsOfficeDebitor.agent
%% outgoing
role:hsOfficeDebitor.agent --> role:hsOfficeBankAccount.tenant
role:hsOfficeDebitor.tenant[debitor.tenant]
%% incoming
role:hsOfficeDebitor.agent ---> role:hsOfficeDebitor.tenant
role:hsOfficePartner.agent --> role:hsOfficeDebitor.tenant
role:hsOfficeBankAccount.admin --> role:hsOfficeDebitor.tenant
%% outgoing
role:hsOfficeDebitor.tenant --> role:hsOfficePartner.tenant
role:hsOfficeDebitor.tenant --> role:hsOfficeContact.guest
role:hsOfficeDebitor.guest[debitor.guest]
%% permissions
role:hsOfficeDebitor.guest --> perm:hsOfficeDebitor.view{{debitor.view}}
%% incoming
role:hsOfficeDebitor.tenant --> role:hsOfficeDebitor.guest
end
end
subgraph debitorRel.anchorPerson:roles[ ]
style debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white
subgraph hsOfficeSepaMandate
role:hsOfficeSepaMandate.owner[sepaMandate.owner]
%% permissions
role:hsOfficeSepaMandate.owner --> perm:hsOfficeSepaMandate.*{{sepaMandate.*}}
%% incoming
role:global.admin ---> role:hsOfficeSepaMandate.owner
role:hsOfficeSepaMandate.admin[sepaMandate.admin]
%% permissions
role:hsOfficeSepaMandate.admin --> perm:hsOfficeSepaMandate.edit{{sepaMandate.edit}}
%% incoming
role:hsOfficeSepaMandate.owner ---> role:hsOfficeSepaMandate.admin
role:hsOfficeSepaMandate.agent[sepaMandate.agent]
%% incoming
role:hsOfficeSepaMandate.admin ---> role:hsOfficeSepaMandate.agent
role:hsOfficeDebitor.admin --> role:hsOfficeSepaMandate.agent
role:hsOfficeBankAccount.admin --> role:hsOfficeSepaMandate.agent
%% outgoing
role:hsOfficeSepaMandate.agent --> role:hsOfficeDebitor.tenant
role:hsOfficeSepaMandate.admin --> role:hsOfficeBankAccount.tenant
role:hsOfficeSepaMandate.tenant[sepaMandate.tenant]
%% incoming
role:hsOfficeSepaMandate.agent --> role:hsOfficeSepaMandate.tenant
%% outgoing
role:hsOfficeSepaMandate.tenant --> role:hsOfficeDebitor.guest
role:hsOfficeSepaMandate.tenant --> role:hsOfficeBankAccount.guest
role:hsOfficeSepaMandate.guest[sepaMandate.guest]
%% permissions
role:hsOfficeSepaMandate.guest --> perm:hsOfficeSepaMandate.view{{sepaMandate.view}}
%% incoming
role:hsOfficeSepaMandate.tenant --> role:hsOfficeSepaMandate.guest
end
subgraph hosting
style hosting fill:#eee
subgraph package
style package fill: #e9f7ef
role:package.owner[package.owner]
--> role:package.admin[package.admin]
--> role:package.tenant[package.tenant]
role:hsOfficeDebitor.agent --> role:package.owner
role:package.admin --> role:hsOfficeDebitor.tenant
role:hsOfficePartner.tenant --> role:hsOfficeDebitor.guest
role:debitorRel.anchorPerson:owner[[debitorRel.anchorPerson:owner]]
role:debitorRel.anchorPerson:admin[[debitorRel.anchorPerson:admin]]
role:debitorRel.anchorPerson:referrer[[debitorRel.anchorPerson:referrer]]
end
end
subgraph debitorRel.holderPerson["`**debitorRel.holderPerson**`"]
direction TB
style debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.holderPerson:roles[ ]
style debitorRel.holderPerson:roles fill:#99bcdb,stroke:white
role:debitorRel.holderPerson:owner[[debitorRel.holderPerson:owner]]
role:debitorRel.holderPerson:admin[[debitorRel.holderPerson:admin]]
role:debitorRel.holderPerson:referrer[[debitorRel.holderPerson:referrer]]
end
end
subgraph partnerRel.holderPerson["`**partnerRel.holderPerson**`"]
direction TB
style partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.holderPerson:roles[ ]
style partnerRel.holderPerson:roles fill:#99bcdb,stroke:white
role:partnerRel.holderPerson:owner[[partnerRel.holderPerson:owner]]
role:partnerRel.holderPerson:admin[[partnerRel.holderPerson:admin]]
role:partnerRel.holderPerson:referrer[[partnerRel.holderPerson:referrer]]
end
end
subgraph debitor["`**debitor**`"]
direction TB
style debitor fill:#dd4901,stroke:#274d6e,stroke-width:8px
subgraph debitor:permissions[ ]
style debitor:permissions fill:#dd4901,stroke:white
perm:debitor:INSERT{{debitor:INSERT}}
perm:debitor:DELETE{{debitor:DELETE}}
perm:debitor:UPDATE{{debitor:UPDATE}}
perm:debitor:SELECT{{debitor:SELECT}}
end
subgraph debitorRel["`**debitorRel**`"]
direction TB
style debitorRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.anchorPerson["`**debitorRel.anchorPerson**`"]
direction TB
style debitorRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.anchorPerson:roles[ ]
style debitorRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:debitorRel.anchorPerson:owner[[debitorRel.anchorPerson:owner]]
role:debitorRel.anchorPerson:admin[[debitorRel.anchorPerson:admin]]
role:debitorRel.anchorPerson:referrer[[debitorRel.anchorPerson:referrer]]
end
end
subgraph debitorRel.holderPerson["`**debitorRel.holderPerson**`"]
direction TB
style debitorRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.holderPerson:roles[ ]
style debitorRel.holderPerson:roles fill:#99bcdb,stroke:white
role:debitorRel.holderPerson:owner[[debitorRel.holderPerson:owner]]
role:debitorRel.holderPerson:admin[[debitorRel.holderPerson:admin]]
role:debitorRel.holderPerson:referrer[[debitorRel.holderPerson:referrer]]
end
end
subgraph debitorRel.contact["`**debitorRel.contact**`"]
direction TB
style debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.contact:roles[ ]
style debitorRel.contact:roles fill:#99bcdb,stroke:white
role:debitorRel.contact:owner[[debitorRel.contact:owner]]
role:debitorRel.contact:admin[[debitorRel.contact:admin]]
role:debitorRel.contact:referrer[[debitorRel.contact:referrer]]
end
end
subgraph debitorRel:roles[ ]
style debitorRel:roles fill:#99bcdb,stroke:white
role:debitorRel:owner[[debitorRel:owner]]
role:debitorRel:admin[[debitorRel:admin]]
role:debitorRel:agent[[debitorRel:agent]]
role:debitorRel:tenant[[debitorRel:tenant]]
end
end
end
subgraph partnerRel["`**partnerRel**`"]
direction TB
style partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.holderPerson["`**partnerRel.holderPerson**`"]
direction TB
style partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.holderPerson:roles[ ]
style partnerRel.holderPerson:roles fill:#99bcdb,stroke:white
role:partnerRel.holderPerson:owner[[partnerRel.holderPerson:owner]]
role:partnerRel.holderPerson:admin[[partnerRel.holderPerson:admin]]
role:partnerRel.holderPerson:referrer[[partnerRel.holderPerson:referrer]]
end
end
subgraph partnerRel.contact["`**partnerRel.contact**`"]
direction TB
style partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.contact:roles[ ]
style partnerRel.contact:roles fill:#99bcdb,stroke:white
role:partnerRel.contact:owner[[partnerRel.contact:owner]]
role:partnerRel.contact:admin[[partnerRel.contact:admin]]
role:partnerRel.contact:referrer[[partnerRel.contact:referrer]]
end
end
subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"]
direction TB
style partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.anchorPerson:roles[ ]
style partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:partnerRel.anchorPerson:owner[[partnerRel.anchorPerson:owner]]
role:partnerRel.anchorPerson:admin[[partnerRel.anchorPerson:admin]]
role:partnerRel.anchorPerson:referrer[[partnerRel.anchorPerson:referrer]]
end
end
subgraph partnerRel:roles[ ]
style partnerRel:roles fill:#99bcdb,stroke:white
role:partnerRel:owner[[partnerRel:owner]]
role:partnerRel:admin[[partnerRel:admin]]
role:partnerRel:agent[[partnerRel:agent]]
role:partnerRel:tenant[[partnerRel:tenant]]
end
end
subgraph partnerRel.contact["`**partnerRel.contact**`"]
direction TB
style partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.contact:roles[ ]
style partnerRel.contact:roles fill:#99bcdb,stroke:white
role:partnerRel.contact:owner[[partnerRel.contact:owner]]
role:partnerRel.contact:admin[[partnerRel.contact:admin]]
role:partnerRel.contact:referrer[[partnerRel.contact:referrer]]
end
end
subgraph debitorRel.contact["`**debitorRel.contact**`"]
direction TB
style debitorRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph debitorRel.contact:roles[ ]
style debitorRel.contact:roles fill:#99bcdb,stroke:white
role:debitorRel.contact:owner[[debitorRel.contact:owner]]
role:debitorRel.contact:admin[[debitorRel.contact:admin]]
role:debitorRel.contact:referrer[[debitorRel.contact:referrer]]
end
end
subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"]
direction TB
style partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.anchorPerson:roles[ ]
style partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:partnerRel.anchorPerson:owner[[partnerRel.anchorPerson:owner]]
role:partnerRel.anchorPerson:admin[[partnerRel.anchorPerson:admin]]
role:partnerRel.anchorPerson:referrer[[partnerRel.anchorPerson:referrer]]
end
end
subgraph refundBankAccount["`**refundBankAccount**`"]
direction TB
style refundBankAccount fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph refundBankAccount:roles[ ]
style refundBankAccount:roles fill:#99bcdb,stroke:white
role:refundBankAccount:owner[[refundBankAccount:owner]]
role:refundBankAccount:admin[[refundBankAccount:admin]]
role:refundBankAccount:referrer[[refundBankAccount:referrer]]
end
end
%% granting roles to roles
role:global:admin -.-> role:debitorRel.anchorPerson:owner
role:debitorRel.anchorPerson:owner -.-> role:debitorRel.anchorPerson:admin
role:debitorRel.anchorPerson:admin -.-> role:debitorRel.anchorPerson:referrer
role:global:admin -.-> role:debitorRel.holderPerson:owner
role:debitorRel.holderPerson:owner -.-> role:debitorRel.holderPerson:admin
role:debitorRel.holderPerson:admin -.-> role:debitorRel.holderPerson:referrer
role:global:admin -.-> role:debitorRel.contact:owner
role:debitorRel.contact:owner -.-> role:debitorRel.contact:admin
role:debitorRel.contact:admin -.-> role:debitorRel.contact:referrer
role:global:admin -.-> role:debitorRel:owner
role:debitorRel:owner -.-> role:debitorRel:admin
role:debitorRel.anchorPerson:admin -.-> role:debitorRel:admin
role:debitorRel:admin -.-> role:debitorRel:agent
role:debitorRel.holderPerson:admin -.-> role:debitorRel:agent
role:debitorRel:agent -.-> role:debitorRel:tenant
role:debitorRel.holderPerson:admin -.-> role:debitorRel:tenant
role:debitorRel.contact:admin -.-> role:debitorRel:tenant
role:debitorRel:tenant -.-> role:debitorRel.anchorPerson:referrer
role:debitorRel:tenant -.-> role:debitorRel.holderPerson:referrer
role:debitorRel:tenant -.-> role:debitorRel.contact:referrer
role:global:admin -.-> role:refundBankAccount:owner
role:refundBankAccount:owner -.-> role:refundBankAccount:admin
role:refundBankAccount:admin -.-> role:refundBankAccount:referrer
role:refundBankAccount:admin ==> role:debitorRel:agent
role:debitorRel:agent ==> role:refundBankAccount:referrer
role:global:admin -.-> role:partnerRel.anchorPerson:owner
role:partnerRel.anchorPerson:owner -.-> role:partnerRel.anchorPerson:admin
role:partnerRel.anchorPerson:admin -.-> role:partnerRel.anchorPerson:referrer
role:global:admin -.-> role:partnerRel.holderPerson:owner
role:partnerRel.holderPerson:owner -.-> role:partnerRel.holderPerson:admin
role:partnerRel.holderPerson:admin -.-> role:partnerRel.holderPerson:referrer
role:global:admin -.-> role:partnerRel.contact:owner
role:partnerRel.contact:owner -.-> role:partnerRel.contact:admin
role:partnerRel.contact:admin -.-> role:partnerRel.contact:referrer
role:global:admin -.-> role:partnerRel:owner
role:partnerRel:owner -.-> role:partnerRel:admin
role:partnerRel.anchorPerson:admin -.-> role:partnerRel:admin
role:partnerRel:admin -.-> role:partnerRel:agent
role:partnerRel.holderPerson:admin -.-> role:partnerRel:agent
role:partnerRel:agent -.-> role:partnerRel:tenant
role:partnerRel.holderPerson:admin -.-> role:partnerRel:tenant
role:partnerRel.contact:admin -.-> role:partnerRel:tenant
role:partnerRel:tenant -.-> role:partnerRel.anchorPerson:referrer
role:partnerRel:tenant -.-> role:partnerRel.holderPerson:referrer
role:partnerRel:tenant -.-> role:partnerRel.contact:referrer
role:partnerRel:admin ==> role:debitorRel:admin
role:partnerRel:agent ==> role:debitorRel:agent
role:debitorRel:agent ==> role:partnerRel:tenant
%% granting permissions to roles
role:global:admin ==> perm:debitor:INSERT
role:debitorRel:owner ==> perm:debitor:DELETE
role:debitorRel:admin ==> perm:debitor:UPDATE
role:debitorRel:tenant ==> perm:debitor:SELECT
```

View File

@@ -1,4 +1,6 @@
--liquibase formatted sql
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
-- ============================================================================
--changeset hs-office-debitor-rbac-OBJECT:1 endDelimiter:--//
@@ -15,233 +17,211 @@ call generateRbacRoleDescriptors('hsOfficeDebitor', 'hs_office_debitor');
-- ============================================================================
--changeset hs-office-debitor-rbac-ROLES-CREATION:1 endDelimiter:--//
--changeset hs-office-debitor-rbac-insert-trigger:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates and updates the roles and their assignments for debitor entities.
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
*/
create or replace function hsOfficeDebitorRbacRolesTrigger()
returns trigger
language plpgsql
strict as $$
create or replace procedure buildRbacSystemForHsOfficeDebitor(
NEW hs_office_debitor
)
language plpgsql as $$
declare
hsOfficeDebitorTenant RbacRoleDescriptor;
oldPartner hs_office_partner;
newPartner hs_office_partner;
newPerson hs_office_person;
oldContact hs_office_contact;
newContact hs_office_contact;
newBankAccount hs_office_bankaccount;
oldBankAccount hs_office_bankaccount;
newPartnerRel hs_office_relation;
newDebitorRel hs_office_relation;
newRefundBankAccount hs_office_bankaccount;
begin
call enterTriggerForObjectUuid(NEW.uuid);
hsOfficeDebitorTenant := hsOfficeDebitorTenant(NEW);
SELECT partnerRel.*
FROM hs_office_relation AS partnerRel
JOIN hs_office_relation AS debitorRel
ON debitorRel.type = 'DEBITOR' AND debitorRel.anchorUuid = partnerRel.holderUuid
WHERE partnerRel.type = 'PARTNER'
AND NEW.debitorRelUuid = debitorRel.uuid
INTO newPartnerRel;
assert newPartnerRel.uuid is not null, format('newPartnerRel must not be null for NEW.debitorRelUuid = %s', NEW.debitorRelUuid);
select * from hs_office_partner as p where p.uuid = NEW.partnerUuid into newPartner;
select * from hs_office_person as p where p.uuid = newPartner.personUuid into newPerson;
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
SELECT * FROM hs_office_relation WHERE uuid = NEW.debitorRelUuid INTO newDebitorRel;
assert newDebitorRel.uuid is not null, format('newDebitorRel must not be null for NEW.debitorRelUuid = %s', NEW.debitorRelUuid);
SELECT * FROM hs_office_bankaccount WHERE uuid = NEW.refundBankAccountUuid INTO newRefundBankAccount;
perform createRoleWithGrants(
hsOfficeDebitorOwner(NEW),
permissions => array['DELETE'],
incomingSuperRoles => array[globalAdmin()],
userUuids => array[currentUserUuid()],
grantedByRole => globalAdmin()
);
call grantRoleToRole(hsOfficeBankAccountReferrer(newRefundBankAccount), hsOfficeRelationAgent(newDebitorRel));
call grantRoleToRole(hsOfficeRelationAdmin(newDebitorRel), hsOfficeRelationAdmin(newPartnerRel));
call grantRoleToRole(hsOfficeRelationAgent(newDebitorRel), hsOfficeBankAccountAdmin(newRefundBankAccount));
call grantRoleToRole(hsOfficeRelationAgent(newDebitorRel), hsOfficeRelationAgent(newPartnerRel));
call grantRoleToRole(hsOfficeRelationTenant(newPartnerRel), hsOfficeRelationAgent(newDebitorRel));
perform createRoleWithGrants(
hsOfficeDebitorAdmin(NEW),
permissions => array['UPDATE'],
incomingSuperRoles => array[hsOfficeDebitorOwner(NEW)]
);
perform createRoleWithGrants(
hsOfficeDebitorAgent(NEW),
incomingSuperRoles => array[
hsOfficeDebitorAdmin(NEW),
hsOfficePartnerAdmin(newPartner),
hsOfficeContactAdmin(newContact)],
outgoingSubRoles => array[
hsOfficeBankAccountTenant(newBankaccount)]
);
perform createRoleWithGrants(
hsOfficeDebitorTenant(NEW),
incomingSuperRoles => array[
hsOfficeDebitorAgent(NEW),
hsOfficePartnerAgent(newPartner),
hsOfficeBankAccountAdmin(newBankaccount)],
outgoingSubRoles => array[
hsOfficePartnerTenant(newPartner),
hsOfficeContactGuest(newContact),
hsOfficeBankAccountGuest(newBankaccount)]
);
perform createRoleWithGrants(
hsOfficeDebitorGuest(NEW),
permissions => array['SELECT'],
incomingSuperRoles => array[
hsOfficeDebitorTenant(NEW)]
);
elsif TG_OP = 'UPDATE' then
if OLD.partnerUuid <> NEW.partnerUuid then
select * from hs_office_partner as p where p.uuid = OLD.partnerUuid into oldPartner;
call revokeRoleFromRole(hsOfficeDebitorAgent(OLD), hsOfficePartnerAdmin(oldPartner));
call grantRoleToRole(hsOfficeDebitorAgent(NEW), hsOfficePartnerAdmin(newPartner));
call revokeRoleFromRole(hsOfficeDebitorTenant(OLD), hsOfficePartnerAgent(oldPartner));
call grantRoleToRole(hsOfficeDebitorTenant(NEW), hsOfficePartnerAgent(newPartner));
call revokeRoleFromRole(hsOfficePartnerTenant(oldPartner), hsOfficeDebitorTenant(OLD));
call grantRoleToRole(hsOfficePartnerTenant(newPartner), hsOfficeDebitorTenant(NEW));
end if;
if OLD.billingContactUuid <> NEW.billingContactUuid then
select * from hs_office_contact as c where c.uuid = OLD.billingContactUuid into oldContact;
call revokeRoleFromRole(hsOfficeDebitorAgent(OLD), hsOfficeContactAdmin(oldContact));
call grantRoleToRole(hsOfficeDebitorAgent(NEW), hsOfficeContactAdmin(newContact));
call revokeRoleFromRole(hsOfficeContactGuest(oldContact), hsOfficeDebitorTenant(OLD));
call grantRoleToRole(hsOfficeContactGuest(newContact), hsOfficeDebitorTenant(NEW));
end if;
if (OLD.refundBankAccountUuid is not null or NEW.refundBankAccountUuid is not null) and
( OLD.refundBankAccountUuid is null or NEW.refundBankAccountUuid is null or
OLD.refundBankAccountUuid <> NEW.refundBankAccountUuid ) then
select * from hs_office_bankaccount as b where b.uuid = OLD.refundBankAccountUuid into oldBankAccount;
if oldBankAccount is not null then
call revokeRoleFromRole(hsOfficeBankAccountTenant(oldBankaccount), hsOfficeDebitorAgent(OLD));
end if;
if newBankAccount is not null then
call grantRoleToRole(hsOfficeBankAccountTenant(newBankaccount), hsOfficeDebitorAgent(NEW));
end if;
if oldBankAccount is not null then
call revokeRoleFromRole(hsOfficeDebitorTenant(OLD), hsOfficeBankAccountAdmin(oldBankaccount));
end if;
if newBankAccount is not null then
call grantRoleToRole(hsOfficeDebitorTenant(NEW), hsOfficeBankAccountAdmin(newBankaccount));
end if;
if oldBankAccount is not null then
call revokeRoleFromRole(hsOfficeBankAccountGuest(oldBankaccount), hsOfficeDebitorTenant(OLD));
end if;
if newBankAccount is not null then
call grantRoleToRole(hsOfficeBankAccountGuest(newBankaccount), hsOfficeDebitorTenant(NEW));
end if;
end if;
else
raise exception 'invalid usage of TRIGGER';
end if;
call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationOwner(newDebitorRel));
call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationTenant(newDebitorRel));
call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationAdmin(newDebitorRel));
call leaveTriggerForObjectUuid(NEW.uuid);
return NEW;
end; $$;
/*
An AFTER INSERT TRIGGER which creates the role structure for a new debitor.
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_debitor row.
*/
create trigger createRbacRolesForHsOfficeDebitor_Trigger
after insert
on hs_office_debitor
for each row
execute procedure hsOfficeDebitorRbacRolesTrigger();
/*
An AFTER UPDATE TRIGGER which updates the role structure of a debitor.
*/
create trigger updateRbacRolesForHsOfficeDebitor_Trigger
after update
on hs_office_debitor
create or replace function insertTriggerForHsOfficeDebitor_tf()
returns trigger
language plpgsql
strict as $$
begin
call buildRbacSystemForHsOfficeDebitor(NEW);
return NEW;
end; $$;
create trigger insertTriggerForHsOfficeDebitor_tg
after insert on hs_office_debitor
for each row
execute procedure hsOfficeDebitorRbacRolesTrigger();
execute procedure insertTriggerForHsOfficeDebitor_tf();
--//
-- ============================================================================
--changeset hs-office-debitor-rbac-update-trigger:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Called from the AFTER UPDATE TRIGGER to re-wire the grants.
*/
create or replace procedure updateRbacRulesForHsOfficeDebitor(
OLD hs_office_debitor,
NEW hs_office_debitor
)
language plpgsql as $$
begin
if NEW.debitorRelUuid is distinct from OLD.debitorRelUuid
or NEW.refundBankAccountUuid is distinct from OLD.refundBankAccountUuid then
delete from rbacgrants g where g.grantedbytriggerof = OLD.uuid;
call buildRbacSystemForHsOfficeDebitor(NEW);
end if;
end; $$;
/*
AFTER INSERT TRIGGER to re-wire the grant structure for a new hs_office_debitor row.
*/
create or replace function updateTriggerForHsOfficeDebitor_tf()
returns trigger
language plpgsql
strict as $$
begin
call updateRbacRulesForHsOfficeDebitor(OLD, NEW);
return NEW;
end; $$;
create trigger updateTriggerForHsOfficeDebitor_tg
after update on hs_office_debitor
for each row
execute procedure updateTriggerForHsOfficeDebitor_tf();
--//
-- ============================================================================
--changeset hs-office-debitor-rbac-INSERT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates INSERT INTO hs_office_debitor permissions for the related global rows.
*/
do language plpgsql $$
declare
row global;
begin
call defineContext('create INSERT INTO hs_office_debitor permissions for the related global rows');
FOR row IN SELECT * FROM global
LOOP
call grantPermissionToRole(
createPermission(row.uuid, 'INSERT', 'hs_office_debitor'),
globalAdmin());
END LOOP;
END;
$$;
/**
Adds hs_office_debitor INSERT permission to specified role of new global rows.
*/
create or replace function hs_office_debitor_global_insert_tf()
returns trigger
language plpgsql
strict as $$
begin
call grantPermissionToRole(
createPermission(NEW.uuid, 'INSERT', 'hs_office_debitor'),
globalAdmin());
return NEW;
end; $$;
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
create trigger z_hs_office_debitor_global_insert_tg
after insert on global
for each row
execute procedure hs_office_debitor_global_insert_tf();
/**
Checks if the user or assumed roles are allowed to insert a row to hs_office_debitor,
where only global-admin has that permission.
*/
create or replace function hs_office_debitor_insert_permission_missing_tf()
returns trigger
language plpgsql as $$
begin
raise exception '[403] insert into hs_office_debitor not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids();
end; $$;
create trigger hs_office_debitor_insert_permission_check_tg
before insert on hs_office_debitor
for each row
when ( not isGlobalAdmin() )
execute procedure hs_office_debitor_insert_permission_missing_tf();
--//
-- ============================================================================
--changeset hs-office-debitor-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('hs_office_debitor', $idName$
'#' ||
(select partnerNumber from hs_office_partner p where p.uuid = target.partnerUuid) ||
to_char(debitorNumberSuffix, 'fm00') ||
':' || (select split_part(idName, ':', 2) from hs_office_partner_iv pi where pi.uuid = target.partnerUuid)
$idName$);
--//
call generateRbacIdentityViewFromQuery('hs_office_debitor',
$idName$
SELECT debitor.uuid AS uuid,
'D-' || (SELECT partner.partnerNumber
FROM hs_office_partner partner
JOIN hs_office_relation partnerRel
ON partnerRel.uuid = partner.partnerRelUUid AND partnerRel.type = 'PARTNER'
JOIN hs_office_relation debitorRel
ON debitorRel.anchorUuid = partnerRel.holderUuid AND debitorRel.type = 'DEBITOR'
WHERE debitorRel.uuid = debitor.debitorRelUuid)
|| to_char(debitorNumberSuffix, 'fm00') as idName
FROM hs_office_debitor AS debitor
$idName$);
--//
-- ============================================================================
--changeset hs-office-debitor-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRestrictedView('hs_office_debitor', 'target.debitorNumberSuffix',
call generateRbacRestrictedView('hs_office_debitor',
$orderBy$
defaultPrefix
$orderBy$,
$updates$
partnerUuid = new.partnerUuid, -- TODO: remove? should never do anything
debitorRelUuid = new.debitorRelUuid,
billable = new.billable,
billingContactUuid = new.billingContactUuid,
debitorNumberSuffix = new.debitorNumberSuffix, -- TODO: Should it be allowed to updated this value?
refundBankAccountUuid = new.refundBankAccountUuid,
vatId = new.vatId,
vatCountryCode = new.vatCountryCode,
vatBusiness = new.vatBusiness,
vatreversecharge = new.vatreversecharge,
defaultPrefix = new.defaultPrefix -- TODO: Should it be allowed to updated this value?
vatReverseCharge = new.vatReverseCharge,
defaultPrefix = new.defaultPrefix
$updates$);
--//
-- ============================================================================
--changeset hs-office-debitor-rbac-NEW-DEBITOR:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates a global permission for new-debitor and assigns it to the hostsharing admins role.
*/
do language plpgsql $$
declare
addDebitorPermissions uuid[];
globalObjectUuid uuid;
globalAdminRoleUuid uuid ;
begin
call defineContext('granting global new-debitor permission to global admin role', null, null, null);
globalAdminRoleUuid := findRoleId(globalAdmin());
globalObjectUuid := (select uuid from global);
addDebitorPermissions := createPermissions(globalObjectUuid, array ['new-debitor']);
call grantPermissionsToRole(globalAdminRoleUuid, addDebitorPermissions);
end;
$$;
/**
Used by the trigger to prevent the add-debitor to current user respectively assumed roles.
*/
create or replace function addHsOfficeDebitorNotAllowedForCurrentSubjects()
returns trigger
language PLPGSQL
as $$
begin
raise exception '[403] new-debitor not permitted for %',
array_to_string(currentSubjects(), ';', 'null');
end; $$;
/**
Checks if the user or assumed roles are allowed to create a new debitor.
*/
create trigger hs_office_debitor_insert_trigger
before insert
on hs_office_debitor
for each row
-- TODO.spec: who is allowed to create new debitors
when ( not hasAssumedRole() )
execute procedure addHsOfficeDebitorNotAllowedForCurrentSubjects();
--//

View File

@@ -9,36 +9,41 @@
Creates a single debitor test record.
*/
create or replace procedure createHsOfficeDebitorTestData(
debitorNumberSuffix numeric(5),
partnerTradeName varchar,
billingContactLabel varchar,
defaultPrefix varchar
withDebitorNumberSuffix numeric(5),
forPartnerPersonName varchar,
forBillingContactLabel varchar,
withDefaultPrefix varchar
)
language plpgsql as $$
declare
currentTask varchar;
idName varchar;
relatedPartner hs_office_partner;
relatedContact hs_office_contact;
relatedDebitorRelUuid uuid;
relatedBankAccountUuid uuid;
begin
idName := cleanIdentifier( partnerTradeName|| '-' || billingContactLabel);
idName := cleanIdentifier( forPartnerPersonName|| '-' || forBillingContactLabel);
currentTask := 'creating debitor test-data ' || idName;
call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global.admin');
execute format('set local hsadminng.currentTask to %L', currentTask);
select partner.* from hs_office_partner partner
join hs_office_person person on person.uuid = partner.personUuid
where person.tradeName = partnerTradeName into relatedPartner;
select c.* from hs_office_contact c where c.label = billingContactLabel into relatedContact;
select b.uuid from hs_office_bankaccount b where b.holder = partnerTradeName into relatedBankAccountUuid;
select debitorRel.uuid
into relatedDebitorRelUuid
from hs_office_relation debitorRel
join hs_office_person person on person.uuid = debitorRel.holderUuid
and (person.tradeName = forPartnerPersonName or person.familyName = forPartnerPersonName)
where debitorRel.type = 'DEBITOR';
raise notice 'creating test debitor: % (#%)', idName, debitorNumberSuffix;
raise notice '- using partner (%): %', relatedPartner.uuid, relatedPartner;
raise notice '- using billingContact (%): %', relatedContact.uuid, relatedContact;
select b.uuid
into relatedBankAccountUuid
from hs_office_bankaccount b
where b.holder = forPartnerPersonName;
raise notice 'creating test debitor: % (#%)', idName, withDebitorNumberSuffix;
-- raise exception 'creating test debitor: (uuid=%, debitorRelUuid=%, debitornumbersuffix=%, billable=%, vatbusiness=%, vatreversecharge=%, refundbankaccountuuid=%, defaultprefix=%)',
-- uuid_generate_v4(), relatedDebitorRelUuid, withDebitorNumberSuffix, true, true, false, relatedBankAccountUuid, withDefaultPrefix;
insert
into hs_office_debitor (uuid, partneruuid, debitornumbersuffix, billable, billingcontactuuid, vatbusiness, vatreversecharge, refundbankaccountuuid, defaultprefix)
values (uuid_generate_v4(), relatedPartner.uuid, debitorNumberSuffix, true, relatedContact.uuid, true, false, relatedBankAccountUuid, defaultPrefix);
into hs_office_debitor (uuid, debitorRelUuid, debitornumbersuffix, billable, vatbusiness, vatreversecharge, refundbankaccountuuid, defaultprefix)
values (uuid_generate_v4(), relatedDebitorRelUuid, withDebitorNumberSuffix, true, true, false, relatedBankAccountUuid, withDefaultPrefix);
end; $$;
--//

View File

@@ -12,7 +12,6 @@ create table if not exists hs_office_membership
(
uuid uuid unique references RbacObject (uuid) initially deferred,
partnerUuid uuid not null references hs_office_partner(uuid),
mainDebitorUuid uuid not null references hs_office_debitor(uuid),
memberNumberSuffix char(2) not null check (
memberNumberSuffix::text ~ '^[0-9][0-9]$'),
validity daterange not null,

View File

@@ -1,75 +1,159 @@
### hs_office_membership RBAC
### rbac membership
This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
```mermaid
%%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB
subgraph global
style global fill:#eee
role:global.admin[global.admin]
end
subgraph hsOfficeDebitor
subgraph partnerRel["`**partnerRel**`"]
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]
style partnerRel fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.contact["`**partnerRel.contact**`"]
direction TB
style partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.contact:roles[ ]
style partnerRel.contact:roles fill:#99bcdb,stroke:white
role:partnerRel.contact:owner[[partnerRel.contact:owner]]
role:partnerRel.contact:admin[[partnerRel.contact:admin]]
role:partnerRel.contact:referrer[[partnerRel.contact:referrer]]
end
end
subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"]
direction TB
style partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.anchorPerson:roles[ ]
style partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:partnerRel.anchorPerson:owner[[partnerRel.anchorPerson:owner]]
role:partnerRel.anchorPerson:admin[[partnerRel.anchorPerson:admin]]
role:partnerRel.anchorPerson:referrer[[partnerRel.anchorPerson:referrer]]
end
end
subgraph partnerRel.holderPerson["`**partnerRel.holderPerson**`"]
direction TB
style partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.holderPerson:roles[ ]
style partnerRel.holderPerson:roles fill:#99bcdb,stroke:white
role:partnerRel.holderPerson:owner[[partnerRel.holderPerson:owner]]
role:partnerRel.holderPerson:admin[[partnerRel.holderPerson:admin]]
role:partnerRel.holderPerson:referrer[[partnerRel.holderPerson:referrer]]
end
end
subgraph partnerRel:roles[ ]
style partnerRel:roles fill:#99bcdb,stroke:white
role:partnerRel:owner[[partnerRel:owner]]
role:partnerRel:admin[[partnerRel:admin]]
role:partnerRel:agent[[partnerRel:agent]]
role:partnerRel:tenant[[partnerRel:tenant]]
end
end
subgraph hsOfficePartner
subgraph partnerRel.contact["`**partnerRel.contact**`"]
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]
style partnerRel.contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.contact:roles[ ]
style partnerRel.contact:roles fill:#99bcdb,stroke:white
role:partnerRel.contact:owner[[partnerRel.contact:owner]]
role:partnerRel.contact:admin[[partnerRel.contact:admin]]
role:partnerRel.contact:referrer[[partnerRel.contact:referrer]]
end
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.agent --> role:hsOfficeDebitor.tenant
role:hsOfficeMembership.tenant[membership.tenant]
%% incoming
role:hsOfficeMembership.agent --> role:hsOfficeMembership.tenant
role:hsOfficePartner.agent --> role:hsOfficeMembership.tenant
role:hsOfficeDebitor.agent --> role:hsOfficeMembership.tenant
%% outgoing
role:hsOfficeMembership.tenant --> role:hsOfficePartner.guest
role:hsOfficeMembership.tenant --> role:hsOfficeDebitor.guest
subgraph membership["`**membership**`"]
direction TB
style membership fill:#dd4901,stroke:#274d6e,stroke-width:8px
role:hsOfficeMembership.guest[membership.guest]
%% permissions
role:hsOfficeMembership.guest --> perm:hsOfficeMembership.view{{membership.view}}
%% incoming
role:hsOfficeMembership.tenant --> role:hsOfficeMembership.guest
role:hsOfficePartner.tenant --> role:hsOfficeMembership.guest
role:hsOfficeDebitor.tenant --> role:hsOfficeMembership.guest
subgraph membership:roles[ ]
style membership:roles fill:#dd4901,stroke:white
role:membership:owner[[membership:owner]]
role:membership:admin[[membership:admin]]
role:membership:referrer[[membership:referrer]]
end
subgraph membership:permissions[ ]
style membership:permissions fill:#dd4901,stroke:white
perm:membership:INSERT{{membership:INSERT}}
perm:membership:DELETE{{membership:DELETE}}
perm:membership:UPDATE{{membership:UPDATE}}
perm:membership:SELECT{{membership:SELECT}}
end
end
subgraph partnerRel.anchorPerson["`**partnerRel.anchorPerson**`"]
direction TB
style partnerRel.anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.anchorPerson:roles[ ]
style partnerRel.anchorPerson:roles fill:#99bcdb,stroke:white
role:partnerRel.anchorPerson:owner[[partnerRel.anchorPerson:owner]]
role:partnerRel.anchorPerson:admin[[partnerRel.anchorPerson:admin]]
role:partnerRel.anchorPerson:referrer[[partnerRel.anchorPerson:referrer]]
end
end
subgraph partnerRel.holderPerson["`**partnerRel.holderPerson**`"]
direction TB
style partnerRel.holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph partnerRel.holderPerson:roles[ ]
style partnerRel.holderPerson:roles fill:#99bcdb,stroke:white
role:partnerRel.holderPerson:owner[[partnerRel.holderPerson:owner]]
role:partnerRel.holderPerson:admin[[partnerRel.holderPerson:admin]]
role:partnerRel.holderPerson:referrer[[partnerRel.holderPerson:referrer]]
end
end
%% granting roles to users
user:creator ==> role:membership:owner
%% granting roles to roles
role:global:admin -.-> role:partnerRel.anchorPerson:owner
role:partnerRel.anchorPerson:owner -.-> role:partnerRel.anchorPerson:admin
role:partnerRel.anchorPerson:admin -.-> role:partnerRel.anchorPerson:referrer
role:global:admin -.-> role:partnerRel.holderPerson:owner
role:partnerRel.holderPerson:owner -.-> role:partnerRel.holderPerson:admin
role:partnerRel.holderPerson:admin -.-> role:partnerRel.holderPerson:referrer
role:global:admin -.-> role:partnerRel.contact:owner
role:partnerRel.contact:owner -.-> role:partnerRel.contact:admin
role:partnerRel.contact:admin -.-> role:partnerRel.contact:referrer
role:global:admin -.-> role:partnerRel:owner
role:partnerRel:owner -.-> role:partnerRel:admin
role:partnerRel.anchorPerson:admin -.-> role:partnerRel:admin
role:partnerRel:admin -.-> role:partnerRel:agent
role:partnerRel.holderPerson:admin -.-> role:partnerRel:agent
role:partnerRel:agent -.-> role:partnerRel:tenant
role:partnerRel.holderPerson:admin -.-> role:partnerRel:tenant
role:partnerRel.contact:admin -.-> role:partnerRel:tenant
role:partnerRel:tenant -.-> role:partnerRel.anchorPerson:referrer
role:partnerRel:tenant -.-> role:partnerRel.holderPerson:referrer
role:partnerRel:tenant -.-> role:partnerRel.contact:referrer
role:partnerRel:admin ==> role:membership:owner
role:membership:owner ==> role:membership:admin
role:partnerRel:agent ==> role:membership:admin
role:membership:admin ==> role:membership:referrer
role:membership:referrer ==> role:partnerRel:tenant
%% granting permissions to roles
role:global:admin ==> perm:membership:INSERT
role:membership:owner ==> perm:membership:DELETE
role:membership:admin ==> perm:membership:UPDATE
role:membership:referrer ==> perm:membership:SELECT
```

View File

@@ -1,4 +1,6 @@
--liquibase formatted sql
-- This code generated was by RbacViewPostgresGenerator, do not amend manually.
-- ============================================================================
--changeset hs-office-membership-rbac-OBJECT:1 endDelimiter:--//
@@ -15,148 +17,162 @@ call generateRbacRoleDescriptors('hsOfficeMembership', 'hs_office_membership');
-- ============================================================================
--changeset hs-office-membership-rbac-ROLES-CREATION:1 endDelimiter:--//
--changeset hs-office-membership-rbac-insert-trigger:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates and updates the roles and their assignments for membership entities.
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
*/
create or replace function hsOfficeMembershipRbacRolesTrigger()
returns trigger
language plpgsql
strict as $$
create or replace procedure buildRbacSystemForHsOfficeMembership(
NEW hs_office_membership
)
language plpgsql as $$
declare
newHsOfficePartner hs_office_partner;
newHsOfficeDebitor hs_office_debitor;
newPartnerRel hs_office_relation;
begin
call enterTriggerForObjectUuid(NEW.uuid);
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;
SELECT partnerRel.*
FROM hs_office_partner AS partner
JOIN hs_office_relation AS partnerRel ON partnerRel.uuid = partner.partnerRelUuid
WHERE partner.uuid = NEW.partnerUuid
INTO newPartnerRel;
assert newPartnerRel.uuid is not null, format('newPartnerRel must not be null for NEW.partnerUuid = %s', NEW.partnerUuid);
if TG_OP = 'INSERT' then
-- === ATTENTION: code generated from related Mermaid flowchart: ===
perform createRoleWithGrants(
hsOfficeMembershipOwner(NEW),
permissions => array['DELETE'],
incomingSuperRoles => array[hsOfficeRelationAdmin(newPartnerRel)],
userUuids => array[currentUserUuid()]
);
perform createRoleWithGrants(
hsOfficeMembershipOwner(NEW),
permissions => array['DELETE'],
incomingSuperRoles => array[globalAdmin()]
);
perform createRoleWithGrants(
hsOfficeMembershipAdmin(NEW),
permissions => array['UPDATE'],
incomingSuperRoles => array[
hsOfficeMembershipOwner(NEW),
hsOfficeRelationAgent(newPartnerRel)]
);
perform createRoleWithGrants(
hsOfficeMembershipAdmin(NEW),
permissions => array['UPDATE'],
incomingSuperRoles => array[hsOfficeMembershipOwner(NEW)]
);
perform createRoleWithGrants(
hsOfficeMembershipAgent(NEW),
incomingSuperRoles => array[hsOfficeMembershipAdmin(NEW), hsOfficePartnerAdmin(newHsOfficePartner), hsOfficeDebitorAdmin(newHsOfficeDebitor)],
outgoingSubRoles => array[hsOfficePartnerTenant(newHsOfficePartner), hsOfficeDebitorTenant(newHsOfficeDebitor)]
);
perform createRoleWithGrants(
hsOfficeMembershipTenant(NEW),
incomingSuperRoles => array[hsOfficeMembershipAgent(NEW), hsOfficePartnerAgent(newHsOfficePartner), hsOfficeDebitorAgent(newHsOfficeDebitor)],
outgoingSubRoles => array[hsOfficePartnerGuest(newHsOfficePartner), hsOfficeDebitorGuest(newHsOfficeDebitor)]
);
perform createRoleWithGrants(
hsOfficeMembershipGuest(NEW),
permissions => array['SELECT'],
incomingSuperRoles => array[hsOfficeMembershipTenant(NEW), hsOfficePartnerTenant(newHsOfficePartner), hsOfficeDebitorTenant(newHsOfficeDebitor)]
);
-- === END of code generated from Mermaid flowchart. ===
else
raise exception 'invalid usage of TRIGGER';
end if;
perform createRoleWithGrants(
hsOfficeMembershipReferrer(NEW),
permissions => array['SELECT'],
incomingSuperRoles => array[hsOfficeMembershipAdmin(NEW)],
outgoingSubRoles => array[hsOfficeRelationTenant(newPartnerRel)]
);
call leaveTriggerForObjectUuid(NEW.uuid);
return NEW;
end; $$;
/*
An AFTER INSERT TRIGGER which creates the role structure for a new customer.
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_office_membership row.
*/
create trigger createRbacRolesForHsOfficeMembership_Trigger
after insert
on hs_office_membership
create or replace function insertTriggerForHsOfficeMembership_tf()
returns trigger
language plpgsql
strict as $$
begin
call buildRbacSystemForHsOfficeMembership(NEW);
return NEW;
end; $$;
create trigger insertTriggerForHsOfficeMembership_tg
after insert on hs_office_membership
for each row
execute procedure hsOfficeMembershipRbacRolesTrigger();
execute procedure insertTriggerForHsOfficeMembership_tf();
--//
-- ============================================================================
--changeset hs-office-membership-rbac-IDENTITY-VIEW:1 endDelimiter:--//
--changeset hs-office-membership-rbac-INSERT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('hs_office_membership', $idName$
'#' ||
(select partnerNumber from hs_office_partner p where p.uuid = target.partnerUuid) ||
memberNumberSuffix ||
':' || (select split_part(idName, ':', 2) from hs_office_partner_iv p where p.uuid = target.partnerUuid)
$idName$);
/*
Creates INSERT INTO hs_office_membership permissions for the related global rows.
*/
do language plpgsql $$
declare
row global;
begin
call defineContext('create INSERT INTO hs_office_membership permissions for the related global rows');
FOR row IN SELECT * FROM global
LOOP
call grantPermissionToRole(
createPermission(row.uuid, 'INSERT', 'hs_office_membership'),
globalAdmin());
END LOOP;
END;
$$;
/**
Adds hs_office_membership INSERT permission to specified role of new global rows.
*/
create or replace function hs_office_membership_global_insert_tf()
returns trigger
language plpgsql
strict as $$
begin
call grantPermissionToRole(
createPermission(NEW.uuid, 'INSERT', 'hs_office_membership'),
globalAdmin());
return NEW;
end; $$;
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
create trigger z_hs_office_membership_global_insert_tg
after insert on global
for each row
execute procedure hs_office_membership_global_insert_tf();
/**
Checks if the user or assumed roles are allowed to insert a row to hs_office_membership,
where only global-admin has that permission.
*/
create or replace function hs_office_membership_insert_permission_missing_tf()
returns trigger
language plpgsql as $$
begin
raise exception '[403] insert into hs_office_membership not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids();
end; $$;
create trigger hs_office_membership_insert_permission_check_tg
before insert on hs_office_membership
for each row
when ( not isGlobalAdmin() )
execute procedure hs_office_membership_insert_permission_missing_tf();
--//
-- ============================================================================
--changeset hs-office-membership-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromQuery('hs_office_membership',
$idName$
SELECT m.uuid AS uuid,
'M-' || p.partnerNumber || m.memberNumberSuffix as idName
FROM hs_office_membership AS m
JOIN hs_office_partner AS p ON p.uuid = m.partnerUuid
$idName$);
--//
-- ============================================================================
--changeset hs-office-membership-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRestrictedView('hs_office_membership',
orderby => 'target.memberNumberSuffix',
columnUpdates => $updates$
$orderBy$
validity
$orderBy$,
$updates$
validity = new.validity,
reasonForTermination = new.reasonForTermination,
membershipFeeBillable = new.membershipFeeBillable
membershipFeeBillable = new.membershipFeeBillable,
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();
--//

View File

@@ -9,35 +9,27 @@
Creates a single membership test record.
*/
create or replace procedure createHsOfficeMembershipTestData(
forPartnerTradeName varchar,
forMainDebitorNumberSuffix numeric,
forPartnerNumber numeric(5),
newMemberNumberSuffix char(2) )
language plpgsql as $$
declare
currentTask varchar;
idName varchar;
relatedPartner hs_office_partner;
relatedDebitor hs_office_debitor;
begin
idName := cleanIdentifier( forPartnerTradeName || '#' || forMainDebitorNumberSuffix);
currentTask := 'creating Membership test-data ' || idName;
currentTask := 'creating Membership test-data ' ||
'P-' || forPartnerNumber::text ||
'M-...' || newMemberNumberSuffix;
call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global.admin');
execute format('set local hsadminng.currentTask to %L', currentTask);
select partner.* from hs_office_partner partner
join hs_office_person person on person.uuid = partner.personUuid
where person.tradeName = forPartnerTradeName into relatedPartner;
select d.* from hs_office_debitor d
where d.partneruuid = relatedPartner.uuid
and d.debitorNumberSuffix = forMainDebitorNumberSuffix
into relatedDebitor;
where partner.partnerNumber = forPartnerNumber into relatedPartner;
raise notice 'creating test Membership: %', idName;
raise notice 'creating test Membership: M-% %', forPartnerNumber, newMemberNumberSuffix;
raise notice '- using partner (%): %', relatedPartner.uuid, relatedPartner;
raise notice '- using debitor (%): %', relatedDebitor.uuid, relatedDebitor;
insert
into hs_office_membership (uuid, partneruuid, maindebitoruuid, memberNumberSuffix, validity, reasonfortermination)
values (uuid_generate_v4(), relatedPartner.uuid, relatedDebitor.uuid, newMemberNumberSuffix, daterange('20221001' , null, '[]'), 'NONE');
into hs_office_membership (uuid, partneruuid, memberNumberSuffix, validity, reasonfortermination)
values (uuid_generate_v4(), relatedPartner.uuid, newMemberNumberSuffix, daterange('20221001' , null, '[]'), 'NONE');
end; $$;
--//
@@ -48,9 +40,9 @@ end; $$;
do language plpgsql $$
begin
call createHsOfficeMembershipTestData('First GmbH', 11, '01');
call createHsOfficeMembershipTestData('Second e.K.', 12, '02');
call createHsOfficeMembershipTestData('Third OHG', 13, '03');
call createHsOfficeMembershipTestData(10001, '01');
call createHsOfficeMembershipTestData(10002, '02');
call createHsOfficeMembershipTestData(10003, '03');
end;
$$;
--//

View File

@@ -42,7 +42,7 @@ begin
-- coopsharestransactions cannot be edited nor deleted, just created+viewed
call grantPermissionsToRole(
getRoleId(hsOfficeMembershipTenant(newHsOfficeMembership)),
getRoleId(hsOfficeMembershipReferrer(newHsOfficeMembership)),
createPermissions(NEW.uuid, array ['SELECT'])
);

View File

@@ -42,7 +42,7 @@ begin
-- coopassetstransactions cannot be edited nor deleted, just created+viewed
call grantPermissionsToRole(
getRoleId(hsOfficeMembershipTenant(newHsOfficeMembership)),
getRoleId(hsOfficeMembershipReferrer(newHsOfficeMembership)),
createPermissions(NEW.uuid, array ['SELECT'])
);