Compare commits

..

No commits in common. "823269d8aa7ade7d3ccf01ef6110b43fda05ac42" and "fbe2204d7277358e2a33863bb2529c24db75a7c4" have entirely different histories.

14 changed files with 185 additions and 205 deletions

View File

@ -839,6 +839,10 @@ public class RbacView {
}; };
} }
public boolean hasFetchSql() {
return fetchSql != null;
}
private String withoutEntitySuffix(final String simpleEntityName) { private String withoutEntitySuffix(final String simpleEntityName) {
return simpleEntityName.substring(0, simpleEntityName.length() - "Entity".length()); return simpleEntityName.substring(0, simpleEntityName.length() - "Entity".length());
} }

View File

@ -94,17 +94,4 @@ public class RbacGrantController implements RbacGrantsApi {
return ResponseEntity.noContent().build(); return ResponseEntity.noContent().build();
} }
// TODO: implement an endpoint to create a Mermaid flowchart with all grants of a given user
// @GetMapping(
// path = "/api/rbac/users/{userUuid}/grants",
// produces = {"text/vnd.mermaid"})
// @Transactional(readOnly = true)
// public ResponseEntity<String> allGrantsOfUserAsMermaid(
// @RequestHeader(name = "current-user") String currentUser,
// @RequestHeader(name = "assumed-roles", required = false) String assumedRoles) {
// final var graph = RbacGrantsDiagramService.allGrantsToUser(currentUser);
// return ResponseEntity.ok(graph);
// }
} }

View File

@ -1,5 +1,5 @@
package net.hostsharing.hsadminng.rbac.rbacrole; package net.hostsharing.hsadminng.rbac.rbacrole;
public enum RbacRoleType { public enum RbacRoleType {
owner, admin, agent, tenant, guest, referrer owner, admin, agent, tenant, guest
} }

View File

@ -1,20 +0,0 @@
--liquibase formatted sql
-- ============================================================================
-- TABLE-COLUMNS-FUNCTION
--changeset table-columns-function:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
create or replace function columnsNames( tableName text )
returns text
stable
language 'plpgsql' as $$
declare columns text[];
begin
columns := (select array(select column_name::text
from information_schema.columns
where table_name = tableName));
return array_to_string(columns, ', ');
end; $$
--//

View File

@ -164,7 +164,7 @@ end; $$;
*/ */
create type RbacRoleType as enum ('owner', 'admin', 'agent', 'tenant', 'guest', 'referrer'); create type RbacRoleType as enum ('owner', 'admin', 'agent', 'tenant', 'guest');
create table RbacRole create table RbacRole
( (
@ -373,12 +373,10 @@ create table RbacPermission
uuid uuid primary key references RbacReference (uuid) on delete cascade, uuid uuid primary key references RbacReference (uuid) on delete cascade,
objectUuid uuid not null references RbacObject, objectUuid uuid not null references RbacObject,
op RbacOp not null, op RbacOp not null,
opTableName varchar(60) opTableName varchar(60),
unique (objectUuid, op)
); );
ALTER TABLE RbacPermission
ADD CONSTRAINT RbacPermission_uc UNIQUE NULLS NOT DISTINCT (objectUuid, op, opTableName);
call create_journal('RbacPermission'); call create_journal('RbacPermission');
create or replace function createPermission(forObjectUuid uuid, forOp RbacOp, forOpTableName text = null) create or replace function createPermission(forObjectUuid uuid, forOp RbacOp, forOpTableName text = null)
@ -397,10 +395,7 @@ begin
raise exception 'forOpTableName must only be specified for ops: [INSERT]'; -- currently no other raise exception 'forOpTableName must only be specified for ops: [INSERT]'; -- currently no other
end if; end if;
permissionUuid := ( permissionUuid = (select uuid from RbacPermission where objectUuid = forObjectUuid and op = forOp and opTableName = forOpTableName);
select uuid from RbacPermission
where objectUuid = forObjectUuid
and op = forOp and opTableName is not distinct from forOpTableName);
if (permissionUuid is null) then if (permissionUuid is null) then
insert into RbacReference ("type") insert into RbacReference ("type")
values ('RbacPermission') values ('RbacPermission')
@ -471,44 +466,8 @@ select uuid
and p.op = forOp and p.op = forOp
and p.opTableName = forOpTableName and p.opTableName = forOpTableName
$$; $$;
create or replace function getPermissionId(forObjectUuid uuid, forOp RbacOp, forOpTableName text = null)
returns uuid
stable -- leakproof
language plpgsql as $$
declare
permissionUuid uuid;
begin
select uuid into permissionUuid
from RbacPermission p
where p.objectUuid = forObjectUuid
and p.op = forOp
and forOpTableName is null or p.opTableName = forOpTableName;
assert permissionUuid is not null,
format('permission %s %s for object UUID %s cannot be found', forOp, forOpTableName, forObjectUuid);
return permissionUuid;
end; $$;
--// --//
-- ============================================================================
--changeset rbac-base-duplicate-role-grant-exception:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
create or replace procedure raiseDuplicateRoleGrantException(subRoleId uuid, superRoleId uuid)
language plpgsql as $$
declare
subRoleIdName text;
superRoleIdName text;
begin
select roleIdName from rbacRole_ev where uuid=subRoleId into subRoleIdName;
select roleIdName from rbacRole_ev where uuid=superRoleId into superRoleIdName;
raise exception '[400] Duplicate role grant detected: role % (%) already granted to % (%)', subRoleId, subRoleIdName, superRoleId, superRoleIdName;
end;
$$;
--//
-- ============================================================================ -- ============================================================================
--changeset rbac-base-GRANTS:1 endDelimiter:--// --changeset rbac-base-GRANTS:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
@ -675,7 +634,7 @@ begin
perform assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole'); perform assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole');
if isGranted(subRoleId, superRoleId) then if isGranted(subRoleId, superRoleId) then
call raiseDuplicateRoleGrantException(subRoleId, superRoleId); raise exception '[400] Cyclic role grant detected between % and %', subRoleId, superRoleId;
end if; end if;
insert insert
@ -691,11 +650,6 @@ declare
superRoleId uuid; superRoleId uuid;
subRoleId uuid; subRoleId uuid;
begin begin
-- FIXME: maybe separate method grantRoleToRoleIfNotNull(...)?
if superRole.objectUuid is null or subRole.objectuuid is null then
return;
end if;
superRoleId := findRoleId(superRole); superRoleId := findRoleId(superRole);
subRoleId := findRoleId(subRole); subRoleId := findRoleId(subRole);
@ -703,7 +657,7 @@ begin
perform assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole'); perform assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole');
if isGranted(subRoleId, superRoleId) then if isGranted(subRoleId, superRoleId) then
call raiseDuplicateRoleGrantException(subRoleId, superRoleId); raise exception '[400] Cyclic role grant detected between % and %', subRoleId, superRoleId;
end if; end if;
insert insert
@ -718,7 +672,6 @@ declare
superRoleId uuid; superRoleId uuid;
subRoleId uuid; subRoleId uuid;
begin begin
if ( superRoleId is null ) then return; end if;
superRoleId := findRoleId(superRole); superRoleId := findRoleId(superRole);
if ( subRoleId is null ) then return; end if; if ( subRoleId is null ) then return; end if;
subRoleId := findRoleId(subRole); subRoleId := findRoleId(subRole);
@ -727,7 +680,7 @@ begin
perform assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole'); perform assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole');
if isGranted(subRoleId, superRoleId) then if isGranted(subRoleId, superRoleId) then
call raiseDuplicateRoleGrantException(subRoleId, superRoleId); raise exception '[400] Cyclic role grant detected between % and %', subRoleId, superRoleId;
end if; end if;
insert insert
@ -751,39 +704,11 @@ begin
if (isGranted(superRoleId, subRoleId)) then if (isGranted(superRoleId, subRoleId)) then
delete from RbacGrants where ascendantUuid = superRoleId and descendantUuid = subRoleId; delete from RbacGrants where ascendantUuid = superRoleId and descendantUuid = subRoleId;
else else
raise exception 'cannot revoke role % (%) from % (%) because it is not granted', raise exception 'cannot revoke role % (%) from % (% because it is not granted',
subRole, subRoleId, superRole, superRoleId; subRole, subRoleId, superRole, superRoleId;
end if; end if;
end; $$; end; $$;
create or replace procedure revokePermissionFromRole(permissionId UUID, superRole RbacRoleDescriptor)
language plpgsql as $$
declare
superRoleId uuid;
permissionOp text;
objectTable text;
objectUuid uuid;
begin
superRoleId := findRoleId(superRole);
perform assertReferenceType('superRoleId (ascendant)', superRoleId, 'RbacRole');
perform assertReferenceType('permission (descendant)', permissionId, 'RbacPermission');
if (isGranted(superRoleId, permissionId)) then
delete from RbacGrants where ascendantUuid = superRoleId and descendantUuid = permissionId;
else
select p.op, o.objectTable, o.uuid
from rbacGrants g
join rbacPermission p on p.uuid=g.descendantUuid
join rbacobject o on o.uuid=p.objectUuid
where g.uuid=permissionId
into permissionOp, objectTable, objectUuid;
raise exception 'cannot revoke permission % (% on %#% (%) from % (%)) because it is not granted',
permissionId, permissionOp, objectTable, objectUuid, permissionId, superRole, superRoleId;
end if;
end; $$;
-- ============================================================================ -- ============================================================================
--changeset rbac-base-QUERY-ACCESSIBLE-OBJECT-UUIDS:1 endDelimiter:--// --changeset rbac-base-QUERY-ACCESSIBLE-OBJECT-UUIDS:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------

