1
0

RBAC Diagram+PostgreSQL Generator and view->SELECT etc. refactoring (#21)

Co-authored-by: Michael Hoennig <michael@hoennig.de>
Reviewed-on: https://dev.hostsharing.net/hostsharing/hs.hsadmin.ng/pulls/21
Reviewed-by: Timotheus Pokorra <timotheus.pokorra@hostsharing.net>
This commit is contained in:
Michael Hoennig
2024-03-11 12:30:43 +01:00
parent d9558f2cfe
commit 187c0db8e2
91 changed files with 4181 additions and 856 deletions

View File

@ -23,22 +23,27 @@ end; $$;
Defines the transaction context.
*/
create or replace procedure defineContext(
currentTask varchar,
currentRequest varchar = null,
currentUser varchar = null,
assumedRoles varchar = null
currentTask varchar(96),
currentRequest text = null,
currentUser varchar(63) = null,
assumedRoles varchar(256) = null
)
language plpgsql as $$
begin
currentTask := coalesce(currentTask, '');
assert length(currentTask) <= 96, FORMAT('currentTask must not be longer than 96 characters: "%s"', currentTask);
assert length(currentTask) > 8, FORMAT('currentTask must be at least 8 characters long: "%s""', currentTask);
execute format('set local hsadminng.currentTask to %L', currentTask);
currentRequest := coalesce(currentRequest, '');
execute format('set local hsadminng.currentRequest to %L', currentRequest);
currentUser := coalesce(currentUser, '');
assert length(currentUser) <= 63, FORMAT('currentUser must not be longer than 63 characters: "%s"', currentUser);
execute format('set local hsadminng.currentUser to %L', currentUser);
assumedRoles := coalesce(assumedRoles, '');
assert length(assumedRoles) <= 256, FORMAT('assumedRoles must not be longer than 256 characters: "%s"', assumedRoles);
execute format('set local hsadminng.assumedRoles to %L', assumedRoles);
call contextDefined(currentTask, currentRequest, currentUser, assumedRoles);

View File

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

View File

@ -86,29 +86,6 @@ create or replace function findRbacUserId(userName varchar)
language sql as $$
select uuid from RbacUser where name = userName
$$;
create type RbacWhenNotExists as enum ('fail', 'create');
create or replace function getRbacUserId(userName varchar, whenNotExists RbacWhenNotExists)
returns uuid
returns null on null input
language plpgsql as $$
declare
userUuid uuid;
begin
userUuid = findRbacUserId(userName);
if (userUuid is null) then
if (whenNotExists = 'fail') then
raise exception 'RbacUser with name="%" not found', userName;
end if;
if (whenNotExists = 'create') then
userUuid = createRbacUser(userName);
end if;
end if;
return userUuid;
end;
$$;
--//
-- ============================================================================
@ -203,15 +180,33 @@ create type RbacRoleDescriptor as
(
objectTable varchar(63), -- for human readability and easier debugging
objectUuid uuid,
roleType RbacRoleType
roleType RbacRoleType,
assumed boolean
);
create or replace function roleDescriptor(objectTable varchar(63), objectUuid uuid, roleType RbacRoleType)
create or replace function assumed()
returns boolean
stable -- leakproof
language sql as $$
select true;
$$;
create or replace function unassumed()
returns boolean
stable -- leakproof
language sql as $$
select false;
$$;
create or replace function roleDescriptor(
objectTable varchar(63), objectUuid uuid, roleType RbacRoleType,
assumed boolean = true) -- just for DSL readability, belongs actually to the grant
returns RbacRoleDescriptor
returns null on null input
stable -- leakproof
language sql as $$
select objectTable, objectUuid, roleType::RbacRoleType;
select objectTable, objectUuid, roleType::RbacRoleType, assumed;
$$;
create or replace function createRole(roleDescriptor RbacRoleDescriptor)
@ -275,21 +270,17 @@ create or replace function findRoleId(roleDescriptor RbacRoleDescriptor)
select uuid from RbacRole where objectUuid = roleDescriptor.objectUuid and roleType = roleDescriptor.roleType;
$$;
create or replace function getRoleId(roleDescriptor RbacRoleDescriptor, whenNotExists RbacWhenNotExists)
create or replace function getRoleId(roleDescriptor RbacRoleDescriptor)
returns uuid
returns null on null input
language plpgsql as $$
declare
roleUuid uuid;
begin
roleUuid = findRoleId(roleDescriptor);
assert roleDescriptor is not null, 'roleDescriptor must not be null';
roleUuid := findRoleId(roleDescriptor);
if (roleUuid is null) then
if (whenNotExists = 'fail') then
raise exception 'RbacRole "%#%.%" not found', roleDescriptor.objectTable, roleDescriptor.objectUuid, roleDescriptor.roleType;
end if;
if (whenNotExists = 'create') then
roleUuid = createRole(roleDescriptor);
end if;
raise exception 'RbacRole "%#%.%" not found', roleDescriptor.objectTable, roleDescriptor.objectUuid, roleDescriptor.roleType;
end if;
return roleUuid;
end;
@ -365,38 +356,63 @@ create trigger deleteRbacRolesOfRbacObject_Trigger
/*
*/
create domain RbacOp as varchar(67)
create domain RbacOp as varchar(67) -- TODO: shorten to 8, once the deprecated values are gone
check (
VALUE = '*'
or VALUE = 'delete'
or VALUE = 'edit'
or VALUE = 'view'
or VALUE = 'assume'
VALUE = 'DELETE'
or VALUE = 'UPDATE'
or VALUE = 'SELECT'
or VALUE = 'INSERT'
or VALUE = 'ASSUME'
-- TODO: all values below are deprecated, use insert with table
or VALUE ~ '^add-[a-z]+$'
or VALUE ~ '^new-[a-z-]+$'
);
create table RbacPermission
(
uuid uuid primary key references RbacReference (uuid) on delete cascade,
objectUuid uuid not null references RbacObject,
op RbacOp not null,
uuid uuid primary key references RbacReference (uuid) on delete cascade,
objectUuid uuid not null references RbacObject,
op RbacOp not null,
opTableName varchar(60),
unique (objectUuid, op)
);
call create_journal('RbacPermission');
create or replace function permissionExists(forObjectUuid uuid, forOp RbacOp)
returns bool
language sql as $$
select exists(
select op
from RbacPermission p
where p.objectUuid = forObjectUuid
and p.op in ('*', forOp)
);
$$;
create or replace function createPermission(forObjectUuid uuid, forOp RbacOp, forOpTableName text = null)
returns uuid
language plpgsql as $$
declare
permissionUuid uuid;
begin
if (forObjectUuid is null) then
raise exception 'forObjectUuid must not be null';
end if;
if (forOp = 'INSERT' and forOpTableName is null) then
raise exception 'INSERT permissions needs forOpTableName';
end if;
if (forOp <> 'INSERT' and forOpTableName is not null) then
raise exception 'forOpTableName must only be specified for ops: [INSERT]'; -- currently no other
end if;
permissionUuid = (select uuid from RbacPermission where objectUuid = forObjectUuid and op = forOp and opTableName = forOpTableName);
if (permissionUuid is null) then
insert into RbacReference ("type")
values ('RbacPermission')
returning uuid into permissionUuid;
begin
insert into RbacPermission (uuid, objectUuid, op, opTableName)
values (permissionUuid, forObjectUuid, forOp, forOpTableName);
exception
when others then
raise exception 'insert into RbacPermission (uuid, objectUuid, op, opTableName)
values (%, %, %, %);', permissionUuid, forObjectUuid, forOp, forOpTableName;
end;
end if;
return permissionUuid;
end; $$;
-- TODO: deprecated, remove and amend all usages to createPermission
create or replace function createPermissions(forObjectUuid uuid, permitOps RbacOp[])
returns uuid[]
language plpgsql as $$
@ -407,9 +423,6 @@ begin
if (forObjectUuid is null) then
raise exception 'forObjectUuid must not be null';
end if;
if (array_length(permitOps, 1) > 1 and '*' = any (permitOps)) then
raise exception '"*" operation must not be assigned along with other operations: %', permitOps;
end if;
for i in array_lower(permitOps, 1)..array_upper(permitOps, 1)
loop
@ -430,7 +443,19 @@ begin
end;
$$;
create or replace function findPermissionId(forObjectUuid uuid, forOp RbacOp)
create or replace function findEffectivePermissionId(forObjectUuid uuid, forOp RbacOp, forOpTableName text = null)
returns uuid
returns null on null input
stable -- leakproof
language sql as $$
select uuid
from RbacPermission p
where p.objectUuid = forObjectUuid
and (forOp = 'SELECT' or p.op = forOp) -- all other RbacOp include 'SELECT'
and p.opTableName = forOpTableName
$$;
create or replace function findPermissionId(forObjectUuid uuid, forOp RbacOp, forOpTableName text = null)
returns uuid
returns null on null input
stable -- leakproof
@ -439,23 +464,8 @@ select uuid
from RbacPermission p
where p.objectUuid = forObjectUuid
and p.op = forOp
and p.opTableName = forOpTableName
$$;
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 $$;
--//
-- ============================================================================
@ -552,6 +562,18 @@ select exists(
);
$$;
create or replace function hasInsertPermission(objectUuid uuid, forOp RbacOp, tableName text )
returns BOOL
stable -- leakproof
language plpgsql as $$
declare
permissionUuid uuid;
begin
permissionUuid = findPermissionId(objectUuid, forOp, tableName);
return permissionUuid is not null;
end;
$$;
create or replace function hasGlobalRoleGranted(userUuid uuid)
returns bool
stable -- leakproof
@ -566,6 +588,27 @@ select exists(
);
$$;
create or replace procedure grantPermissionToRole(roleUuid uuid, permissionUuid uuid)
language plpgsql as $$
begin
perform assertReferenceType('roleId (ascendant)', roleUuid, 'RbacRole');
perform assertReferenceType('permissionId (descendant)', permissionUuid, 'RbacPermission');
insert
into RbacGrants (grantedByTriggerOf, ascendantUuid, descendantUuid, assumed)
values (currentTriggerObjectUuid(), roleUuid, permissionUuid, true)
on conflict do nothing; -- allow granting multiple times
end;
$$;
create or replace procedure grantPermissionToRole(roleDesc RbacRoleDescriptor, permissionUuid uuid)
language plpgsql as $$
begin
call grantPermissionToRole(findRoleId(roleDesc), permissionUuid);
end;
$$;
-- TODO: deprecated, remove and use grantPermissionToRole(...)
create or replace procedure grantPermissionsToRole(roleUuid uuid, permissionIds uuid[])
language plpgsql as $$
begin
@ -697,7 +740,7 @@ begin
select descendantUuid
from grants) as granted
join RbacPermission perm
on granted.descendantUuid = perm.uuid and perm.op in ('*', requiredOp)
on granted.descendantUuid = perm.uuid and (requiredOp = 'SELECT' or perm.op = requiredOp)
join RbacObject obj on obj.uuid = perm.objectUuid and obj.objectTable = forObjectTable
limit maxObjects + 1;
@ -789,6 +832,5 @@ do $$
create role restricted;
grant all privileges on all tables in schema public to restricted;
end if;
end $$
end $$;
--//

View File

@ -30,24 +30,35 @@ begin
insert
into RbacGrants (grantedByRoleUuid, ascendantUuid, descendantUuid, assumed)
values (grantedByRoleUuid, userUuid, roleUuid, doAssume);
-- TODO.spec: What should happen on mupltiple grants? What if options (doAssume) are not the same?
-- TODO.spec: What should happen on multiple grants? What if options (doAssume) are not the same?
-- Most powerful or latest grant wins? What about managed?
-- on conflict do nothing; -- allow granting multiple times
end; $$;
create or replace procedure grantRoleToUser(grantedByRoleUuid uuid, grantedRoleUuid uuid, userUuid uuid, doAssume boolean = true)
language plpgsql as $$
declare
grantedByRoleIdName text;
grantedRoleIdName text;
begin
perform assertReferenceType('grantingRoleUuid', grantedByRoleUuid, 'RbacRole');
perform assertReferenceType('grantedRoleUuid (descendant)', grantedRoleUuid, 'RbacRole');
perform assertReferenceType('userUuid (ascendant)', userUuid, 'RbacUser');
if NOT isGranted(currentSubjectsUuids(), grantedByRoleUuid) then
raise exception '[403] Access to granted-by-role % forbidden for %', grantedByRoleUuid, currentSubjects();
end if;
assert grantedByRoleUuid is not null, 'grantedByRoleUuid must not be null';
assert grantedRoleUuid is not null, 'grantedRoleUuid must not be null';
assert userUuid is not null, 'userUuid must not be null';
if NOT isGranted(currentSubjectsUuids(), grantedByRoleUuid) then
select roleIdName from rbacRole_ev where uuid=grantedByRoleUuid into grantedByRoleIdName;
raise exception '[403] Access to granted-by-role % (%) forbidden for % (%)',
grantedByRoleIdName, grantedByRoleUuid, currentSubjects(), currentSubjectsUuids();
end if;
if NOT isGranted(grantedByRoleUuid, grantedRoleUuid) then
raise exception '[403] Access to granted role % forbidden for %', grantedRoleUuid, currentSubjects();
select roleIdName from rbacRole_ev where uuid=grantedByRoleUuid into grantedByRoleIdName;
select roleIdName from rbacRole_ev where uuid=grantedRoleUuid into grantedRoleIdName;
raise exception '[403] Access to granted role % (%) forbidden for % (%)',
grantedRoleIdName, grantedRoleUuid, grantedByRoleIdName, grantedByRoleUuid;
end if;
insert
@ -99,4 +110,17 @@ begin
where g.ascendantUuid = userUuid and g.descendantUuid = grantedRoleUuid
and g.grantedByRoleUuid = revokeRoleFromUser.grantedByRoleUuid;
end; $$;
--/
--//
-- ============================================================================
--changeset rbac-user-grant-REVOKE-PERMISSION-FROM-ROLE:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
create or replace procedure revokePermissionFromRole(permissionUuid uuid, superRoleUuid uuid)
language plpgsql as $$
begin
raise INFO 'delete from RbacGrants where ascendantUuid = % and descendantUuid = %', superRoleUuid, permissionUuid;
delete from RbacGrants as g
where g.ascendantUuid = superRoleUuid and g.descendantUuid = permissionUuid;
end; $$;
--//

View File

@ -337,11 +337,9 @@ grant all privileges on RbacOwnGrantedPermissions_rv to ${HSADMINNG_POSTGRES_RES
/*
Returns all permissions granted to the given user,
which are also visible to the current user or assumed roles.
*/
create or replace function grantedPermissions(targetUserUuid uuid)
returns table(roleUuid uuid, roleName text, permissionUuid uuid, op RbacOp, objectTable varchar, objectIdName varchar, objectUuid uuid)
*/
create or replace function grantedPermissionsRaw(targetUserUuid uuid)
returns table(roleUuid uuid, roleName text, permissionUuid uuid, op RbacOp, opTableName varchar(60), objectTable varchar(60), objectIdName varchar, objectUuid uuid)
returns null on null input
language plpgsql as $$
declare
@ -357,11 +355,13 @@ begin
return query select
xp.roleUuid,
(xp.roleObjectTable || '#' || xp.roleObjectIdName || '.' || xp.roleType) as roleName,
xp.permissionUuid, xp.op, xp.permissionObjectTable, xp.permissionObjectIdName, xp.permissionObjectUuid
xp.permissionUuid, xp.op, xp.opTableName,
xp.permissionObjectTable, xp.permissionObjectIdName, xp.permissionObjectUuid
from (select
r.uuid as roleUuid, r.roletype, ro.objectTable as roleObjectTable,
findIdNameByObjectUuid(ro.objectTable, ro.uuid) as roleObjectIdName,
p.uuid as permissionUuid, p.op, po.objecttable as permissionObjectTable,
p.uuid as permissionUuid, p.op, p.opTableName,
po.objecttable as permissionObjectTable,
findIdNameByObjectUuid(po.objectTable, po.uuid) as permissionObjectIdName,
po.uuid as permissionObjectUuid
from queryPermissionsGrantedToSubjectId( targetUserUuid) as p
@ -373,4 +373,15 @@ begin
) xp;
-- @formatter:on
end; $$;
create or replace function grantedPermissions(targetUserUuid uuid)
returns table(roleUuid uuid, roleName text, permissionUuid uuid, op RbacOp, opTableName varchar(60), objectTable varchar(60), objectIdName varchar, objectUuid uuid)
returns null on null input
language sql as $$
select * from grantedPermissionsRaw(targetUserUuid)
union all
select roleUuid, roleName, permissionUuid, 'SELECT'::RbacOp, opTableName, objectTable, objectIdName, objectUuid
from grantedPermissionsRaw(targetUserUuid)
where op <> 'SELECT'::RbacOp;
$$;
--//

View File

@ -13,24 +13,6 @@ begin
return createPermissions(forObjectUuid, permitOps);
end; $$;
create or replace function toRoleUuids(roleDescriptors RbacRoleDescriptor[])
returns uuid[]
language plpgsql
strict as $$
declare
superRoleDescriptor RbacRoleDescriptor;
superRoleUuids uuid[] := array []::uuid[];
begin
foreach superRoleDescriptor in array roleDescriptors
loop
if superRoleDescriptor is not null then
superRoleUuids := superRoleUuids || getRoleId(superRoleDescriptor, 'fail');
end if;
end loop;
return superRoleUuids;
end; $$;
-- =================================================================
-- CREATE ROLE
@ -50,32 +32,37 @@ create or replace function createRoleWithGrants(
language plpgsql as $$
declare
roleUuid uuid;
superRoleUuid uuid;
subRoleDesc RbacRoleDescriptor;
superRoleDesc RbacRoleDescriptor;
subRoleUuid uuid;
superRoleUuid uuid;
userUuid uuid;
grantedByRoleUuid uuid;
begin
roleUuid := createRole(roleDescriptor);
if cardinality(permissions) >0 then
if cardinality(permissions) > 0 then
call grantPermissionsToRole(roleUuid, toPermissionUuids(roleDescriptor.objectuuid, permissions));
end if;
foreach superRoleUuid in array toRoleUuids(incomingSuperRoles)
foreach superRoleDesc in array array_remove(incomingSuperRoles, null)
loop
call grantRoleToRole(roleUuid, superRoleUuid);
superRoleUuid := getRoleId(superRoleDesc);
call grantRoleToRole(roleUuid, superRoleUuid, superRoleDesc.assumed);
end loop;
foreach subRoleUuid in array toRoleUuids(outgoingSubRoles)
foreach subRoleDesc in array array_remove(outgoingSubRoles, null)
loop
call grantRoleToRole(subRoleUuid, roleUuid);
subRoleUuid := getRoleId(subRoleDesc);
call grantRoleToRole(subRoleUuid, roleUuid, subRoleDesc.assumed);
end loop;
if cardinality(userUuids) > 0 then
if grantedByRole is null then
raise exception 'to directly assign users to roles, grantingRole has to be given';
grantedByRoleUuid := roleUuid;
else
grantedByRoleUuid := getRoleId(grantedByRole);
end if;
grantedByRoleUuid := getRoleId(grantedByRole, 'fail');
foreach userUuid in array userUuids
loop
call grantRoleToUserUnchecked(grantedByRoleUuid, roleUuid, userUuid);

View File

@ -13,8 +13,7 @@ declare
begin
createInsertTriggerSQL = format($sql$
create trigger createRbacObjectFor_%s_Trigger
before insert
on %s
before insert on %s
for each row
execute procedure insertRelatedRbacObject();
$sql$, targetTable, targetTable);
@ -36,50 +35,50 @@ end; $$;
--changeset rbac-generators-ROLE-DESCRIPTORS:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
create or replace procedure generateRbacRoleDescriptors(prefix text, targetTable text)
create procedure generateRbacRoleDescriptors(prefix text, targetTable text)
language plpgsql as $$
declare
sql text;
begin
sql = format($sql$
create or replace function %1$sOwner(entity %2$s)
create or replace function %1$sOwner(entity %2$s, assumed boolean = true)
returns RbacRoleDescriptor
language plpgsql
strict as $f$
begin
return roleDescriptor('%2$s', entity.uuid, 'owner');
return roleDescriptor('%2$s', entity.uuid, 'owner', assumed);
end; $f$;
create or replace function %1$sAdmin(entity %2$s)
create or replace function %1$sAdmin(entity %2$s, assumed boolean = true)
returns RbacRoleDescriptor
language plpgsql
strict as $f$
begin
return roleDescriptor('%2$s', entity.uuid, 'admin');
return roleDescriptor('%2$s', entity.uuid, 'admin', assumed);
end; $f$;
create or replace function %1$sAgent(entity %2$s)
create or replace function %1$sAgent(entity %2$s, assumed boolean = true)
returns RbacRoleDescriptor
language plpgsql
strict as $f$
begin
return roleDescriptor('%2$s', entity.uuid, 'agent');
return roleDescriptor('%2$s', entity.uuid, 'agent', assumed);
end; $f$;
create or replace function %1$sTenant(entity %2$s)
create or replace function %1$sTenant(entity %2$s, assumed boolean = true)
returns RbacRoleDescriptor
language plpgsql
strict as $f$
begin
return roleDescriptor('%2$s', entity.uuid, 'tenant');
return roleDescriptor('%2$s', entity.uuid, 'tenant', assumed);
end; $f$;
create or replace function %1$sGuest(entity %2$s)
create or replace function %1$sGuest(entity %2$s, assumed boolean = true)
returns RbacRoleDescriptor
language plpgsql
strict as $f$
begin
return roleDescriptor('%2$s', entity.uuid, 'guest');
return roleDescriptor('%2$s', entity.uuid, 'guest', assumed);
end; $f$;
$sql$, prefix, targetTable);
@ -92,7 +91,7 @@ end; $$;
--changeset rbac-generators-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
create or replace procedure generateRbacIdentityView(targetTable text, idNameExpression text)
create or replace procedure generateRbacIdentityViewFromQuery(targetTable text, sqlQuery text)
language plpgsql as $$
declare
sql text;
@ -101,11 +100,9 @@ begin
-- create a view to the target main table which maps an idName to the objectUuid
sql = format($sql$
create or replace view %1$s_iv as
select target.uuid, cleanIdentifier(%2$s) as idName
from %1$s as target;
create or replace view %1$s_iv as %2$s;
grant all privileges on %1$s_iv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
$sql$, targetTable, idNameExpression);
$sql$, targetTable, sqlQuery);
execute sql;
-- creates a function which maps an idName to the objectUuid
@ -130,6 +127,20 @@ begin
$sql$, targetTable);
execute sql;
end; $$;
create or replace procedure generateRbacIdentityViewFromProjection(targetTable text, sqlProjection text)
language plpgsql as $$
declare
sqlQuery text;
begin
targettable := lower(targettable);
sqlQuery = format($sql$
select target.uuid, cleanIdentifier(%2$s) as idName
from %1$s as target;
$sql$, targetTable, sqlProjection);
call generateRbacIdentityViewFromQuery(targetTable, sqlQuery);
end; $$;
--//
@ -145,13 +156,13 @@ begin
targetTable := lower(targetTable);
/*
Creates a restricted view based on the 'view' permission of the current subject.
Creates a restricted view based on the 'SELECT' permission of the current subject.
*/
sql := format($sql$
set session session authorization default;
create view %1$s_rv as
with accessibleObjects as (
select queryAccessibleObjectUuidsOfSubjectIds('view', '%1$s', currentSubjectsUuids())
select queryAccessibleObjectUuidsOfSubjectIds('SELECT', '%1$s', currentSubjectsUuids())
)
select target.*
from %1$s as target
@ -200,7 +211,7 @@ begin
returns trigger
language plpgsql as $f$
begin
if old.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('delete', '%1$s', currentSubjectsUuids())) then
if old.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('DELETE', '%1$s', currentSubjectsUuids())) then
delete from %1$s p where p.uuid = old.uuid;
return old;
end if;
@ -223,7 +234,7 @@ begin
/**
Instead of update trigger function for the restricted view
based on the 'edit' permission of the current subject.
based on the 'UPDATE' permission of the current subject.
*/
if columnUpdates is not null then
sql := format($sql$
@ -231,7 +242,7 @@ begin
returns trigger
language plpgsql as $f$
begin
if old.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('edit', '%1$s', currentSubjectsUuids())) then
if old.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('UPDATE', '%1$s', currentSubjectsUuids())) then
update %1$s
set %2$s
where uuid = old.uuid;

View File

@ -22,6 +22,19 @@ grant select on global to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
--//
-- ============================================================================
--changeset rbac-global-IS-GLOBAL-ADMIN:1 endDelimiter:--//
-- ------------------------------------------------------------------
create or replace function isGlobalAdmin()
returns boolean
language plpgsql as $$
begin
return isGranted(currentSubjectsUuids(), findRoleId(globalAdmin()));
end; $$;
--//
-- ============================================================================
--changeset rbac-global-HAS-GLOBAL-PERMISSION:1 endDelimiter:--//
-- ------------------------------------------------------------------
@ -96,12 +109,12 @@ commit;
/*
A global administrator role.
*/
create or replace function globalAdmin()
create or replace function globalAdmin(assumed boolean = true)
returns RbacRoleDescriptor
returns null on null input
stable -- leakproof
language sql as $$
select 'global', (select uuid from RbacObject where objectTable = 'global'), 'admin'::RbacRoleType;
select 'global', (select uuid from RbacObject where objectTable = 'global'), 'admin'::RbacRoleType, assumed;
$$;
begin transaction;

View File

@ -0,0 +1,43 @@
### rbac customer
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-11T11:29:11.571772062.
```mermaid
%%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB
subgraph customer["`**customer**`"]
direction TB
style customer fill:#dd4901,stroke:#274d6e,stroke-width:8px
subgraph customer:roles[ ]
style customer:roles fill:#dd4901,stroke:white
role:customer:owner[[customer:owner]]
role:customer:admin[[customer:admin]]
role:customer:tenant[[customer:tenant]]
end
subgraph customer:permissions[ ]
style customer:permissions fill:#dd4901,stroke:white
perm:customer:DELETE{{customer:DELETE}}
perm:customer:UPDATE{{customer:UPDATE}}
perm:customer:SELECT{{customer:SELECT}}
end
end
%% granting roles to users
user:creator ==>|XX| role:customer:owner
%% granting roles to roles
role:global:admin ==>|XX| role:customer:owner
role:customer:owner ==> role:customer:admin
role:customer:admin ==> role:customer:tenant
%% granting permissions to roles
role:customer:owner ==> perm:customer:DELETE
role:customer:admin ==> perm:customer:UPDATE
role:customer:tenant ==> perm:customer:SELECT
```

View File

@ -1,4 +1,5 @@
--liquibase formatted sql
-- This code generated was by RbacViewPostgresGenerator at 2024-03-11T11:29:11.584886824.
-- ============================================================================
--changeset test-customer-rbac-OBJECT:1 endDelimiter:--//
@ -15,82 +16,103 @@ call generateRbacRoleDescriptors('testCustomer', 'test_customer');
-- ============================================================================
--changeset test-customer-rbac-ROLES-CREATION:1 endDelimiter:--//
--changeset test-customer-rbac-insert-trigger:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates the roles and their assignments for a new customer for the AFTER INSERT TRIGGER.
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
*/
create or replace function createRbacRolesForTestCustomer()
returns trigger
language plpgsql
strict as $$
declare
testCustomerOwnerUuid uuid;
customerAdminUuid uuid;
begin
if TG_OP <> 'INSERT' then
raise exception 'invalid usage of TRIGGER AFTER INSERT';
end if;
create or replace procedure buildRbacSystemForTestCustomer(
NEW test_customer
)
language plpgsql as $$
declare
begin
call enterTriggerForObjectUuid(NEW.uuid);
-- the owner role with full access for Hostsharing administrators
testCustomerOwnerUuid = createRoleWithGrants(
perform createRoleWithGrants(
testCustomerOwner(NEW),
permissions => array['*'],
incomingSuperRoles => array[globalAdmin()]
);
permissions => array['DELETE'],
userUuids => array[currentUserUuid()],
incomingSuperRoles => array[globalAdmin(unassumed())]
);
-- the admin role for the customer's admins, who can view and add products
customerAdminUuid = createRoleWithGrants(
perform createRoleWithGrants(
testCustomerAdmin(NEW),
permissions => array['view', 'add-package'],
-- NO auto assume for customer owner to avoid exploding permissions for administrators
userUuids => array[getRbacUserId(NEW.adminUserName, 'create')], -- implicitly ignored if null
grantedByRole => globalAdmin()
);
permissions => array['UPDATE'],
incomingSuperRoles => array[testCustomerOwner(NEW)]
);
-- allow the customer owner role (thus administrators) to assume the customer admin role
call grantRoleToRole(customerAdminUuid, testCustomerOwnerUuid, false);
-- the tenant role which later can be used by owners+admins of sub-objects
perform createRoleWithGrants(
testCustomerTenant(NEW),
permissions => array['view']
);
permissions => array['SELECT'],
incomingSuperRoles => array[testCustomerAdmin(NEW)]
);
call leaveTriggerForObjectUuid(NEW.uuid);
return NEW;
end; $$;
/*
An AFTER INSERT TRIGGER which creates the role structure for a new customer.
AFTER INSERT TRIGGER to create the role+grant structure for a new test_customer row.
*/
drop trigger if exists createRbacRolesForTestCustomer_Trigger on test_customer;
create trigger createRbacRolesForTestCustomer_Trigger
after insert
on test_customer
create or replace function insertTriggerForTestCustomer_tf()
returns trigger
language plpgsql
strict as $$
begin
call buildRbacSystemForTestCustomer(NEW);
return NEW;
end; $$;
create trigger insertTriggerForTestCustomer_tg
after insert on test_customer
for each row
execute procedure createRbacRolesForTestCustomer();
execute procedure insertTriggerForTestCustomer_tf();
--//
-- ============================================================================
--changeset test-customer-rbac-INSERT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/**
Checks if the user or assumed roles are allowed to insert a row to test_customer.
*/
create or replace function test_customer_insert_permission_missing_tf()
returns trigger
language plpgsql as $$
begin
raise exception '[403] insert into test_customer not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids();
end; $$;
create trigger test_customer_insert_permission_check_tg
before insert on test_customer
for each row
-- As there is no explicit INSERT grant specified for this table,
-- only global admins are allowed to insert any rows.
when ( not isGlobalAdmin() )
execute procedure test_customer_insert_permission_missing_tf();
--//
-- ============================================================================
--changeset test-customer-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityView('test_customer', $idName$
target.prefix
call generateRbacIdentityViewFromProjection('test_customer', $idName$
prefix
$idName$);
--//
-- ============================================================================
--changeset test-customer-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRestrictedView('test_customer', 'target.prefix',
call generateRbacRestrictedView('test_customer',
'reference',
$updates$
reference = new.reference,
prefix = new.prefix,
@ -99,47 +121,3 @@ call generateRbacRestrictedView('test_customer', 'target.prefix',
--//
-- ============================================================================
--changeset test-customer-rbac-ADD-CUSTOMER:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates a global permission for add-customer and assigns it to the hostsharing admins role.
*/
do language plpgsql $$
declare
addCustomerPermissions uuid[];
globalObjectUuid uuid;
globalAdminRoleUuid uuid ;
begin
call defineContext('granting global add-customer permission to global admin role', null, null, null);
globalAdminRoleUuid := findRoleId(globalAdmin());
globalObjectUuid := (select uuid from global);
addCustomerPermissions := createPermissions(globalObjectUuid, array ['add-customer']);
call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions);
end;
$$;
/**
Used by the trigger to prevent the add-customer to current user respectively assumed roles.
*/
create or replace function addTestCustomerNotAllowedForCurrentSubjects()
returns trigger
language PLPGSQL
as $$
begin
raise exception '[403] add-customer not permitted for %',
array_to_string(currentSubjects(), ';', 'null');
end; $$;
/**
Checks if the user or assumed roles are allowed to add a new customer.
*/
create trigger test_customer_insert_trigger
before insert
on test_customer
for each row
when ( not hasGlobalPermission('add-customer') )
execute procedure addTestCustomerNotAllowedForCurrentSubjects();
--//

View File

@ -28,6 +28,8 @@ declare
currentTask varchar;
custRowId uuid;
custAdminName varchar;
custAdminUuid uuid;
newCust test_customer;
begin
currentTask = 'creating RBAC test customer #' || custReference || '/' || custPrefix;
call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global.admin');
@ -35,10 +37,19 @@ begin
custRowId = uuid_generate_v4();
custAdminName = 'customer-admin@' || custPrefix || '.example.com';
custAdminUuid = createRbacUser(custAdminName);
insert
into test_customer (reference, prefix, adminUserName)
values (custReference, custPrefix, custAdminName);
select * into newCust
from test_customer where reference=custReference;
call grantRoleToUser(
getRoleId(testCustomerOwner(newCust)),
getRoleId(testCustomerAdmin(newCust)),
custAdminUuid,
true);
end; $$;
--//

View File

@ -0,0 +1,59 @@
### rbac package
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-11T11:29:11.624847792.
```mermaid
%%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB
subgraph package["`**package**`"]
direction TB
style package fill:#dd4901,stroke:#274d6e,stroke-width:8px
subgraph package:roles[ ]
style package:roles fill:#dd4901,stroke:white
role:package:owner[[package:owner]]
role:package:admin[[package:admin]]
role:package:tenant[[package:tenant]]
end
subgraph package:permissions[ ]
style package:permissions fill:#dd4901,stroke:white
perm:package:INSERT{{package:INSERT}}
perm:package:DELETE{{package:DELETE}}
perm:package:UPDATE{{package:UPDATE}}
perm:package:SELECT{{package:SELECT}}
end
end
subgraph customer["`**customer**`"]
direction TB
style customer fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph customer:roles[ ]
style customer:roles fill:#99bcdb,stroke:white
role:customer:owner[[customer:owner]]
role:customer:admin[[customer:admin]]
role:customer:tenant[[customer:tenant]]
end
end
%% granting roles to roles
role:global:admin -.->|XX| role:customer:owner
role:customer:owner -.-> role:customer:admin
role:customer:admin -.-> role:customer:tenant
role:customer:admin ==> role:package:owner
role:package:owner ==> role:package:admin
role:package:admin ==> role:package:tenant
role:package:tenant ==> role:customer:tenant
%% granting permissions to roles
role:customer:admin ==> perm:package:INSERT
role:package:owner ==> perm:package:DELETE
role:package:owner ==> perm:package:UPDATE
role:package:tenant ==> perm:package:SELECT
```

View File

@ -1,4 +1,5 @@
--liquibase formatted sql
-- This code generated was by RbacViewPostgresGenerator at 2024-03-11T11:29:11.625353859.
-- ============================================================================
--changeset test-package-rbac-OBJECT:1 endDelimiter:--//
@ -15,95 +16,211 @@ call generateRbacRoleDescriptors('testPackage', 'test_package');
-- ============================================================================
--changeset test-package-rbac-ROLES-CREATION:1 endDelimiter:--//
--changeset test-package-rbac-insert-trigger:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates the roles and their assignments for a new package for the AFTER INSERT TRIGGER.
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
*/
create or replace function createRbacRolesForTestPackage()
returns trigger
language plpgsql
strict as $$
create or replace procedure buildRbacSystemForTestPackage(
NEW test_package
)
language plpgsql as $$
declare
parentCustomer test_customer;
newCustomer test_customer;
begin
if TG_OP <> 'INSERT' then
raise exception 'invalid usage of TRIGGER AFTER INSERT';
end if;
call enterTriggerForObjectUuid(NEW.uuid);
SELECT * FROM test_customer c
WHERE c.uuid= NEW.customerUuid
into newCustomer;
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
perform createRoleWithGrants(
testPackageOwner(NEW),
permissions => array ['*'],
incomingSuperRoles => array[testCustomerAdmin(parentCustomer)]
);
testPackageOwner(NEW),
permissions => array['DELETE', 'UPDATE'],
incomingSuperRoles => array[testCustomerAdmin(newCustomer)]
);
-- an owner role is created and assigned to the package owner role
perform createRoleWithGrants(
testPackageAdmin(NEW),
permissions => array ['add-domain'],
testPackageAdmin(NEW),
incomingSuperRoles => array[testPackageOwner(NEW)]
);
);
-- and a package tenant role is created and assigned to the package admin as well
perform createRoleWithGrants(
testPackageTenant(NEW),
permissions => array['view'],
incomingsuperroles => array[testPackageAdmin(NEW)],
outgoingSubRoles => array[testCustomerTenant(parentCustomer)]
);
testPackageTenant(NEW),
permissions => array['SELECT'],
incomingSuperRoles => array[testPackageAdmin(NEW)],
outgoingSubRoles => array[testCustomerTenant(newCustomer)]
);
call leaveTriggerForObjectUuid(NEW.uuid);
return NEW;
end; $$;
/*
An AFTER INSERT TRIGGER which creates the role structure for a new package.
AFTER INSERT TRIGGER to create the role+grant structure for a new test_package row.
*/
create trigger createRbacRolesForTestPackage_Trigger
after insert
on test_package
create or replace function insertTriggerForTestPackage_tf()
returns trigger
language plpgsql
strict as $$
begin
call buildRbacSystemForTestPackage(NEW);
return NEW;
end; $$;
create trigger insertTriggerForTestPackage_tg
after insert on test_package
for each row
execute procedure createRbacRolesForTestPackage();
execute procedure insertTriggerForTestPackage_tf();
--//
-- ============================================================================
--changeset test-package-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityView('test_package', 'target.name');
--//
-- ============================================================================
--changeset test-package-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
--changeset test-package-rbac-update-trigger:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates a view to the customer main table which maps the identifying name
(in this case, the prefix) to the objectUuid.
Called from the AFTER UPDATE TRIGGER to re-wire the grants.
*/
-- drop view if exists test_package_rv;
-- create or replace view test_package_rv as
-- select target.*
-- from test_package as target
-- where target.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('view', 'test_package', currentSubjectsUuids()))
-- order by target.name;
-- grant all privileges on test_package_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
call generateRbacRestrictedView('test_package', 'target.name',
$updates$
version = new.version,
customerUuid = new.customerUuid,
name = new.name,
description = new.description
$updates$);
create or replace procedure updateRbacRulesForTestPackage(
OLD test_package,
NEW test_package
)
language plpgsql as $$
declare
oldCustomer test_customer;
newCustomer test_customer;
begin
call enterTriggerForObjectUuid(NEW.uuid);
SELECT * FROM test_customer c
WHERE c.uuid= OLD.customerUuid
into oldCustomer;
SELECT * FROM test_customer c
WHERE c.uuid= NEW.customerUuid
into newCustomer;
if NEW.customerUuid <> OLD.customerUuid then
call revokePermissionFromRole(findPermissionId(OLD.uuid, 'INSERT'), testCustomerAdmin(oldCustomer));
call revokeRoleFromRole(testPackageOwner(OLD), testCustomerAdmin(oldCustomer));
call grantRoleToRole(testPackageOwner(NEW), testCustomerAdmin(newCustomer));
call revokeRoleFromRole(testCustomerTenant(oldCustomer), testPackageTenant(OLD));
call grantRoleToRole(testCustomerTenant(newCustomer), testPackageTenant(NEW));
end if;
call leaveTriggerForObjectUuid(NEW.uuid);
end; $$;
/*
AFTER INSERT TRIGGER to re-wire the grant structure for a new test_package row.
*/
create or replace function updateTriggerForTestPackage_tf()
returns trigger
language plpgsql
strict as $$
begin
call updateRbacRulesForTestPackage(OLD, NEW);
return NEW;
end; $$;
create trigger updateTriggerForTestPackage_tg
after update on test_package
for each row
execute procedure updateTriggerForTestPackage_tf();
--//
-- ============================================================================
--changeset test-package-rbac-INSERT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates INSERT INTO test_package permissions for the related test_customer rows.
*/
do language plpgsql $$
declare
row test_customer;
permissionUuid uuid;
roleUuid uuid;
begin
call defineContext('create INSERT INTO test_package permissions for the related test_customer rows');
FOR row IN SELECT * FROM test_customer
LOOP
roleUuid := findRoleId(testCustomerAdmin(row));
permissionUuid := createPermission(row.uuid, 'INSERT', 'test_package');
call grantPermissionToRole(roleUuid, permissionUuid);
END LOOP;
END;
$$;
/**
Adds test_package INSERT permission to specified role of new test_customer rows.
*/
create or replace function test_package_test_customer_insert_tf()
returns trigger
language plpgsql
strict as $$
begin
call grantPermissionToRole(
testCustomerAdmin(NEW),
createPermission(NEW.uuid, 'INSERT', 'test_package'));
return NEW;
end; $$;
create trigger test_package_test_customer_insert_tg
after insert on test_customer
for each row
execute procedure test_package_test_customer_insert_tf();
/**
Checks if the user or assumed roles are allowed to insert a row to test_package.
*/
create or replace function test_package_insert_permission_missing_tf()
returns trigger
language plpgsql as $$
begin
raise exception '[403] insert into test_package not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids();
end; $$;
create trigger test_package_insert_permission_check_tg
before insert on test_package
for each row
when ( not hasInsertPermission(NEW.customerUuid, 'INSERT', 'test_package') )
execute procedure test_package_insert_permission_missing_tf();
--//
-- ============================================================================
--changeset test-package-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityViewFromProjection('test_package', $idName$
name
$idName$);
--//
-- ============================================================================
--changeset test-package-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRestrictedView('test_package',
'name',
$updates$
version = new.version,
customerUuid = new.customerUuid,
description = new.description
$updates$);
--//

View File

@ -26,7 +26,7 @@ begin
custAdminUser = 'customer-admin@' || cust.prefix || '.example.com';
custAdminRole = 'test_customer#' || cust.prefix || '.admin';
call defineContext(currentTask, null, custAdminUser, custAdminRole);
call defineContext(currentTask, null, 'superuser-fran@hostsharing.net', custAdminRole);
raise notice 'task: % by % as %', currentTask, custAdminUser, custAdminRole;
insert
@ -35,7 +35,7 @@ begin
returning * into pac;
call grantRoleToUser(
getRoleId(testCustomerAdmin(cust), 'fail'),
getRoleId(testCustomerAdmin(cust)),
findRoleId(testPackageAdmin(pac)),
createRbacUser('pac-admin-' || pacName || '@' || cust.prefix || '.example.com'),
true);

View File

@ -0,0 +1,88 @@
### rbac domain
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-11T11:29:11.644658132.
```mermaid
%%{init:{'flowchart':{'htmlLabels':false}}}%%
flowchart TB
subgraph package.customer["`**package.customer**`"]
direction TB
style package.customer fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph package.customer:roles[ ]
style package.customer:roles fill:#99bcdb,stroke:white
role:package.customer:owner[[package.customer:owner]]
role:package.customer:admin[[package.customer:admin]]
role:package.customer:tenant[[package.customer:tenant]]
end
end
subgraph package["`**package**`"]
direction TB
style package fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph package.customer["`**package.customer**`"]
direction TB
style package.customer fill:#99bcdb,stroke:#274d6e,stroke-width:8px
subgraph package.customer:roles[ ]
style package.customer:roles fill:#99bcdb,stroke:white
role:package.customer:owner[[package.customer:owner]]
role:package.customer:admin[[package.customer:admin]]
role:package.customer:tenant[[package.customer:tenant]]
end
end
subgraph package:roles[ ]
style package:roles fill:#99bcdb,stroke:white
role:package:owner[[package:owner]]
role:package:admin[[package:admin]]
role:package:tenant[[package:tenant]]
end
end
subgraph domain["`**domain**`"]
direction TB
style domain fill:#dd4901,stroke:#274d6e,stroke-width:8px
subgraph domain:roles[ ]
style domain:roles fill:#dd4901,stroke:white
role:domain:owner[[domain:owner]]
role:domain:admin[[domain:admin]]
end
subgraph domain:permissions[ ]
style domain:permissions fill:#dd4901,stroke:white
perm:domain:INSERT{{domain:INSERT}}
perm:domain:DELETE{{domain:DELETE}}
perm:domain:UPDATE{{domain:UPDATE}}
perm:domain:SELECT{{domain:SELECT}}
end
end
%% granting roles to roles
role:global:admin -.->|XX| role:package.customer:owner
role:package.customer:owner -.-> role:package.customer:admin
role:package.customer:admin -.-> role:package.customer:tenant
role:package.customer:admin -.-> role:package:owner
role:package:owner -.-> role:package:admin
role:package:admin -.-> role:package:tenant
role:package:tenant -.-> role:package.customer:tenant
role:package:admin ==> role:domain:owner
role:domain:owner ==> role:package:tenant
role:domain:owner ==> role:domain:admin
role:domain:admin ==> role:package:tenant
%% granting permissions to roles
role:package:admin ==> perm:domain:INSERT
role:domain:owner ==> perm:domain:DELETE
role:domain:owner ==> perm:domain:UPDATE
role:domain:admin ==> perm:domain:SELECT
```

View File

@ -1,4 +1,5 @@
--liquibase formatted sql
-- This code generated was by RbacViewPostgresGenerator at 2024-03-11T11:29:11.645391647.
-- ============================================================================
--changeset test-domain-rbac-OBJECT:1 endDelimiter:--//
@ -11,107 +12,214 @@ call generateRelatedRbacObject('test_domain');
--changeset test-domain-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRoleDescriptors('testDomain', 'test_domain');
create or replace function createTestDomainTenantRoleIfNotExists(domain test_domain)
returns uuid
returns null on null input
language plpgsql as $$
declare
domainTenantRoleDesc RbacRoleDescriptor;
domainTenantRoleUuid uuid;
begin
domainTenantRoleDesc = testdomainTenant(domain);
domainTenantRoleUuid = findRoleId(domainTenantRoleDesc);
if domainTenantRoleUuid is not null then
return domainTenantRoleUuid;
end if;
return createRoleWithGrants(
domainTenantRoleDesc,
permissions => array['view'],
incomingSuperRoles => array[testdomainAdmin(domain)]
);
end; $$;
--//
-- ============================================================================
--changeset test-domain-rbac-ROLES-CREATION:1 endDelimiter:--//
--changeset test-domain-rbac-insert-trigger:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates the roles and their assignments for a new domain for the AFTER INSERT TRIGGER.
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
*/
create or replace function createRbacRulesForTestDomain()
create or replace procedure buildRbacSystemForTestDomain(
NEW test_domain
)
language plpgsql as $$
declare
newPackage test_package;
begin
call enterTriggerForObjectUuid(NEW.uuid);
SELECT * FROM test_package p
WHERE p.uuid= NEW.packageUuid
into newPackage;
perform createRoleWithGrants(
testDomainOwner(NEW),
permissions => array['DELETE', 'UPDATE'],
incomingSuperRoles => array[testPackageAdmin(newPackage)],
outgoingSubRoles => array[testPackageTenant(newPackage)]
);
perform createRoleWithGrants(
testDomainAdmin(NEW),
permissions => array['SELECT'],
incomingSuperRoles => array[testDomainOwner(NEW)],
outgoingSubRoles => array[testPackageTenant(newPackage)]
);
call leaveTriggerForObjectUuid(NEW.uuid);
end; $$;
/*
AFTER INSERT TRIGGER to create the role+grant structure for a new test_domain row.
*/
create or replace function insertTriggerForTestDomain_tf()
returns trigger
language plpgsql
strict as $$
declare
parentPackage test_package;
begin
if TG_OP <> 'INSERT' then
raise exception 'invalid usage of TRIGGER AFTER INSERT';
end if;
call enterTriggerForObjectUuid(NEW.uuid);
select * from test_package where uuid = NEW.packageUuid into parentPackage;
-- an owner role is created and assigned to the package's admin group
perform createRoleWithGrants(
testDomainOwner(NEW),
permissions => array['*'],
incomingSuperRoles => array[testPackageAdmin(parentPackage)]
);
-- and a domain admin role is created and assigned to the domain owner as well
perform createRoleWithGrants(
testDomainAdmin(NEW),
permissions => array['edit'],
incomingSuperRoles => array[testDomainOwner(NEW)],
outgoingSubRoles => array[testPackageTenant(parentPackage)]
);
-- a tenent role is only created on demand
call leaveTriggerForObjectUuid(NEW.uuid);
call buildRbacSystemForTestDomain(NEW);
return NEW;
end; $$;
/*
An AFTER INSERT TRIGGER which creates the role structure for a new domain.
*/
drop trigger if exists createRbacRulesForTestDomain_Trigger on test_domain;
create trigger createRbacRulesForTestDomain_Trigger
after insert
on test_domain
create trigger insertTriggerForTestDomain_tg
after insert on test_domain
for each row
execute procedure createRbacRulesForTestDomain();
execute procedure insertTriggerForTestDomain_tf();
--//
-- ============================================================================
--changeset test-domain-rbac-update-trigger:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Called from the AFTER UPDATE TRIGGER to re-wire the grants.
*/
create or replace procedure updateRbacRulesForTestDomain(
OLD test_domain,
NEW test_domain
)
language plpgsql as $$
declare
oldPackage test_package;
newPackage test_package;
begin
call enterTriggerForObjectUuid(NEW.uuid);
SELECT * FROM test_package p
WHERE p.uuid= OLD.packageUuid
into oldPackage;
SELECT * FROM test_package p
WHERE p.uuid= NEW.packageUuid
into newPackage;
if NEW.packageUuid <> OLD.packageUuid then
call revokePermissionFromRole(findPermissionId(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;
call leaveTriggerForObjectUuid(NEW.uuid);
end; $$;
/*
AFTER INSERT TRIGGER to re-wire the grant structure for a new test_domain row.
*/
create or replace function updateTriggerForTestDomain_tf()
returns trigger
language plpgsql
strict as $$
begin
call updateRbacRulesForTestDomain(OLD, NEW);
return NEW;
end; $$;
create trigger updateTriggerForTestDomain_tg
after update on test_domain
for each row
execute procedure updateTriggerForTestDomain_tf();
--//
-- ============================================================================
--changeset test-domain-rbac-INSERT:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates INSERT INTO test_domain permissions for the related test_package rows.
*/
do language plpgsql $$
declare
row test_package;
permissionUuid uuid;
roleUuid uuid;
begin
call defineContext('create INSERT INTO test_domain permissions for the related test_package rows');
FOR row IN SELECT * FROM test_package
LOOP
roleUuid := findRoleId(testPackageAdmin(row));
permissionUuid := createPermission(row.uuid, 'INSERT', 'test_domain');
call grantPermissionToRole(roleUuid, permissionUuid);
END LOOP;
END;
$$;
/**
Adds test_domain INSERT permission to specified role of new test_package rows.
*/
create or replace function test_domain_test_package_insert_tf()
returns trigger
language plpgsql
strict as $$
begin
call grantPermissionToRole(
testPackageAdmin(NEW),
createPermission(NEW.uuid, 'INSERT', 'test_domain'));
return NEW;
end; $$;
create trigger test_domain_test_package_insert_tg
after insert on test_package
for each row
execute procedure test_domain_test_package_insert_tf();
/**
Checks if the user or assumed roles are allowed to insert a row to test_domain.
*/
create or replace function test_domain_insert_permission_missing_tf()
returns trigger
language plpgsql as $$
begin
raise exception '[403] insert into test_domain not allowed for current subjects % (%)',
currentSubjects(), currentSubjectsUuids();
end; $$;
create trigger test_domain_insert_permission_check_tg
before insert on test_domain
for each row
when ( not hasInsertPermission(NEW.packageUuid, 'INSERT', 'test_domain') )
execute procedure test_domain_insert_permission_missing_tf();
--//
-- ============================================================================
--changeset test-domain-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityView('test_domain', $idName$
target.name
call generateRbacIdentityViewFromProjection('test_domain', $idName$
name
$idName$);
--//
-- ============================================================================
--changeset test-domain-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates a view to the customer main table which maps the identifying name
(in this case, the prefix) to the objectUuid.
*/
drop view if exists test_domain_rv;
create or replace view test_domain_rv as
select target.*
from test_domain as target
where target.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('view', 'domain', currentSubjectsUuids()));
grant all privileges on test_domain_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
call generateRbacRestrictedView('test_domain',
'name',
$updates$
version = new.version,
packageUuid = new.packageUuid,
description = new.description
$updates$);
--//

View File

@ -33,7 +33,7 @@ begin
perform createRoleWithGrants(
hsOfficeContactOwner(NEW),
permissions => array['*'],
permissions => array['DELETE'],
incomingSuperRoles => array[globalAdmin()],
userUuids => array[currentUserUuid()],
grantedByRole => globalAdmin()
@ -41,7 +41,7 @@ begin
perform createRoleWithGrants(
hsOfficeContactAdmin(NEW),
permissions => array['edit'],
permissions => array['UPDATE'],
incomingSuperRoles => array[hsOfficeContactOwner(NEW)]
);
@ -52,7 +52,7 @@ begin
perform createRoleWithGrants(
hsOfficeContactGuest(NEW),
permissions => array['view'],
permissions => array['SELECT'],
incomingSuperRoles => array[hsOfficeContactTenant(NEW)]
);
@ -75,7 +75,7 @@ execute procedure createRbacRolesForHsOfficeContact();
--changeset hs-office-contact-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityView('hs_office_contact', $idName$
call generateRbacIdentityViewFromProjection('hs_office_contact', $idName$
target.label
$idName$);
--//

View File

@ -31,16 +31,16 @@ begin
perform createRoleWithGrants(
hsOfficePersonOwner(NEW),
permissions => array['*'],
permissions => array['DELETE'],
incomingSuperRoles => array[globalAdmin()],
userUuids => array[currentUserUuid()],
grantedByRole => globalAdmin()
);
-- TODO: who is admin? the person itself? is it allowed for the person itself or a representative to edit the data?
-- TODO: who is admin? the person itself? is it allowed for the person itself or a representative to update the data?
perform createRoleWithGrants(
hsOfficePersonAdmin(NEW),
permissions => array['edit'],
permissions => array['UPDATE'],
incomingSuperRoles => array[hsOfficePersonOwner(NEW)]
);
@ -51,7 +51,7 @@ begin
perform createRoleWithGrants(
hsOfficePersonGuest(NEW),
permissions => array['view'],
permissions => array['SELECT'],
incomingSuperRoles => array[hsOfficePersonTenant(NEW)]
);
@ -73,7 +73,7 @@ execute procedure createRbacRolesForHsOfficePerson();
-- ============================================================================
--changeset hs-office-person-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityView('hs_office_person', $idName$
call generateRbacIdentityViewFromProjection('hs_office_person', $idName$
concat(target.tradeName, target.familyName, target.givenName)
$idName$);
--//

View File

@ -42,151 +42,3 @@ subgraph hsOfficeRelationship
end
```
if TG_OP = 'INSERT' then
-- the owner role with full access for admins of the relAnchor global admins
ownerRole = createRole(
hsOfficeRelationshipOwner(NEW),
grantingPermissions(forObjectUuid => NEW.uuid, permitOps => array ['*']),
beneathRoles(array[
globalAdmin(),
hsOfficePersonAdmin(newRelAnchor)])
);
-- the admin role with full access for the owner
adminRole = createRole(
hsOfficeRelationshipAdmin(NEW),
grantingPermissions(forObjectUuid => NEW.uuid, permitOps => array ['edit']),
beneathRole(ownerRole)
);
-- the tenant role for those related users who can view the data
perform createRole(
hsOfficeRelationshipTenant,
grantingPermissions(forObjectUuid => NEW.uuid, permitOps => array ['view']),
beneathRoles(array[
hsOfficePersonAdmin(newRelAnchor),
hsOfficePersonAdmin(newRelHolder),
hsOfficeContactAdmin(newContact)]),
withSubRoles(array[
hsOfficePersonTenant(newRelAnchor),
hsOfficePersonTenant(newRelHolder),
hsOfficeContactTenant(newContact)])
);
-- anchor and holder admin roles need each others tenant role
-- to be able to see the joined relationship
call grantRoleToRole(hsOfficePersonTenant(newRelAnchor), hsOfficePersonAdmin(newRelHolder));
call grantRoleToRole(hsOfficePersonTenant(newRelHolder), hsOfficePersonAdmin(newRelAnchor));
call grantRoleToRoleIfNotNull(hsOfficePersonTenant(newRelHolder), hsOfficeContactAdmin(newContact));
elsif TG_OP = 'UPDATE' then
if OLD.contactUuid <> NEW.contactUuid then
-- nothing but the contact can be updated,
-- in other cases, a new relationship needs to be created and the old updated
select * from hs_office_contact as c where c.uuid = OLD.contactUuid into oldContact;
call revokeRoleFromRole( hsOfficeRelationshipTenant, hsOfficeContactAdmin(oldContact) );
call grantRoleToRole( hsOfficeRelationshipTenant, hsOfficeContactAdmin(newContact) );
call revokeRoleFromRole( hsOfficeContactTenant(oldContact), hsOfficeRelationshipTenant );
call grantRoleToRole( hsOfficeContactTenant(newContact), hsOfficeRelationshipTenant );
end if;
else
raise exception 'invalid usage of TRIGGER';
end if;
return NEW;
end; $$;
/*
An AFTER INSERT TRIGGER which creates the role structure for a new customer.
*/
create trigger createRbacRolesForHsOfficeRelationship_Trigger
after insert
on hs_office_relationship
for each row
execute procedure hsOfficeRelationshipRbacRolesTrigger();
/*
An AFTER UPDATE TRIGGER which updates the role structure of a customer.
*/
create trigger updateRbacRolesForHsOfficeRelationship_Trigger
after update
on hs_office_relationship
for each row
execute procedure hsOfficeRelationshipRbacRolesTrigger();
--//
-- ============================================================================
--changeset hs-office-relationship-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityView('hs_office_relationship', $idName$
(select idName from hs_office_person_iv p where p.uuid = target.relAnchorUuid)
|| '-with-' || target.relType || '-' ||
(select idName from hs_office_person_iv p where p.uuid = target.relHolderUuid)
$idName$);
--//
-- ============================================================================
--changeset hs-office-relationship-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacRestrictedView('hs_office_relationship',
'(select idName from hs_office_person_iv p where p.uuid = target.relHolderUuid)',
$updates$
contactUuid = new.contactUuid
$updates$);
--//
-- TODO: exception if one tries to amend any other column
-- ============================================================================
--changeset hs-office-relationship-rbac-NEW-RELATHIONSHIP:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates a global permission for new-relationship and assigns it to the hostsharing admins role.
*/
do language plpgsql $$
declare
addCustomerPermissions uuid[];
globalObjectUuid uuid;
globalAdminRoleUuid uuid ;
begin
call defineContext('granting global new-relationship permission to global admin role', null, null, null);
globalAdminRoleUuid := findRoleId(globalAdmin());
globalObjectUuid := (select uuid from global);
addCustomerPermissions := createPermissions(globalObjectUuid, array ['new-relationship']);
call grantPermissionsToRole(globalAdminRoleUuid, addCustomerPermissions);
end;
$$;
/**
Used by the trigger to prevent the add-customer to current user respectively assumed roles.
*/
create or replace function addHsOfficeRelationshipNotAllowedForCurrentSubjects()
returns trigger
language PLPGSQL
as $$
begin
raise exception '[403] new-relationship not permitted for %',
array_to_string(currentSubjects(), ';', 'null');
end; $$;
/**
Checks if the user or assumed roles are allowed to create a new customer.
*/
create trigger hs_office_relationship_insert_trigger
before insert
on hs_office_relationship
for each row
-- TODO.spec: who is allowed to create new relationships
when ( not hasAssumedRole() )
execute procedure addHsOfficeRelationshipNotAllowedForCurrentSubjects();
--//

View File

@ -45,7 +45,7 @@ begin
perform createRoleWithGrants(
hsOfficeRelationshipOwner(NEW),
permissions => array['*'],
permissions => array['DELETE'],
incomingSuperRoles => array[
globalAdmin(),
hsOfficePersonAdmin(newRelAnchor)]
@ -53,14 +53,14 @@ begin
perform createRoleWithGrants(
hsOfficeRelationshipAdmin(NEW),
permissions => array['edit'],
permissions => array['UPDATE'],
incomingSuperRoles => array[hsOfficeRelationshipOwner(NEW)]
);
-- the tenant role for those related users who can view the data
perform createRoleWithGrants(
hsOfficeRelationshipTenant,
permissions => array['view'],
permissions => array['SELECT'],
incomingSuperRoles => array[
hsOfficeRelationshipAdmin(NEW),
hsOfficePersonAdmin(newRelAnchor),
@ -124,7 +124,7 @@ execute procedure hsOfficeRelationshipRbacRolesTrigger();
-- ============================================================================
--changeset hs-office-relationship-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityView('hs_office_relationship', $idName$
call generateRbacIdentityViewFromProjection('hs_office_relationship', $idName$
(select idName from hs_office_person_iv p where p.uuid = target.relAnchorUuid)
|| '-with-' || target.relType || '-' ||
(select idName from hs_office_person_iv p where p.uuid = target.relHolderUuid)

View File

@ -48,13 +48,13 @@ begin
perform createRoleWithGrants(
hsOfficePartnerOwner(NEW),
permissions => array['*'],
permissions => array['DELETE'],
incomingSuperRoles => array[globalAdmin()]
);
perform createRoleWithGrants(
hsOfficePartnerAdmin(NEW),
permissions => array['edit'],
permissions => array['UPDATE'],
incomingSuperRoles => array[
hsOfficePartnerOwner(NEW)],
outgoingSubRoles => array[
@ -84,7 +84,7 @@ begin
perform createRoleWithGrants(
hsOfficePartnerGuest(NEW),
permissions => array['view'],
permissions => array['SELECT'],
incomingSuperRoles => array[hsOfficePartnerTenant(NEW)]
);
@ -98,21 +98,21 @@ begin
--Attention: Cannot be in partner-details because of insert order (partner is not in database yet)
call grantPermissionsToRole(
getRoleId(hsOfficePartnerOwner(NEW), 'fail'),
createPermissions(NEW.detailsUuid, array ['*'])
getRoleId(hsOfficePartnerOwner(NEW)),
createPermissions(NEW.detailsUuid, array ['DELETE'])
);
call grantPermissionsToRole(
getRoleId(hsOfficePartnerAdmin(NEW), 'fail'),
createPermissions(NEW.detailsUuid, array ['edit'])
getRoleId(hsOfficePartnerAdmin(NEW)),
createPermissions(NEW.detailsUuid, array ['UPDATE'])
);
call grantPermissionsToRole(
-- Yes, here hsOfficePartnerAGENT is used, not hsOfficePartnerTENANT.
-- Do NOT grant view permission on partner-details to hsOfficePartnerTENANT!
-- Otherwise package-admins etc. would be able to read the data.
getRoleId(hsOfficePartnerAgent(NEW), 'fail'),
createPermissions(NEW.detailsUuid, array ['view'])
getRoleId(hsOfficePartnerAgent(NEW)),
createPermissions(NEW.detailsUuid, array ['SELECT'])
);
@ -187,7 +187,7 @@ execute procedure hsOfficePartnerRbacRolesTrigger();
-- ============================================================================
--changeset hs-office-partner-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityView('hs_office_partner', $idName$
call generateRbacIdentityViewFromProjection('hs_office_partner', $idName$
partnerNumber || ':' ||
(select idName from hs_office_person_iv p where p.uuid = target.personuuid)
|| '-' ||

View File

@ -7,13 +7,10 @@ call generateRelatedRbacObject('hs_office_partner_details');
--//
-- ============================================================================
--changeset hs-office-partner-details-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityView('hs_office_partner_details', $idName$
call generateRbacIdentityViewFromProjection('hs_office_partner_details', $idName$
(select idName || '-details' from hs_office_partner_iv partner_iv
join hs_office_partner partner on (partner_iv.uuid = partner.uuid)
where partner.detailsUuid = target.uuid)
@ -38,7 +35,7 @@ call generateRbacRestrictedView('hs_office_partner_details',
-- ============================================================================
--changeset hs-office-partner-details-rbac-NEW-CONTACT:1 endDelimiter:--//
--changeset hs-office-partner-details-rbac-NEW-PARTNER-DETAILS:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Creates a global permission for new-partner-details and assigns it to the hostsharing admins role.

View File

@ -4,14 +4,14 @@
flowchart TB
subgraph global
style hsOfficeBankAccount fill: #e9f7ef
style global fill: lightgray
role:global.admin[global.admin]
end
subgraph hsOfficeBankAccount
direction TB
style hsOfficeBankAccount fill: #e9f7ef
style hsOfficeBankAccount fill: lightgreen
user:hsOfficeBankAccount.creator([bankAccount.creator])

View File

@ -33,7 +33,7 @@ begin
perform createRoleWithGrants(
hsOfficeBankAccountOwner(NEW),
permissions => array['delete'],
permissions => array['DELETE'],
incomingSuperRoles => array[globalAdmin()],
userUuids => array[currentUserUuid()],
grantedByRole => globalAdmin()
@ -51,7 +51,7 @@ begin
perform createRoleWithGrants(
hsOfficeBankAccountGuest(NEW),
permissions => array['view'],
permissions => array['SELECT'],
incomingSuperRoles => array[hsOfficeBankAccountTenant(NEW)]
);
@ -74,7 +74,7 @@ execute procedure createRbacRolesForHsOfficeBankAccount();
--changeset hs-office-bankaccount-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityView('hs_office_bankaccount', $idName$
call generateRbacIdentityViewFromProjection('hs_office_bankaccount', $idName$
target.holder
$idName$);
--//

View File

@ -41,13 +41,13 @@ begin
perform createRoleWithGrants(
hsOfficeSepaMandateOwner(NEW),
permissions => array['*'],
permissions => array['DELETE'],
incomingSuperRoles => array[globalAdmin()]
);
perform createRoleWithGrants(
hsOfficeSepaMandateAdmin(NEW),
permissions => array['edit'],
permissions => array['UPDATE'],
incomingSuperRoles => array[hsOfficeSepaMandateOwner(NEW)],
outgoingSubRoles => array[hsOfficeBankAccountTenant(newHsOfficeBankAccount)]
);
@ -66,7 +66,7 @@ begin
perform createRoleWithGrants(
hsOfficeSepaMandateGuest(NEW),
permissions => array['view'],
permissions => array['SELECT'],
incomingSuperRoles => array[hsOfficeSepaMandateTenant(NEW)]
);
@ -94,7 +94,7 @@ execute procedure hsOfficeSepaMandateRbacRolesTrigger();
-- ============================================================================
--changeset hs-office-sepamandate-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityView('hs_office_sepamandate', idNameExpression => 'target.reference');
call generateRbacIdentityViewFromProjection('hs_office_sepamandate', 'target.reference');
--//

View File

@ -49,7 +49,7 @@ begin
perform createRoleWithGrants(
hsOfficeDebitorOwner(NEW),
permissions => array['*'],
permissions => array['DELETE'],
incomingSuperRoles => array[globalAdmin()],
userUuids => array[currentUserUuid()],
grantedByRole => globalAdmin()
@ -57,7 +57,7 @@ begin
perform createRoleWithGrants(
hsOfficeDebitorAdmin(NEW),
permissions => array['edit'],
permissions => array['UPDATE'],
incomingSuperRoles => array[hsOfficeDebitorOwner(NEW)]
);
@ -85,7 +85,7 @@ begin
perform createRoleWithGrants(
hsOfficeDebitorGuest(NEW),
permissions => array['view'],
permissions => array['SELECT'],
incomingSuperRoles => array[
hsOfficeDebitorTenant(NEW)]
);
@ -173,7 +173,7 @@ execute procedure hsOfficeDebitorRbacRolesTrigger();
-- ============================================================================
--changeset hs-office-debitor-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityView('hs_office_debitor', $idName$
call generateRbacIdentityViewFromProjection('hs_office_debitor', $idName$
'#' ||
(select partnerNumber from hs_office_partner p where p.uuid = target.partnerUuid) ||
to_char(debitorNumberSuffix, 'fm00') ||

View File

@ -41,13 +41,13 @@ begin
perform createRoleWithGrants(
hsOfficeMembershipOwner(NEW),
permissions => array['*'],
permissions => array['DELETE'],
incomingSuperRoles => array[globalAdmin()]
);
perform createRoleWithGrants(
hsOfficeMembershipAdmin(NEW),
permissions => array['edit'],
permissions => array['UPDATE'],
incomingSuperRoles => array[hsOfficeMembershipOwner(NEW)]
);
@ -65,7 +65,7 @@ begin
perform createRoleWithGrants(
hsOfficeMembershipGuest(NEW),
permissions => array['view'],
permissions => array['SELECT'],
incomingSuperRoles => array[hsOfficeMembershipTenant(NEW), hsOfficePartnerTenant(newHsOfficePartner), hsOfficeDebitorTenant(newHsOfficeDebitor)]
);
@ -93,7 +93,7 @@ execute procedure hsOfficeMembershipRbacRolesTrigger();
-- ============================================================================
--changeset hs-office-membership-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityView('hs_office_membership', idNameExpression => $idName$
call generateRbacIdentityViewFromProjection('hs_office_membership', $idName$
'#' ||
(select partnerNumber from hs_office_partner p where p.uuid = target.partnerUuid) ||
memberNumberSuffix ||

View File

@ -42,8 +42,8 @@ begin
-- coopsharestransactions cannot be edited nor deleted, just created+viewed
call grantPermissionsToRole(
getRoleId(hsOfficeMembershipTenant(newHsOfficeMembership), 'fail'),
createPermissions(NEW.uuid, array ['view'])
getRoleId(hsOfficeMembershipTenant(newHsOfficeMembership)),
createPermissions(NEW.uuid, array ['SELECT'])
);
else
@ -68,8 +68,7 @@ execute procedure hsOfficeCoopSharesTransactionRbacRolesTrigger();
-- ============================================================================
--changeset hs-office-coopSharesTransaction-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityView('hs_office_coopSharesTransaction',
idNameExpression => 'target.reference');
call generateRbacIdentityViewFromProjection('hs_office_coopSharesTransaction', 'target.reference');
--//

View File

@ -42,8 +42,8 @@ begin
-- coopassetstransactions cannot be edited nor deleted, just created+viewed
call grantPermissionsToRole(
getRoleId(hsOfficeMembershipTenant(newHsOfficeMembership), 'fail'),
createPermissions(NEW.uuid, array ['view'])
getRoleId(hsOfficeMembershipTenant(newHsOfficeMembership)),
createPermissions(NEW.uuid, array ['SELECT'])
);
else
@ -68,8 +68,7 @@ execute procedure hsOfficeCoopAssetsTransactionRbacRolesTrigger();
-- ============================================================================
--changeset hs-office-coopAssetsTransaction-rbac-IDENTITY-VIEW:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
call generateRbacIdentityView('hs_office_coopAssetsTransaction',
idNameExpression => 'target.reference');
call generateRbacIdentityViewFromProjection('hs_office_coopAssetsTransaction', 'target.reference');
--//