diff --git a/sql/historization.sql b/sql/historization.sql index 3c038522..2f4087b4 100644 --- a/sql/historization.sql +++ b/sql/historization.sql @@ -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; diff --git a/src/main/resources/db/changelog/031-rbac-current.sql b/src/main/resources/db/changelog/010-context.sql similarity index 59% rename from src/main/resources/db/changelog/031-rbac-current.sql rename to src/main/resources/db/changelog/010-context.sql index 2ced4045..95bc003d 100644 --- a/src/main/resources/db/changelog/031-rbac-current.sql +++ b/src/main/resources/db/changelog/010-context.sql @@ -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; $$; --// diff --git a/src/main/resources/db/changelog/030-rbac-base.sql b/src/main/resources/db/changelog/050-rbac-base.sql similarity index 100% rename from src/main/resources/db/changelog/030-rbac-base.sql rename to src/main/resources/db/changelog/050-rbac-base.sql diff --git a/src/main/resources/db/changelog/033-rbac-user-grant.sql b/src/main/resources/db/changelog/051-rbac-user-grant.sql similarity index 100% rename from src/main/resources/db/changelog/033-rbac-user-grant.sql rename to src/main/resources/db/changelog/051-rbac-user-grant.sql diff --git a/src/main/resources/db/changelog/054-rbac-context.sql b/src/main/resources/db/changelog/054-rbac-context.sql new file mode 100644 index 00000000..98745566 --- /dev/null +++ b/src/main/resources/db/changelog/054-rbac-context.sql @@ -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; $$; +--// + diff --git a/src/main/resources/db/changelog/035-rbac-views.sql b/src/main/resources/db/changelog/055-rbac-views.sql similarity index 100% rename from src/main/resources/db/changelog/035-rbac-views.sql rename to src/main/resources/db/changelog/055-rbac-views.sql diff --git a/src/main/resources/db/changelog/037-rbac-role-builder.sql b/src/main/resources/db/changelog/057-rbac-role-builder.sql similarity index 100% rename from src/main/resources/db/changelog/037-rbac-role-builder.sql rename to src/main/resources/db/changelog/057-rbac-role-builder.sql diff --git a/src/main/resources/db/changelog/039-rbac-statistics.sql b/src/main/resources/db/changelog/059-rbac-statistics.sql similarity index 100% rename from src/main/resources/db/changelog/039-rbac-statistics.sql rename to src/main/resources/db/changelog/059-rbac-statistics.sql diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index 929a6f33..b75de8f0 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -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: