2022-09-16 15:25:58 +02:00
|
|
|
--liquibase formatted sql
|
|
|
|
|
|
|
|
|
|
|
|
-- ============================================================================
|
|
|
|
--changeset rbac-generators-RELATED-OBJECT:1 endDelimiter:--//
|
|
|
|
-- ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
create or replace procedure generateRelatedRbacObject(targetTable varchar)
|
|
|
|
language plpgsql as $$
|
|
|
|
declare
|
|
|
|
createInsertTriggerSQL text;
|
|
|
|
createDeleteTriggerSQL text;
|
|
|
|
begin
|
|
|
|
createInsertTriggerSQL = format($sql$
|
|
|
|
create trigger createRbacObjectFor_%s_Trigger
|
2024-03-11 12:30:43 +01:00
|
|
|
before insert on %s
|
2022-09-16 15:25:58 +02:00
|
|
|
for each row
|
|
|
|
execute procedure insertRelatedRbacObject();
|
|
|
|
$sql$, targetTable, targetTable);
|
|
|
|
execute createInsertTriggerSQL;
|
|
|
|
|
|
|
|
createDeleteTriggerSQL = format($sql$
|
|
|
|
create trigger deleteRbacRulesFor_%s_Trigger
|
2022-09-19 20:43:14 +02:00
|
|
|
after delete
|
2022-09-16 15:25:58 +02:00
|
|
|
on %s
|
|
|
|
for each row
|
|
|
|
execute procedure deleteRelatedRbacObject();
|
|
|
|
$sql$, targetTable, targetTable);
|
|
|
|
execute createDeleteTriggerSQL;
|
|
|
|
end; $$;
|
|
|
|
--//
|
|
|
|
|
|
|
|
|
|
|
|
-- ============================================================================
|
|
|
|
--changeset rbac-generators-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
|
|
|
-- ----------------------------------------------------------------------------
|
|
|
|
|
2024-03-11 12:30:43 +01:00
|
|
|
create procedure generateRbacRoleDescriptors(prefix text, targetTable text)
|
2022-09-16 15:25:58 +02:00
|
|
|
language plpgsql as $$
|
|
|
|
declare
|
|
|
|
sql text;
|
|
|
|
begin
|
|
|
|
sql = format($sql$
|
2024-03-11 12:30:43 +01:00
|
|
|
create or replace function %1$sOwner(entity %2$s, assumed boolean = true)
|
2022-09-16 15:25:58 +02:00
|
|
|
returns RbacRoleDescriptor
|
|
|
|
language plpgsql
|
|
|
|
strict as $f$
|
|
|
|
begin
|
2024-04-02 12:01:37 +02:00
|
|
|
return roleDescriptor('%2$s', entity.uuid, 'OWNER', assumed);
|
2022-09-16 15:25:58 +02:00
|
|
|
end; $f$;
|
|
|
|
|
2024-03-11 12:30:43 +01:00
|
|
|
create or replace function %1$sAdmin(entity %2$s, assumed boolean = true)
|
2022-09-16 15:25:58 +02:00
|
|
|
returns RbacRoleDescriptor
|
|
|
|
language plpgsql
|
|
|
|
strict as $f$
|
|
|
|
begin
|
2024-04-02 12:01:37 +02:00
|
|
|
return roleDescriptor('%2$s', entity.uuid, 'ADMIN', assumed);
|
2022-09-16 15:25:58 +02:00
|
|
|
end; $f$;
|
|
|
|
|
2024-03-11 12:30:43 +01:00
|
|
|
create or replace function %1$sAgent(entity %2$s, assumed boolean = true)
|
2022-10-12 15:48:56 +02:00
|
|
|
returns RbacRoleDescriptor
|
|
|
|
language plpgsql
|
|
|
|
strict as $f$
|
|
|
|
begin
|
2024-04-02 12:01:37 +02:00
|
|
|
return roleDescriptor('%2$s', entity.uuid, 'AGENT', assumed);
|
2022-10-12 15:48:56 +02:00
|
|
|
end; $f$;
|
|
|
|
|
2024-03-11 12:30:43 +01:00
|
|
|
create or replace function %1$sTenant(entity %2$s, assumed boolean = true)
|
2022-09-16 15:25:58 +02:00
|
|
|
returns RbacRoleDescriptor
|
|
|
|
language plpgsql
|
|
|
|
strict as $f$
|
|
|
|
begin
|
2024-04-02 12:01:37 +02:00
|
|
|
return roleDescriptor('%2$s', entity.uuid, 'TENANT', assumed);
|
2022-09-16 15:25:58 +02:00
|
|
|
end; $f$;
|
|
|
|
|
2024-03-26 11:25:18 +01:00
|
|
|
-- TODO: remove guest role
|
2024-03-11 12:30:43 +01:00
|
|
|
create or replace function %1$sGuest(entity %2$s, assumed boolean = true)
|
2022-10-12 15:48:56 +02:00
|
|
|
returns RbacRoleDescriptor
|
|
|
|
language plpgsql
|
|
|
|
strict as $f$
|
|
|
|
begin
|
2024-04-02 12:01:37 +02:00
|
|
|
return roleDescriptor('%2$s', entity.uuid, 'GUEST', assumed);
|
2022-10-12 15:48:56 +02:00
|
|
|
end; $f$;
|
|
|
|
|
2024-03-26 11:25:18 +01:00
|
|
|
create or replace function %1$sReferrer(entity %2$s)
|
|
|
|
returns RbacRoleDescriptor
|
|
|
|
language plpgsql
|
|
|
|
strict as $f$
|
|
|
|
begin
|
2024-04-02 12:01:37 +02:00
|
|
|
return roleDescriptor('%2$s', entity.uuid, 'REFERRER');
|
2024-03-26 11:25:18 +01:00
|
|
|
end; $f$;
|
|
|
|
|
2022-09-16 15:25:58 +02:00
|
|
|
$sql$, prefix, targetTable);
|
|
|
|
execute sql;
|
|
|
|
end; $$;
|
|
|
|
--//
|
2022-09-16 16:14:39 +02:00
|
|
|
|
|
|
|
|
|
|
|
-- ============================================================================
|
|
|
|
--changeset rbac-generators-IDENTITY-VIEW:1 endDelimiter:--//
|
|
|
|
-- ----------------------------------------------------------------------------
|
|
|
|
|
2024-03-11 12:30:43 +01:00
|
|
|
create or replace procedure generateRbacIdentityViewFromQuery(targetTable text, sqlQuery text)
|
2022-09-16 16:14:39 +02:00
|
|
|
language plpgsql as $$
|
|
|
|
declare
|
|
|
|
sql text;
|
|
|
|
begin
|
2022-10-19 07:39:10 +02:00
|
|
|
targettable := lower(targettable);
|
|
|
|
|
2022-09-16 16:14:39 +02:00
|
|
|
-- create a view to the target main table which maps an idName to the objectUuid
|
|
|
|
sql = format($sql$
|
2024-03-11 12:30:43 +01:00
|
|
|
create or replace view %1$s_iv as %2$s;
|
2024-01-23 15:11:23 +01:00
|
|
|
grant all privileges on %1$s_iv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
|
2024-03-11 12:30:43 +01:00
|
|
|
$sql$, targetTable, sqlQuery);
|
2022-09-16 16:14:39 +02:00
|
|
|
execute sql;
|
|
|
|
|
|
|
|
-- creates a function which maps an idName to the objectUuid
|
|
|
|
sql = format($sql$
|
|
|
|
create or replace function %1$sUuidByIdName(givenIdName varchar)
|
|
|
|
returns uuid
|
2024-06-06 13:46:14 +02:00
|
|
|
language plpgsql as $f$
|
|
|
|
declare
|
|
|
|
singleMatch uuid;
|
|
|
|
begin
|
|
|
|
select uuid into strict singleMatch from %1$s_iv iv where iv.idName = givenIdName;
|
|
|
|
return singleMatch;
|
|
|
|
end; $f$;
|
2022-09-16 16:14:39 +02:00
|
|
|
$sql$, targetTable);
|
|
|
|
execute sql;
|
|
|
|
|
|
|
|
-- creates a function which maps an objectUuid to the related idName
|
|
|
|
sql = format($sql$
|
|
|
|
create or replace function %1$sIdNameByUuid(givenUuid uuid)
|
|
|
|
returns varchar
|
|
|
|
language sql
|
|
|
|
strict as $f$
|
|
|
|
select idName from %1$s_iv iv where iv.uuid = givenUuid;
|
|
|
|
$f$;
|
|
|
|
$sql$, targetTable);
|
|
|
|
execute sql;
|
|
|
|
end; $$;
|
2024-03-11 12:30:43 +01:00
|
|
|
|
|
|
|
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; $$;
|
2022-09-16 16:14:39 +02:00
|
|
|
--//
|
2022-09-19 20:43:14 +02:00
|
|
|
|
|
|
|
|
|
|
|
-- ============================================================================
|
|
|
|
--changeset rbac-generators-RESTRICTED-VIEW:1 endDelimiter:--//
|
|
|
|
-- ----------------------------------------------------------------------------
|
|
|
|
|
2024-03-26 11:25:18 +01:00
|
|
|
create or replace procedure generateRbacRestrictedView(targetTable text, orderBy text, columnUpdates text = null, columnNames text = '*')
|
2022-09-19 20:43:14 +02:00
|
|
|
language plpgsql as $$
|
|
|
|
declare
|
|
|
|
sql text;
|
2024-03-26 11:25:18 +01:00
|
|
|
newColumns text;
|
2022-09-19 20:43:14 +02:00
|
|
|
begin
|
2022-10-19 07:39:10 +02:00
|
|
|
targetTable := lower(targetTable);
|
2024-03-26 11:25:18 +01:00
|
|
|
if columnNames = '*' then
|
|
|
|
columnNames := columnsNames(targetTable);
|
|
|
|
end if;
|
2022-10-19 07:39:10 +02:00
|
|
|
|
2022-09-19 20:43:14 +02:00
|
|
|
/*
|
2024-03-11 12:30:43 +01:00
|
|
|
Creates a restricted view based on the 'SELECT' permission of the current subject.
|
2022-09-19 20:43:14 +02:00
|
|
|
*/
|
|
|
|
sql := format($sql$
|
2024-07-27 10:18:07 +02:00
|
|
|
create or replace view %1$s_rv as
|
|
|
|
with accessible_%1$s_uuids as (
|
|
|
|
|
|
|
|
with recursive grants as (
|
|
|
|
select descendantUuid, ascendantUuid, 1 as level
|
|
|
|
from RbacGrants
|
|
|
|
where assumed
|
|
|
|
and ascendantUuid = any (currentSubjectsuUids())
|
|
|
|
union all
|
|
|
|
select g.descendantUuid, g.ascendantUuid, level + 1 as level
|
|
|
|
from RbacGrants g
|
|
|
|
inner join grants on grants.descendantUuid = g.ascendantUuid
|
|
|
|
where g.assumed
|
|
|
|
),
|
|
|
|
granted as (
|
|
|
|
select distinct descendantUuid
|
|
|
|
from grants
|
|
|
|
)
|
|
|
|
select distinct perm.objectUuid as objectUuid
|
|
|
|
from granted
|
|
|
|
join RbacPermission perm on granted.descendantUuid = perm.uuid
|
|
|
|
join RbacObject obj on obj.uuid = perm.objectUuid
|
|
|
|
where perm.op = 'SELECT'
|
|
|
|
and obj.objectTable = '%1$s'
|
|
|
|
limit 8001
|
2022-10-17 12:18:12 +02:00
|
|
|
)
|
|
|
|
select target.*
|
|
|
|
from %1$s as target
|
2024-07-27 10:18:07 +02:00
|
|
|
where target.uuid in (select * from accessible_%1$s_uuids)
|
2022-10-17 12:18:12 +02:00
|
|
|
order by %2$s;
|
2024-07-27 10:18:07 +02:00
|
|
|
|
|
|
|
grant all privileges on %1$s_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};
|
2022-09-19 20:43:14 +02:00
|
|
|
$sql$, targetTable, orderBy);
|
|
|
|
execute sql;
|
|
|
|
|
|
|
|
/**
|
|
|
|
Instead of insert trigger function for the restricted view.
|
|
|
|
*/
|
2024-03-26 11:25:18 +01:00
|
|
|
newColumns := 'new.' || replace(columnNames, ',', ', new.');
|
2022-09-19 20:43:14 +02:00
|
|
|
sql := format($sql$
|
2024-03-26 11:25:18 +01:00
|
|
|
create or replace function %1$sInsert()
|
|
|
|
returns trigger
|
|
|
|
language plpgsql as $f$
|
|
|
|
declare
|
|
|
|
newTargetRow %1$s;
|
|
|
|
begin
|
|
|
|
insert
|
|
|
|
into %1$s (%2$s)
|
|
|
|
values (%3$s)
|
|
|
|
returning * into newTargetRow;
|
|
|
|
return newTargetRow;
|
|
|
|
end; $f$;
|
|
|
|
$sql$, targetTable, columnNames, newColumns);
|
2022-09-19 20:43:14 +02:00
|
|
|
execute sql;
|
|
|
|
|
|
|
|
/*
|
|
|
|
Creates an instead of insert trigger for the restricted view.
|
|
|
|
*/
|
|
|
|
sql := format($sql$
|
|
|
|
create trigger %1$sInsert_tg
|
|
|
|
instead of insert
|
|
|
|
on %1$s_rv
|
|
|
|
for each row
|
|
|
|
execute function %1$sInsert();
|
|
|
|
$sql$, targetTable);
|
|
|
|
execute sql;
|
|
|
|
|
|
|
|
/**
|
|
|
|
Instead of delete trigger function for the restricted view.
|
|
|
|
*/
|
|
|
|
sql := format($sql$
|
|
|
|
create or replace function %1$sDelete()
|
|
|
|
returns trigger
|
|
|
|
language plpgsql as $f$
|
|
|
|
begin
|
2024-03-11 12:30:43 +01:00
|
|
|
if old.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('DELETE', '%1$s', currentSubjectsUuids())) then
|
2022-09-19 20:43:14 +02:00
|
|
|
delete from %1$s p where p.uuid = old.uuid;
|
|
|
|
return old;
|
|
|
|
end if;
|
|
|
|
raise exception '[403] Subject %% is not allowed to delete %1$s uuid %%', currentSubjectsUuids(), old.uuid;
|
|
|
|
end; $f$;
|
|
|
|
$sql$, targetTable);
|
|
|
|
execute sql;
|
|
|
|
|
|
|
|
/*
|
|
|
|
Creates an instead of delete trigger for the restricted view.
|
|
|
|
*/
|
|
|
|
sql := format($sql$
|
|
|
|
create trigger %1$sDelete_tg
|
|
|
|
instead of delete
|
|
|
|
on %1$s_rv
|
|
|
|
for each row
|
|
|
|
execute function %1$sDelete();
|
|
|
|
$sql$, targetTable);
|
|
|
|
execute sql;
|
|
|
|
|
|
|
|
/**
|
|
|
|
Instead of update trigger function for the restricted view
|
2024-03-11 12:30:43 +01:00
|
|
|
based on the 'UPDATE' permission of the current subject.
|
2022-09-19 20:43:14 +02:00
|
|
|
*/
|
2022-10-18 17:29:10 +02:00
|
|
|
if columnUpdates is not null then
|
|
|
|
sql := format($sql$
|
|
|
|
create or replace function %1$sUpdate()
|
|
|
|
returns trigger
|
|
|
|
language plpgsql as $f$
|
|
|
|
begin
|
2024-03-11 12:30:43 +01:00
|
|
|
if old.uuid in (select queryAccessibleObjectUuidsOfSubjectIds('UPDATE', '%1$s', currentSubjectsUuids())) then
|
2022-10-18 17:29:10 +02:00
|
|
|
update %1$s
|
|
|
|
set %2$s
|
|
|
|
where uuid = old.uuid;
|
|
|
|
return old;
|
|
|
|
end if;
|
|
|
|
raise exception '[403] Subject %% is not allowed to update %1$s uuid %%', currentSubjectsUuids(), old.uuid;
|
|
|
|
end; $f$;
|
|
|
|
$sql$, targetTable, columnUpdates);
|
|
|
|
execute sql;
|
|
|
|
|
|
|
|
/*
|
|
|
|
Creates an instead of delete trigger for the restricted view.
|
|
|
|
*/
|
|
|
|
sql = format($sql$
|
|
|
|
create trigger %1$sUpdate_tg
|
|
|
|
instead of update
|
|
|
|
on %1$s_rv
|
|
|
|
for each row
|
|
|
|
execute function %1$sUpdate();
|
|
|
|
$sql$, targetTable);
|
|
|
|
execute sql;
|
|
|
|
end if;
|
2022-09-19 20:43:14 +02:00
|
|
|
end; $$;
|
|
|
|
--//
|