View File

@ -56,17 +56,14 @@ begin
roleTypeToAssume = split_part(roleNameParts, '#', 3); roleTypeToAssume = split_part(roleNameParts, '#', 3);
objectUuidToAssume = findObjectUuidByIdName(objectTableToAssume, objectNameToAssume); objectUuidToAssume = findObjectUuidByIdName(objectTableToAssume, objectNameToAssume);
if objectUuidToAssume is null then
raise exception '[401] object % cannot be found in table %', objectNameToAssume, objectTableToAssume;
end if;
select uuid select uuid as roleuuidToAssume
from RbacRole r from RbacRole r
where r.objectUuid = objectUuidToAssume where r.objectUuid = objectUuidToAssume
and r.roleType = roleTypeToAssume and r.roleType = roleTypeToAssume
into roleUuidToAssume; into roleUuidToAssume;
if roleUuidToAssume is null then if roleUuidToAssume is null then
raise exception '[403] role % does not exist or is not accessible for user %', roleName, currentUser(); raise exception '[403] role % not accessible for user %', roleName, currentSubjects();
end if; end if;
if not isGranted(currentUserUuid, roleUuidToAssume) then if not isGranted(currentUserUuid, roleUuidToAssume) then
raise exception '[403] user % has no permission to assume role %', currentUser(), roleName; raise exception '[403] user % has no permission to assume role %', currentUser(), roleName;

View File

@ -37,7 +37,7 @@ declare
subRoleUuid uuid; subRoleUuid uuid;
superRoleUuid uuid; superRoleUuid uuid;
userUuid uuid; userUuid uuid;
userGrantsByRoleUuid uuid; grantedByRoleUuid uuid;
begin begin
roleUuid := createRole(roleDescriptor); roleUuid := createRole(roleDescriptor);
@ -58,15 +58,14 @@ begin
end loop; end loop;
if cardinality(userUuids) > 0 then if cardinality(userUuids) > 0 then
-- direct grants to users need a grantedByRole which can revoke the grant
if grantedByRole is null then if grantedByRole is null then
userGrantsByRoleUuid := roleUuid; -- FIXME: or do we want to require an explicit userGrantsByRoleUuid? grantedByRoleUuid := roleUuid;
else else
userGrantsByRoleUuid := getRoleId(grantedByRole); grantedByRoleUuid := getRoleId(grantedByRole);
end if; end if;
foreach userUuid in array userUuids foreach userUuid in array userUuids
loop loop
call grantRoleToUserUnchecked(userGrantsByRoleUuid, roleUuid, userUuid); call grantRoleToUserUnchecked(grantedByRoleUuid, roleUuid, userUuid);
end loop; end loop;
end if; end if;

View File

@ -73,7 +73,6 @@ begin
return roleDescriptor('%2$s', entity.uuid, 'tenant', assumed); return roleDescriptor('%2$s', entity.uuid, 'tenant', assumed);
end; $f$; end; $f$;
-- TODO: remove guest role
create or replace function %1$sGuest(entity %2$s, assumed boolean = true) create or replace function %1$sGuest(entity %2$s, assumed boolean = true)
returns RbacRoleDescriptor returns RbacRoleDescriptor
language plpgsql language plpgsql
@ -82,14 +81,6 @@ begin
return roleDescriptor('%2$s', entity.uuid, 'guest', assumed); return roleDescriptor('%2$s', entity.uuid, 'guest', assumed);
end; $f$; end; $f$;
create or replace function %1$sReferrer(entity %2$s)
returns RbacRoleDescriptor
language plpgsql
strict as $f$
begin
return roleDescriptor('%2$s', entity.uuid, 'referrer');
end; $f$;
$sql$, prefix, targetTable); $sql$, prefix, targetTable);
execute sql; execute sql;
end; $$; end; $$;
@ -157,16 +148,12 @@ end; $$;
--changeset rbac-generators-RESTRICTED-VIEW:1 endDelimiter:--// --changeset rbac-generators-RESTRICTED-VIEW:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
create or replace procedure generateRbacRestrictedView(targetTable text, orderBy text, columnUpdates text = null, columnNames text = '*') create or replace procedure generateRbacRestrictedView(targetTable text, orderBy text, columnUpdates text = null)
language plpgsql as $$ language plpgsql as $$
declare declare
sql text; sql text;
newColumns text;
begin begin
targetTable := lower(targetTable); targetTable := lower(targetTable);
if columnNames = '*' then
columnNames := columnsNames(targetTable);
end if;
/* /*
Creates a restricted view based on the 'SELECT' permission of the current subject. Creates a restricted view based on the 'SELECT' permission of the current subject.
@ -188,7 +175,6 @@ begin
/** /**
Instead of insert trigger function for the restricted view. Instead of insert trigger function for the restricted view.
*/ */
newColumns := 'new.' || replace(columnNames, ',', ', new.');
sql := format($sql$ sql := format($sql$
create or replace function %1$sInsert() create or replace function %1$sInsert()
returns trigger returns trigger
@ -197,12 +183,12 @@ begin
newTargetRow %1$s; newTargetRow %1$s;
begin begin
insert insert
into %1$s (%2$s) into %1$s
values (%3$s) values (new.*)
returning * into newTargetRow; returning * into newTargetRow;
return newTargetRow; return newTargetRow;
end; $f$; end; $f$;
$sql$, targetTable, columnNames, newColumns); $sql$, targetTable);
execute sql; execute sql;
/* /*

View File

@ -118,32 +118,9 @@ select 'global', (select uuid from RbacObject where objectTable = 'global'), 'ad
$$; $$;
begin transaction; begin transaction;
call defineContext('creating global admin role', null, null, null); call defineContext('creating global admin role', null, null, null);
select createRole(globalAdmin()); select createRole(globalAdmin());
commit; commit;
--//
-- ============================================================================
--changeset rbac-global-GUEST-ROLE:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
A global guest role.
*/
create or replace function globalGuest(assumed boolean = true)
returns RbacRoleDescriptor
returns null on null input
stable -- leakproof
language sql as $$
select 'global', (select uuid from RbacObject where objectTable = 'global'), 'guest'::RbacRoleType, assumed;
$$;
begin transaction;
call defineContext('creating global guest role', null, null, null);
select createRole(globalGuest());
commit;
--//
-- ============================================================================ -- ============================================================================
--changeset rbac-global-ADMIN-USERS:1 context:dev,tc endDelimiter:--// --changeset rbac-global-ADMIN-USERS:1 context:dev,tc endDelimiter:--//

View File

@ -38,6 +38,8 @@ begin
SELECT * FROM test_package p SELECT * FROM test_package p
WHERE p.uuid= NEW.packageUuid WHERE p.uuid= NEW.packageUuid
INTO newPackage; INTO newPackage;
assert newPackage.uuid is not null, format('newPackage must not be null for NEW.packageUuid = %s', NEW.packageUuid);
perform createRoleWithGrants( perform createRoleWithGrants(
testDomainOwner(NEW), testDomainOwner(NEW),
@ -89,12 +91,41 @@ create or replace procedure updateRbacRulesForTestDomain(
NEW test_domain NEW test_domain
) )
language plpgsql as $$ language plpgsql as $$
begin
if NEW.packageUuid is distinct from OLD.packageUuid then declare
delete from rbacgrants g where g.grantedbytriggerof = OLD.uuid; oldPackage test_package;
call buildRbacSystemForTestDomain(NEW); newPackage test_package;
begin
call enterTriggerForObjectUuid(NEW.uuid);
SELECT * FROM test_package p
WHERE p.uuid= OLD.packageUuid
INTO oldPackage;
assert oldPackage.uuid is not null, format('oldPackage must not be null for OLD.packageUuid = %s', OLD.packageUuid);
SELECT * FROM test_package p
WHERE p.uuid= NEW.packageUuid
INTO newPackage;
assert newPackage.uuid is not null, format('newPackage must not be null for NEW.packageUuid = %s', NEW.packageUuid);
if NEW.packageUuid <> OLD.packageUuid then
call revokePermissionFromRole(getPermissionId(OLD.uuid, 'INSERT'), testPackageAdmin(oldPackage));
call revokeRoleFromRole(testDomainOwner(OLD), testPackageAdmin(oldPackage));
call grantRoleToRole(testDomainOwner(NEW), testPackageAdmin(newPackage));
call revokeRoleFromRole(testPackageTenant(oldPackage), testDomainOwner(OLD));
call grantRoleToRole(testPackageTenant(newPackage), testDomainOwner(NEW));
call revokeRoleFromRole(testPackageTenant(oldPackage), testDomainAdmin(OLD));
call grantRoleToRole(testPackageTenant(newPackage), testDomainAdmin(NEW));
end if; end if;
call leaveTriggerForObjectUuid(NEW.uuid);
end; $$; end; $$;
/* /*

View File

@ -38,10 +38,14 @@ begin
call enterTriggerForObjectUuid(NEW.uuid); call enterTriggerForObjectUuid(NEW.uuid);
select * from hs_office_person as p where p.uuid = NEW.holderUuid INTO newHolderPerson; select * from hs_office_person as p where p.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 newAnchorPerson; select * from hs_office_person as p where p.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 as c where c.uuid = NEW.contactUuid INTO newContact; select * from hs_office_contact as c where c.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( perform createRoleWithGrants(
hsOfficeRelationOwner(NEW), hsOfficeRelationOwner(NEW),
@ -69,13 +73,13 @@ begin
hsOfficeRelationTenant(NEW), hsOfficeRelationTenant(NEW),
permissions => array['SELECT'], permissions => array['SELECT'],
incomingSuperRoles => array[ incomingSuperRoles => array[
hsOfficeContactAdmin(newContact),
hsOfficeRelationAgent(NEW), hsOfficeRelationAgent(NEW),
hsOfficeContactAdmin(newContact),
hsOfficePersonAdmin(newHolderPerson)], hsOfficePersonAdmin(newHolderPerson)],
outgoingSubRoles => array[ outgoingSubRoles => array[
hsOfficePersonReferrer(newHolderPerson),
hsOfficeContactReferrer(newContact), hsOfficeContactReferrer(newContact),
hsOfficePersonReferrer(newAnchorPerson), hsOfficePersonReferrer(newAnchorPerson)]
hsOfficePersonReferrer(newHolderPerson)]
); );
call leaveTriggerForObjectUuid(NEW.uuid); call leaveTriggerForObjectUuid(NEW.uuid);
@ -114,12 +118,48 @@ create or replace procedure updateRbacRulesForHsOfficeRelation(
NEW hs_office_relation NEW hs_office_relation
) )
language plpgsql as $$ language plpgsql as $$
begin
if NEW.contactUuid is distinct from OLD.contactUuid then declare
delete from rbacgrants g where g.grantedbytriggerof = OLD.uuid; oldHolderPerson hs_office_person;
call buildRbacSystemForHsOfficeRelation(NEW); 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 as p where p.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 as p where p.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 = 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 as p where p.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 as c where c.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 as c where c.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; end if;
call leaveTriggerForObjectUuid(NEW.uuid);
end; $$; end; $$;
/* /*

View File

@ -57,8 +57,8 @@ begin
hsOfficeSepaMandateAgent(NEW), hsOfficeSepaMandateAgent(NEW),
incomingSuperRoles => array[hsOfficeSepaMandateAdmin(NEW)], incomingSuperRoles => array[hsOfficeSepaMandateAdmin(NEW)],
outgoingSubRoles => array[ outgoingSubRoles => array[
hsOfficeRelationAgent(newDebitorRel), hsOfficeBankAccountReferrer(newBankAccount),
hsOfficeBankAccountReferrer(newBankAccount)] hsOfficeRelationAgent(newDebitorRel)]
); );
perform createRoleWithGrants( perform createRoleWithGrants(

View File

@ -41,6 +41,7 @@ begin
FROM hs_office_relation AS partnerRel FROM hs_office_relation AS partnerRel
WHERE ${debitorRel}.anchorUuid = partnerRel.holderUuid WHERE ${debitorRel}.anchorUuid = partnerRel.holderUuid
INTO newPartnerRel; INTO newPartnerRel;
assert newPartnerRel.uuid is not null, format('newPartnerRel must not be null for NEW.partnerRelUuid = %s', NEW.partnerRelUuid);
SELECT * SELECT *
FROM hs_office_relation AS r FROM hs_office_relation AS r
@ -52,6 +53,7 @@ begin
FROM hs_office_relation AS r FROM hs_office_relation AS r
WHERE r.type = 'DEBITOR' AND r.holderUuid = NEW.debitorRelUuid WHERE r.type = 'DEBITOR' AND r.holderUuid = NEW.debitorRelUuid
INTO newRefundBankAccount; INTO newRefundBankAccount;
assert newRefundBankAccount.uuid is not null, format('newRefundBankAccount must not be null for NEW.refundBankAccountUuid = %s', NEW.refundBankAccountUuid);
call grantRoleToRole(hsOfficeBankAccountReferrer(newRefundBankAccount), hsOfficeRelationAgent(newDebitorRel)); call grantRoleToRole(hsOfficeBankAccountReferrer(newRefundBankAccount), hsOfficeRelationAgent(newDebitorRel));
call grantRoleToRole(hsOfficeRelationAdmin(newDebitorRel), hsOfficeRelationAdmin(newPartnerRel)); call grantRoleToRole(hsOfficeRelationAdmin(newDebitorRel), hsOfficeRelationAdmin(newPartnerRel));
@ -99,12 +101,66 @@ create or replace procedure updateRbacRulesForHsOfficeDebitor(
NEW hs_office_debitor NEW hs_office_debitor
) )
language plpgsql as $$ language plpgsql as $$
begin
if NEW.refundBankAccountUuid is distinct from OLD.refundBankAccountUuid then declare
delete from rbacgrants g where g.grantedbytriggerof = OLD.uuid; oldPartnerRel hs_office_relation;
call buildRbacSystemForHsOfficeDebitor(NEW); newPartnerRel hs_office_relation;
oldDebitorRel hs_office_relation;
newDebitorRel hs_office_relation;
oldRefundBankAccount hs_office_bankaccount;
newRefundBankAccount hs_office_bankaccount;
begin
call enterTriggerForObjectUuid(NEW.uuid);
SELECT *
FROM hs_office_relation AS partnerRel
WHERE ${debitorRel}.anchorUuid = partnerRel.holderUuid
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 AS partnerRel
WHERE ${debitorRel}.anchorUuid = partnerRel.holderUuid
INTO newPartnerRel;
assert newPartnerRel.uuid is not null, format('newPartnerRel must not be null for NEW.partnerRelUuid = %s', NEW.partnerRelUuid);
SELECT *
FROM hs_office_relation AS r
WHERE r.type = 'DEBITOR' AND r.holderUuid = OLD.debitorRelUuid
INTO oldDebitorRel;
assert oldDebitorRel.uuid is not null, format('oldDebitorRel must not be null for OLD.debitorRelUuid = %s', OLD.debitorRelUuid);
SELECT *
FROM hs_office_relation AS r
WHERE r.type = 'DEBITOR' AND r.holderUuid = 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_relation AS r
WHERE r.type = 'DEBITOR' AND r.holderUuid = OLD.debitorRelUuid
INTO oldRefundBankAccount;
assert oldRefundBankAccount.uuid is not null, format('oldRefundBankAccount must not be null for OLD.refundBankAccountUuid = %s', OLD.refundBankAccountUuid);
SELECT *
FROM hs_office_relation AS r
WHERE r.type = 'DEBITOR' AND r.holderUuid = NEW.debitorRelUuid
INTO newRefundBankAccount;
assert newRefundBankAccount.uuid is not null, format('newRefundBankAccount must not be null for NEW.refundBankAccountUuid = %s', NEW.refundBankAccountUuid);
if NEW.refundBankAccountUuid <> OLD.refundBankAccountUuid then
call revokeRoleFromRole(hsOfficeRelationAgent(oldDebitorRel), hsOfficeBankAccountAdmin(oldRefundBankAccount));
call grantRoleToRole(hsOfficeRelationAgent(newDebitorRel), hsOfficeBankAccountAdmin(newRefundBankAccount));
call revokeRoleFromRole(hsOfficeBankAccountReferrer(oldRefundBankAccount), hsOfficeRelationAgent(oldDebitorRel));
call grantRoleToRole(hsOfficeBankAccountReferrer(newRefundBankAccount), hsOfficeRelationAgent(newDebitorRel));
end if; end if;
call leaveTriggerForObjectUuid(NEW.uuid);
end; $$; end; $$;
/* /*

View File

@ -11,8 +11,6 @@ databaseChangeLog:
file: db/changelog/005-uuid-ossp-extension.sql file: db/changelog/005-uuid-ossp-extension.sql
- include: - include:
file: db/changelog/006-numeric-hash-functions.sql file: db/changelog/006-numeric-hash-functions.sql
- include:
file: db/changelog/007-table-columns.sql
- include: - include:
file: db/changelog/009-check-environment.sql file: db/changelog/009-check-environment.sql
- include: - include: