RBAC generator with conditional grants used for REPRESENTATIVE-Relation (#33)
Co-authored-by: Michael Hoennig <michael@hoennig.de> Reviewed-on: https://dev.hostsharing.net/hostsharing/hs.hsadmin.ng/pulls/33 Reviewed-by: Marc Sandlus <marc.sandlus@hostsharing.net>
This commit is contained in:
@@ -248,7 +248,7 @@ declare
|
||||
objectUuidOfRole uuid;
|
||||
roleUuid uuid;
|
||||
begin
|
||||
-- TODO.refact: extract function toRbacRoleDescriptor(roleIdName varchar) + find other occurrences
|
||||
-- TODO.refa: extract function toRbacRoleDescriptor(roleIdName varchar) + find other occurrences
|
||||
roleParts = overlay(roleIdName placing '#' from length(roleIdName) + 1 - strpos(reverse(roleIdName), ':'));
|
||||
objectTableFromRoleIdName = split_part(roleParts, '#', 1);
|
||||
objectNameFromRoleIdName = split_part(roleParts, '#', 2);
|
||||
@@ -356,16 +356,13 @@ create trigger deleteRbacRolesOfRbacObject_Trigger
|
||||
/*
|
||||
|
||||
*/
|
||||
create domain RbacOp as varchar(67) -- TODO: shorten to 8, once the deprecated values are gone
|
||||
create domain RbacOp as varchar(6)
|
||||
check (
|
||||
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
|
||||
@@ -417,37 +414,6 @@ begin
|
||||
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 $$
|
||||
declare
|
||||
refId uuid;
|
||||
permissionIds uuid[] = array []::uuid[];
|
||||
begin
|
||||
if (forObjectUuid is null) then
|
||||
raise exception 'forObjectUuid must not be null';
|
||||
end if;
|
||||
|
||||
for i in array_lower(permitOps, 1)..array_upper(permitOps, 1)
|
||||
loop
|
||||
refId = (select uuid from RbacPermission where objectUuid = forObjectUuid and op = permitOps[i]);
|
||||
if (refId is null) then
|
||||
insert
|
||||
into RbacReference ("type")
|
||||
values ('RbacPermission')
|
||||
returning uuid into refId;
|
||||
insert
|
||||
into RbacPermission (uuid, objectUuid, op)
|
||||
values (refId, forObjectUuid, permitOps[i]);
|
||||
end if;
|
||||
permissionIds = permissionIds || refId;
|
||||
end loop;
|
||||
|
||||
return permissionIds;
|
||||
end;
|
||||
$$;
|
||||
|
||||
create or replace function findEffectivePermissionId(forObjectUuid uuid, forOp RbacOp, forOpTableName text = null)
|
||||
returns uuid
|
||||
returns null on null input
|
||||
@@ -649,25 +615,6 @@ begin
|
||||
end;
|
||||
$$;
|
||||
|
||||
-- TODO: deprecated, remove and use grantPermissionToRole(...)
|
||||
create or replace procedure grantPermissionsToRole(roleUuid uuid, permissionIds uuid[])
|
||||
language plpgsql as $$
|
||||
begin
|
||||
if cardinality(permissionIds) = 0 then return; end if;
|
||||
|
||||
for i in array_lower(permissionIds, 1)..array_upper(permissionIds, 1)
|
||||
loop
|
||||
perform assertReferenceType('roleId (ascendant)', roleUuid, 'RbacRole');
|
||||
perform assertReferenceType('permissionId (descendant)', permissionIds[i], 'RbacPermission');
|
||||
|
||||
insert
|
||||
into RbacGrants (grantedByTriggerOf, ascendantUuid, descendantUuid, assumed)
|
||||
values (currentTriggerObjectUuid(), roleUuid, permissionIds[i], true)
|
||||
on conflict do nothing; -- allow granting multiple times
|
||||
end loop;
|
||||
end;
|
||||
$$;
|
||||
|
||||
create or replace procedure grantRoleToRole(subRoleId uuid, superRoleId uuid, doAssume bool = true)
|
||||
language plpgsql as $$
|
||||
begin
|
||||
@@ -691,7 +638,7 @@ declare
|
||||
superRoleId uuid;
|
||||
subRoleId uuid;
|
||||
begin
|
||||
-- TODO: maybe separate method grantRoleToRoleIfNotNull(...) for NULLABLE references
|
||||
-- TODO.refa: maybe separate method grantRoleToRoleIfNotNull(...) for NULLABLE references
|
||||
if superRole.objectUuid is null or subRole.objectuuid is null then
|
||||
return;
|
||||
end if;
|
||||
@@ -712,30 +659,6 @@ begin
|
||||
on conflict do nothing; -- allow granting multiple times
|
||||
end; $$;
|
||||
|
||||
create or replace procedure grantRoleToRoleIfNotNull(subRole RbacRoleDescriptor, superRole RbacRoleDescriptor, doAssume bool = true)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
superRoleId uuid;
|
||||
subRoleId uuid;
|
||||
begin
|
||||
if ( superRoleId is null ) then return; end if;
|
||||
superRoleId := findRoleId(superRole);
|
||||
if ( subRoleId is null ) then return; end if;
|
||||
subRoleId := findRoleId(subRole);
|
||||
|
||||
perform assertReferenceType('superRoleId (ascendant)', superRoleId, 'RbacRole');
|
||||
perform assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole');
|
||||
|
||||
if isGranted(subRoleId, superRoleId) then
|
||||
call raiseDuplicateRoleGrantException(subRoleId, superRoleId);
|
||||
end if;
|
||||
|
||||
insert
|
||||
into RbacGrants (grantedByTriggerOf, ascendantuuid, descendantUuid, assumed)
|
||||
values (currentTriggerObjectUuid(), superRoleId, subRoleId, doAssume)
|
||||
on conflict do nothing; -- allow granting multiple times
|
||||
end; $$;
|
||||
|
||||
create or replace procedure revokeRoleFromRole(subRole RbacRoleDescriptor, superRole RbacRoleDescriptor)
|
||||
language plpgsql as $$
|
||||
declare
|
||||
|
@@ -20,19 +20,18 @@ begin
|
||||
return currentSubjectsUuids[1];
|
||||
end; $$;
|
||||
|
||||
create or replace procedure grantRoleToUserUnchecked(grantedByRoleUuid uuid, roleUuid uuid, userUuid uuid, doAssume boolean = true)
|
||||
create or replace procedure grantRoleToUserUnchecked(grantedByRoleUuid uuid, grantedRoleUuid uuid, userUuid uuid, doAssume boolean = true)
|
||||
language plpgsql as $$
|
||||
begin
|
||||
perform assertReferenceType('grantingRoleUuid', grantedByRoleUuid, 'RbacRole');
|
||||
perform assertReferenceType('roleId (descendant)', roleUuid, 'RbacRole');
|
||||
perform assertReferenceType('roleId (descendant)', grantedRoleUuid, 'RbacRole');
|
||||
perform assertReferenceType('userId (ascendant)', userUuid, 'RbacUser');
|
||||
|
||||
insert
|
||||
into RbacGrants (grantedByRoleUuid, ascendantUuid, descendantUuid, assumed)
|
||||
values (grantedByRoleUuid, userUuid, roleUuid, doAssume);
|
||||
-- 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
|
||||
values (grantedByRoleUuid, userUuid, grantedRoleUuid, doAssume)
|
||||
-- TODO: check if grantedByRoleUuid+doAssume are the same, otherwise raise exception?
|
||||
on conflict do nothing; -- allow granting multiple times
|
||||
end; $$;
|
||||
|
||||
create or replace procedure grantRoleToUser(grantedByRoleUuid uuid, grantedRoleUuid uuid, userUuid uuid, doAssume boolean = true)
|
||||
|
@@ -6,6 +6,7 @@
|
||||
--changeset rbac-role-builder-create-role:1 endDelimiter:--//
|
||||
-- -----------------------------------------------------------------
|
||||
|
||||
-- TODO: rename to defineRoleWithGrants because it does not complain if the role already exists
|
||||
create or replace function createRoleWithGrants(
|
||||
roleDescriptor RbacRoleDescriptor,
|
||||
permissions RbacOp[] = array[]::RbacOp[],
|
||||
@@ -28,7 +29,7 @@ declare
|
||||
userUuid uuid;
|
||||
userGrantsByRoleUuid uuid;
|
||||
begin
|
||||
roleUuid := createRole(roleDescriptor);
|
||||
roleUuid := coalesce(findRoleId(roleDescriptor), createRole(roleDescriptor));
|
||||
|
||||
foreach permission in array permissions
|
||||
loop
|
||||
|
Reference in New Issue
Block a user