1
0

hs-office-partner-details

This commit is contained in:
Michael Hoennig
2022-10-20 20:11:31 +02:00
parent dc0835fa25
commit e1895e3735
26 changed files with 573 additions and 212 deletions

View File

@ -372,7 +372,7 @@ create domain RbacOp as varchar(67)
or VALUE = 'view'
or VALUE = 'assume'
or VALUE ~ '^add-[a-z]+$'
or VALUE ~ '^new-[a-z]+$'
or VALUE ~ '^new-[a-z-]+$'
);
create table RbacPermission

View File

@ -63,7 +63,7 @@ begin
and r.roleType = roleTypeToAssume
into roleUuidToAssume;
if roleUuidToAssume is null then
raise exception '[403] role % not accessible for user %', roleName, currentUser();
raise exception '[403] role % not accessible for user %', roleName, currentSubjects();
end if;
if not isGranted(currentUserUuid, roleUuidToAssume) then
raise exception '[403] user % has no permission to assume role %', currentUser(), roleName;

View File

@ -1,14 +1,13 @@
--liquibase formatted sql
-- ============================================================================
--changeset hs-office-partner-MAIN-TABLE:1 endDelimiter:--//
--changeset hs-office-partner-DETAILS-TABLE:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
create table if not exists hs_office_partner
create table hs_office_partner_details
(
uuid uuid unique references RbacObject (uuid) initially deferred,
personUuid uuid not null references hs_office_person(uuid),
contactUuid uuid not null references hs_office_contact(uuid),
registrationOffice varchar(96),
registrationNumber varchar(96),
birthName varchar(96),
@ -18,6 +17,27 @@ create table if not exists hs_office_partner
--//
-- ============================================================================
--changeset hs-office-partner-DETAILS-TABLE-JOURNAL:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call create_journal('hs_office_partner_details');
--//
-- ============================================================================
--changeset hs-office-partner-MAIN-TABLE:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
create table hs_office_partner
(
uuid uuid unique references RbacObject (uuid) initially deferred,
personUuid uuid not null references hs_office_person(uuid),
contactUuid uuid not null references hs_office_contact(uuid),
detailsUuid uuid not null references hs_office_partner_details(uuid) on delete cascade
);
--//
-- ============================================================================
--changeset hs-office-partner-MAIN-TABLE-JOURNAL:1 endDelimiter:--//
-- ----------------------------------------------------------------------------

View File

@ -27,17 +27,27 @@ subgraph hsOfficePerson
--> role:hsOfficePerson.guest[person.guest]
end
subgraph hsOfficePartnerDetails
direction TB
perm:hsOfficePartnerDetails.*{{partner.*}}
perm:hsOfficePartnerDetails.edit{{partner.edit}}
perm:hsOfficePartnerDetails.view{{partner.view}}
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
@ -45,6 +55,8 @@ subgraph hsOfficePartner
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

View File

@ -39,6 +39,8 @@ begin
if TG_OP = 'INSERT' then
-- === ATTENTION: code generated from related Mermaid flowchart: ===
perform createRoleWithGrants(
hsOfficePartnerOwner(NEW),
permissions => array['*'],
@ -72,14 +74,40 @@ begin
hsOfficeContactGuest(newContact)]
);
perform createRoleWithGrants(
hsOfficePartnerGuest(NEW),
permissions => array['view'],
incomingSuperRoles => array[
hsOfficePartnerTenant(NEW)]
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), 'fail'),
createPermissions(NEW.detailsUuid, array ['*'])
);
call grantPermissionsToRole(
getRoleId(hsOfficePartnerAdmin(NEW), 'fail'),
createPermissions(NEW.detailsUuid, array ['edit'])
);
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), 'fail'),
createPermissions(NEW.detailsUuid, array ['view'])
);
elsif TG_OP = 'UPDATE' then
if OLD.personUuid <> NEW.personUuid then
@ -87,10 +115,10 @@ begin
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;
@ -152,12 +180,7 @@ call generateRbacRestrictedView('hs_office_partner',
'(select idName from hs_office_person_iv p where p.uuid = target.personUuid)',
$updates$
personUuid = new.personUuid,
contactUuid = new.contactUuid,
registrationOffice = new.registrationOffice,
registrationNumber = new.registrationNumber,
birthday = new.birthday,
birthName = new.birthName,
dateOfDeath = new.dateOfDeath
contactUuid = new.contactUuid
$updates$);
--//

View File

@ -0,0 +1,85 @@
--liquibase formatted sql
-- ============================================================================
--changeset hs-office-partner-details-rbac-OBJECT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRelatedRbacObject('hs_office_partner_details');
--//
-- ============================================================================
--changeset hs-office-partner-details-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityView('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$);
--//
-- ============================================================================
--changeset hs-office-partner-details-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRestrictedView('hs_office_partner_details',
'target.uuid', -- no specific order required
$updates$
registrationOffice = new.registrationOffice,
registrationNumber = new.registrationNumber,
birthName = new.birthName,
birthday = new.birthday,
dateOfDeath = new.dateOfDeath
$updates$);
--//
-- ============================================================================
--changeset hs-office-partner-details-rbac-NEW-CONTACT: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

@ -11,11 +11,12 @@
create or replace procedure createHsOfficePartnerTestData( personTradeOrFamilyName varchar, contactLabel varchar )
language plpgsql as $$
declare
currentTask varchar;
idName varchar;
relatedPerson hs_office_person;
relatedContact hs_office_contact;
birthday date;
currentTask varchar;
idName varchar;
relatedPerson hs_office_person;
relatedContact hs_office_contact;
relatedDetailsUuid uuid;
birthday date;
begin
idName := cleanIdentifier( personTradeOrFamilyName|| '-' || contactLabel);
currentTask := 'creating partner test-data ' || idName;
@ -36,34 +37,25 @@ begin
raise notice 'creating test partner: %', idName;
raise notice '- using person (%): %', relatedPerson.uuid, relatedPerson;
raise notice '- using contact (%): %', relatedContact.uuid, relatedContact;
if relatedPerson.persontype = 'NATURAL' then
insert
into hs_office_partner_details (uuid, birthName, birthday)
values (uuid_generate_v4(), 'Meyer', '1987-10-31')
returning uuid into relatedDetailsUuid;
else
insert
into hs_office_partner_details (uuid, registrationOffice, registrationNumber)
values (uuid_generate_v4(), 'Hamburg', '12345')
returning uuid into relatedDetailsUuid;
end if;
insert
into hs_office_partner (uuid, personuuid, contactuuid, birthday)
values (uuid_generate_v4(), relatedPerson.uuid, relatedContact.uuid, birthDay);
into hs_office_partner (uuid, personuuid, contactuuid, detailsUuid)
values (uuid_generate_v4(), relatedPerson.uuid, relatedContact.uuid, relatedDetailsUuid);
end; $$;
--//
/*
Creates a range of test partner for mass data generation.
*/
create or replace procedure createHsOfficePartnerTestData(
startCount integer, -- count of auto generated rows before the run
endCount integer -- count of auto generated rows after the run
)
language plpgsql as $$
declare
person hs_office_person;
contact hs_office_contact;
begin
for t in startCount..endCount
loop
select p.* from hs_office_person p where tradeName = intToVarChar(t, 4) into person;
select c.* from hs_office_contact c where c.label = intToVarChar(t, 4) || '#' || t into contact;
call createHsOfficePartnerTestData(person.uuid, contact.uuid);
commit;
end loop;
end; $$;
--//
-- ============================================================================

View File

@ -65,6 +65,8 @@ databaseChangeLog:
file: db/changelog/220-hs-office-partner.sql
- include:
file: db/changelog/223-hs-office-partner-rbac.sql
- include:
file: db/changelog/224-hs-office-partner-details-rbac.sql
- include:
file: db/changelog/228-hs-office-partner-test-data.sql
- include: