introduce separate database-schema for hs_booking

This commit is contained in:
Michael Hoennig 2024-09-18 13:28:36 +02:00
parent 23b60641e3
commit a43088cb81
37 changed files with 229 additions and 217 deletions

View File

@ -283,8 +283,8 @@ At this point, the import took 21mins with these statistics:
| call buildRbacSystemForHsOfficeRelation(NEW) | 1276 | 0 | 8 |
| with recursive grants as ( select descendantUuid, ascendantUuid from RbacGrants where descendantUuid = grantedId union all select ""grant"".descendantUuid, ""grant"".ascendantUuid from RbacGrants ""grant"" inner join grants recur on recur.ascendantUuid = ""grant"".descendantUuid ) select exists ( select $3 from grants where ascendantUuid = any(granteeIds) ) or grantedId = any(granteeIds) | 47540 | 0 | 0 |
| insert into RbacGrants (grantedByTriggerOf, ascendantuuid, descendantUuid, assumed) values (currentTriggerObjectUuid(), superRoleId, subRoleId, doAssume) on conflict do nothing" | 40472 | 0 | 0 |
| insert into public.hs_booking_item_rv (caption,parentitemuuid,projectuuid,resources,type,validity,version,uuid) values ($1,$2,$3,$4,$5,$6,$7,$8) | 926 | 0 | 7 |
| insert into hs_booking_item (resources, version, projectuuid, type, parentitemuuid, validity, uuid, caption) values (new.resources, new. version, new. projectuuid, new. type, new. parentitemuuid, new. validity, new. uuid, new. caption) returning * | 926 | 0 | 7 |
| insert into public.hs_booking.item_rv (caption,parentitemuuid,projectuuid,resources,type,validity,version,uuid) values ($1,$2,$3,$4,$5,$6,$7,$8) | 926 | 0 | 7 |
| insert into hs_booking.item (resources, version, projectuuid, type, parentitemuuid, validity, uuid, caption) values (new.resources, new. version, new. projectuuid, new. type, new. parentitemuuid, new. validity, new. uuid, new. caption) returning * | 926 | 0 | 7 |
The slowest query now was fetching Relations joined with Contact, Anchor-Person and Holder-Person, for all tables using the restricted (RBAC) views (_rv).
@ -306,8 +306,8 @@ We changed these mappings from `EAGER` (default) to `LAZY` to `@ManyToOne(fetch
insert into public.hs_office.relation_rv (anchoruuid,contactuuid,holderuuid,mark,type,version,uuid) values ($1,$2,$3,$4,$5,$6,$7) | 1261 | 0 | 8 |
| insert into hs_office.relation (uuid, version, anchoruuid, holderuuid, contactuuid, type, mark) values (new.uuid, new. version, new. anchoruuid, new. holderuuid, new. contactuuid, new. type, new. mark) returning * | 1261 | 0 | 8 |
| call buildRbacSystemForHsOfficeRelation(NEW) | 1276 | 0 | 7 |
| insert into public.hs_booking_item_rv (caption,parentitemuuid,projectuuid,resources,type,validity,version,uuid) values ($1,$2,$3,$4,$5,$6,$7,$8) | 926 | 0 | 7 |
| insert into hs_booking_item (resources, version, projectuuid, type, parentitemuuid, validity, uuid, caption) values (new.resources, new. version, new. projectuuid, new. type, new. parentitemuuid, new. validity, new. uuid, new. caption) returning * | 926 | 0 | 7 |
| insert into public.hs_booking.item_rv (caption,parentitemuuid,projectuuid,resources,type,validity,version,uuid) values ($1,$2,$3,$4,$5,$6,$7,$8) | 926 | 0 | 7 |
| insert into hs_booking.item (resources, version, projectuuid, type, parentitemuuid, validity, uuid, caption) values (new.resources, new. version, new. projectuuid, new. type, new. parentitemuuid, new. validity, new. uuid, new. caption) returning * | 926 | 0 | 7 |
insert into RbacGrants (grantedByTriggerOf, ascendantuuid, descendantUuid, assumed) values (currentTriggerObjectUuid(), superRoleId, subRoleId, doAssume) on conflict do nothing | 40472 | 0 | 0 |
Now, finally, the total runtime of the import was down to 12 minutes. This is repeatable, where originally, the import took about 25mins in most cases and just rarely - and for unknown reasons - 10min.

View File

@ -6,10 +6,10 @@
rollback;
begin transaction;
call defineContext('historization testing', null, 'superuser-alex@hostsharing.net',
-- 'hs_booking_project#D-1000000-hshdefaultproject:ADMIN'); -- prod+test
'hs_booking_project#D-1000313-D-1000313defaultproject:ADMIN'); -- prod+test
-- 'hs_booking_project#D-1000300-mihdefaultproject:ADMIN'); -- prod
-- 'hs_booking_project#D-1000300-mimdefaultproject:ADMIN'); -- test
-- 'hs_booking.project#D-1000000-hshdefaultproject:ADMIN'); -- prod+test
'hs_booking.project#D-1000313-D-1000313defaultproject:ADMIN'); -- prod+test
-- 'hs_booking.project#D-1000300-mihdefaultproject:ADMIN'); -- prod
-- 'hs_booking.project#D-1000300-mimdefaultproject:ADMIN'); -- test
-- update hs_hosting_asset set caption='lug00 b' where identifier = 'lug00' and type = 'MANAGED_WEBSPACE'; -- prod
-- update hs_hosting_asset set caption='hsh00 A ' || now()::text where identifier = 'hsh00' and type = 'MANAGED_WEBSPACE'; -- test
-- update hs_hosting_asset set caption='hsh00 B ' || now()::text where identifier = 'hsh00' and type = 'MANAGED_WEBSPACE'; -- test

View File

@ -53,8 +53,8 @@ select distinct perm.objectuuid
rollback transaction;
begin transaction;
CALL defineContext('performance testing', null, 'superuser-alex@hostsharing.net',
'hs_booking_project#D-1000000-hshdefaultproject:ADMIN');
-- 'hs_booking_project#D-1000300-mihdefaultproject:ADMIN');
'hs_booking.project#D-1000000-hshdefaultproject:ADMIN');
-- 'hs_booking.project#D-1000300-mihdefaultproject:ADMIN');
SET TRANSACTION READ ONLY;
EXPLAIN ANALYZE select * from hs_hosting_asset_example_gv;
end transaction ;
@ -89,8 +89,8 @@ BEGIN
start_time := clock_timestamp();
CALL defineContext('performance testing', null, 'superuser-alex@hostsharing.net',
'hs_booking_project#D-1000000-hshdefaultproject:ADMIN');
-- 'hs_booking_project#D-1000300-mihdefaultproject:ADMIN');
'hs_booking.project#D-1000000-hshdefaultproject:ADMIN');
-- 'hs_booking.project#D-1000300-mihdefaultproject:ADMIN');
SET TRANSACTION READ ONLY;
FOR i IN 0..25 LOOP
@ -128,8 +128,8 @@ $$;
rollback transaction;
begin transaction;
CALL defineContext('performance testing', null, 'superuser-alex@hostsharing.net',
'hs_booking_project#D-1000000-hshdefaultproject:ADMIN');
-- 'hs_booking_project#D-1000300-mihdefaultproject:ADMIN');
'hs_booking.project#D-1000000-hshdefaultproject:ADMIN');
-- 'hs_booking.project#D-1000300-mihdefaultproject:ADMIN');
SET TRANSACTION READ ONLY;
EXPLAIN SELECT * from (

View File

@ -18,7 +18,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
// a partial HsOfficeDebitorEntity to reduce the number of SQL queries to load the entity
@Entity
@Table(name = "hs_booking_debitor_xv")
@Table(schema = "hs_booking", name = "debitor_xv")
@Getter
@Builder
@NoArgsConstructor

View File

@ -31,7 +31,7 @@ import static net.hostsharing.hsadminng.rbac.generator.RbacView.SQL.directlyFetc
import static net.hostsharing.hsadminng.rbac.generator.RbacView.rbacViewFor;
@Entity
@Table(name = "hs_booking_item_rv")
@Table(schema = "hs_booking", name = "item_rv")
@SuperBuilder(toBuilder = true)
@Getter
@Setter

View File

@ -13,7 +13,7 @@ import jakarta.persistence.Table;
@Entity
@Table(name = "hs_booking_item")
@Table(schema = "hs_booking", name = "item")
@SuperBuilder(toBuilder = true)
@Getter
@Setter

View File

@ -71,7 +71,7 @@ public abstract class HsBookingProject implements Stringifyable, BaseEntity<HsBo
return rbacViewFor("project", HsBookingProjectRbacEntity.class)
.withIdentityView(SQL.query("""
SELECT bookingProject.uuid as uuid, debitorIV.idName || '-' || base.cleanIdentifier(bookingProject.caption) as idName
FROM hs_booking_project bookingProject
FROM hs_booking.project bookingProject
JOIN hs_office.debitor_iv debitorIV ON debitorIV.uuid = bookingProject.debitorUuid
"""))
.withRestrictedViewOrderBy(SQL.expression("caption"))

View File

@ -32,7 +32,7 @@ import static net.hostsharing.hsadminng.rbac.generator.RbacView.SQL.fetchedBySql
import static net.hostsharing.hsadminng.rbac.generator.RbacView.rbacViewFor;
@Entity
@Table(name = "hs_booking_project_rv")
@Table(schema = "hs_booking", name = "project_rv")
@SuperBuilder(toBuilder = true)
@Getter
@Setter
@ -43,7 +43,7 @@ public class HsBookingProjectRbacEntity extends HsBookingProject {
return rbacViewFor("project", HsBookingProjectRbacEntity.class)
.withIdentityView(SQL.query("""
SELECT bookingProject.uuid as uuid, debitorIV.idName || '-' || base.cleanIdentifier(bookingProject.caption) as idName
FROM hs_booking_project bookingProject
FROM hs_booking.project bookingProject
JOIN hs_office.debitor_iv debitorIV ON debitorIV.uuid = bookingProject.debitorUuid
"""))
.withRestrictedViewOrderBy(SQL.expression("caption"))

View File

@ -10,7 +10,7 @@ import jakarta.persistence.Table;
@Entity
@Table(name = "hs_booking_project")
@Table(schema = "hs_booking", name = "project")
@SuperBuilder(toBuilder = true)
@Getter
@Setter

View File

@ -26,14 +26,14 @@ public interface HsHostingAssetRbacRepository extends HsHostingAssetRepository<H
ha.type,
ha.version
from hs_hosting_asset_rv ha
left join hs_booking_item bi on bi.uuid = ha.bookingitemuuid
left join hs_booking.item bi on bi.uuid = ha.bookingitemuuid
left join hs_hosting_asset pha on pha.uuid = ha.parentassetuuid
where (:projectUuid is null or bi.projectuuid=:projectUuid)
and (:parentAssetUuid is null or pha.uuid=:parentAssetUuid)
and (:type is null or :type=cast(ha.type as text))
""", nativeQuery = true)
// The JPQL query did not generate "left join" but just "join".
// I also optimized the query by not using the _rv for hs_booking_item and hs_hosting_asset, only for hs_hosting_asset_rv.
// I also optimized the query by not using the _rv for hs_booking.item and hs_hosting_asset, only for hs_hosting_asset_rv.
List<HsHostingAssetRbacEntity> findAllByCriteriaImpl(UUID projectUuid, UUID parentAssetUuid, String type);
default List<HsHostingAssetRbacEntity> findAllByCriteria(final UUID projectUuid, final UUID parentAssetUuid, final HsHostingAssetType type) {
return findAllByCriteriaImpl(projectUuid, parentAssetUuid, HsHostingAssetType.asString(type));

View File

@ -25,14 +25,14 @@ public interface HsHostingAssetRealRepository extends HsHostingAssetRepository<H
ha.type,
ha.version
from hs_hosting_asset_rv ha
left join hs_booking_item bi on bi.uuid = ha.bookingitemuuid
left join hs_booking.item bi on bi.uuid = ha.bookingitemuuid
left join hs_hosting_asset pha on pha.uuid = ha.parentassetuuid
where (:projectUuid is null or bi.projectuuid=:projectUuid)
and (:parentAssetUuid is null or pha.uuid=:parentAssetUuid)
and (:type is null or :type=cast(ha.type as text))
""", nativeQuery = true)
// The JPQL query did not generate "left join" but just "join".
// I also optimized the query by not using the _rv for hs_booking_item and hs_hosting_asset, only for hs_hosting_asset_rv.
// I also optimized the query by not using the _rv for hs_booking.item and hs_hosting_asset, only for hs_hosting_asset_rv.
List<HsHostingAssetRealEntity> findAllByCriteriaImpl(UUID projectUuid, UUID parentAssetUuid, String type);
default List<HsHostingAssetRealEntity> findAllByCriteria(final UUID projectUuid, final UUID parentAssetUuid, final HsHostingAssetType type) {
return findAllByCriteriaImpl(projectUuid, parentAssetUuid, HsHostingAssetType.asString(type));

View File

@ -986,7 +986,7 @@ public class RbacView {
// this is just a workaround:
return getRawTableName()
.replace("hs_office.", "hsof.")
.replace("hs_booking_", "hsbk_")
.replace("hs_booking.", "hsbk_")
.replace("hs_hosting_", "hsho_")
.replace("coopsharestransaction", "coopsharetx")
.replace("coopassetstransaction", "coopassettx");

View File

@ -9,6 +9,9 @@ create or replace function base.combine_table_schema_and_name(tableSchema name,
returns text
language plpgsql as $$
begin
assert LEFT(tableSchema, 1) <> '"', 'tableSchema must not start with "';
assert LEFT(tableName, 1) <> '"', 'tableName must not start with "';
if tableSchema is null or tableSchema = 'public' or tableSchema = '' then
return tableName::text;
else

View File

@ -63,7 +63,6 @@ begin
if (currentSubject is null or currentSubject = '') then
raise exception 'hsadminng.currentSubject must be defined, please use "SET LOCAL ...;"';
end if;
raise notice 'currentSubject: %', currentSubject;
-- determine task
currentTask = current_setting('hsadminng.currentTask');
@ -81,8 +80,9 @@ begin
"alive" := false;
end if;
sql := format('INSERT INTO %3$I_ex VALUES (DEFAULT, pg_current_xact_id(), %1$L, %2$L, $1.*)',
sql := format('INSERT INTO %3$s_ex VALUES (DEFAULT, pg_current_xact_id(), %1$L, %2$L, $1.*)',
TG_OP, alive, base.combine_table_schema_and_name(tg_table_schema, tg_table_name)::name);
-- raise exception 'generated-SQL: %', sql;
execute sql using "row";
return "row";
@ -117,12 +117,12 @@ begin
' EXCLUDING CONSTRAINTS' ||
' EXCLUDING STATISTICS' ||
')';
raise notice 'sql: %', createHistTableSql;
-- raise notice 'sql: %', createHistTableSql;
execute createHistTableSql;
-- create the historical view
viewName = quote_ident(format('%s_hv', baseTable));
exVersionsTable = quote_ident(format('%s_ex', baseTable));
viewName = baseTable || '_hv';
exVersionsTable = baseTable || '_ex';
baseCols = (select string_agg(quote_ident(column_name), ', ')
from information_schema.columns
where table_schema = 'public'
@ -147,14 +147,13 @@ begin
')',
viewName, baseCols, exVersionsTable
);
raise notice 'sql: %', createViewSQL;
-- raise notice 'generated-sql: %', createViewSQL;
execute createViewSQL;
-- "-9-" to put the trigger execution after any alphabetically lesser tx-triggers
createTriggerSQL = 'CREATE TRIGGER tx_9_historicize_tg' ||
' AFTER INSERT OR DELETE OR UPDATE ON ' || baseTable ||
' FOR EACH ROW EXECUTE PROCEDURE base.tx_historicize_tf()';
raise notice 'sql: %', createTriggerSQL;
execute createTriggerSQL;
end; $$;

View File

@ -0,0 +1,8 @@
--liquibase formatted sql
-- ============================================================================
--changeset michael.hoennig:hs-booking-SCHEMA endDelimiter:--//
-- ----------------------------------------------------------------------------
CREATE SCHEMA hs_booking;
--//

View File

@ -4,7 +4,7 @@
--changeset michael.hoennig:hs-booking-debitor-RESTRICTED-VIEW endDelimiter:--//
-- ----------------------------------------------------------------------------
create view hs_booking_debitor_xv as
create view hs_booking.debitor_xv as
select debitor.uuid,
debitor.version,
(partner.partnerNumber::varchar || debitor.debitorNumberSuffix)::numeric as debitorNumber,

View File

@ -4,7 +4,7 @@
--changeset michael.hoennig:booking-project-MAIN-TABLE endDelimiter:--//
-- ----------------------------------------------------------------------------
create table if not exists hs_booking_project
create table if not exists hs_booking.project
(
uuid uuid unique references rbac.object (uuid),
version int not null default 0,
@ -18,12 +18,12 @@ create table if not exists hs_booking_project
--changeset michael.hoennig:hs-booking-project-MAIN-TABLE-JOURNAL endDelimiter:--//
-- ----------------------------------------------------------------------------
call base.create_journal('hs_booking_project');
call base.create_journal('hs_booking.project');
--//
-- ============================================================================
--changeset michael.hoennig:hs-booking-project-MAIN-TABLE-HISTORIZATION endDelimiter:--//
-- ----------------------------------------------------------------------------
call base.tx_create_historicization('hs_booking_project');
call base.tx_create_historicization('hs_booking.project');
--//

View File

@ -5,14 +5,14 @@
-- ============================================================================
--changeset RbacObjectGenerator:hs-booking-project-rbac-OBJECT endDelimiter:--//
-- ----------------------------------------------------------------------------
call rbac.generateRelatedRbacObject('hs_booking_project');
call rbac.generateRelatedRbacObject('hs_booking.project');
--//
-- ============================================================================
--changeset RbacRoleDescriptorsGenerator:hs-booking-project-rbac-ROLE-DESCRIPTORS endDelimiter:--//
-- ----------------------------------------------------------------------------
call rbac.generateRbacRoleDescriptors('hsBookingProject', 'hs_booking_project');
call rbac.generateRbacRoleDescriptors('hsBookingProject', 'hs_booking.project');
--//
@ -24,8 +24,8 @@ call rbac.generateRbacRoleDescriptors('hsBookingProject', 'hs_booking_project');
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
*/
create or replace procedure hs_booking_project_build_rbac_system(
NEW hs_booking_project
create or replace procedure hs_booking.project_build_rbac_system(
NEW hs_booking.project
)
language plpgsql as $$
@ -76,22 +76,22 @@ begin
end; $$;
/*
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_booking_project row.
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_booking.project row.
*/
create or replace function hs_booking_project_build_rbac_system_after_insert_tf()
create or replace function hs_booking.project_build_rbac_system_after_insert_tf()
returns trigger
language plpgsql
strict as $$
begin
call hs_booking_project_build_rbac_system(NEW);
call hs_booking.project_build_rbac_system(NEW);
return NEW;
end; $$;
create trigger build_rbac_system_after_insert_tg
after insert on hs_booking_project
after insert on hs_booking.project
for each row
execute procedure hs_booking_project_build_rbac_system_after_insert_tf();
execute procedure hs_booking.project_build_rbac_system_after_insert_tf();
--//
@ -102,45 +102,45 @@ execute procedure hs_booking_project_build_rbac_system_after_insert_tf();
-- granting INSERT permission to hs_office.relation ----------------------------
/*
Grants INSERT INTO hs_booking_project permissions to specified role of pre-existing hs_office.relation rows.
Grants INSERT INTO hs_booking.project permissions to specified role of pre-existing hs_office.relation rows.
*/
do language plpgsql $$
declare
row hs_office.relation;
begin
call base.defineContext('create INSERT INTO hs_booking_project permissions for pre-exising hs_office.relation rows');
call base.defineContext('create INSERT INTO hs_booking.project permissions for pre-exising hs_office.relation rows');
FOR row IN SELECT * FROM hs_office.relation
WHERE type = 'DEBITOR'
LOOP
call rbac.grantPermissionToRole(
rbac.createPermission(row.uuid, 'INSERT', 'hs_booking_project'),
rbac.createPermission(row.uuid, 'INSERT', 'hs_booking.project'),
hsOfficeRelationADMIN(row));
END LOOP;
end;
$$;
/**
Grants hs_booking_project INSERT permission to specified role of new relation rows.
Grants hs_booking.project INSERT permission to specified role of new relation rows.
*/
create or replace function new_hsbk_project_grants_insert_to_relation_tf()
create or replace function hs_booking.new_project_grants_insert_to_relation_tf()
returns trigger
language plpgsql
strict as $$
begin
if NEW.type = 'DEBITOR' then
call rbac.grantPermissionToRole(
rbac.createPermission(NEW.uuid, 'INSERT', 'hs_booking_project'),
rbac.createPermission(NEW.uuid, 'INSERT', 'hs_booking.project'),
hsOfficeRelationADMIN(NEW));
end if;
return NEW;
end; $$;
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
create trigger z_new_hs_booking_project_grants_after_insert_tg
create trigger z_new_project_grants_after_insert_tg
after insert on hs_office.relation
for each row
execute procedure new_hsbk_project_grants_insert_to_relation_tf();
execute procedure hs_booking.new_project_grants_insert_to_relation_tf();
-- ============================================================================
@ -148,9 +148,9 @@ execute procedure new_hsbk_project_grants_insert_to_relation_tf();
-- ----------------------------------------------------------------------------
/**
Checks if the user respectively the assumed roles are allowed to insert a row to hs_booking_project.
Checks if the user respectively the assumed roles are allowed to insert a row to hs_booking.project.
*/
create or replace function hs_booking_project_insert_permission_check_tf()
create or replace function hs_booking.project_insert_permission_check_tf()
returns trigger
language plpgsql as $$
declare
@ -162,19 +162,19 @@ begin
JOIN hs_office.debitor debitor ON debitor.debitorRelUuid = debitorRel.uuid
WHERE debitor.uuid = NEW.debitorUuid
);
assert superObjectUuid is not null, 'object uuid fetched depending on hs_booking_project.debitorUuid must not be null, also check fetchSql in RBAC DSL';
if rbac.hasInsertPermission(superObjectUuid, 'hs_booking_project') then
assert superObjectUuid is not null, 'object uuid fetched depending on hs_booking.project.debitorUuid must not be null, also check fetchSql in RBAC DSL';
if rbac.hasInsertPermission(superObjectUuid, 'hs_booking.project') then
return NEW;
end if;
raise exception '[403] insert into hs_booking_project values(%) not allowed for current subjects % (%)',
raise exception '[403] insert into hs_booking.project values(%) not allowed for current subjects % (%)',
NEW, base.currentSubjects(), rbac.currentSubjectOrAssumedRolesUuids();
end; $$;
create trigger hs_booking_project_insert_permission_check_tg
before insert on hs_booking_project
create trigger project_insert_permission_check_tg
before insert on hs_booking.project
for each row
execute procedure hs_booking_project_insert_permission_check_tf();
execute procedure hs_booking.project_insert_permission_check_tf();
--//
@ -182,10 +182,10 @@ create trigger hs_booking_project_insert_permission_check_tg
--changeset RbacIdentityViewGenerator:hs-booking-project-rbac-IDENTITY-VIEW endDelimiter:--//
-- ----------------------------------------------------------------------------
call rbac.generateRbacIdentityViewFromQuery('hs_booking_project',
call rbac.generateRbacIdentityViewFromQuery('hs_booking.project',
$idName$
SELECT bookingProject.uuid as uuid, debitorIV.idName || '-' || base.cleanIdentifier(bookingProject.caption) as idName
FROM hs_booking_project bookingProject
FROM hs_booking.project bookingProject
JOIN hs_office.debitor_iv debitorIV ON debitorIV.uuid = bookingProject.debitorUuid
$idName$);
--//
@ -194,7 +194,7 @@ call rbac.generateRbacIdentityViewFromQuery('hs_booking_project',
-- ============================================================================
--changeset RbacRestrictedViewGenerator:hs-booking-project-rbac-RESTRICTED-VIEW endDelimiter:--//
-- ----------------------------------------------------------------------------
call rbac.generateRbacRestrictedView('hs_booking_project',
call rbac.generateRbacRestrictedView('hs_booking.project',
$orderBy$
caption
$orderBy$,

View File

@ -6,7 +6,7 @@
-- ----------------------------------------------------------------------------
/*
Creates a single hs_booking_project test record.
Creates a single hs_booking.project test record.
*/
create or replace procedure createHsBookingProjectTransactionTestData(
givenPartnerNumber numeric,
@ -27,7 +27,7 @@ begin
raise notice 'creating test booking-project: %', givenDebitorSuffix::text;
raise notice '- using debitor (%): %', relatedDebitor.uuid, relatedDebitor;
insert
into hs_booking_project (uuid, debitoruuid, caption)
into hs_booking.project (uuid, debitoruuid, caption)
values (uuid_generate_v4(), relatedDebitor.uuid, 'D-' || givenPartnerNumber::text || givenDebitorSuffix || ' default project');
end; $$;
--//

View File

@ -14,18 +14,18 @@ create type HsBookingItemType as enum (
CREATE CAST (character varying as HsBookingItemType) WITH INOUT AS IMPLICIT;
create table if not exists hs_booking_item
create table if not exists hs_booking.item
(
uuid uuid unique references rbac.object (uuid),
version int not null default 0,
projectUuid uuid null references hs_booking_project(uuid),
projectUuid uuid null references hs_booking.project(uuid),
type HsBookingItemType not null,
parentItemUuid uuid null references hs_booking_item(uuid) initially deferred,
parentItemUuid uuid null references hs_booking.item(uuid) initially deferred,
validity daterange not null,
caption varchar(80) not null,
resources jsonb not null,
constraint chk_hs_booking_item_has_project_or_parent_asset
constraint booking_item_has_project_or_parent_asset
check (projectUuid is not null or parentItemUuid is not null)
);
--//
@ -35,13 +35,13 @@ create table if not exists hs_booking_item
--changeset michael.hoennig:hs-booking-item-MAIN-TABLE-JOURNAL endDelimiter:--//
-- ----------------------------------------------------------------------------
call base.create_journal('hs_booking_item');
call base.create_journal('hs_booking.item');
--//
-- ============================================================================
--changeset michael.hoennig:hs-booking-item-MAIN-TABLE-HISTORIZATION endDelimiter:--//
-- ----------------------------------------------------------------------------
call base.tx_create_historicization('hs_booking_item');
call base.tx_create_historicization('hs_booking.item');
--//

View File

@ -5,14 +5,14 @@
-- ============================================================================
--changeset RbacObjectGenerator:hs-booking-item-rbac-OBJECT endDelimiter:--//
-- ----------------------------------------------------------------------------
call rbac.generateRelatedRbacObject('hs_booking_item');
call rbac.generateRelatedRbacObject('hs_booking.item');
--//
-- ============================================================================
--changeset RbacRoleDescriptorsGenerator:hs-booking-item-rbac-ROLE-DESCRIPTORS endDelimiter:--//
-- ----------------------------------------------------------------------------
call rbac.generateRbacRoleDescriptors('hsBookingItem', 'hs_booking_item');
call rbac.generateRbacRoleDescriptors('hsBookingItem', 'hs_booking.item');
--//
@ -24,21 +24,21 @@ call rbac.generateRbacRoleDescriptors('hsBookingItem', 'hs_booking_item');
Creates the roles, grants and permission for the AFTER INSERT TRIGGER.
*/
create or replace procedure hs_booking_item_build_rbac_system(
NEW hs_booking_item
create or replace procedure hs_booking.item_build_rbac_system(
NEW hs_booking.item
)
language plpgsql as $$
declare
newProject hs_booking_project;
newParentItem hs_booking_item;
newProject hs_booking.project;
newParentItem hs_booking.item;
begin
call rbac.enterTriggerForObjectUuid(NEW.uuid);
SELECT * FROM hs_booking_project WHERE uuid = NEW.projectUuid INTO newProject;
SELECT * FROM hs_booking.project WHERE uuid = NEW.projectUuid INTO newProject;
SELECT * FROM hs_booking_item WHERE uuid = NEW.parentItemUuid INTO newParentItem;
SELECT * FROM hs_booking.item WHERE uuid = NEW.parentItemUuid INTO newParentItem;
perform rbac.defineRoleWithGrants(
hsBookingItemOWNER(NEW),
@ -75,22 +75,22 @@ begin
end; $$;
/*
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_booking_item row.
AFTER INSERT TRIGGER to create the role+grant structure for a new hs_booking.item row.
*/
create or replace function hs_booking_item_build_rbac_system_after_insert_tf()
create or replace function hs_booking.item_build_rbac_system_after_insert_tf()
returns trigger
language plpgsql
strict as $$
begin
call hs_booking_item_build_rbac_system(NEW);
call hs_booking.item_build_rbac_system(NEW);
return NEW;
end; $$;
create trigger build_rbac_system_after_insert_tg
after insert on hs_booking_item
after insert on hs_booking.item
for each row
execute procedure hs_booking_item_build_rbac_system_after_insert_tf();
execute procedure hs_booking.item_build_rbac_system_after_insert_tf();
--//
@ -101,115 +101,115 @@ execute procedure hs_booking_item_build_rbac_system_after_insert_tf();
-- granting INSERT permission to rbac.global ----------------------------
/*
Grants INSERT INTO hs_booking_item permissions to specified role of pre-existing rbac.global rows.
Grants INSERT INTO hs_booking.item permissions to specified role of pre-existing rbac.global rows.
*/
do language plpgsql $$
declare
row rbac.global;
begin
call base.defineContext('create INSERT INTO hs_booking_item permissions for pre-exising rbac.global rows');
call base.defineContext('create INSERT INTO hs_booking.item permissions for pre-exising rbac.global rows');
FOR row IN SELECT * FROM rbac.global
-- unconditional for all rows in that table
LOOP
call rbac.grantPermissionToRole(
rbac.createPermission(row.uuid, 'INSERT', 'hs_booking_item'),
rbac.createPermission(row.uuid, 'INSERT', 'hs_booking.item'),
rbac.globalADMIN());
END LOOP;
end;
$$;
/**
Grants hs_booking_item INSERT permission to specified role of new global rows.
Grants hs_booking.item INSERT permission to specified role of new global rows.
*/
create or replace function new_hsbk_item_grants_insert_to_global_tf()
create or replace function hs_booking.new_item_grants_insert_to_global_tf()
returns trigger
language plpgsql
strict as $$
begin
-- unconditional for all rows in that table
call rbac.grantPermissionToRole(
rbac.createPermission(NEW.uuid, 'INSERT', 'hs_booking_item'),
rbac.createPermission(NEW.uuid, 'INSERT', 'hs_booking.item'),
rbac.globalADMIN());
-- end.
return NEW;
end; $$;
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
create trigger z_new_hs_booking_item_grants_after_insert_tg
create trigger z_new_item_grants_after_insert_tg
after insert on rbac.global
for each row
execute procedure new_hsbk_item_grants_insert_to_global_tf();
execute procedure hs_booking.new_item_grants_insert_to_global_tf();
-- granting INSERT permission to hs_booking_project ----------------------------
-- granting INSERT permission to hs_booking.project ----------------------------
/*
Grants INSERT INTO hs_booking_item permissions to specified role of pre-existing hs_booking_project rows.
Grants INSERT INTO hs_booking.item permissions to specified role of pre-existing hs_booking.project rows.
*/
do language plpgsql $$
declare
row hs_booking_project;
row hs_booking.project;
begin
call base.defineContext('create INSERT INTO hs_booking_item permissions for pre-exising hs_booking_project rows');
call base.defineContext('create INSERT INTO hs_booking.item permissions for pre-exising hs_booking.project rows');
FOR row IN SELECT * FROM hs_booking_project
FOR row IN SELECT * FROM hs_booking.project
-- unconditional for all rows in that table
LOOP
call rbac.grantPermissionToRole(
rbac.createPermission(row.uuid, 'INSERT', 'hs_booking_item'),
rbac.createPermission(row.uuid, 'INSERT', 'hs_booking.item'),
hsBookingProjectADMIN(row));
END LOOP;
end;
$$;
/**
Grants hs_booking_item INSERT permission to specified role of new hs_booking_project rows.
Grants hs_booking.item INSERT permission to specified role of new project rows.
*/
create or replace function new_hsbk_item_grants_insert_to_hsbk_project_tf()
create or replace function hs_booking.new_item_grants_insert_to_project_tf()
returns trigger
language plpgsql
strict as $$
begin
-- unconditional for all rows in that table
call rbac.grantPermissionToRole(
rbac.createPermission(NEW.uuid, 'INSERT', 'hs_booking_item'),
rbac.createPermission(NEW.uuid, 'INSERT', 'hs_booking.item'),
hsBookingProjectADMIN(NEW));
-- end.
return NEW;
end; $$;
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
create trigger z_new_hs_booking_item_grants_after_insert_tg
after insert on hs_booking_project
create trigger z_new_item_grants_after_insert_tg
after insert on hs_booking.project
for each row
execute procedure new_hsbk_item_grants_insert_to_hsbk_project_tf();
execute procedure hs_booking.new_item_grants_insert_to_project_tf();
-- granting INSERT permission to hs_booking_item ----------------------------
-- granting INSERT permission to hs_booking.item ----------------------------
-- Granting INSERT INTO hs_hosting_asset permissions to specified role of pre-existing hs_hosting_asset rows slipped,
-- because there cannot yet be any pre-existing rows in the same table yet.
/**
Grants hs_booking_item INSERT permission to specified role of new hs_booking_item rows.
Grants hs_booking.item INSERT permission to specified role of new item rows.
*/
create or replace function new_hsbk_item_grants_insert_to_hsbk_item_tf()
create or replace function hs_booking.new_item_grants_insert_to_item_tf()
returns trigger
language plpgsql
strict as $$
begin
-- unconditional for all rows in that table
call rbac.grantPermissionToRole(
rbac.createPermission(NEW.uuid, 'INSERT', 'hs_booking_item'),
rbac.createPermission(NEW.uuid, 'INSERT', 'hs_booking.item'),
hsBookingItemADMIN(NEW));
-- end.
return NEW;
end; $$;
-- z_... is to put it at the end of after insert triggers, to make sure the roles exist
create trigger z_new_hs_booking_item_grants_after_insert_tg
after insert on hs_booking_item
create trigger z_new_item_grants_after_insert_tg
after insert on hs_booking.item
for each row
execute procedure new_hsbk_item_grants_insert_to_hsbk_item_tf();
execute procedure hs_booking.new_item_grants_insert_to_item_tf();
-- ============================================================================
@ -217,9 +217,9 @@ execute procedure new_hsbk_item_grants_insert_to_hsbk_item_tf();
-- ----------------------------------------------------------------------------
/**
Checks if the user respectively the assumed roles are allowed to insert a row to hs_booking_item.
Checks if the user respectively the assumed roles are allowed to insert a row to hs_booking.item.
*/
create or replace function hs_booking_item_insert_permission_check_tf()
create or replace function hs_booking.item_insert_permission_check_tf()
returns trigger
language plpgsql as $$
declare
@ -230,22 +230,22 @@ begin
return NEW;
end if;
-- check INSERT permission via direct foreign key: NEW.projectUuid
if rbac.hasInsertPermission(NEW.projectUuid, 'hs_booking_item') then
if rbac.hasInsertPermission(NEW.projectUuid, 'hs_booking.item') then
return NEW;
end if;
-- check INSERT permission via direct foreign key: NEW.parentItemUuid
if rbac.hasInsertPermission(NEW.parentItemUuid, 'hs_booking_item') then
if rbac.hasInsertPermission(NEW.parentItemUuid, 'hs_booking.item') then
return NEW;
end if;
raise exception '[403] insert into hs_booking_item values(%) not allowed for current subjects % (%)',
raise exception '[403] insert into hs_booking.item values(%) not allowed for current subjects % (%)',
NEW, base.currentSubjects(), rbac.currentSubjectOrAssumedRolesUuids();
end; $$;
create trigger hs_booking_item_insert_permission_check_tg
before insert on hs_booking_item
create trigger item_insert_permission_check_tg
before insert on hs_booking.item
for each row
execute procedure hs_booking_item_insert_permission_check_tf();
execute procedure hs_booking.item_insert_permission_check_tf();
--//
@ -253,7 +253,7 @@ create trigger hs_booking_item_insert_permission_check_tg
--changeset RbacIdentityViewGenerator:hs-booking-item-rbac-IDENTITY-VIEW endDelimiter:--//
-- ----------------------------------------------------------------------------
call rbac.generateRbacIdentityViewFromProjection('hs_booking_item',
call rbac.generateRbacIdentityViewFromProjection('hs_booking.item',
$idName$
caption
$idName$);
@ -263,7 +263,7 @@ call rbac.generateRbacIdentityViewFromProjection('hs_booking_item',
-- ============================================================================
--changeset RbacRestrictedViewGenerator:hs-booking-item-rbac-RESTRICTED-VIEW endDelimiter:--//
-- ----------------------------------------------------------------------------
call rbac.generateRbacRestrictedView('hs_booking_item',
call rbac.generateRbacRestrictedView('hs_booking.item',
$orderBy$
validity
$orderBy$,

View File

@ -6,7 +6,7 @@
-- ----------------------------------------------------------------------------
/*
Creates a single hs_booking_item test record.
Creates a single hs_booking.item test record.
*/
create or replace procedure createHsBookingItemTransactionTestData(
givenPartnerNumber numeric,
@ -14,12 +14,12 @@ create or replace procedure createHsBookingItemTransactionTestData(
)
language plpgsql as $$
declare
relatedProject hs_booking_project;
relatedProject hs_booking.project;
privateCloudUuid uuid;
managedServerUuid uuid;
begin
select project.* into relatedProject
from hs_booking_project project
from hs_booking.project project
where project.caption = 'D-' || givenPartnerNumber || givenDebitorSuffix || ' default project';
raise notice 'creating test booking-item: %', givenPartnerNumber::text || givenDebitorSuffix::text;
@ -27,7 +27,7 @@ begin
privateCloudUuid := uuid_generate_v4();
managedServerUuid := uuid_generate_v4();
insert
into hs_booking_item (uuid, projectuuid, type, parentitemuuid, caption, validity, resources)
into hs_booking.item (uuid, projectuuid, type, parentitemuuid, caption, validity, resources)
values (privateCloudUuid, relatedProject.uuid, 'PRIVATE_CLOUD', null, 'some PrivateCloud', daterange('20240401', null, '[]'), '{ "CPU": 10, "RAM": 32, "SSD": 4000, "HDD": 10000, "Traffic": 2000 }'::jsonb),
(uuid_generate_v4(), null, 'MANAGED_SERVER', privateCloudUuid, 'some ManagedServer', daterange('20230115', '20240415', '[)'), '{ "CPU": 2, "RAM": 4, "SSD": 500, "Traffic": 500 }'::jsonb),
(uuid_generate_v4(), null, 'CLOUD_SERVER', privateCloudUuid, 'test CloudServer', daterange('20230115', '20240415', '[)'), '{ "CPU": 2, "RAM": 4, "SSD": 750, "Traffic": 500 }'::jsonb),

View File

@ -32,7 +32,7 @@ create table if not exists hs_hosting_asset
(
uuid uuid unique references rbac.object (uuid),
version int not null default 0,
bookingItemUuid uuid null references hs_booking_item(uuid),
bookingItemUuid uuid null references hs_booking.item(uuid),
type HsHostingAssetType not null,
parentAssetUuid uuid null references hs_hosting_asset(uuid) initially deferred,
assignedToAssetUuid uuid null references hs_hosting_asset(uuid) initially deferred,
@ -138,7 +138,7 @@ declare
expectedBookingItemType HsBookingItemType;
begin
actualBookingItemType := (select type
from hs_booking_item
from hs_booking.item
where NEW.bookingItemUuid = uuid);
if NEW.type = 'CLOUD_SERVER' then

View File

@ -30,7 +30,7 @@ create or replace procedure hs_hosting_asset_build_rbac_system(
language plpgsql as $$
declare
newBookingItem hs_booking_item;
newBookingItem hs_booking.item;
newAssignedToAsset hs_hosting_asset;
newAlarmContact hs_office.contact;
newParentAsset hs_hosting_asset;
@ -38,7 +38,7 @@ declare
begin
call rbac.enterTriggerForObjectUuid(NEW.uuid);
SELECT * FROM hs_booking_item WHERE uuid = NEW.bookingItemUuid INTO newBookingItem;
SELECT * FROM hs_booking.item WHERE uuid = NEW.bookingItemUuid INTO newBookingItem;
SELECT * FROM hs_hosting_asset WHERE uuid = NEW.assignedToAssetUuid INTO newAssignedToAsset;

View File

@ -11,12 +11,12 @@
create or replace procedure createHsHostingAssetTestData(givenProjectCaption varchar)
language plpgsql as $$
declare
relatedProject hs_booking_project;
relatedProject hs_booking.project;
relatedDebitor hs_office.debitor;
privateCloudBI hs_booking_item;
managedServerBI hs_booking_item;
cloudServerBI hs_booking_item;
managedWebspaceBI hs_booking_item;
privateCloudBI hs_booking.item;
managedServerBI hs_booking.item;
cloudServerBI hs_booking.item;
managedWebspaceBI hs_booking.item;
debitorNumberSuffix varchar;
defaultPrefix varchar;
managedServerUuid uuid;
@ -33,7 +33,7 @@ begin
call base.defineContext('creating hosting-asset test-data', null, 'superuser-alex@hostsharing.net', 'rbac.global#global:ADMIN');
select project.* into relatedProject
from hs_booking_project project
from hs_booking.project project
where project.caption = givenProjectCaption;
assert relatedProject.uuid is not null, 'relatedProject for "' || givenProjectCaption || '" must not be null';
@ -43,25 +43,25 @@ begin
assert relatedDebitor.uuid is not null, 'relatedDebitor for "' || givenProjectCaption || '" must not be null';
select item.* into privateCloudBI
from hs_booking_item item
from hs_booking.item item
where item.projectUuid = relatedProject.uuid
and item.type = 'PRIVATE_CLOUD';
assert privateCloudBI.uuid is not null, 'relatedPrivateCloudBookingItem for "' || givenProjectCaption|| '" must not be null';
select item.* into managedServerBI
from hs_booking_item item
from hs_booking.item item
where item.projectUuid = relatedProject.uuid
and item.type = 'MANAGED_SERVER';
assert managedServerBI.uuid is not null, 'relatedManagedServerBookingItem for "' || givenProjectCaption|| '" must not be null';
select item.* into cloudServerBI
from hs_booking_item item
from hs_booking.item item
where item.parentItemuuid = privateCloudBI.uuid
and item.type = 'CLOUD_SERVER';
assert cloudServerBI.uuid is not null, 'relatedCloudServerBookingItem for "' || givenProjectCaption|| '" must not be null';
select item.* into managedWebspaceBI
from hs_booking_item item
from hs_booking.item item
where item.projectUuid = relatedProject.uuid
and item.type = 'MANAGED_WEBSPACE';
assert managedWebspaceBI.uuid is not null, 'relatedManagedWebspaceBookingItem for "' || givenProjectCaption|| '" must not be null';

View File

@ -16,8 +16,8 @@ select *
from hs_hosting_asset
group by type
union all
select to_char(count(*)::int, '9 999 999 999'), 'objects', 'hs_booking_item', type::text
from hs_booking_item
select to_char(count(*)::int, '9 999 999 999'), 'objects', 'hs_booking.item', type::text
from hs_booking.item
group by type
) as totals order by replace(count, ' ', '')::int desc;
--//

View File

@ -143,6 +143,8 @@ databaseChangeLog:
file: db/changelog/5-hs-office/512-coopassets/5126-hs-office-coopassets-migration.sql
- include:
file: db/changelog/5-hs-office/512-coopassets/5128-hs-office-coopassets-test-data.sql
- include:
file: db/changelog/6-hs-booking/600-hs-booking-schema.sql
- include:
file: db/changelog/6-hs-booking/610-booking-debitor/6100-hs-booking-debitor.sql
- include:

View File

@ -251,7 +251,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
RestAssured // @formatter:off
.given()
.header("current-subject", "superuser-alex@hostsharing.net")
.header("assumed-roles", "hs_booking_project#D-1000313-D-1000313defaultproject:ADMIN")
.header("assumed-roles", "hs_booking.project#D-1000313-D-1000313defaultproject:ADMIN")
.port(port)
.when()
.get("http://localhost/api/hs/booking/items/" + givenBookingItem.getUuid())
@ -295,7 +295,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
RestAssured // @formatter:off
.given()
.header("current-subject", "superuser-alex@hostsharing.net")
.header("assumed-roles", "hs_booking_project#D-1000111-D-1000111defaultproject:AGENT")
.header("assumed-roles", "hs_booking.project#D-1000111-D-1000111defaultproject:AGENT")
.contentType(ContentType.JSON)
.body("""
{

View File

@ -70,7 +70,7 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup
final var query = em.createNativeQuery("""
select currentTask, targetTable, targetOp, targetdelta->>'caption'
from base.tx_journal_v
where targettable = 'hs_booking_item';
where targettable = 'hs_booking.item';
""");
// when
@ -78,13 +78,13 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup
// then
assertThat(customerLogEntries).map(Arrays::toString).contains(
"[creating booking-item test-data, hs_booking_item, INSERT, prod CloudServer]",
"[creating booking-item test-data, hs_booking_item, INSERT, separate ManagedServer]",
"[creating booking-item test-data, hs_booking_item, INSERT, separate ManagedWebspace]",
"[creating booking-item test-data, hs_booking_item, INSERT, some ManagedServer]",
"[creating booking-item test-data, hs_booking_item, INSERT, some ManagedWebspace]",
"[creating booking-item test-data, hs_booking_item, INSERT, some PrivateCloud]",
"[creating booking-item test-data, hs_booking_item, INSERT, test CloudServer]");
"[creating booking-item test-data, hs_booking.item, INSERT, prod CloudServer]",
"[creating booking-item test-data, hs_booking.item, INSERT, separate ManagedServer]",
"[creating booking-item test-data, hs_booking.item, INSERT, separate ManagedWebspace]",
"[creating booking-item test-data, hs_booking.item, INSERT, some ManagedServer]",
"[creating booking-item test-data, hs_booking.item, INSERT, some ManagedWebspace]",
"[creating booking-item test-data, hs_booking.item, INSERT, some PrivateCloud]",
"[creating booking-item test-data, hs_booking.item, INSERT, test CloudServer]");
}
@Test
@ -92,7 +92,7 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup
// given
final String nativeQuerySql = """
select count(*)
from hs_booking_item_hv ha;
from hs_booking.item_hv ha;
""";
// when
@ -101,7 +101,7 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup
@SuppressWarnings("unchecked") final var countBefore = (Integer) query.getSingleResult();
// then
assertThat(countBefore).as("hs_booking_item should not contain rows for a timestamp in the past").isEqualTo(0);
assertThat(countBefore).as("hs_booking.item should not contain rows for a timestamp in the past").isEqualTo(0);
// and when
historicalContext(Timestamp.from(ZonedDateTime.now().plusHours(1).toInstant()));
@ -109,7 +109,7 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup
@SuppressWarnings("unchecked") final var countAfter = (Integer) query.getSingleResult();
// then
assertThat(countAfter).as("hs_booking_item should contain rows for a timestamp in the future").isGreaterThan(1);
assertThat(countAfter).as("hs_booking.item should contain rows for a timestamp in the future").isGreaterThan(1);
}
@Nested
@ -167,32 +167,32 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup
final var all = rawRoleRepo.findAll();
assertThat(distinctRoleNamesOf(all)).containsExactlyInAnyOrder(Array.from(
initialRoleNames,
"hs_booking_item#somenewbookingitem:ADMIN",
"hs_booking_item#somenewbookingitem:AGENT",
"hs_booking_item#somenewbookingitem:OWNER",
"hs_booking_item#somenewbookingitem:TENANT"));
"hs_booking.item#somenewbookingitem:ADMIN",
"hs_booking.item#somenewbookingitem:AGENT",
"hs_booking.item#somenewbookingitem:OWNER",
"hs_booking.item#somenewbookingitem:TENANT"));
assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll()))
.containsExactlyInAnyOrder(fromFormatted(
initialGrantNames,
// rbac.global-admin
"{ grant perm:hs_booking_item#somenewbookingitem:INSERT>hs_booking_item to role:hs_booking_item#somenewbookingitem:ADMIN by system and assume }",
"{ grant perm:hs_booking_item#somenewbookingitem:DELETE to role:rbac.global#global:ADMIN by system and assume }",
"{ grant perm:hs_booking.item#somenewbookingitem:INSERT>hs_booking.item to role:hs_booking.item#somenewbookingitem:ADMIN by system and assume }",
"{ grant perm:hs_booking.item#somenewbookingitem:DELETE to role:rbac.global#global:ADMIN by system and assume }",
// owner
"{ grant role:hs_booking_item#somenewbookingitem:OWNER to role:hs_booking_project#D-1000111-D-1000111defaultproject:AGENT by system and assume }",
"{ grant role:hs_booking.item#somenewbookingitem:OWNER to role:hs_booking.project#D-1000111-D-1000111defaultproject:AGENT by system and assume }",
// admin
"{ grant perm:hs_booking_item#somenewbookingitem:UPDATE to role:hs_booking_item#somenewbookingitem:ADMIN by system and assume }",
"{ grant role:hs_booking_item#somenewbookingitem:ADMIN to role:hs_booking_item#somenewbookingitem:OWNER by system and assume }",
"{ grant perm:hs_booking.item#somenewbookingitem:UPDATE to role:hs_booking.item#somenewbookingitem:ADMIN by system and assume }",
"{ grant role:hs_booking.item#somenewbookingitem:ADMIN to role:hs_booking.item#somenewbookingitem:OWNER by system and assume }",
// agent
"{ grant role:hs_booking_item#somenewbookingitem:AGENT to role:hs_booking_item#somenewbookingitem:ADMIN by system and assume }",
"{ grant role:hs_booking.item#somenewbookingitem:AGENT to role:hs_booking.item#somenewbookingitem:ADMIN by system and assume }",
// tenant
"{ grant role:hs_booking_item#somenewbookingitem:TENANT to role:hs_booking_item#somenewbookingitem:AGENT by system and assume }",
"{ grant perm:hs_booking_item#somenewbookingitem:SELECT to role:hs_booking_item#somenewbookingitem:TENANT by system and assume }",
"{ grant role:hs_booking_project#D-1000111-D-1000111defaultproject:TENANT to role:hs_booking_item#somenewbookingitem:TENANT by system and assume }",
"{ grant role:hs_booking.item#somenewbookingitem:TENANT to role:hs_booking.item#somenewbookingitem:AGENT by system and assume }",
"{ grant perm:hs_booking.item#somenewbookingitem:SELECT to role:hs_booking.item#somenewbookingitem:TENANT by system and assume }",
"{ grant role:hs_booking.project#D-1000111-D-1000111defaultproject:TENANT to role:hs_booking.item#somenewbookingitem:TENANT by system and assume }",
null));
}
@ -230,7 +230,7 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup
// given:
context("person-FirbySusan@example.com");
final var debitor = debitorRepo.findDebitorByDebitorNumber(1000111);
context("person-FirbySusan@example.com", "hs_booking_project#D-1000111-D-1000111defaultproject:OWNER");
context("person-FirbySusan@example.com", "hs_booking.project#D-1000111-D-1000111defaultproject:OWNER");
final var projectUuid = debitor.stream()
.map(d -> realProjectRepo.findAllByDebitorUuid(d.getUuid()))
.flatMap(List::stream)
@ -258,7 +258,7 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup
// when
final var result = jpaAttempt.transacted(() -> {
context("superuser-alex@hostsharing.net", "hs_booking_project#D-1000111-D-1000111defaultproject:AGENT");
context("superuser-alex@hostsharing.net", "hs_booking.project#D-1000111-D-1000111defaultproject:AGENT");
final var foundBookingItem = em.find(HsBookingItemRbacEntity.class, givenBookingItemUuid);
foundBookingItem.getResources().put("CPU", 2);
foundBookingItem.getResources().remove("SSD-storage");
@ -311,12 +311,12 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup
@Test
public void nonGlobalAdmin_canNotDeleteTheirRelatedBookingItem() {
// given
context("superuser-alex@hostsharing.net", "hs_booking_project#D-1000111-D-1000111defaultproject:AGENT");
context("superuser-alex@hostsharing.net", "hs_booking.project#D-1000111-D-1000111defaultproject:AGENT");
final var givenBookingItem = givenSomeTemporaryBookingItem("D-1000111 default project");
// when
final var result = jpaAttempt.transacted(() -> {
context("person-FirbySusan@example.com", "hs_booking_project#D-1000111-D-1000111defaultproject:AGENT");
context("person-FirbySusan@example.com", "hs_booking.project#D-1000111-D-1000111defaultproject:AGENT");
assertThat(rbacBookingItemRepo.findByUuid(givenBookingItem.getUuid())).isPresent();
rbacBookingItemRepo.deleteByUuid(givenBookingItem.getUuid());
@ -325,7 +325,7 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup
// then
result.assertExceptionWithRootCauseMessage(
JpaSystemException.class,
"[403] Subject ", " is not allowed to delete hs_booking_item");
"[403] Subject ", " is not allowed to delete hs_booking.item");
assertThat(jpaAttempt.transacted(() -> {
context("superuser-alex@hostsharing.net");
return rbacBookingItemRepo.findByUuid(givenBookingItem.getUuid());
@ -335,7 +335,7 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup
@Test
public void deletingABookingItemAlsoDeletesRelatedRolesAndGrants() {
// given
context("superuser-alex@hostsharing.net", "hs_booking_project#D-1000111-D-1000111defaultproject:AGENT");
context("superuser-alex@hostsharing.net", "hs_booking.project#D-1000111-D-1000111defaultproject:AGENT");
final var initialRoleNames = Array.from(distinctRoleNamesOf(rawRoleRepo.findAll()));
final var initialGrantNames = Array.from(distinctGrantDisplaysOf(rawGrantRepo.findAll()));
final var givenBookingItem = givenSomeTemporaryBookingItem("D-1000111 default project");

View File

@ -168,7 +168,7 @@ class HsBookingProjectControllerAcceptanceTest extends ContextBasedTestWithClean
RestAssured // @formatter:off
.given()
.header("current-subject", "person-TuckerJack@example.com")
.header("assumed-roles", "hs_booking_project#D-1000313-D-1000313defaultproject:AGENT")
.header("assumed-roles", "hs_booking.project#D-1000313-D-1000313defaultproject:AGENT")
.port(port)
.when()
.get("http://localhost/api/hs/booking/projects/" + givenBookingProjectUuid)

View File

@ -65,7 +65,7 @@ class HsBookingProjectRepositoryIntegrationTest extends ContextBasedTestWithClea
final var query = em.createNativeQuery("""
select currentTask, targetTable, targetOp, targetdelta->>'caption'
from base.tx_journal_v
where targettable = 'hs_booking_project';
where targettable = 'hs_booking.project';
""");
// when
@ -73,9 +73,9 @@ class HsBookingProjectRepositoryIntegrationTest extends ContextBasedTestWithClea
// then
assertThat(customerLogEntries).map(Arrays::toString).contains(
"[creating booking-project test-data, hs_booking_project, INSERT, D-1000111 default project]",
"[creating booking-project test-data, hs_booking_project, INSERT, D-1000212 default project]",
"[creating booking-project test-data, hs_booking_project, INSERT, D-1000313 default project]");
"[creating booking-project test-data, hs_booking.project, INSERT, D-1000111 default project]",
"[creating booking-project test-data, hs_booking.project, INSERT, D-1000212 default project]",
"[creating booking-project test-data, hs_booking.project, INSERT, D-1000313 default project]");
}
@Test
@ -83,7 +83,7 @@ class HsBookingProjectRepositoryIntegrationTest extends ContextBasedTestWithClea
// given
final String nativeQuerySql = """
select count(*)
from hs_booking_project_hv ha;
from hs_booking.project_hv ha;
""";
// when
@ -92,7 +92,7 @@ class HsBookingProjectRepositoryIntegrationTest extends ContextBasedTestWithClea
@SuppressWarnings("unchecked") final var countBefore = (Integer) query.getSingleResult();
// then
assertThat(countBefore).as("hs_booking_project_hv should not contain rows for a timestamp in the past").isEqualTo(0);
assertThat(countBefore).as("hs_booking.project_hv should not contain rows for a timestamp in the past").isEqualTo(0);
// and when
historicalContext(Timestamp.from(ZonedDateTime.now().plusHours(1).toInstant()));
@ -100,7 +100,7 @@ class HsBookingProjectRepositoryIntegrationTest extends ContextBasedTestWithClea
@SuppressWarnings("unchecked") final var countAfter = (Integer) query.getSingleResult();
// then
assertThat(countAfter).as("hs_booking_project_hv should contain rows for a timestamp in the future").isGreaterThan(1);
assertThat(countAfter).as("hs_booking.project_hv should contain rows for a timestamp in the future").isGreaterThan(1);
}
@Nested
@ -152,33 +152,33 @@ class HsBookingProjectRepositoryIntegrationTest extends ContextBasedTestWithClea
final var all = rawRoleRepo.findAll();
assertThat(distinctRoleNamesOf(all)).containsExactlyInAnyOrder(Array.from(
initialRoleNames,
"hs_booking_project#D-1000111-somenewbookingproject:ADMIN",
"hs_booking_project#D-1000111-somenewbookingproject:AGENT",
"hs_booking_project#D-1000111-somenewbookingproject:OWNER",
"hs_booking_project#D-1000111-somenewbookingproject:TENANT"));
"hs_booking.project#D-1000111-somenewbookingproject:ADMIN",
"hs_booking.project#D-1000111-somenewbookingproject:AGENT",
"hs_booking.project#D-1000111-somenewbookingproject:OWNER",
"hs_booking.project#D-1000111-somenewbookingproject:TENANT"));
assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll()))
.map(s -> s.replace("hs_office.", ""))
.containsExactlyInAnyOrder(fromFormatted(
initialGrantNames,
// rbacgGlobal-admin
"{ grant perm:hs_booking_project#D-1000111-somenewbookingproject:DELETE to role:rbac.global#global:ADMIN by system and assume }",
"{ grant perm:hs_booking.project#D-1000111-somenewbookingproject:DELETE to role:rbac.global#global:ADMIN by system and assume }",
// owner
"{ grant role:hs_booking_project#D-1000111-somenewbookingproject:ADMIN to role:hs_booking_project#D-1000111-somenewbookingproject:OWNER by system and assume }",
"{ grant role:hs_booking.project#D-1000111-somenewbookingproject:ADMIN to role:hs_booking.project#D-1000111-somenewbookingproject:OWNER by system and assume }",
// admin
"{ grant role:hs_booking_project#D-1000111-somenewbookingproject:AGENT to role:hs_booking_project#D-1000111-somenewbookingproject:ADMIN by system and assume }",
"{ grant perm:hs_booking_project#D-1000111-somenewbookingproject:UPDATE to role:hs_booking_project#D-1000111-somenewbookingproject:ADMIN by system and assume }",
"{ grant perm:hs_booking_project#D-1000111-somenewbookingproject:INSERT>hs_booking_item to role:hs_booking_project#D-1000111-somenewbookingproject:ADMIN by system and assume }",
"{ grant role:hs_booking.project#D-1000111-somenewbookingproject:AGENT to role:hs_booking.project#D-1000111-somenewbookingproject:ADMIN by system and assume }",
"{ grant perm:hs_booking.project#D-1000111-somenewbookingproject:UPDATE to role:hs_booking.project#D-1000111-somenewbookingproject:ADMIN by system and assume }",
"{ grant perm:hs_booking.project#D-1000111-somenewbookingproject:INSERT>hs_booking.item to role:hs_booking.project#D-1000111-somenewbookingproject:ADMIN by system and assume }",
// agent
"{ grant role:hs_booking_project#D-1000111-somenewbookingproject:OWNER to role:relation#FirstGmbH-with-DEBITOR-FirstGmbH:AGENT by system }",
"{ grant role:hs_booking_project#D-1000111-somenewbookingproject:TENANT to role:hs_booking_project#D-1000111-somenewbookingproject:AGENT by system and assume }",
"{ grant role:hs_booking.project#D-1000111-somenewbookingproject:OWNER to role:relation#FirstGmbH-with-DEBITOR-FirstGmbH:AGENT by system }",
"{ grant role:hs_booking.project#D-1000111-somenewbookingproject:TENANT to role:hs_booking.project#D-1000111-somenewbookingproject:AGENT by system and assume }",
// tenant
"{ grant role:relation#FirstGmbH-with-DEBITOR-FirstGmbH:TENANT to role:hs_booking_project#D-1000111-somenewbookingproject:TENANT by system and assume }",
"{ grant perm:hs_booking_project#D-1000111-somenewbookingproject:SELECT to role:hs_booking_project#D-1000111-somenewbookingproject:TENANT by system and assume }",
"{ grant role:relation#FirstGmbH-with-DEBITOR-FirstGmbH:TENANT to role:hs_booking.project#D-1000111-somenewbookingproject:TENANT by system and assume }",
"{ grant perm:hs_booking.project#D-1000111-somenewbookingproject:SELECT to role:hs_booking.project#D-1000111-somenewbookingproject:TENANT by system and assume }",
null));
}
@ -214,7 +214,7 @@ class HsBookingProjectRepositoryIntegrationTest extends ContextBasedTestWithClea
public void packetAgent_canViewOnlyRelatedBookingProjects(final TestCase testCase) {
// given:
context("person-FirbySusan@example.com", "hs_booking_project#D-1000111-D-1000111defaultproject:AGENT");
context("person-FirbySusan@example.com", "hs_booking.project#D-1000111-D-1000111defaultproject:AGENT");
final var debitorUuid = debitorRepo.findByDebitorNumber(1000111).stream()
.findAny().orElseThrow().getUuid();
@ -238,7 +238,7 @@ class HsBookingProjectRepositoryIntegrationTest extends ContextBasedTestWithClea
// when
final var result = jpaAttempt.transacted(() -> {
context("superuser-alex@hostsharing.net", "hs_booking_project#D-1000111-sometempproject:ADMIN");
context("superuser-alex@hostsharing.net", "hs_booking.project#D-1000111-sometempproject:ADMIN");
final var foundBookingProject = em.find(HsBookingProjectRbacEntity.class, givenBookingProjectUuid);
foundBookingProject.setCaption("updated caption");
return toCleanup(repoUnderTest(testCase).save(foundBookingProject));
@ -290,7 +290,7 @@ class HsBookingProjectRepositoryIntegrationTest extends ContextBasedTestWithClea
// when
final var result = jpaAttempt.transacted(() -> {
context("person-FirbySusan@example.com", "hs_booking_project#D-1000111-sometempproject:AGENT");
context("person-FirbySusan@example.com", "hs_booking.project#D-1000111-sometempproject:AGENT");
assertThat(rbacProjectRepo.findByUuid(givenBookingProject.getUuid())).isPresent();
repoUnderTest(TestCase.RBAC).deleteByUuid(givenBookingProject.getUuid());
@ -299,7 +299,7 @@ class HsBookingProjectRepositoryIntegrationTest extends ContextBasedTestWithClea
// then
result.assertExceptionWithRootCauseMessage(
JpaSystemException.class,
"[403] Subject ", " is not allowed to delete hs_booking_project");
"[403] Subject ", " is not allowed to delete hs_booking.project");
assertThat(jpaAttempt.transacted(() -> {
context("superuser-alex@hostsharing.net");
return rbacProjectRepo.findByUuid(givenBookingProject.getUuid());

View File

@ -454,7 +454,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
RestAssured // @formatter:off
.given()
.header("current-subject", "person-TuckerJack@example.com")
.header("assumed-roles", "hs_booking_project#D-1000313-D-1000313defaultproject:AGENT")
.header("assumed-roles", "hs_booking.project#D-1000313-D-1000313defaultproject:AGENT")
.port(port)
.when()
.get("http://localhost/api/hs/hosting/assets/" + givenAssetUuid)

View File

@ -167,7 +167,7 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu
public void createsAndGrantsRoles() {
// given
// TODO.test: remove context(...) once all entities have real entities
context("superuser-alex@hostsharing.net", "hs_booking_project#D-1000111-D-1000111defaultproject:AGENT");
context("superuser-alex@hostsharing.net", "hs_booking.project#D-1000111-D-1000111defaultproject:AGENT");
final var givenManagedServer = givenHostingAsset("D-1000111 default project", MANAGED_SERVER);
final var newWebspaceBookingItem = newBookingItem(givenManagedServer.getBookingItem(), HsBookingItemType.MANAGED_WEBSPACE, "fir01");
em.flush();
@ -175,7 +175,7 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu
final var initialGrantNames = distinctGrantDisplaysOf(rawGrantRepo.findAll());
// when
context("superuser-alex@hostsharing.net", "hs_booking_project#D-1000111-D-1000111defaultproject:AGENT");
context("superuser-alex@hostsharing.net", "hs_booking.project#D-1000111-D-1000111defaultproject:AGENT");
final var result = attempt(em, () -> {
final var newAsset = HsHostingAssetRbacEntity.builder()
.bookingItem(newWebspaceBookingItem)
@ -205,13 +205,13 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu
// owner
"{ grant role:hs_hosting_asset#fir00:OWNER to user:superuser-alex@hostsharing.net by hs_hosting_asset#fir00:OWNER and assume }",
"{ grant role:hs_hosting_asset#fir00:OWNER to role:hs_booking_item#fir01:ADMIN by system and assume }",
"{ grant role:hs_hosting_asset#fir00:OWNER to role:hs_booking.item#fir01:ADMIN by system and assume }",
"{ grant role:hs_hosting_asset#fir00:OWNER to role:hs_hosting_asset#vm1011:ADMIN by system and assume }",
"{ grant perm:hs_hosting_asset#fir00:DELETE to role:hs_hosting_asset#fir00:OWNER by system and assume }",
// admin
"{ grant role:hs_hosting_asset#fir00:ADMIN to role:hs_hosting_asset#fir00:OWNER by system and assume }",
"{ grant role:hs_hosting_asset#fir00:ADMIN to role:hs_booking_item#fir01:AGENT by system and assume }",
"{ grant role:hs_hosting_asset#fir00:ADMIN to role:hs_booking.item#fir01:AGENT by system and assume }",
"{ grant perm:hs_hosting_asset#fir00:UPDATE to role:hs_hosting_asset#fir00:ADMIN by system and assume }",
// agent
@ -219,7 +219,7 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu
"{ grant role:hs_hosting_asset#fir00:AGENT to role:hs_hosting_asset#fir00:ADMIN by system and assume }",
// tenant
"{ grant role:hs_booking_item#fir01:TENANT to role:hs_hosting_asset#fir00:TENANT by system and assume }",
"{ grant role:hs_booking.item#fir01:TENANT to role:hs_hosting_asset#fir00:TENANT by system and assume }",
"{ grant role:hs_hosting_asset#fir00:TENANT to role:hs_hosting_asset#fir00:AGENT by system and assume }",
"{ grant role:hs_hosting_asset#vm1011:TENANT to role:hs_hosting_asset#fir00:TENANT by system and assume }",
"{ grant perm:hs_hosting_asset#fir00:SELECT to role:hs_hosting_asset#fir00:TENANT by system and assume }",
@ -287,7 +287,7 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu
@Test
public void normalUser_canViewOnlyRelatedAssets() {
// given:
context("person-FirbySusan@example.com", "hs_booking_project#D-1000111-D-1000111defaultproject:AGENT");
context("person-FirbySusan@example.com", "hs_booking.project#D-1000111-D-1000111defaultproject:AGENT");
final var projectUuid = projectRepo.findByCaption("D-1000111 default project").stream()
.findAny().orElseThrow().getUuid();
@ -397,7 +397,7 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu
// when
final var result = jpaAttempt.transacted(() -> {
context("person-FirbySusan@example.com", "hs_booking_project#D-1000111-D-1000111defaultproject:AGENT");
context("person-FirbySusan@example.com", "hs_booking.project#D-1000111-D-1000111defaultproject:AGENT");
assertThat(rbacAssetRepo.findByUuid(givenAsset.getUuid())).isPresent();
rbacAssetRepo.deleteByUuid(givenAsset.getUuid());

View File

@ -250,10 +250,10 @@ public class CsvDataImport extends ContextBasedTest {
// TODO.perf: could we instead skip creating test-data based on an env var?
em.createNativeQuery("delete from hs_hosting_asset where true").executeUpdate();
em.createNativeQuery("delete from hs_hosting_asset_ex where true").executeUpdate();
em.createNativeQuery("delete from hs_booking_item where true").executeUpdate();
em.createNativeQuery("delete from hs_booking_item_ex where true").executeUpdate();
em.createNativeQuery("delete from hs_booking_project where true").executeUpdate();
em.createNativeQuery("delete from hs_booking_project_ex where true").executeUpdate();
em.createNativeQuery("delete from hs_booking.item where true").executeUpdate();
em.createNativeQuery("delete from hs_booking.item_ex where true").executeUpdate();
em.createNativeQuery("delete from hs_booking.project where true").executeUpdate();
em.createNativeQuery("delete from hs_booking.project_ex where true").executeUpdate();
em.createNativeQuery("delete from hs_office.coopassetstransaction where true").executeUpdate();
em.createNativeQuery("delete from hs_office.coopassetstransaction_legacy_id where true").executeUpdate();
em.createNativeQuery("delete from hs_office.coopsharestransaction where true").executeUpdate();

View File

@ -913,7 +913,7 @@ public class ImportHostingAssets extends BaseOfficeDataImport {
@Test
@Order(19910)
void verifyBookingItemsAreActuallyPersisted() {
final var biCount = (Integer) em.createNativeQuery("select count(*) from hs_booking_item", Integer.class)
final var biCount = (Integer) em.createNativeQuery("select count(*) from hs_booking.item", Integer.class)
.getSingleResult();
assertThat(biCount).isGreaterThan(isImportingControlledTestData() ? 5 : 500);
}
@ -1068,7 +1068,7 @@ public class ImportHostingAssets extends BaseOfficeDataImport {
assumeThatWeAreImportingControlledTestData();
final var haCount = jpaAttempt.transacted(() -> {
context(rbacSuperuser, "hs_booking_project#D-1000300-mimdefaultproject:AGENT");
context(rbacSuperuser, "hs_booking.project#D-1000300-mimdefaultproject:AGENT");
return (Integer) em.createNativeQuery("select count(*) from hs_hosting_asset_rv where type='EMAIL_ADDRESS'", Integer.class)
.getSingleResult();
}).assertSuccessful().returnedValue();

View File

@ -185,7 +185,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
.containsExactlyInAnyOrder(Array.fromFormatted(
initialGrantNames,
"{ grant perm:relation#FirstGmbH-with-DEBITOR-FourtheG:INSERT>sepamandate to role:relation#FirstGmbH-with-DEBITOR-FourtheG:ADMIN by system and assume }",
"{ grant perm:relation#FirstGmbH-with-DEBITOR-FourtheG:INSERT>hs_booking_project to role:relation#FirstGmbH-with-DEBITOR-FourtheG:ADMIN by system and assume }",
"{ grant perm:relation#FirstGmbH-with-DEBITOR-FourtheG:INSERT>hs_booking.project to role:relation#FirstGmbH-with-DEBITOR-FourtheG:ADMIN by system and assume }",
// owner
"{ grant perm:debitor#D-1000122:DELETE to role:relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER by system and assume }",

View File

@ -305,7 +305,7 @@ public abstract class ContextBasedTestWithCleanup extends ContextBasedTest {
protected String[] roleNames(final String sqlLikeExpression) {
final var pattern = Pattern.compile(sqlLikeExpression);
//noinspection unchecked
final List<Object[]> rows = (List<Object[]>) em.createNativeQuery("select * from rbac.role_ev where roleidname like 'hs_booking_project#%'")
final List<Object[]> rows = (List<Object[]>) em.createNativeQuery("select * from rbac.role_ev where roleidname like 'hs_booking.project#%'")
.getResultList();
return rows.stream()
.map(row -> (row[0]).toString())