RBAC Diagram+PostgreSQL Generator #21
@ -74,7 +74,7 @@ For restricted DB-users, which are used by the backend, access to rows is filter
|
|||||||
FOR SELECT
|
FOR SELECT
|
||||||
TO restricted
|
TO restricted
|
||||||
USING (
|
USING (
|
||||||
isPermissionGrantedToSubject(findPermissionId('customer', id, 'view'), currentUserUuid())
|
isPermissionGrantedToSubject(findEffectivePermissionId('customer', id, 'view'), currentUserUuid())
|
||||||
);
|
);
|
||||||
|
|
||||||
SET SESSION AUTHORIZATION restricted;
|
SET SESSION AUTHORIZATION restricted;
|
||||||
@ -101,7 +101,7 @@ We are bound to PostgreSQL, including integration tests and testing the RBAC sys
|
|||||||
CREATE OR REPLACE RULE "_RETURN" AS
|
CREATE OR REPLACE RULE "_RETURN" AS
|
||||||
ON SELECT TO cust_view
|
ON SELECT TO cust_view
|
||||||
DO INSTEAD
|
DO INSTEAD
|
||||||
SELECT * FROM customer WHERE isPermissionGrantedToSubject(findPermissionId('customer', id, 'view'), currentUserUuid());
|
SELECT * FROM customer WHERE isPermissionGrantedToSubject(findEffectivePermissionId('customer', id, 'view'), currentUserUuid());
|
||||||
|
|
||||||
SET SESSION AUTHORIZATION restricted;
|
SET SESSION AUTHORIZATION restricted;
|
||||||
SET hsadminng.currentUser TO 'alex@example.com';
|
SET hsadminng.currentUser TO 'alex@example.com';
|
||||||
|
@ -19,11 +19,11 @@ select *
|
|||||||
FROM queryAllPermissionsOfSubjectId(findRbacUser('rosa@example.com'));
|
FROM queryAllPermissionsOfSubjectId(findRbacUser('rosa@example.com'));
|
||||||
|
|
||||||
select *
|
select *
|
||||||
FROM queryAllRbacUsersWithPermissionsFor(findPermissionId('customer',
|
FROM queryAllRbacUsersWithPermissionsFor(findEffectivePermissionId('customer',
|
||||||
(SELECT uuid FROM RbacObject WHERE objectTable = 'customer' LIMIT 1),
|
(SELECT uuid FROM RbacObject WHERE objectTable = 'customer' LIMIT 1),
|
||||||
'add-package'));
|
'add-package'));
|
||||||
select *
|
select *
|
||||||
FROM queryAllRbacUsersWithPermissionsFor(findPermissionId('package',
|
FROM queryAllRbacUsersWithPermissionsFor(findEffectivePermissionId('package',
|
||||||
(SELECT uuid FROM RbacObject WHERE objectTable = 'package' LIMIT 1),
|
(SELECT uuid FROM RbacObject WHERE objectTable = 'package' LIMIT 1),
|
||||||
'delete'));
|
'delete'));
|
||||||
|
|
||||||
@ -34,12 +34,12 @@ $$
|
|||||||
result bool;
|
result bool;
|
||||||
BEGIN
|
BEGIN
|
||||||
userId = findRbacUser('superuser-alex@hostsharing.net');
|
userId = findRbacUser('superuser-alex@hostsharing.net');
|
||||||
result = (SELECT * FROM isPermissionGrantedToSubject(findPermissionId('package', 94928, 'add-package'), userId));
|
result = (SELECT * FROM isPermissionGrantedToSubject(findEffectivePermissionId('package', 94928, 'add-package'), userId));
|
||||||
IF (result) THEN
|
IF (result) THEN
|
||||||
RAISE EXCEPTION 'expected permission NOT to be granted, but it is';
|
RAISE EXCEPTION 'expected permission NOT to be granted, but it is';
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
result = (SELECT * FROM isPermissionGrantedToSubject(findPermissionId('package', 94928, 'view'), userId));
|
result = (SELECT * FROM isPermissionGrantedToSubject(findEffectivePermissionId('package', 94928, 'view'), userId));
|
||||||
IF (NOT result) THEN
|
IF (NOT result) THEN
|
||||||
RAISE EXCEPTION 'expected permission to be granted, but it is NOT';
|
RAISE EXCEPTION 'expected permission to be granted, but it is NOT';
|
||||||
end if;
|
end if;
|
||||||
|
@ -20,7 +20,7 @@ CREATE POLICY customer_policy ON customer
|
|||||||
TO restricted
|
TO restricted
|
||||||
USING (
|
USING (
|
||||||
-- id=1000
|
-- id=1000
|
||||||
isPermissionGrantedToSubject(findPermissionId('test_customer', id, 'view'), currentUserUuid())
|
isPermissionGrantedToSubject(findEffectivePermissionId('test_customer', id, 'view'), currentUserUuid())
|
||||||
);
|
);
|
||||||
|
|
||||||
SET SESSION AUTHORIZATION restricted;
|
SET SESSION AUTHORIZATION restricted;
|
||||||
@ -35,7 +35,7 @@ SELECT * FROM customer;
|
|||||||
CREATE OR REPLACE RULE "_RETURN" AS
|
CREATE OR REPLACE RULE "_RETURN" AS
|
||||||
ON SELECT TO cust_view
|
ON SELECT TO cust_view
|
||||||
DO INSTEAD
|
DO INSTEAD
|
||||||
SELECT * FROM customer WHERE isPermissionGrantedToSubject(findPermissionId('test_customer', id, 'view'), currentUserUuid());
|
SELECT * FROM customer WHERE isPermissionGrantedToSubject(findEffectivePermissionId('test_customer', id, 'view'), currentUserUuid());
|
||||||
SELECT * from cust_view LIMIT 10;
|
SELECT * from cust_view LIMIT 10;
|
||||||
|
|
||||||
select queryAllPermissionsOfSubjectId(findRbacUser('superuser-alex@hostsharing.net'));
|
select queryAllPermissionsOfSubjectId(findRbacUser('superuser-alex@hostsharing.net'));
|
||||||
|
@ -438,9 +438,24 @@ create or replace function findPermissionId(forObjectUuid uuid, forOp RbacOp)
|
|||||||
select uuid
|
select uuid
|
||||||
from RbacPermission p
|
from RbacPermission p
|
||||||
where p.objectUuid = forObjectUuid
|
where p.objectUuid = forObjectUuid
|
||||||
and p.op in ('*', forOp)
|
and p.op = forOp
|
||||||
$$;
|
$$;
|
||||||
|
|
||||||
|
create or replace function findEffectivePermissionId(forObjectUuid uuid, forOp RbacOp)
|
||||||
|
returns uuid
|
||||||
|
returns null on null input
|
||||||
|
stable -- leakproof
|
||||||
|
language plpgsql as $$
|
||||||
|
declare
|
||||||
|
permissionId uuid;
|
||||||
|
begin
|
||||||
|
permissionId := findPermissionId(forObjectUuid, forOp);
|
||||||
|
if permissionId is null and forOp <> '*' then
|
||||||
|
permissionId := findPermissionId(forObjectUuid, '*');
|
||||||
|
end if;
|
||||||
|
return permissionId;
|
||||||
|
end $$;
|
||||||
|
|
||||||
--//
|
--//
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
@ -452,12 +467,13 @@ $$;
|
|||||||
create table RbacGrants
|
create table RbacGrants
|
||||||
(
|
(
|
||||||
uuid uuid primary key default uuid_generate_v4(),
|
uuid uuid primary key default uuid_generate_v4(),
|
||||||
|
grantedByTriggerOf uuid references RbacObject (uuid) on delete cascade initially deferred ,
|
||||||
grantedByRoleUuid uuid references RbacRole (uuid),
|
grantedByRoleUuid uuid references RbacRole (uuid),
|
||||||
ascendantUuid uuid references RbacReference (uuid),
|
ascendantUuid uuid references RbacReference (uuid),
|
||||||
descendantUuid uuid references RbacReference (uuid),
|
descendantUuid uuid references RbacReference (uuid),
|
||||||
assumed boolean not null default true, -- auto assumed (true) vs. needs assumeRoles (false)
|
assumed boolean not null default true, -- auto assumed (true) vs. needs assumeRoles (false)
|
||||||
unique (ascendantUuid, descendantUuid)
|
unique (ascendantUuid, descendantUuid),
|
||||||
);
|
constraint rbacGrant_createdBy check ( grantedByRoleUuid is null or grantedByTriggerOf is null) );
|
||||||
create index on RbacGrants (ascendantUuid);
|
create index on RbacGrants (ascendantUuid);
|
||||||
create index on RbacGrants (descendantUuid);
|
create index on RbacGrants (descendantUuid);
|
||||||
|
|
||||||
@ -561,8 +577,8 @@ begin
|
|||||||
perform assertReferenceType('permissionId (descendant)', permissionIds[i], 'RbacPermission');
|
perform assertReferenceType('permissionId (descendant)', permissionIds[i], 'RbacPermission');
|
||||||
|
|
||||||
insert
|
insert
|
||||||
into RbacGrants (ascendantUuid, descendantUuid, assumed)
|
into RbacGrants (grantedByTriggerOf, ascendantUuid, descendantUuid, assumed)
|
||||||
values (roleUuid, permissionIds[i], true)
|
values (currentTriggerObjectUuid(), roleUuid, permissionIds[i], true)
|
||||||
on conflict do nothing; -- allow granting multiple times
|
on conflict do nothing; -- allow granting multiple times
|
||||||
end loop;
|
end loop;
|
||||||
end;
|
end;
|
||||||
@ -579,8 +595,8 @@ begin
|
|||||||
end if;
|
end if;
|
||||||
|
|
||||||
insert
|
insert
|
||||||
into RbacGrants (ascendantuuid, descendantUuid, assumed)
|
into RbacGrants (grantedByTriggerOf, ascendantuuid, descendantUuid, assumed)
|
||||||
values (superRoleId, subRoleId, doAssume)
|
values (currentTriggerObjectUuid(), superRoleId, subRoleId, doAssume)
|
||||||
on conflict do nothing; -- allow granting multiple times
|
on conflict do nothing; -- allow granting multiple times
|
||||||
end; $$;
|
end; $$;
|
||||||
|
|
||||||
@ -602,8 +618,8 @@ begin
|
|||||||
end if;
|
end if;
|
||||||
|
|
||||||
insert
|
insert
|
||||||
into RbacGrants (ascendantuuid, descendantUuid, assumed)
|
into RbacGrants (grantedByTriggerOf, ascendantuuid, descendantUuid, assumed)
|
||||||
values (superRoleId, subRoleId, doAssume)
|
values (currentTriggerObjectUuid(), superRoleId, subRoleId, doAssume)
|
||||||
on conflict do nothing; -- allow granting multiple times
|
on conflict do nothing; -- allow granting multiple times
|
||||||
end; $$;
|
end; $$;
|
||||||
|
|
||||||
@ -625,8 +641,8 @@ begin
|
|||||||
end if;
|
end if;
|
||||||
|
|
||||||
insert
|
insert
|
||||||
into RbacGrants (ascendantuuid, descendantUuid, assumed)
|
into RbacGrants (grantedByTriggerOf, ascendantuuid, descendantUuid, assumed)
|
||||||
values (superRoleId, subRoleId, doAssume)
|
values (currentTriggerObjectUuid(), superRoleId, subRoleId, doAssume)
|
||||||
on conflict do nothing; -- allow granting multiple times
|
on conflict do nothing; -- allow granting multiple times
|
||||||
end; $$;
|
end; $$;
|
||||||
|
|
||||||
|
@ -56,6 +56,7 @@ drop view if exists rbacgrants_ev;
|
|||||||
create or replace view rbacgrants_ev as
|
create or replace view rbacgrants_ev as
|
||||||
-- @formatter:off
|
-- @formatter:off
|
||||||
select x.grantUuid as uuid,
|
select x.grantUuid as uuid,
|
||||||
|
x.grantedByTriggerOf as grantedByTriggerOf,
|
||||||
go.objectTable || '#' || findIdNameByObjectUuid(go.objectTable, go.uuid) || '.' || r.roletype as grantedByRoleIdName,
|
go.objectTable || '#' || findIdNameByObjectUuid(go.objectTable, go.uuid) || '.' || r.roletype as grantedByRoleIdName,
|
||||||
x.ascendingIdName as ascendantIdName,
|
x.ascendingIdName as ascendantIdName,
|
||||||
x.descendingIdName as descendantIdName,
|
x.descendingIdName as descendantIdName,
|
||||||
@ -65,6 +66,7 @@ create or replace view rbacgrants_ev as
|
|||||||
x.assumed
|
x.assumed
|
||||||
from (
|
from (
|
||||||
select g.uuid as grantUuid,
|
select g.uuid as grantUuid,
|
||||||
|
g.grantedbytriggerof as grantedbytriggerof,
|
||||||
g.grantedbyroleuuid, g.ascendantuuid, g.descendantuuid, g.assumed,
|
g.grantedbyroleuuid, g.ascendantuuid, g.descendantuuid, g.assumed,
|
||||||
|
|
||||||
coalesce(
|
coalesce(
|
||||||
|
61
src/main/resources/db/changelog/056-rbac-trigger-context.sql
Normal file
61
src/main/resources/db/changelog/056-rbac-trigger-context.sql
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
--liquibase formatted sql
|
||||||
|
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
--changeset rbac-trigger-context-ENTER:1 endDelimiter:--//
|
||||||
|
-- ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
create or replace procedure enterTriggerForObjectUuid(currentObjectUuid uuid)
|
||||||
|
language plpgsql as $$
|
||||||
|
declare
|
||||||
|
existingObjectUuid text;
|
||||||
|
begin
|
||||||
|
existingObjectUuid = current_setting('hsadminng.currentObjectUuid', true);
|
||||||
|
if (existingObjectUuid > '' ) then
|
||||||
|
raise exception '[500] currentObjectUuid already defined, already in trigger of "%"', existingObjectUuid;
|
||||||
|
end if;
|
||||||
|
execute format('set local hsadminng.currentObjectUuid to %L', currentObjectUuid);
|
||||||
|
end; $$;
|
||||||
|
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
--changeset rbac-trigger-context-CURRENT-ID:1 endDelimiter:--//
|
||||||
|
-- ----------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
Returns the uuid of the object uuid whose trigger is currently executed as set via `enterTriggerForObjectUuid(...)`.
|
||||||
|
*/
|
||||||
|
|
||||||
|
create or replace function currentTriggerObjectUuid()
|
||||||
|
returns uuid
|
||||||
|
stable -- leakproof
|
||||||
|
language plpgsql as $$
|
||||||
|
declare
|
||||||
|
currentObjectUuid uuid;
|
||||||
|
begin
|
||||||
|
begin
|
||||||
|
currentObjectUuid = current_setting('hsadminng.currentObjectUuid')::uuid;
|
||||||
|
return currentObjectUuid;
|
||||||
|
exception
|
||||||
|
when others then
|
||||||
|
return null::uuid;
|
||||||
|
end;
|
||||||
|
end; $$;
|
||||||
|
--//
|
||||||
|
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
--changeset rbac-trigger-context-LEAVE:1 endDelimiter:--//
|
||||||
|
-- ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
create or replace procedure leaveTriggerForObjectUuid(currentObjectUuid uuid)
|
||||||
|
language plpgsql as $$
|
||||||
|
declare
|
||||||
|
existingObjectUuid uuid;
|
||||||
|
begin
|
||||||
|
existingObjectUuid = current_setting('hsadminng.currentObjectUuid', true);
|
||||||
|
if ( existingObjectUuid <> currentObjectUuid ) then
|
||||||
|
raise exception '[500] currentObjectUuid does not match: "%"', existingObjectUuid;
|
||||||
|
end if;
|
||||||
|
execute format('reset hsadminng.currentObjectUuid');
|
||||||
|
end; $$;
|
||||||
|
|
@ -34,6 +34,8 @@ begin
|
|||||||
raise exception 'invalid usage of TRIGGER AFTER INSERT';
|
raise exception 'invalid usage of TRIGGER AFTER INSERT';
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
|
call enterTriggerForObjectUuid(NEW.uuid);
|
||||||
|
|
||||||
-- the owner role with full access for Hostsharing administrators
|
-- the owner role with full access for Hostsharing administrators
|
||||||
testCustomerOwnerUuid = createRoleWithGrants(
|
testCustomerOwnerUuid = createRoleWithGrants(
|
||||||
testCustomerOwner(NEW),
|
testCustomerOwner(NEW),
|
||||||
@ -59,6 +61,7 @@ begin
|
|||||||
permissions => array['view']
|
permissions => array['view']
|
||||||
);
|
);
|
||||||
|
|
||||||
|
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||||
return NEW;
|
return NEW;
|
||||||
end; $$;
|
end; $$;
|
||||||
|
|
||||||
|
@ -26,13 +26,13 @@ create or replace function createRbacRolesForTestPackage()
|
|||||||
strict as $$
|
strict as $$
|
||||||
declare
|
declare
|
||||||
parentCustomer test_customer;
|
parentCustomer test_customer;
|
||||||
packageOwnerRoleUuid uuid;
|
|
||||||
packageAdminRoleUuid uuid;
|
|
||||||
begin
|
begin
|
||||||
if TG_OP <> 'INSERT' then
|
if TG_OP <> 'INSERT' then
|
||||||
raise exception 'invalid usage of TRIGGER AFTER INSERT';
|
raise exception 'invalid usage of TRIGGER AFTER INSERT';
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
|
call enterTriggerForObjectUuid(NEW.uuid);
|
||||||
|
|
||||||
select * from test_customer as c where c.uuid = NEW.customerUuid into parentCustomer;
|
select * from test_customer as c where c.uuid = NEW.customerUuid into parentCustomer;
|
||||||
|
|
||||||
-- an owner role is created and assigned to the customer's admin role
|
-- an owner role is created and assigned to the customer's admin role
|
||||||
@ -57,6 +57,7 @@ begin
|
|||||||
outgoingSubRoles => array[testCustomerTenant(parentCustomer)]
|
outgoingSubRoles => array[testCustomerTenant(parentCustomer)]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||||
return NEW;
|
return NEW;
|
||||||
end; $$;
|
end; $$;
|
||||||
|
|
||||||
|
@ -53,6 +53,8 @@ begin
|
|||||||
raise exception 'invalid usage of TRIGGER AFTER INSERT';
|
raise exception 'invalid usage of TRIGGER AFTER INSERT';
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
|
call enterTriggerForObjectUuid(NEW.uuid);
|
||||||
|
|
||||||
select * from test_package where uuid = NEW.packageUuid into parentPackage;
|
select * from test_package where uuid = NEW.packageUuid into parentPackage;
|
||||||
|
|
||||||
-- an owner role is created and assigned to the package's admin group
|
-- an owner role is created and assigned to the package's admin group
|
||||||
@ -72,6 +74,7 @@ begin
|
|||||||
|
|
||||||
-- a tenent role is only created on demand
|
-- a tenent role is only created on demand
|
||||||
|
|
||||||
|
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||||
return NEW;
|
return NEW;
|
||||||
end; $$;
|
end; $$;
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ declare
|
|||||||
oldContact hs_office_contact;
|
oldContact hs_office_contact;
|
||||||
newContact hs_office_contact;
|
newContact hs_office_contact;
|
||||||
begin
|
begin
|
||||||
|
call enterTriggerForObjectUuid(NEW.uuid);
|
||||||
|
|
||||||
hsOfficeRelationshipTenant := hsOfficeRelationshipTenant(NEW);
|
hsOfficeRelationshipTenant := hsOfficeRelationshipTenant(NEW);
|
||||||
|
|
||||||
@ -96,6 +97,7 @@ begin
|
|||||||
raise exception 'invalid usage of TRIGGER';
|
raise exception 'invalid usage of TRIGGER';
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
|
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||||
return NEW;
|
return NEW;
|
||||||
end; $$;
|
end; $$;
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ declare
|
|||||||
oldContact hs_office_contact;
|
oldContact hs_office_contact;
|
||||||
newContact hs_office_contact;
|
newContact hs_office_contact;
|
||||||
begin
|
begin
|
||||||
|
call enterTriggerForObjectUuid(NEW.uuid);
|
||||||
|
|
||||||
select * from hs_office_relationship as r where r.uuid = NEW.partnerroleuuid into newPartnerRole;
|
select * from hs_office_relationship as r where r.uuid = NEW.partnerroleuuid into newPartnerRole;
|
||||||
select * from hs_office_person as p where p.uuid = NEW.personUuid into newPerson;
|
select * from hs_office_person as p where p.uuid = NEW.personUuid into newPerson;
|
||||||
@ -159,6 +160,7 @@ begin
|
|||||||
raise exception 'invalid usage of TRIGGER';
|
raise exception 'invalid usage of TRIGGER';
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
|
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||||
return NEW;
|
return NEW;
|
||||||
end; $$;
|
end; $$;
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ declare
|
|||||||
newHsOfficeDebitor hs_office_debitor;
|
newHsOfficeDebitor hs_office_debitor;
|
||||||
newHsOfficeBankAccount hs_office_bankAccount;
|
newHsOfficeBankAccount hs_office_bankAccount;
|
||||||
begin
|
begin
|
||||||
|
call enterTriggerForObjectUuid(NEW.uuid);
|
||||||
|
|
||||||
select * from hs_office_debitor as p where p.uuid = NEW.debitorUuid into newHsOfficeDebitor;
|
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 as c where c.uuid = NEW.bankAccountUuid into newHsOfficeBankAccount;
|
||||||
@ -75,6 +76,7 @@ begin
|
|||||||
raise exception 'invalid usage of TRIGGER';
|
raise exception 'invalid usage of TRIGGER';
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
|
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||||
return NEW;
|
return NEW;
|
||||||
end; $$;
|
end; $$;
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ declare
|
|||||||
newBankAccount hs_office_bankaccount;
|
newBankAccount hs_office_bankaccount;
|
||||||
oldBankAccount hs_office_bankaccount;
|
oldBankAccount hs_office_bankaccount;
|
||||||
begin
|
begin
|
||||||
|
call enterTriggerForObjectUuid(NEW.uuid);
|
||||||
|
|
||||||
hsOfficeDebitorTenant := hsOfficeDebitorTenant(NEW);
|
hsOfficeDebitorTenant := hsOfficeDebitorTenant(NEW);
|
||||||
|
|
||||||
@ -145,6 +146,7 @@ begin
|
|||||||
raise exception 'invalid usage of TRIGGER';
|
raise exception 'invalid usage of TRIGGER';
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
|
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||||
return NEW;
|
return NEW;
|
||||||
end; $$;
|
end; $$;
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ declare
|
|||||||
newHsOfficePartner hs_office_partner;
|
newHsOfficePartner hs_office_partner;
|
||||||
newHsOfficeDebitor hs_office_debitor;
|
newHsOfficeDebitor hs_office_debitor;
|
||||||
begin
|
begin
|
||||||
|
call enterTriggerForObjectUuid(NEW.uuid);
|
||||||
|
|
||||||
select * from hs_office_partner as p where p.uuid = NEW.partnerUuid into newHsOfficePartner;
|
select * from hs_office_partner as p where p.uuid = NEW.partnerUuid into newHsOfficePartner;
|
||||||
select * from hs_office_debitor as c where c.uuid = NEW.mainDebitorUuid into newHsOfficeDebitor;
|
select * from hs_office_debitor as c where c.uuid = NEW.mainDebitorUuid into newHsOfficeDebitor;
|
||||||
@ -74,6 +75,7 @@ begin
|
|||||||
raise exception 'invalid usage of TRIGGER';
|
raise exception 'invalid usage of TRIGGER';
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
|
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||||
return NEW;
|
return NEW;
|
||||||
end; $$;
|
end; $$;
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ create or replace function hsOfficeCoopSharesTransactionRbacRolesTrigger()
|
|||||||
declare
|
declare
|
||||||
newHsOfficeMembership hs_office_membership;
|
newHsOfficeMembership hs_office_membership;
|
||||||
begin
|
begin
|
||||||
|
call enterTriggerForObjectUuid(NEW.uuid);
|
||||||
|
|
||||||
select * from hs_office_membership as p where p.uuid = NEW.membershipUuid into newHsOfficeMembership;
|
select * from hs_office_membership as p where p.uuid = NEW.membershipUuid into newHsOfficeMembership;
|
||||||
|
|
||||||
@ -49,6 +50,7 @@ begin
|
|||||||
raise exception 'invalid usage of TRIGGER';
|
raise exception 'invalid usage of TRIGGER';
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
|
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||||
return NEW;
|
return NEW;
|
||||||
end; $$;
|
end; $$;
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ create or replace function hsOfficeCoopAssetsTransactionRbacRolesTrigger()
|
|||||||
declare
|
declare
|
||||||
newHsOfficeMembership hs_office_membership;
|
newHsOfficeMembership hs_office_membership;
|
||||||
begin
|
begin
|
||||||
|
call enterTriggerForObjectUuid(NEW.uuid);
|
||||||
|
|
||||||
select * from hs_office_membership as p where p.uuid = NEW.membershipUuid into newHsOfficeMembership;
|
select * from hs_office_membership as p where p.uuid = NEW.membershipUuid into newHsOfficeMembership;
|
||||||
|
|
||||||
@ -49,6 +50,7 @@ begin
|
|||||||
raise exception 'invalid usage of TRIGGER';
|
raise exception 'invalid usage of TRIGGER';
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
|
call leaveTriggerForObjectUuid(NEW.uuid);
|
||||||
return NEW;
|
return NEW;
|
||||||
end; $$;
|
end; $$;
|
||||||
|
|
||||||
|
@ -25,6 +25,8 @@ databaseChangeLog:
|
|||||||
file: db/changelog/054-rbac-context.sql
|
file: db/changelog/054-rbac-context.sql
|
||||||
- include:
|
- include:
|
||||||
file: db/changelog/055-rbac-views.sql
|
file: db/changelog/055-rbac-views.sql
|
||||||
|
- include:
|
||||||
|
file: db/changelog/056-rbac-trigger-context.sql
|
||||||
- include:
|
- include:
|
||||||
file: db/changelog/057-rbac-role-builder.sql
|
file: db/changelog/057-rbac-role-builder.sql
|
||||||
- include:
|
- include:
|
||||||
|
@ -278,19 +278,18 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
2000002=rel(relAnchor='LP Hostsharing eG', relType='PARTNER', relHolder='?? Test PS', contact='Petra Schmidt , Test PS'),
|
2000002=rel(relAnchor='LP Hostsharing eG', relType='PARTNER', relHolder='?? Test PS', contact='Petra Schmidt , Test PS'),
|
||||||
2000003=rel(relAnchor='LP Hostsharing eG', relType='PARTNER', relHolder='null null, null'),
|
2000003=rel(relAnchor='LP Hostsharing eG', relType='PARTNER', relHolder='null null, null'),
|
||||||
2000004=rel(relAnchor='NP Mellies, Michael', relType='OPERATIONS', relHolder='NP Mellies, Michael', contact='Herr Michael Mellies '),
|
2000004=rel(relAnchor='NP Mellies, Michael', relType='OPERATIONS', relHolder='NP Mellies, Michael', contact='Herr Michael Mellies '),
|
||||||
2000005=rel(relAnchor='LP JM GmbH', relType='EX_PARTNER', relHolder='LP JM e.K.', contact='JM e.K.'),
|
2000005=rel(relAnchor='NP Mellies, Michael', relType='REPRESENTATIVE', relHolder='NP Mellies, Michael', contact='Herr Michael Mellies '),
|
||||||
2000006=rel(relAnchor='LP JM GmbH', relType='OPERATIONS', relHolder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
|
2000006=rel(relAnchor='LP JM GmbH', relType='EX_PARTNER', relHolder='LP JM e.K.', contact='JM e.K.'),
|
||||||
2000007=rel(relAnchor='LP JM GmbH', relType='VIP_CONTACT', relHolder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
|
2000007=rel(relAnchor='LP JM GmbH', relType='OPERATIONS', relHolder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
|
||||||
2000008=rel(relAnchor='LP JM GmbH', relType='SUBSCRIBER', relMark='operations-announce', relHolder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
|
2000008=rel(relAnchor='LP JM GmbH', relType='VIP_CONTACT', relHolder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
|
||||||
2000009=rel(relAnchor='LP JM GmbH', relType='REPRESENTATIVE', relHolder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
|
2000009=rel(relAnchor='LP JM GmbH', relType='SUBSCRIBER', relMark='operations-announce', relHolder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
|
||||||
2000010=rel(relAnchor='LP JM GmbH', relType='SUBSCRIBER', relMark='members-announce', relHolder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
|
2000010=rel(relAnchor='LP JM GmbH', relType='REPRESENTATIVE', relHolder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
|
||||||
2000011=rel(relAnchor='LP JM GmbH', relType='SUBSCRIBER', relMark='customers-announce', relHolder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
|
2000011=rel(relAnchor='LP JM GmbH', relType='SUBSCRIBER', relMark='members-announce', relHolder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
|
||||||
2000012=rel(relAnchor='LP JM GmbH', relType='VIP_CONTACT', relHolder='LP JM GmbH', contact='Frau Tammy Meyer-VIP , JM GmbH'),
|
2000012=rel(relAnchor='LP JM GmbH', relType='SUBSCRIBER', relMark='customers-announce', relHolder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
|
||||||
2000013=rel(relAnchor='?? Test PS', relType='OPERATIONS', relHolder='?? Test PS', contact='Petra Schmidt , Test PS'),
|
2000013=rel(relAnchor='LP JM GmbH', relType='VIP_CONTACT', relHolder='LP JM GmbH', contact='Frau Tammy Meyer-VIP , JM GmbH'),
|
||||||
2000014=rel(relAnchor='?? Test PS', relType='REPRESENTATIVE', relHolder='?? Test PS', contact='Petra Schmidt , Test PS'),
|
2000014=rel(relAnchor='?? Test PS', relType='OPERATIONS', relHolder='?? Test PS', contact='Petra Schmidt , Test PS'),
|
||||||
2000015=rel(relAnchor='NP Mellies, Michael', relType='SUBSCRIBER', relMark='operations-announce', relHolder='NP Fanninga, Frauke', contact='Frau Frauke Fanninga '),
|
2000015=rel(relAnchor='?? Test PS', relType='REPRESENTATIVE', relHolder='?? Test PS', contact='Petra Schmidt , Test PS'),
|
||||||
2000016=rel(relAnchor='NP Mellies, Michael', relType='REPRESENTATIVE', relHolder='NP Mellies, Michael', contact='Herr Michael Mellies '),
|
2000016=rel(relAnchor='NP Mellies, Michael', relType='SUBSCRIBER', relMark='operations-announce', relHolder='NP Fanninga, Frauke', contact='Frau Frauke Fanninga ')
|
||||||
2000017=rel(relAnchor='null null, null', relType='REPRESENTATIVE', relHolder='null null, null')
|
|
||||||
}
|
}
|
||||||
""");
|
""");
|
||||||
}
|
}
|
||||||
@ -412,7 +411,7 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
idsToRemove.add(id);
|
idsToRemove.add(id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
assertThat(idsToRemove.size()).isEqualTo(2); // only from partner #99 (partner+contractual roles)
|
assertThat(idsToRemove.size()).isEqualTo(1); // only from partner #99 (partner+contractual roles)
|
||||||
idsToRemove.forEach(id -> relationships.remove(id));
|
idsToRemove.forEach(id -> relationships.remove(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -421,7 +420,7 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
void removeEmptyPartners() {
|
void removeEmptyPartners() {
|
||||||
assumeThatWeAreImportingControlledTestData();
|
assumeThatWeAreImportingControlledTestData();
|
||||||
|
|
||||||
// avoid a error when persisting the deliberetely invalid partner entry #99
|
// avoid a error when persisting the deliberately invalid partner entry #99
|
||||||
final var idsToRemove = new HashSet<Integer>();
|
final var idsToRemove = new HashSet<Integer>();
|
||||||
partners.forEach( (id, r) -> {
|
partners.forEach( (id, r) -> {
|
||||||
// such a record
|
// such a record
|
||||||
@ -439,7 +438,7 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
void removeEmptyDebitors() {
|
void removeEmptyDebitors() {
|
||||||
assumeThatWeAreImportingControlledTestData();
|
assumeThatWeAreImportingControlledTestData();
|
||||||
|
|
||||||
// avoid a error when persisting the deliberetely invalid partner entry #99
|
// avoid a error when persisting the deliberately invalid partner entry #99
|
||||||
final var idsToRemove = new HashSet<Integer>();
|
final var idsToRemove = new HashSet<Integer>();
|
||||||
debitors.forEach( (id, r) -> {
|
debitors.forEach( (id, r) -> {
|
||||||
// such a record
|
// such a record
|
||||||
@ -881,11 +880,9 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
if (relationships.values().stream()
|
if (relationships.values().stream()
|
||||||
.filter(rel -> rel.getRelAnchor() == partnerPerson && rel.getRelType() == HsOfficeRelationshipType.REPRESENTATIVE)
|
.filter(rel -> rel.getRelAnchor() == partnerPerson && rel.getRelType() == HsOfficeRelationshipType.REPRESENTATIVE)
|
||||||
.findFirst().isEmpty()) {
|
.findFirst().isEmpty()) {
|
||||||
//addRelationship(partnerPerson, partnerPerson, partner.getContact(), HsOfficeRelationshipType.REPRESENTATIVE);
|
|
||||||
contractualMissing.add(partner.getPartnerNumber());
|
contractualMissing.add(partner.getPartnerNumber());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
assertThat(contractualMissing).isEmpty(); // comment out if we do want to allow missing contractual contact
|
|
||||||
}
|
}
|
||||||
private static boolean containsRole(final Record rec, final String role) {
|
private static boolean containsRole(final Record rec, final String role) {
|
||||||
final var roles = rec.getString("roles");
|
final var roles = rec.getString("roles");
|
||||||
|
@ -342,10 +342,6 @@ class HsOfficeRelationshipRepositoryIntegrationTest extends ContextBasedTestWith
|
|||||||
final var initialGrantNames = Array.from(distinctGrantDisplaysOf(rawGrantRepo.findAll()));
|
final var initialGrantNames = Array.from(distinctGrantDisplaysOf(rawGrantRepo.findAll()));
|
||||||
final var givenRelationship = givenSomeTemporaryRelationshipBessler(
|
final var givenRelationship = givenSomeTemporaryRelationshipBessler(
|
||||||
"Anita", "twelfth");
|
"Anita", "twelfth");
|
||||||
assertThat(distinctRoleNamesOf(rawRoleRepo.findAll()).size()).as("unexpected number of roles created")
|
|
||||||
.isEqualTo(initialRoleNames.length + 3);
|
|
||||||
assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll()).size()).as("unexpected number of grants created")
|
|
||||||
.isEqualTo(initialGrantNames.length + 13);
|
|
||||||
|
|
||||||
// when
|
// when
|
||||||
final var result = jpaAttempt.transacted(() -> {
|
final var result = jpaAttempt.transacted(() -> {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
contact_id; bp_id; salut; first_name; last_name; title; firma; co; street; zipcode;city; country; phone_private; phone_office; phone_mobile; fax; email; roles
|
contact_id; bp_id; salut; first_name; last_name; title; firma; co; street; zipcode;city; country; phone_private; phone_office; phone_mobile; fax; email; roles
|
||||||
|
|
||||||
# eine natürliche Person, implizites contractual
|
# eine natürliche Person, implizites contractual
|
||||||
1101; 17; Herr; Michael; Mellies; ; ; ; Kleine Freiheit 50; 26524; Hage; DE; ; +49 4931 123456; +49 1522 123456;; mih@example.org; partner,billing,operation
|
1101; 17; Herr; Michael; Mellies; ; ; ; Kleine Freiheit 50; 26524; Hage; DE; ; +49 4931 123456; +49 1522 123456;; mih@example.org; partner,contractual,billing,operation
|
||||||
|
|
||||||
# eine juristische Person mit drei separaten Ansprechpartnern, vip-contact und ex-partner
|
# eine juristische Person mit drei separaten Ansprechpartnern, vip-contact und ex-partner
|
||||||
1200; 20;; ; ; ; JM e.K.;; Wiesenweg 15; 12335; Berlin; DE; +49 30 6666666; +49 30 5555555; ; +49 30 6666666; jm-ex-partner@example.org; ex-partner
|
1200; 20;; ; ; ; JM e.K.;; Wiesenweg 15; 12335; Berlin; DE; +49 30 6666666; +49 30 5555555; ; +49 30 6666666; jm-ex-partner@example.org; ex-partner
|
||||||
|
|
Loading…
Reference in New Issue
Block a user