improved RBAC generators #26
@ -94,4 +94,17 @@ 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);
|
||||||
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
owner, admin, agent, tenant, guest, referrer
|
||||||
}
|
}
|
||||||
|
20
src/main/resources/db/changelog/007-table-columns.sql
Normal file
20
src/main/resources/db/changelog/007-table-columns.sql
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
--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; $$
|
||||||
|
--//
|
@ -164,7 +164,7 @@ end; $$;
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
create type RbacRoleType as enum ('owner', 'admin', 'agent', 'tenant', 'guest');
|
create type RbacRoleType as enum ('owner', 'admin', 'agent', 'tenant', 'guest', 'referrer');
|
||||||
|
|
||||||
create table RbacRole
|
create table RbacRole
|
||||||
(
|
(
|
||||||
@ -373,10 +373,12 @@ 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)
|
||||||
@ -395,7 +397,10 @@ 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 = (select uuid from RbacPermission where objectUuid = forObjectUuid and op = forOp and opTableName = forOpTableName);
|
permissionUuid := (
|
||||||
|
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')
|
||||||
@ -466,8 +471,44 @@ 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:--//
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
@ -634,7 +675,7 @@ begin
|
|||||||
perform assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole');
|
perform assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole');
|
||||||
|
|
||||||
if isGranted(subRoleId, superRoleId) then
|
if isGranted(subRoleId, superRoleId) then
|
||||||
raise exception '[400] Cyclic role grant detected between % and %', subRoleId, superRoleId;
|
call raiseDuplicateRoleGrantException(subRoleId, superRoleId);
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
insert
|
insert
|
||||||
@ -650,6 +691,11 @@ declare
|
|||||||
superRoleId uuid;
|
superRoleId uuid;
|
||||||
subRoleId uuid;
|
subRoleId uuid;
|
||||||
begin
|
begin
|
||||||
|
-- FIXME: maybe separate method grantRoleToRoleIfNotNull(...)?
|
||||||
hsh-michaelhoennig marked this conversation as resolved
Outdated
|
|||||||
|
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);
|
||||||
|
|
||||||
@ -657,7 +703,7 @@ begin
|
|||||||
perform assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole');
|
perform assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole');
|
||||||
|
|
||||||
if isGranted(subRoleId, superRoleId) then
|
if isGranted(subRoleId, superRoleId) then
|
||||||
raise exception '[400] Cyclic role grant detected between % and %', subRoleId, superRoleId;
|
call raiseDuplicateRoleGrantException(subRoleId, superRoleId);
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
insert
|
insert
|
||||||
@ -672,6 +718,7 @@ 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);
|
||||||
@ -680,7 +727,7 @@ begin
|
|||||||
perform assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole');
|
perform assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole');
|
||||||
|
|
||||||
if isGranted(subRoleId, superRoleId) then
|
if isGranted(subRoleId, superRoleId) then
|
||||||
raise exception '[400] Cyclic role grant detected between % and %', subRoleId, superRoleId;
|
call raiseDuplicateRoleGrantException(subRoleId, superRoleId);
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
insert
|
insert
|
||||||
@ -704,11 +751,39 @@ 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:--//
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
|
@ -56,14 +56,17 @@ 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 as roleuuidToAssume
|
select uuid
|
||||||
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 % not accessible for user %', roleName, currentSubjects();
|
raise exception '[403] role % does not exist or is not accessible for user %', roleName, currentUser();
|
||||||
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;
|
||||||
|
@ -31,13 +31,13 @@ create or replace function createRoleWithGrants(
|
|||||||
called on null input
|
called on null input
|
||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
declare
|
declare
|
||||||
roleUuid uuid;
|
roleUuid uuid;
|
||||||
subRoleDesc RbacRoleDescriptor;
|
subRoleDesc RbacRoleDescriptor;
|
||||||
superRoleDesc RbacRoleDescriptor;
|
superRoleDesc RbacRoleDescriptor;
|
||||||
subRoleUuid uuid;
|
subRoleUuid uuid;
|
||||||
superRoleUuid uuid;
|
superRoleUuid uuid;
|
||||||
userUuid uuid;
|
userUuid uuid;
|
||||||
grantedByRoleUuid uuid;
|
userGrantsByRoleUuid uuid;
|
||||||
begin
|
begin
|
||||||
roleUuid := createRole(roleDescriptor);
|
roleUuid := createRole(roleDescriptor);
|
||||||
|
|
||||||
@ -58,14 +58,15 @@ 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
|
||||||
grantedByRoleUuid := roleUuid;
|
userGrantsByRoleUuid := roleUuid; -- FIXME: or do we want to require an explicit userGrantsByRoleUuid?
|
||||||
hsh-michaelhoennig marked this conversation as resolved
Outdated
|
|||||||
else
|
else
|
||||||
grantedByRoleUuid := getRoleId(grantedByRole);
|
userGrantsByRoleUuid := getRoleId(grantedByRole);
|
||||||
end if;
|
end if;
|
||||||
foreach userUuid in array userUuids
|
foreach userUuid in array userUuids
|
||||||
loop
|
loop
|
||||||
call grantRoleToUserUnchecked(grantedByRoleUuid, roleUuid, userUuid);
|
call grantRoleToUserUnchecked(userGrantsByRoleUuid, roleUuid, userUuid);
|
||||||
end loop;
|
end loop;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
|
@ -73,6 +73,7 @@ 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
|
||||||
@ -81,6 +82,14 @@ 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; $$;
|
||||||
@ -148,12 +157,16 @@ 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)
|
create or replace procedure generateRbacRestrictedView(targetTable text, orderBy text, columnUpdates text = null, columnNames text = '*')
|
||||||
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.
|
||||||
@ -175,20 +188,21 @@ 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
|
||||||
language plpgsql as $f$
|
language plpgsql as $f$
|
||||||
declare
|
declare
|
||||||
newTargetRow %1$s;
|
newTargetRow %1$s;
|
||||||
begin
|
begin
|
||||||
insert
|
insert
|
||||||
into %1$s
|
into %1$s (%2$s)
|
||||||
values (new.*)
|
values (%3$s)
|
||||||
returning * into newTargetRow;
|
returning * into newTargetRow;
|
||||||
return newTargetRow;
|
return newTargetRow;
|
||||||
end; $f$;
|
end; $f$;
|
||||||
$sql$, targetTable);
|
$sql$, targetTable, columnNames, newColumns);
|
||||||
execute sql;
|
execute sql;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -118,9 +118,32 @@ 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:--//
|
||||||
|
@ -38,8 +38,6 @@ 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),
|
||||||
@ -91,41 +89,12 @@ create or replace procedure updateRbacRulesForTestDomain(
|
|||||||
NEW test_domain
|
NEW test_domain
|
||||||
)
|
)
|
||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
|
|
||||||
declare
|
|
||||||
oldPackage test_package;
|
|
||||||
newPackage test_package;
|
|
||||||
|
|
||||||
begin
|
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));
|
|
||||||
|
|
||||||
|
if NEW.packageUuid is distinct from OLD.packageUuid then
|
||||||
|
delete from rbacgrants g where g.grantedbytriggerof = OLD.uuid;
|
||||||
|
call buildRbacSystemForTestDomain(NEW);
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
|
||||||
end; $$;
|
end; $$;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -38,14 +38,10 @@ 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),
|
||||||
@ -73,13 +69,13 @@ begin
|
|||||||
hsOfficeRelationTenant(NEW),
|
hsOfficeRelationTenant(NEW),
|
||||||
permissions => array['SELECT'],
|
permissions => array['SELECT'],
|
||||||
incomingSuperRoles => array[
|
incomingSuperRoles => array[
|
||||||
hsOfficeRelationAgent(NEW),
|
|
||||||
hsOfficeContactAdmin(newContact),
|
hsOfficeContactAdmin(newContact),
|
||||||
|
hsOfficeRelationAgent(NEW),
|
||||||
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);
|
||||||
@ -118,48 +114,12 @@ create or replace procedure updateRbacRulesForHsOfficeRelation(
|
|||||||
NEW hs_office_relation
|
NEW hs_office_relation
|
||||||
)
|
)
|
||||||
language plpgsql as $$
|
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
|
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));
|
|
||||||
|
|
||||||
|
if NEW.contactUuid is distinct from OLD.contactUuid then
|
||||||
|
delete from rbacgrants g where g.grantedbytriggerof = OLD.uuid;
|
||||||
|
call buildRbacSystemForHsOfficeRelation(NEW);
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
|
||||||
end; $$;
|
end; $$;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -57,8 +57,8 @@ begin
|
|||||||
hsOfficeSepaMandateAgent(NEW),
|
hsOfficeSepaMandateAgent(NEW),
|
||||||
incomingSuperRoles => array[hsOfficeSepaMandateAdmin(NEW)],
|
incomingSuperRoles => array[hsOfficeSepaMandateAdmin(NEW)],
|
||||||
outgoingSubRoles => array[
|
outgoingSubRoles => array[
|
||||||
hsOfficeBankAccountReferrer(newBankAccount),
|
hsOfficeRelationAgent(newDebitorRel),
|
||||||
hsOfficeRelationAgent(newDebitorRel)]
|
hsOfficeBankAccountReferrer(newBankAccount)]
|
||||||
);
|
);
|
||||||
|
|
||||||
perform createRoleWithGrants(
|
perform createRoleWithGrants(
|
||||||
|
@ -41,7 +41,6 @@ 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
|
||||||
@ -53,7 +52,6 @@ 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));
|
||||||
@ -101,66 +99,12 @@ create or replace procedure updateRbacRulesForHsOfficeDebitor(
|
|||||||
NEW hs_office_debitor
|
NEW hs_office_debitor
|
||||||
)
|
)
|
||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
|
|
||||||
declare
|
|
||||||
oldPartnerRel hs_office_relation;
|
|
||||||
newPartnerRel hs_office_relation;
|
|
||||||
oldDebitorRel hs_office_relation;
|
|
||||||
newDebitorRel hs_office_relation;
|
|
||||||
oldRefundBankAccount hs_office_bankaccount;
|
|
||||||
newRefundBankAccount hs_office_bankaccount;
|
|
||||||
|
|
||||||
begin
|
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));
|
|
||||||
|
|
||||||
|
if NEW.refundBankAccountUuid is distinct from OLD.refundBankAccountUuid then
|
||||||
|
delete from rbacgrants g where g.grantedbytriggerof = OLD.uuid;
|
||||||
|
call buildRbacSystemForHsOfficeDebitor(NEW);
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
call leaveTriggerForObjectUuid(NEW.uuid);
|
|
||||||
end; $$;
|
end; $$;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -11,6 +11,8 @@ 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:
|
||||||
|
Loading…
Reference in New Issue
Block a user
anschauen