re-numbering rbac db-migration scripts while extracting context (currentUser etc.)

This commit is contained in:
Michael Hoennig 2022-08-23 14:36:22 +02:00
parent 661f23e1e2
commit 81cfbc62e4
9 changed files with 127 additions and 76 deletions

View File

@ -107,7 +107,7 @@ END; $$;
CREATE OR REPLACE PROCEDURE create_historicization(baseTable varchar)
LANGUAGE plpgsql AS $$
DECLARE
createHistTableSql varchar;
createHistTableSql varchar;
createTriggerSQL varchar;
viewName varchar;
versionsTable varchar;

View File

@ -1,7 +1,36 @@
--liquibase formatted sql
-- ============================================================================
--changeset rbac-current-CURRENT-USER:1 endDelimiter:--//
--changeset context-CURRENT-TASK:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Returns the current tas as set by `hsadminng.currentTask`.
Raises exception if not set.
*/
create or replace function currentTask()
returns varchar(96)
stable leakproof
language plpgsql as $$
declare
currentTask varchar(96);
begin
begin
currentTask := current_setting('hsadminng.currentTask');
exception
when others then
currentTask := null;
end;
if (currentTask is null or currentTask = '') then
raise exception '[401] hsadminng.currentTask must be defined, please use "SET LOCAL ...;"';
end if;
raise debug 'currentTask: %', currentTask;
return currentTask;
end; $$;
--//
-- ============================================================================
--changeset context-CURRENT-USER:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Returns the current user as set by `hsadminng.currentUser`.
@ -26,26 +55,10 @@ begin
raise debug 'currentUser: %', currentUser;
return currentUser;
end; $$;
create or replace function currentUserId()
returns uuid
stable leakproof
language plpgsql as $$
declare
currentUser varchar(63);
currentUserId uuid;
begin
currentUser := currentUser();
currentUserId = (select uuid from RbacUser where name = currentUser);
if currentUserId is null then
raise exception '[401] hsadminng.currentUser defined as %, but does not exists', currentUser;
end if;
return currentUserId;
end; $$;
--//
-- ============================================================================
--changeset rbac-current-ASSUMED-ROLES:1 endDelimiter:--//
--changeset context-ASSUMED-ROLES:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Returns assumed role names as set in `hsadminng.assumedRoles`
@ -133,56 +146,5 @@ begin
return array [currentUser()]::varchar(63)[];
end if;
end; $$;
create or replace function currentSubjectIds()
returns uuid[]
stable leakproof
language plpgsql as $$
declare
currentUserId uuid;
roleNames varchar(63)[];
roleName varchar(63);
objectTableToAssume varchar(63);
objectNameToAssume varchar(63);
objectUuidToAssume uuid;
roleTypeToAssume RbacRoleType;
roleIdsToAssume uuid[];
roleUuidToAssume uuid;
begin
currentUserId := currentUserId();
if currentUserId is null then
raise exception '[401] user % does not exist', currentUser();
end if;
roleNames := assumedRoles();
if cardinality(roleNames) = 0 then
return array [currentUserId];
end if;
raise notice 'assuming roles: %', roleNames;
foreach roleName in array roleNames
loop
roleName = overlay(roleName placing '#' from length(roleName) + 1 - strpos(reverse(roleName), '.'));
objectTableToAssume = split_part(roleName, '#', 1);
objectNameToAssume = split_part(roleName, '#', 2);
roleTypeToAssume = split_part(roleName, '#', 3);
objectUuidToAssume = findObjectUuidByIdName(objectTableToAssume, objectNameToAssume);
-- TODO: either the result needs to be cached at least per transaction or we need to get rid of SELCT in a loop
select uuid as roleuuidToAssume
from RbacRole r
where r.objectUuid = objectUuidToAssume
and r.roleType = roleTypeToAssume
into roleUuidToAssume;
if (not isGranted(currentUserId, roleUuidToAssume)) then
raise exception '[403] user % (%) has no permission to assume role % (%)', currentUser(), currentUserId, roleName, roleUuidToAssume;
end if;
roleIdsToAssume := roleIdsToAssume || roleUuidToAssume;
end loop;
return roleIdsToAssume;
end; $$;
--//

View File

@ -0,0 +1,87 @@
--liquibase formatted sql
-- ============================================================================
--changeset rbac-context-CURRENT-USER-ID:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Returns the id of the current user as set by `hsadminng.currentUser`.
Raises exception if not set.
*/
create or replace function currentUserId()
returns uuid
stable leakproof
language plpgsql as $$
declare
currentUser varchar(63);
currentUserId uuid;
begin
currentUser := currentUser();
currentUserId = (select uuid from RbacUser where name = currentUser);
if currentUserId is null then
raise exception '[401] hsadminng.currentUser defined as %, but does not exists', currentUser;
end if;
return currentUserId;
end; $$;
--//
-- ============================================================================
--changeset rbac-context-CURRENT-SUBJECT-IDS:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
/*
Returns id of current user as set in `hsadminng.currentUser`
or, if any, ids of assumed role names as set in `hsadminng.assumedRoles`
or empty array, if not set.
*/
create or replace function currentSubjectIds()
returns uuid[]
stable leakproof
language plpgsql as $$
declare
currentUserId uuid;
roleNames varchar(63)[];
roleName varchar(63);
objectTableToAssume varchar(63);
objectNameToAssume varchar(63);
objectUuidToAssume uuid;
roleTypeToAssume RbacRoleType;
roleIdsToAssume uuid[];
roleUuidToAssume uuid;
begin
currentUserId := currentUserId();
if currentUserId is null then
raise exception '[401] user % does not exist', currentUser();
end if;
roleNames := assumedRoles();
if cardinality(roleNames) = 0 then
return array [currentUserId];
end if;
raise notice 'assuming roles: %', roleNames;
foreach roleName in array roleNames
loop
roleName = overlay(roleName placing '#' from length(roleName) + 1 - strpos(reverse(roleName), '.'));
objectTableToAssume = split_part(roleName, '#', 1);
objectNameToAssume = split_part(roleName, '#', 2);
roleTypeToAssume = split_part(roleName, '#', 3);
objectUuidToAssume = findObjectUuidByIdName(objectTableToAssume, objectNameToAssume);
-- TODO: either the result needs to be cached at least per transaction or we need to get rid of SELCT in a loop
select uuid as roleuuidToAssume
from RbacRole r
where r.objectUuid = objectUuidToAssume
and r.roleType = roleTypeToAssume
into roleUuidToAssume;
if (not isGranted(currentUserId, roleUuidToAssume)) then
raise exception '[403] user % (%) has no permission to assume role % (%)', currentUser(), currentUserId, roleName, roleUuidToAssume;
end if;
roleIdsToAssume := roleIdsToAssume || roleUuidToAssume;
end loop;
return roleIdsToAssume;
end; $$;
--//

View File

@ -10,17 +10,19 @@ databaseChangeLog:
- include:
file: db/changelog/005-uuid-ossp-extension.sql
- include:
file: db/changelog/030-rbac-base.sql
file: db/changelog/010-context.sql
- include:
file: db/changelog/031-rbac-current.sql
file: db/changelog/050-rbac-base.sql
- include:
file: db/changelog/033-rbac-user-grant.sql
file: db/changelog/051-rbac-user-grant.sql
- include:
file: db/changelog/035-rbac-views.sql
file: db/changelog/054-rbac-context.sql
- include:
file: db/changelog/037-rbac-role-builder.sql
file: db/changelog/055-rbac-views.sql
- include:
file: db/changelog/039-rbac-statistics.sql
file: db/changelog/057-rbac-role-builder.sql
- include:
file: db/changelog/059-rbac-statistics.sql
- include:
file: db/changelog/100-hs-base.sql
- include: