From 2138b3eed019229dc4a94325a28b93e7e9a88d84 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Thu, 15 Aug 2024 10:38:43 +0200 Subject: [PATCH] fix-domain-setup-rbac-grant-problems (#88) Co-authored-by: Michael Hoennig Reviewed-on: https://dev.hostsharing.net/hostsharing/hs.hsadmin.ng/pulls/88 Reviewed-by: Marc Sandlus --- ...e-cte-experiments-for-accessible-uuids.sql | 142 ++++++++++++++++++ .../hs/booking/item/HsBookingItemEntity.java | 4 +- .../project/HsBookingProjectEntity.java | 2 +- .../hosting/asset/HsHostingAssetEntity.java | 1 + .../hs/hosting/asset/HsHostingAssetType.java | 2 +- .../rbacgrant/RbacGrantsDiagramService.java | 2 +- .../changelog/0-basis/008-raise-functions.sql | 19 ++- .../changelog/1-rbac/1058-rbac-generators.sql | 49 +++--- .../6203-hs-booking-project-rbac.md | 2 +- .../6203-hs-booking-project-rbac.sql | 2 +- .../7013-hs-hosting-asset-rbac.md | 2 + .../7013-hs-hosting-asset-rbac.sql | 4 +- .../7018-hs-hosting-asset-test-data.sql | 7 +- ...HsBookingItemControllerAcceptanceTest.java | 3 +- .../item/HsBookingItemEntityUnitTest.java | 2 +- ...sBookingItemRepositoryIntegrationTest.java | 24 +-- ...ookingProjectControllerAcceptanceTest.java | 3 +- ...okingProjectRepositoryIntegrationTest.java | 10 +- ...sHostingAssetControllerAcceptanceTest.java | 7 +- ...HostingAssetRepositoryIntegrationTest.java | 32 +++- .../hs/migration/ImportHostingAssets.java | 80 +++++++--- .../resources/migration/hosting/inet_addr.csv | 1 + .../resources/migration/hosting/packet.csv | 1 + .../migration/hosting/packet_component.csv | 1 + .../resources/migration/hosting/unixuser.csv | 1 + 25 files changed, 317 insertions(+), 86 deletions(-) create mode 100644 sql/recursive-cte-experiments-for-accessible-uuids.sql diff --git a/sql/recursive-cte-experiments-for-accessible-uuids.sql b/sql/recursive-cte-experiments-for-accessible-uuids.sql new file mode 100644 index 00000000..f8795961 --- /dev/null +++ b/sql/recursive-cte-experiments-for-accessible-uuids.sql @@ -0,0 +1,142 @@ +-- just a permanent playground to explore optimization of the central recursive CTE query for RBAC + +rollback transaction; +begin transaction; +SET TRANSACTION READ ONLY; +call defineContext('performance testing', null, 'superuser-alex@hostsharing.net', + 'hs_booking_project#D-1000000-hshdefaultproject:ADMIN'); +-- 'hs_booking_project#D-1000300-mihdefaultproject:ADMIN'); +select count(type) as counter, type from hs_hosting_asset_rv + group by type + order by counter desc; +commit transaction; + + + + +rollback transaction; +begin transaction; +SET TRANSACTION READ ONLY; +call defineContext('performance testing', null, 'superuser-alex@hostsharing.net', + 'hs_booking_project#D-1000000-hshdefaultproject:ADMIN'); +-- 'hs_booking_project#D-1000300-mihdefaultproject:ADMIN'); + +with accessible_hs_hosting_asset_uuids as + (with recursive + recursive_grants as + (select distinct rbacgrants.descendantuuid, + rbacgrants.ascendantuuid, + 1 as level, + true + from rbacgrants + where rbacgrants.assumed + and (rbacgrants.ascendantuuid = any (currentsubjectsuuids())) + union all + select distinct g.descendantuuid, + g.ascendantuuid, + grants.level + 1 as level, + assertTrue(grants.level < 22, 'too many grant-levels: ' || grants.level) + from rbacgrants g + join recursive_grants grants on grants.descendantuuid = g.ascendantuuid + where g.assumed), + grant_count AS ( + SELECT COUNT(*) AS grant_count FROM recursive_grants + ), + count_check as (select assertTrue((select count(*) as grant_count from recursive_grants) < 300000, + 'too many grants for current subjects: ' || (select count(*) as grant_count from recursive_grants)) + as valid) + select distinct perm.objectuuid + from recursive_grants + join rbacpermission perm on recursive_grants.descendantuuid = perm.uuid + join rbacobject obj on obj.uuid = perm.objectuuid + join count_check cc on cc.valid + where obj.objecttable::text = 'hs_hosting_asset'::text) +select type, +-- count(*) as counter + target.uuid, +-- target.version, +-- target.bookingitemuuid, +-- target.type, +-- target.parentassetuuid, +-- target.assignedtoassetuuid, + target.identifier, + target.caption +-- target.config, +-- target.alarmcontactuuid + from hs_hosting_asset target + where (target.uuid in (select accessible_hs_hosting_asset_uuids.objectuuid + from accessible_hs_hosting_asset_uuids)) + and target.type in ('EMAIL_ADDRESS', 'CLOUD_SERVER', 'MANAGED_SERVER', 'MANAGED_WEBSPACE') +-- and target.type = 'EMAIL_ADDRESS' +-- order by target.identifier; +-- group by type +-- order by counter desc +; +commit transaction; + + + + +rollback transaction; +begin transaction; +SET TRANSACTION READ ONLY; +call defineContext('performance testing', null, 'superuser-alex@hostsharing.net', + 'hs_booking_project#D-1000000-hshdefaultproject:ADMIN'); +-- 'hs_booking_project#D-1000300-mihdefaultproject:ADMIN'); + +with one_path as (with recursive path as ( + -- Base case: Start with the row where ascending equals the starting UUID + select ascendantuuid, + descendantuuid, + array [ascendantuuid] as path_so_far + from rbacgrants + where ascendantuuid = any (currentsubjectsuuids()) + + union all + + -- Recursive case: Find the next step in the path + select c.ascendantuuid, + c.descendantuuid, + p.path_so_far || c.ascendantuuid + from rbacgrants c + inner join + path p on c.ascendantuuid = p.descendantuuid + where c.ascendantuuid != all (p.path_so_far) -- Prevent cycles + ) + -- Final selection: Output all paths that reach the target UUID + select distinct array_length(path_so_far, 1), + path_so_far || descendantuuid as full_path + from path + join rbacpermission perm on perm.uuid = path.descendantuuid + join hs_hosting_asset ha on ha.uuid = perm.objectuuid + -- JOIN rbacrole_ev re on re.uuid = any(path_so_far) + where ha.identifier = 'vm1068' + order by array_length(path_so_far, 1) + limit 1 + ) +select + ( + SELECT ARRAY_AGG(re.roleidname ORDER BY ord.idx) + FROM UNNEST(one_path.full_path) WITH ORDINALITY AS ord(uuid, idx) + JOIN rbacrole_ev re ON ord.uuid = re.uuid + ) AS name_array + from one_path; +commit transaction; + +with grants as ( + select uuid + from rbacgrants + where descendantuuid in ( + select uuid + from rbacrole + where objectuuid in ( + select uuid + from hs_hosting_asset + -- where type = 'DOMAIN_MBOX_SETUP' + -- and identifier = 'example.org|MBOX' + where type = 'EMAIL_ADDRESS' + and identifier='test@example.org' + )) +) +select * from rbacgrants_ev gev where exists ( select uuid from grants where gev.uuid = grants.uuid ); + diff --git a/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemEntity.java index 58a5d4b8..81c87e03 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemEntity.java @@ -74,10 +74,10 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify; public class HsBookingItemEntity implements Stringifyable, BaseEntity, PropertiesProvider { private static Stringify stringify = stringify(HsBookingItemEntity.class) - .withProp(HsBookingItemEntity::getProject) .withProp(HsBookingItemEntity::getType) - .withProp(e -> e.getValidity().asString()) .withProp(HsBookingItemEntity::getCaption) + .withProp(HsBookingItemEntity::getProject) + .withProp(e -> e.getValidity().asString()) .withProp(HsBookingItemEntity::getResources) .quotedValues(false); diff --git a/src/main/java/net/hostsharing/hsadminng/hs/booking/project/HsBookingProjectEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/booking/project/HsBookingProjectEntity.java index c44d43f5..1d893ac0 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/booking/project/HsBookingProjectEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/booking/project/HsBookingProjectEntity.java @@ -94,7 +94,7 @@ public class HsBookingProjectEntity implements Stringifyable, BaseEntity { - with.incomingSuperRole("debitorRel", AGENT); + with.incomingSuperRole("debitorRel", AGENT).unassumed(); }) .createSubRole(ADMIN, (with) -> { with.permission(UPDATE); diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntity.java index 46b315ff..2ae4ae70 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntity.java @@ -185,6 +185,7 @@ public class HsHostingAssetEntity implements HsHostingAsset { with.permission(UPDATE); }) .createSubRole(AGENT, (with) -> { + with.incomingSuperRole("assignedToAsset", AGENT); // TODO.spec: or ADMIN? with.outgoingSubRole("assignedToAsset", TENANT); with.outgoingSubRole("alarmContact", REFERRER); }) diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetType.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetType.java index f08248c4..e11b1430 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetType.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetType.java @@ -264,7 +264,7 @@ public enum HsHostingAssetType implements Node { package Booking #feb28c { %{bookingNodes} } - + package Hosting #feb28c{ %{hostingGroups} } diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantsDiagramService.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantsDiagramService.java index fd33f358..f1369067 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantsDiagramService.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantsDiagramService.java @@ -215,7 +215,7 @@ public class RbacGrantsDiagramService { @NotNull private static String cleanId(final String idName) { return idName.replaceAll("@.*", "") - .replace("[", "").replace("]", "").replace("(", "").replace(")", "").replace(",", "").replace(">", ":"); + .replace("[", "").replace("]", "").replace("(", "").replace(")", "").replace(",", "").replace(">", ":").replace("|", "_"); } diff --git a/src/main/resources/db/changelog/0-basis/008-raise-functions.sql b/src/main/resources/db/changelog/0-basis/008-raise-functions.sql index 15b34d7d..ad298dc9 100644 --- a/src/main/resources/db/changelog/0-basis/008-raise-functions.sql +++ b/src/main/resources/db/changelog/0-basis/008-raise-functions.sql @@ -1,11 +1,10 @@ --liquibase formatted sql -- ============================================================================ --- RAISE-FUNCTIONS --changeset RAISE-FUNCTIONS:1 endDelimiter:--// -- ---------------------------------------------------------------------------- /* - Like RAISE EXCEPTION ... just as an expression instead of a statement. + Like `RAISE EXCEPTION` ... just as an expression instead of a statement. */ create or replace function raiseException(msg text) returns varchar @@ -14,3 +13,19 @@ begin raise exception using message = msg; end; $$; --// + + +-- ============================================================================ +--changeset ASSERT-FUNCTIONS:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- +/* + Like `ASSERT` but as an expression instead of a statement. + */ +create or replace function assertTrue(expectedTrue boolean, msg text) + returns boolean + language plpgsql as $$ +begin + assert expectedTrue, msg; + return expectedTrue; +end; $$; +--// diff --git a/src/main/resources/db/changelog/1-rbac/1058-rbac-generators.sql b/src/main/resources/db/changelog/1-rbac/1058-rbac-generators.sql index 59223d9d..44281bed 100644 --- a/src/main/resources/db/changelog/1-rbac/1058-rbac-generators.sql +++ b/src/main/resources/db/changelog/1-rbac/1058-rbac-generators.sql @@ -177,26 +177,35 @@ begin sql := format($sql$ create or replace view %1$s_rv as with accessible_%1$s_uuids as ( - - -- TODO.perf: this CTE query makes RBAC-SELECT-permission-queries so slow (~500ms), any idea how to optimize? - -- My guess is, that the depth of role-grants causes the problem. - 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 and level<10 - ) - select distinct perm.objectUuid as objectUuid - from grants - join RbacPermission perm on grants.descendantUuid = perm.uuid - join RbacObject obj on obj.uuid = perm.objectUuid - where obj.objectTable = '%1$s' -- 'SELECT' permission is included in all other permissions - limit 8001 + with recursive + recursive_grants as + (select distinct rbacgrants.descendantuuid, + rbacgrants.ascendantuuid, + 1 as level, + true + from rbacgrants + where rbacgrants.assumed + and (rbacgrants.ascendantuuid = any (currentsubjectsuuids())) + union all + select distinct g.descendantuuid, + g.ascendantuuid, + grants.level + 1 as level, + assertTrue(grants.level < 22, 'too many grant-levels: ' || grants.level) + from rbacgrants g + join recursive_grants grants on grants.descendantuuid = g.ascendantuuid + where g.assumed), + grant_count AS ( + SELECT COUNT(*) AS grant_count FROM recursive_grants + ), + count_check as (select assertTrue((select count(*) as grant_count from recursive_grants) < 400000, + 'too many grants for current subjects: ' || (select count(*) as grant_count from recursive_grants)) + as valid) + select distinct perm.objectuuid + from recursive_grants + join rbacpermission perm on recursive_grants.descendantuuid = perm.uuid + join rbacobject obj on obj.uuid = perm.objectuuid + join count_check cc on cc.valid + where obj.objectTable = '%1$s' -- 'SELECT' permission is included in all other permissions ) select target.* from %1$s as target diff --git a/src/main/resources/db/changelog/6-hs-booking/620-booking-project/6203-hs-booking-project-rbac.md b/src/main/resources/db/changelog/6-hs-booking/620-booking-project/6203-hs-booking-project-rbac.md index 270908a8..7fb81cd7 100644 --- a/src/main/resources/db/changelog/6-hs-booking/620-booking-project/6203-hs-booking-project-rbac.md +++ b/src/main/resources/db/changelog/6-hs-booking/620-booking-project/6203-hs-booking-project-rbac.md @@ -48,7 +48,7 @@ role:global:ADMIN -.-> role:debitorRel:OWNER role:debitorRel:OWNER -.-> role:debitorRel:ADMIN role:debitorRel:ADMIN -.-> role:debitorRel:AGENT role:debitorRel:AGENT -.-> role:debitorRel:TENANT -role:debitorRel:AGENT ==> role:project:OWNER +role:debitorRel:AGENT ==>|XX| role:project:OWNER role:project:OWNER ==> role:project:ADMIN role:project:ADMIN ==> role:project:AGENT role:project:AGENT ==> role:project:TENANT diff --git a/src/main/resources/db/changelog/6-hs-booking/620-booking-project/6203-hs-booking-project-rbac.sql b/src/main/resources/db/changelog/6-hs-booking/620-booking-project/6203-hs-booking-project-rbac.sql index e0e0a9b7..c6f3544d 100644 --- a/src/main/resources/db/changelog/6-hs-booking/620-booking-project/6203-hs-booking-project-rbac.sql +++ b/src/main/resources/db/changelog/6-hs-booking/620-booking-project/6203-hs-booking-project-rbac.sql @@ -49,7 +49,7 @@ begin perform createRoleWithGrants( hsBookingProjectOWNER(NEW), - incomingSuperRoles => array[hsOfficeRelationAGENT(newDebitorRel)] + incomingSuperRoles => array[hsOfficeRelationAGENT(newDebitorRel, unassumed())] ); perform createRoleWithGrants( diff --git a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac.md b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac.md index 019bb0a2..d06f9f9a 100644 --- a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac.md +++ b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac.md @@ -49,6 +49,7 @@ subgraph assignedToAsset["`**assignedToAsset**`"] subgraph assignedToAsset:roles[ ] style assignedToAsset:roles fill:#99bcdb,stroke:white + role:assignedToAsset:AGENT[[assignedToAsset:AGENT]] role:assignedToAsset:TENANT[[assignedToAsset:TENANT]] end end @@ -97,6 +98,7 @@ role:asset:OWNER ==> role:asset:ADMIN role:bookingItem:AGENT ==> role:asset:ADMIN role:parentAsset:AGENT ==> role:asset:ADMIN role:asset:ADMIN ==> role:asset:AGENT +role:assignedToAsset:AGENT ==> role:asset:AGENT role:asset:AGENT ==> role:assignedToAsset:TENANT role:asset:AGENT ==> role:alarmContact:REFERRER role:asset:AGENT ==> role:asset:TENANT diff --git a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac.sql b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac.sql index 91afe2b6..5ec3e044 100644 --- a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac.sql +++ b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7013-hs-hosting-asset-rbac.sql @@ -67,7 +67,9 @@ begin perform createRoleWithGrants( hsHostingAssetAGENT(NEW), - incomingSuperRoles => array[hsHostingAssetADMIN(NEW)], + incomingSuperRoles => array[ + hsHostingAssetADMIN(NEW), + hsHostingAssetAGENT(newAssignedToAsset)], outgoingSubRoles => array[ hsHostingAssetTENANT(newAssignedToAsset), hsOfficeContactREFERRER(newAlarmContact)] diff --git a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7018-hs-hosting-asset-test-data.sql b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7018-hs-hosting-asset-test-data.sql index 9e8f3317..a74b6126 100644 --- a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7018-hs-hosting-asset-test-data.sql +++ b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7018-hs-hosting-asset-test-data.sql @@ -23,6 +23,7 @@ declare managedServerUuid uuid; managedWebspaceUuid uuid; webUnixUserUuid uuid; + mboxUnixUserUuid uuid; domainSetupUuid uuid; domainMBoxSetupUuid uuid; mariaDbInstanceUuid uuid; @@ -71,6 +72,7 @@ begin select uuid_generate_v4() into managedServerUuid; select uuid_generate_v4() into managedWebspaceUuid; select uuid_generate_v4() into webUnixUserUuid; + select uuid_generate_v4() into mboxUnixUserUuid; select uuid_generate_v4() into domainSetupUuid; select uuid_generate_v4() into domainMBoxSetupUuid; select uuid_generate_v4() into mariaDbInstanceUuid; @@ -94,11 +96,12 @@ begin (uuid_generate_v4(), null, 'PGSQL_DATABASE', pgSqlUserUuid, pgSqlInstanceUuid, defaultPrefix || '01_web', 'some default Postgresql database','{ "encryption": "utf8", "collation": "utf8"}'::jsonb ), (uuid_generate_v4(), null, 'EMAIL_ALIAS', managedWebspaceUuid, null, defaultPrefix || '01-web', 'some E-Mail-Alias', '{ "target": [ "office@example.org", "archive@example.com" ] }'::jsonb), (webUnixUserUuid, null, 'UNIX_USER', managedWebspaceUuid, null, defaultPrefix || '01-web', 'some UnixUser for Website', '{ "SSD-soft-quota": "128", "SSD-hard-quota": "256", "HDD-soft-quota": "512", "HDD-hard-quota": "1024"}'::jsonb), + (mboxUnixUserUuid, null, 'UNIX_USER', managedWebspaceUuid, null, defaultPrefix || '01-mbox', 'some UnixUser for E-Mail', '{ "SSD-soft-quota": "128", "SSD-hard-quota": "256", "HDD-soft-quota": "512", "HDD-hard-quota": "1024"}'::jsonb), (domainSetupUuid, null, 'DOMAIN_SETUP', null, null, defaultPrefix || '.example.org', 'some Domain-Setup', '{}'::jsonb), (uuid_generate_v4(), null, 'DOMAIN_DNS_SETUP', domainSetupUuid, null, defaultPrefix || '.example.org|DNS', 'some Domain-DNS-Setup', '{}'::jsonb), (uuid_generate_v4(), null, 'DOMAIN_HTTP_SETUP', domainSetupUuid, webUnixUserUuid, defaultPrefix || '.example.org|HTTP', 'some Domain-HTTP-Setup', '{ "option-htdocsfallback": true, "use-fcgiphpbin": "/usr/lib/cgi-bin/php", "validsubdomainnames": "*"}'::jsonb), - (uuid_generate_v4(), null, 'DOMAIN_SMTP_SETUP', domainSetupUuid, managedWebspaceUuid, defaultPrefix || '.example.org|DNS', 'some Domain-SMPT-Setup', '{}'::jsonb), - (domainMBoxSetupUuid, null, 'DOMAIN_MBOX_SETUP', domainSetupUuid, managedWebspaceUuid, defaultPrefix || '.example.org|DNS', 'some Domain-MBOX-Setup', '{}'::jsonb), + (uuid_generate_v4(), null, 'DOMAIN_SMTP_SETUP', domainSetupUuid, managedWebspaceUuid, defaultPrefix || '.example.org|SMTP', 'some Domain-SMTP-Setup', '{}'::jsonb), + (domainMBoxSetupUuid, null, 'DOMAIN_MBOX_SETUP', domainSetupUuid, managedWebspaceUuid, defaultPrefix || '.example.org|MBOX', 'some Domain-MBOX-Setup', '{}'::jsonb), (uuid_generate_v4(), null, 'EMAIL_ADDRESS', domainMBoxSetupUuid, null, 'test@' || defaultPrefix || '.example.org', 'some E-Mail-Address', '{}'::jsonb); end; $$; --// diff --git a/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemControllerAcceptanceTest.java index 71753976..b28e3e4e 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemControllerAcceptanceTest.java @@ -287,7 +287,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup class PatchBookingItem { @Test - void globalAdmin_canPatchAllUpdatablePropertiesOfBookingItem() { + void projectAgent_canPatchAllUpdatablePropertiesOfBookingItem() { final var givenBookingItem = givenSomeNewBookingItem("D-1000111 default project", MANAGED_WEBSPACE, resource("HDD", 100), resource("SSD", 50), resource("Traffic", 250)); @@ -295,6 +295,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup RestAssured // @formatter:off .given() .header("current-user", "superuser-alex@hostsharing.net") + .header("assumed-roles", "hs_booking_project#D-1000111-D-1000111defaultproject:AGENT") .contentType(ContentType.JSON) .body(""" { diff --git a/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemEntityUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemEntityUnitTest.java index 627eabc2..23e0307f 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemEntityUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemEntityUnitTest.java @@ -53,7 +53,7 @@ class HsBookingItemEntityUnitTest { void toStringContainsAllPropertiesAndResourcesSortedByKey() { final var result = givenBookingItem.toString(); - assertThat(result).isEqualToIgnoringWhitespace("HsBookingItemEntity(D-1234500:test project, CLOUD_SERVER, [2020-01-01,2031-01-01), some caption, { \"CPU\": 2, \"HDD-storage\": 2048, \"SSD-storage\": 512 })"); + assertThat(result).isEqualToIgnoringWhitespace("HsBookingItemEntity(CLOUD_SERVER, some caption, D-1234500:test project, [2020-01-01,2031-01-01), { \"CPU\": 2, \"HDD-storage\": 2048, \"SSD-storage\": 512 })"); } @Test diff --git a/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemRepositoryIntegrationTest.java index d0d58cfc..9c1c04d0 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemRepositoryIntegrationTest.java @@ -170,9 +170,9 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup // then allTheseBookingItemsAreReturned( result, - "HsBookingItemEntity(D-1000212:D-1000212 default project, MANAGED_WEBSPACE, [2022-10-01,), separate ManagedWebspace, { Daemons: 0, Multi: 1, SSD: 100, Traffic: 50 })", - "HsBookingItemEntity(D-1000212:D-1000212 default project, MANAGED_SERVER, [2022-10-01,), separate ManagedServer, { CPU: 2, RAM: 8, SSD: 500, Traffic: 500 })", - "HsBookingItemEntity(D-1000212:D-1000212 default project, PRIVATE_CLOUD, [2024-04-01,), some PrivateCloud, { CPU: 10, HDD: 10000, RAM: 32, SSD: 4000, Traffic: 2000 })"); + "HsBookingItemEntity(MANAGED_SERVER, separate ManagedServer, D-1000212:D-1000212 default project, [2022-10-01,), { CPU: 2, RAM: 8, SSD: 500, Traffic: 500 })", + "HsBookingItemEntity(MANAGED_WEBSPACE, separate ManagedWebspace, D-1000212:D-1000212 default project, [2022-10-01,), { Daemons: 0, Multi: 1, SSD: 100, Traffic: 50 })", + "HsBookingItemEntity(PRIVATE_CLOUD, some PrivateCloud, D-1000212:D-1000212 default project, [2024-04-01,), { CPU: 10, HDD: 10000, RAM: 32, SSD: 4000, Traffic: 2000 })"); assertThat(result.stream().filter(bi -> bi.getRelatedHostingAsset()!=null).findAny()) .as("at least one relatedProject expected, but none found => fetching relatedProject does not work") .isNotEmpty(); @@ -182,7 +182,9 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup public void normalUser_canViewOnlyRelatedBookingItems() { // given: context("person-FirbySusan@example.com"); - final var projectUuid = debitorRepo.findDebitorByDebitorNumber(1000111).stream() + final var debitor = debitorRepo.findDebitorByDebitorNumber(1000111); + context("person-FirbySusan@example.com", "hs_booking_project#D-1000111-D-1000111defaultproject:OWNER"); + final var projectUuid = debitor.stream() .map(d -> projectRepo.findAllByDebitorUuid(d.getUuid())) .flatMap(List::stream) .findAny().orElseThrow().getUuid(); @@ -193,9 +195,9 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup // then: exactlyTheseBookingItemsAreReturned( result, - "HsBookingItemEntity(D-1000111:D-1000111 default project, MANAGED_WEBSPACE, [2022-10-01,), separate ManagedWebspace, { Daemons : 0, Multi : 1, SSD : 100, Traffic : 50 })", - "HsBookingItemEntity(D-1000111:D-1000111 default project, MANAGED_SERVER, [2022-10-01,), separate ManagedServer, { CPU : 2, RAM : 8, SSD : 500, Traffic : 500 })", - "HsBookingItemEntity(D-1000111:D-1000111 default project, PRIVATE_CLOUD, [2024-04-01,), some PrivateCloud, { CPU : 10, HDD : 10000, RAM : 32, SSD : 4000, Traffic : 2000 })"); + "HsBookingItemEntity(MANAGED_SERVER, separate ManagedServer, D-1000111:D-1000111 default project, [2022-10-01,), { CPU : 2, RAM : 8, SSD : 500, Traffic : 500 })", + "HsBookingItemEntity(MANAGED_WEBSPACE, separate ManagedWebspace, D-1000111:D-1000111 default project, [2022-10-01,), { Daemons : 0, Multi : 1, SSD : 100, Traffic : 50 })", + "HsBookingItemEntity(PRIVATE_CLOUD, some PrivateCloud, D-1000111:D-1000111 default project, [2024-04-01,), { CPU : 10, HDD : 10000, RAM : 32, SSD : 4000, Traffic : 2000 })"); } } @@ -209,7 +211,7 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup // when final var result = jpaAttempt.transacted(() -> { - context("superuser-alex@hostsharing.net"); + context("superuser-alex@hostsharing.net", "hs_booking_project#D-1000111-D-1000111defaultproject:AGENT"); final var foundBookingItem = em.find(HsBookingItemEntity.class, givenBookingItemUuid); foundBookingItem.getResources().put("CPU", 2); foundBookingItem.getResources().remove("SSD-storage"); @@ -262,12 +264,12 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup @Test public void nonGlobalAdmin_canNotDeleteTheirRelatedBookingItem() { // given - context("superuser-alex@hostsharing.net", null); + 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"); + context("person-FirbySusan@example.com", "hs_booking_project#D-1000111-D-1000111defaultproject:AGENT"); assertThat(bookingItemRepo.findByUuid(givenBookingItem.getUuid())).isPresent(); bookingItemRepo.deleteByUuid(givenBookingItem.getUuid()); @@ -286,7 +288,7 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup @Test public void deletingABookingItemAlsoDeletesRelatedRolesAndGrants() { // given - context("superuser-alex@hostsharing.net"); + 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"); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/booking/project/HsBookingProjectControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/booking/project/HsBookingProjectControllerAcceptanceTest.java index 9a4c2391..94194b1f 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/booking/project/HsBookingProjectControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/booking/project/HsBookingProjectControllerAcceptanceTest.java @@ -163,7 +163,7 @@ class HsBookingProjectControllerAcceptanceTest extends ContextBasedTestWithClean } @Test - void debitorAgentUser_canGetRelatedBookingProject() { + void projectAgentUser_canGetRelatedBookingProject() { context.define("superuser-alex@hostsharing.net"); final var givenBookingProjectUuid = bookingProjectRepo.findByCaption("D-1000313 default project").stream() .findAny().orElseThrow().getUuid(); @@ -171,6 +171,7 @@ class HsBookingProjectControllerAcceptanceTest extends ContextBasedTestWithClean RestAssured // @formatter:off .given() .header("current-user", "person-TuckerJack@example.com") + .header("assumed-roles", "hs_booking_project#D-1000313-D-1000313defaultproject:AGENT") .port(port) .when() .get("http://localhost/api/hs/booking/projects/" + givenBookingProjectUuid) diff --git a/src/test/java/net/hostsharing/hsadminng/hs/booking/project/HsBookingProjectRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/booking/project/HsBookingProjectRepositoryIntegrationTest.java index e73bf942..8e3b7168 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/booking/project/HsBookingProjectRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/booking/project/HsBookingProjectRepositoryIntegrationTest.java @@ -125,7 +125,7 @@ class HsBookingProjectRepositoryIntegrationTest extends ContextBasedTestWithClea "{ 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 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 @@ -161,9 +161,10 @@ class HsBookingProjectRepositoryIntegrationTest extends ContextBasedTestWithClea } @Test - public void normalUser_canViewOnlyRelatedBookingProjects() { + public void packetAgent_canViewOnlyRelatedBookingProjects() { + // given: - context("person-FirbySusan@example.com"); + context("person-FirbySusan@example.com", "hs_booking_project#D-1000111-D-1000111defaultproject:AGENT"); final var debitorUuid = debitorRepo.findByDebitorNumber(1000111).stream() .findAny().orElseThrow().getUuid(); @@ -233,12 +234,11 @@ class HsBookingProjectRepositoryIntegrationTest extends ContextBasedTestWithClea @Test public void nonGlobalAdmin_canNotDeleteTheirRelatedBookingProject() { // given - context("superuser-alex@hostsharing.net", null); final var givenBookingProject = givenSomeTemporaryBookingProject(1000111); // when final var result = jpaAttempt.transacted(() -> { - context("person-FirbySusan@example.com"); + context("person-FirbySusan@example.com", "hs_booking_project#D-1000111-sometempproject:AGENT"); assertThat(bookingProjectRepo.findByUuid(givenBookingProject.getUuid())).isPresent(); bookingProjectRepo.deleteByUuid(givenBookingProject.getUuid()); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetControllerAcceptanceTest.java index 476b6bb0..0fcb35b4 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetControllerAcceptanceTest.java @@ -324,10 +324,12 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup assertThat(givenHostingAsset.getBookingItem().getResources().get("Multi")) .as("precondition failed") .isEqualTo(1); + final var preExistingUnixUserCount = assetRepo.findAllByCriteria(null, givenHostingAsset.getUuid(), UNIX_USER).size(); + final var UNIX_USER_PER_MULTI_OPTION = 25; jpaAttempt.transacted(() -> { context.define("superuser-alex@hostsharing.net"); - for (int n = 0; n < 25; ++n) { + for (int n = 0; n < UNIX_USER_PER_MULTI_OPTION -preExistingUnixUserCount+1; ++n) { toCleanup(assetRepo.save( HsHostingAssetEntity.builder() .type(UNIX_USER) @@ -413,7 +415,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup } @Test - void debitorAgentUser_canGetRelatedAsset() { + void projectAgentUser_canGetRelatedAsset() { context.define("superuser-alex@hostsharing.net"); final var givenAssetUuid = assetRepo.findByIdentifier("vm1013").stream() .filter(bi -> bi.getBookingItem().getProject().getCaption().equals("D-1000313 default project")) @@ -422,6 +424,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup RestAssured // @formatter:off .given() .header("current-user", "person-TuckerJack@example.com") + .header("assumed-roles", "hs_booking_project#D-1000313-D-1000313defaultproject:AGENT") .port(port) .when() .get("http://localhost/api/hs/hosting/assets/" + givenAssetUuid) diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetRepositoryIntegrationTest.java index ae733e54..682610de 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetRepositoryIntegrationTest.java @@ -28,6 +28,7 @@ import java.util.Map; import static java.util.Map.entry; import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.CLOUD_SERVER; import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.DOMAIN_SETUP; +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.EMAIL_ADDRESS; import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_SERVER; import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_WEBSPACE; import static net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantEntity.distinctGrantDisplaysOf; @@ -98,7 +99,7 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu @Test public void createsAndGrantsRoles() { // given - context("superuser-alex@hostsharing.net"); + 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(); @@ -152,7 +153,7 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu "{ 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 }", // workaround + "{ grant perm:hs_hosting_asset#fir00:SELECT to role:hs_hosting_asset#fir00:TENANT by system and assume }", null)); } @@ -195,7 +196,7 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu } @Nested - class FindByDebitorUuid { + class FindAssets { @Test public void globalAdmin_withoutAssumedRole_canViewArbitraryAssetsOfAllDebitors() { @@ -214,9 +215,9 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu } @Test - public void normalUser_canViewOnlyRelatedAsset() { + public void normalUser_canViewOnlyRelatedAssets() { // given: - context("person-FirbySusan@example.com"); + 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(); @@ -231,7 +232,7 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu } @Test - public void normalUser_canFilterAssetsRelatedToParentAsset() { + public void managedServerAgent_canFindAssetsRelatedToManagedServer() { // given context("superuser-alex@hostsharing.net"); final var parentAssetUuid = assetRepo.findByIdentifier("vm1012").stream() @@ -249,6 +250,21 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu "HsHostingAssetEntity(MARIADB_INSTANCE, vm1012.MariaDB.default, some default MariaDB instance, MANAGED_SERVER:vm1012)", "HsHostingAssetEntity(PGSQL_INSTANCE, vm1012.Postgresql.default, some default Postgresql instance, MANAGED_SERVER:vm1012)"); } + + @Test + public void managedServerAgent_canFindRelatedEmailAddresses() { + // given + context("superuser-alex@hostsharing.net"); + + // when + context("superuser-alex@hostsharing.net", "hs_hosting_asset#sec01:AGENT"); + final var result = assetRepo.findAllByCriteria(null, null, EMAIL_ADDRESS); + + // then + exactlyTheseAssetsAreReturned( + result, + "HsHostingAssetEntity(EMAIL_ADDRESS, test@sec.example.org, some E-Mail-Address, DOMAIN_MBOX_SETUP:sec.example.org|MBOX)"); + } } @Nested @@ -310,12 +326,12 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu @Test public void relatedOwner_canDeleteTheirRelatedAsset() { // given - context("superuser-alex@hostsharing.net", null); + context("superuser-alex@hostsharing.net", "hs_booking_project#D-1000111-D-1000111defaultproject:AGENT"); final var givenAsset = givenSomeTemporaryAsset("D-1000111 default project", "vm1000"); // when final var result = jpaAttempt.transacted(() -> { - context("person-FirbySusan@example.com"); + context("person-FirbySusan@example.com", "hs_booking_project#D-1000111-D-1000111defaultproject:AGENT"); assertThat(assetRepo.findByUuid(givenAsset.getUuid())).isPresent(); assetRepo.deleteByUuid(givenAsset.getUuid()); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/migration/ImportHostingAssets.java b/src/test/java/net/hostsharing/hsadminng/hs/migration/ImportHostingAssets.java index 041424f4..410485eb 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/migration/ImportHostingAssets.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/migration/ImportHostingAssets.java @@ -34,6 +34,7 @@ import org.springframework.test.annotation.DirtiesContext; import java.io.Reader; import java.net.IDN; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -183,9 +184,9 @@ public class ImportHostingAssets extends ImportOfficeData { { 363=HsHostingAssetRealEntity(IPV4_NUMBER, 83.223.95.34), 381=HsHostingAssetRealEntity(IPV4_NUMBER, 83.223.95.52), + 401=HsHostingAssetRealEntity(IPV4_NUMBER, 83.223.95.72), 402=HsHostingAssetRealEntity(IPV4_NUMBER, 83.223.95.73), - 433=HsHostingAssetRealEntity(IPV4_NUMBER, 83.223.95.104), - 457=HsHostingAssetRealEntity(IPV4_NUMBER, 83.223.95.128) + 433=HsHostingAssetRealEntity(IPV4_NUMBER, 83.223.95.104) } """); } @@ -239,13 +240,13 @@ public class ImportHostingAssets extends ImportOfficeData { HsBookingItemType.MANAGED_SERVER, HsBookingItemType.MANAGED_WEBSPACE)).isEqualToIgnoringWhitespace(""" { - 10630=HsBookingItemEntity(D-1000000:hsh default project, MANAGED_WEBSPACE, [2001-06-01,), BI hsh00), - 10968=HsBookingItemEntity(D-1015200:rar default project, MANAGED_SERVER, [2013-04-01,), BI vm1061), - 10978=HsBookingItemEntity(D-1000000:hsh default project, MANAGED_SERVER, [2013-04-01,), BI vm1050), - 11061=HsBookingItemEntity(D-1000300:mim default project, MANAGED_SERVER, [2013-08-19,), BI vm1068), - 11094=HsBookingItemEntity(D-1000300:mim default project, MANAGED_WEBSPACE, [2013-09-10,), BI lug00), - 11112=HsBookingItemEntity(D-1000300:mim default project, MANAGED_WEBSPACE, [2013-09-17,), BI mim00), - 23611=HsBookingItemEntity(D-1101800:wws default project, CLOUD_SERVER, [2022-08-10,), BI vm2097) + 10630=HsBookingItemEntity(MANAGED_WEBSPACE, BI hsh00, D-1000000:hsh default project, [2001-06-01,)), + 10968=HsBookingItemEntity(MANAGED_SERVER, BI vm1061, D-1015200:rar default project, [2013-04-01,)), + 10978=HsBookingItemEntity(MANAGED_SERVER, BI vm1050, D-1000000:hsh default project, [2013-04-01,)), + 11061=HsBookingItemEntity(MANAGED_SERVER, BI vm1068, D-1000300:mim default project, [2013-08-19,)), + 11094=HsBookingItemEntity(MANAGED_WEBSPACE, BI lug00, D-1000300:mim default project, [2013-09-10,)), + 11111=HsBookingItemEntity(MANAGED_WEBSPACE, BI xyz68, D-1000000:vm1068 Monitor, [2013-08-19,)), + 23611=HsBookingItemEntity(CLOUD_SERVER, BI vm2097, D-1101800:wws default project, [2022-08-10,)) } """); assertThat(firstOfEach(9, packetAssets)).isEqualToIgnoringWhitespace(""" @@ -255,10 +256,10 @@ public class ImportHostingAssets extends ImportOfficeData { 10978=HsHostingAssetRealEntity(MANAGED_SERVER, vm1050, HA vm1050, D-1000000:hsh default project:BI vm1050), 11061=HsHostingAssetRealEntity(MANAGED_SERVER, vm1068, HA vm1068, D-1000300:mim default project:BI vm1068), 11094=HsHostingAssetRealEntity(MANAGED_WEBSPACE, lug00, HA lug00, MANAGED_SERVER:vm1068, D-1000300:mim default project:BI lug00), + 11111=HsHostingAssetRealEntity(MANAGED_WEBSPACE, xyz68, HA xyz68, MANAGED_SERVER:vm1068, D-1000000:vm1068 Monitor:BI xyz68), 11112=HsHostingAssetRealEntity(MANAGED_WEBSPACE, mim00, HA mim00, MANAGED_SERVER:vm1068, D-1000300:mim default project:BI mim00), 11447=HsHostingAssetRealEntity(MANAGED_SERVER, vm1093, HA vm1093, D-1000000:hsh default project:BI vm1093), - 19959=HsHostingAssetRealEntity(MANAGED_WEBSPACE, dph00, HA dph00, MANAGED_SERVER:vm1093, D-1101900:dph default project:BI dph00), - 23611=HsHostingAssetRealEntity(CLOUD_SERVER, vm2097, HA vm2097, D-1101800:wws default project:BI vm2097) + 19959=HsHostingAssetRealEntity(MANAGED_WEBSPACE, dph00, HA dph00, MANAGED_SERVER:vm1093, D-1101900:dph default project:BI dph00) } """); } @@ -287,8 +288,8 @@ public class ImportHostingAssets extends ImportOfficeData { 10978=HsHostingAssetRealEntity(MANAGED_SERVER, vm1050, HA vm1050, D-1000000:hsh default project:BI vm1050), 11061=HsHostingAssetRealEntity(MANAGED_SERVER, vm1068, HA vm1068, D-1000300:mim default project:BI vm1068), 11094=HsHostingAssetRealEntity(MANAGED_WEBSPACE, lug00, HA lug00, MANAGED_SERVER:vm1068, D-1000300:mim default project:BI lug00), - 11112=HsHostingAssetRealEntity(MANAGED_WEBSPACE, mim00, HA mim00, MANAGED_SERVER:vm1068, D-1000300:mim default project:BI mim00), - 11447=HsHostingAssetRealEntity(MANAGED_SERVER, vm1093, HA vm1093, D-1000000:hsh default project:BI vm1093) + 11111=HsHostingAssetRealEntity(MANAGED_WEBSPACE, xyz68, HA xyz68, MANAGED_SERVER:vm1068, D-1000000:vm1068 Monitor:BI xyz68), + 11112=HsHostingAssetRealEntity(MANAGED_WEBSPACE, mim00, HA mim00, MANAGED_SERVER:vm1068, D-1000300:mim default project:BI mim00) } """); assertThat(firstOfEachType( @@ -298,15 +299,16 @@ public class ImportHostingAssets extends ImportOfficeData { HsBookingItemType.MANAGED_WEBSPACE)) .isEqualToIgnoringWhitespace(""" { - 10630=HsBookingItemEntity(D-1000000:hsh default project, MANAGED_WEBSPACE, [2001-06-01,), BI hsh00, {"HDD": 10, "Multi": 25, "SLA-Platform": "EXT24H", "SSD": 16, "Traffic": 50}), - 10968=HsBookingItemEntity(D-1015200:rar default project, MANAGED_SERVER, [2013-04-01,), BI vm1061, {"CPU": 6, "HDD": 250, "RAM": 14, "SLA-EMail": true, "SLA-Maria": true, "SLA-Office": true, "SLA-PgSQL": true, "SLA-Platform": "EXT4H", "SLA-Web": true, "SSD": 375, "Traffic": 250}), - 10978=HsBookingItemEntity(D-1000000:hsh default project, MANAGED_SERVER, [2013-04-01,), BI vm1050, {"CPU": 4, "HDD": 250, "RAM": 32, "SLA-EMail": true, "SLA-Maria": true, "SLA-Office": true, "SLA-PgSQL": true, "SLA-Platform": "EXT4H", "SLA-Web": true, "SSD": 150, "Traffic": 250}), - 11061=HsBookingItemEntity(D-1000300:mim default project, MANAGED_SERVER, [2013-08-19,), BI vm1068, {"CPU": 2, "HDD": 250, "RAM": 4, "SLA-EMail": true, "SLA-Maria": true, "SLA-Office": true, "SLA-PgSQL": true, "SLA-Platform": "EXT2H", "SLA-Web": true, "Traffic": 250}), - 11094=HsBookingItemEntity(D-1000300:mim default project, MANAGED_WEBSPACE, [2013-09-10,), BI lug00, {"Multi": 5, "SLA-Platform": "EXT24H", "SSD": 1, "Traffic": 10}), - 11112=HsBookingItemEntity(D-1000300:mim default project, MANAGED_WEBSPACE, [2013-09-17,), BI mim00, {"Multi": 5, "SLA-Platform": "EXT24H", "SSD": 3, "Traffic": 20}), - 11447=HsBookingItemEntity(D-1000000:hsh default project, MANAGED_SERVER, [2014-11-28,), BI vm1093, {"CPU": 6, "HDD": 500, "RAM": 16, "SLA-EMail": true, "SLA-Maria": true, "SLA-Office": true, "SLA-PgSQL": true, "SLA-Platform": "EXT4H", "SLA-Web": true, "SSD": 300, "Traffic": 250}), - 19959=HsBookingItemEntity(D-1101900:dph default project, MANAGED_WEBSPACE, [2021-06-02,), BI dph00, {"Multi": 1, "SLA-Platform": "EXT24H", "SSD": 25, "Traffic": 20}), - 23611=HsBookingItemEntity(D-1101800:wws default project, CLOUD_SERVER, [2022-08-10,), BI vm2097, {"CPU": 8, "RAM": 12, "SLA-Infrastructure": "EXT4H", "SSD": 25, "Traffic": 250}) + 10630=HsBookingItemEntity(MANAGED_WEBSPACE, BI hsh00, D-1000000:hsh default project, [2001-06-01,), {"HDD": 10, "Multi": 25, "SLA-Platform": "EXT24H", "SSD": 16, "Traffic": 50}), + 10968=HsBookingItemEntity(MANAGED_SERVER, BI vm1061, D-1015200:rar default project, [2013-04-01,), {"CPU": 6, "HDD": 250, "RAM": 14, "SLA-EMail": true, "SLA-Maria": true, "SLA-Office": true, "SLA-PgSQL": true, "SLA-Platform": "EXT4H", "SLA-Web": true, "SSD": 375, "Traffic": 250}), + 10978=HsBookingItemEntity(MANAGED_SERVER, BI vm1050, D-1000000:hsh default project, [2013-04-01,), {"CPU": 4, "HDD": 250, "RAM": 32, "SLA-EMail": true, "SLA-Maria": true, "SLA-Office": true, "SLA-PgSQL": true, "SLA-Platform": "EXT4H", "SLA-Web": true, "SSD": 150, "Traffic": 250}), + 11061=HsBookingItemEntity(MANAGED_SERVER, BI vm1068, D-1000300:mim default project, [2013-08-19,), {"CPU": 2, "HDD": 250, "RAM": 4, "SLA-EMail": true, "SLA-Maria": true, "SLA-Office": true, "SLA-PgSQL": true, "SLA-Platform": "EXT2H", "SLA-Web": true, "Traffic": 250}), + 11094=HsBookingItemEntity(MANAGED_WEBSPACE, BI lug00, D-1000300:mim default project, [2013-09-10,), {"Multi": 5, "SLA-Platform": "EXT24H", "SSD": 1, "Traffic": 10}), + 11111=HsBookingItemEntity(MANAGED_WEBSPACE, BI xyz68, D-1000000:vm1068 Monitor, [2013-08-19,), {"SSD": 3}), + 11112=HsBookingItemEntity(MANAGED_WEBSPACE, BI mim00, D-1000300:mim default project, [2013-09-17,), {"Multi": 5, "SLA-Platform": "EXT24H", "SSD": 3, "Traffic": 20}), + 11447=HsBookingItemEntity(MANAGED_SERVER, BI vm1093, D-1000000:hsh default project, [2014-11-28,), {"CPU": 6, "HDD": 500, "RAM": 16, "SLA-EMail": true, "SLA-Maria": true, "SLA-Office": true, "SLA-PgSQL": true, "SLA-Platform": "EXT4H", "SLA-Web": true, "SSD": 300, "Traffic": 250}), + 19959=HsBookingItemEntity(MANAGED_WEBSPACE, BI dph00, D-1101900:dph default project, [2021-06-02,), {"Multi": 1, "SLA-Platform": "EXT24H", "SSD": 25, "Traffic": 20}), + 23611=HsBookingItemEntity(CLOUD_SERVER, BI vm2097, D-1101800:wws default project, [2022-08-10,), {"CPU": 8, "RAM": 12, "SLA-Infrastructure": "EXT4H", "SSD": 25, "Traffic": 250}) } """); } @@ -335,6 +337,7 @@ public class ImportHostingAssets extends ImportOfficeData { 5811=HsHostingAssetRealEntity(UNIX_USER, lug00-ola.a, LUG OLA - POP a, MANAGED_WEBSPACE:lug00, {"SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "shell": "/usr/bin/passwd", "userid": 102094}), 5813=HsHostingAssetRealEntity(UNIX_USER, lug00-ola.b, LUG OLA - POP b, MANAGED_WEBSPACE:lug00, {"SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "shell": "/usr/bin/passwd", "userid": 102095}), 5835=HsHostingAssetRealEntity(UNIX_USER, lug00-test, Test, MANAGED_WEBSPACE:lug00, {"SSD hard quota": 1024, "SSD soft quota": 1024, "locked": false, "shell": "/usr/bin/passwd", "userid": 102106}), + 5961=HsHostingAssetRealEntity(UNIX_USER, xyz68, Monitoring h68, MANAGED_WEBSPACE:xyz68, {"SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "shell": "/bin/bash", "userid": 102141}), 5964=HsHostingAssetRealEntity(UNIX_USER, mim00, Michael Mellis, MANAGED_WEBSPACE:mim00, {"SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "shell": "/bin/bash", "userid": 102147}), 5966=HsHostingAssetRealEntity(UNIX_USER, mim00-1981, Jahrgangstreffen 1981, MANAGED_WEBSPACE:mim00, {"SSD hard quota": 256, "SSD soft quota": 128, "locked": false, "shell": "/bin/bash", "userid": 102148}), 5990=HsHostingAssetRealEntity(UNIX_USER, mim00-mail, Mailbox, MANAGED_WEBSPACE:mim00, {"SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "shell": "/bin/bash", "userid": 102160}), @@ -880,6 +883,7 @@ public class ImportHostingAssets extends ImportOfficeData { 5811=HsHostingAssetRealEntity(UNIX_USER, lug00-ola.a, LUG OLA - POP a, MANAGED_WEBSPACE:lug00, {"SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "password": null, "shell": "/usr/bin/passwd", "userid": 102094}), 5813=HsHostingAssetRealEntity(UNIX_USER, lug00-ola.b, LUG OLA - POP b, MANAGED_WEBSPACE:lug00, {"SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "password": null, "shell": "/usr/bin/passwd", "userid": 102095}), 5835=HsHostingAssetRealEntity(UNIX_USER, lug00-test, Test, MANAGED_WEBSPACE:lug00, {"SSD hard quota": 1024, "SSD soft quota": 1024, "locked": false, "password": null, "shell": "/usr/bin/passwd", "userid": 102106}), + 5961=HsHostingAssetRealEntity(UNIX_USER, xyz68, Monitoring h68, MANAGED_WEBSPACE:xyz68, {"SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "password": null, "shell": "/bin/bash", "userid": 102141}), 5964=HsHostingAssetRealEntity(UNIX_USER, mim00, Michael Mellis, MANAGED_WEBSPACE:mim00, {"SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "password": null, "shell": "/bin/bash", "userid": 102147}), 5966=HsHostingAssetRealEntity(UNIX_USER, mim00-1981, Jahrgangstreffen 1981, MANAGED_WEBSPACE:mim00, {"SSD hard quota": 256, "SSD soft quota": 128, "locked": false, "password": null, "shell": "/bin/bash", "userid": 102148}), 5990=HsHostingAssetRealEntity(UNIX_USER, mim00-mail, Mailbox, MANAGED_WEBSPACE:mim00, {"SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "password": null, "shell": "/bin/bash", "userid": 102160}), @@ -909,8 +913,8 @@ public class ImportHostingAssets extends ImportOfficeData { verifyActuallyPersistedHostingAssetCount(CLOUD_SERVER, 1, 50); verifyActuallyPersistedHostingAssetCount(MANAGED_SERVER, 4, 100); - verifyActuallyPersistedHostingAssetCount(MANAGED_WEBSPACE, 4, 100); - verifyActuallyPersistedHostingAssetCount(UNIX_USER, 14, 100); + verifyActuallyPersistedHostingAssetCount(MANAGED_WEBSPACE, 5, 100); + verifyActuallyPersistedHostingAssetCount(UNIX_USER, 15, 100); verifyActuallyPersistedHostingAssetCount(EMAIL_ALIAS, 9, 1400); verifyActuallyPersistedHostingAssetCount(PGSQL_DATABASE, 8, 100); verifyActuallyPersistedHostingAssetCount(MARIADB_DATABASE, 8, 100); @@ -918,6 +922,19 @@ public class ImportHostingAssets extends ImportOfficeData { verifyActuallyPersistedHostingAssetCount(EMAIL_ADDRESS, 71, 30000); } + @Test + @Order(19930) + void verifyProjectAgentsCanViewEmailAddresses() { + assumeThatWeAreImportingControlledTestData(); + + final var haCount = jpaAttempt.transacted(() -> { + 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(); + assertThat(haCount).isEqualTo(68); + } + // ============================================================================================ @Test @@ -1095,7 +1112,20 @@ public class ImportHostingAssets extends ImportOfficeData { final var managedWebspace = pac(packet_id); final var parentAsset = hive(hive_id).serverRef.get(); managedWebspace.setParentAsset(parentAsset); - managedWebspace.getBookingItem().setParentItem(parentAsset.getBookingItem()); + + if (parentAsset.getRelatedProject() != managedWebspace.getRelatedProject() + && managedWebspace.getRelatedProject().getDebitor().getDebitorNumber() == 10000_00 ) { + assertThat(managedWebspace.getIdentifier()).startsWith("xyz"); + final var hshDebitor = managedWebspace.getBookingItem().getProject().getDebitor(); + final var newProject = HsBookingProjectEntity.builder() + .debitor(hshDebitor) + .caption(parentAsset.getIdentifier() + " Monitor") + .build(); + bookingProjects.put(Collections.max(bookingProjects.keySet())+1, newProject); + managedWebspace.getBookingItem().setProject(newProject); + } else { + managedWebspace.getBookingItem().setParentItem(parentAsset.getBookingItem()); + } } }); } diff --git a/src/test/resources/migration/hosting/inet_addr.csv b/src/test/resources/migration/hosting/inet_addr.csv index 15bab1fb..bee797c4 100644 --- a/src/test/resources/migration/hosting/inet_addr.csv +++ b/src/test/resources/migration/hosting/inet_addr.csv @@ -1,6 +1,7 @@ inet_addr_id;inet_addr;description 363;83.223.95.34; 381;83.223.95.52; +401;83.223.95.72; 402;83.223.95.73; 433;83.223.95.104; 457;83.223.95.128; diff --git a/src/test/resources/migration/hosting/packet.csv b/src/test/resources/migration/hosting/packet.csv index 63637444..6e27b41b 100644 --- a/src/test/resources/migration/hosting/packet.csv +++ b/src/test/resources/migration/hosting/packet.csv @@ -4,6 +4,7 @@ packet_id;basepacket_code;packet_name;bp_id;hive_id;created;cancelled;cur_inet_a 10978;SRV/MGD;vm1050;213;1014;2013-04-01;;433;;1 11061;SRV/MGD;vm1068;100;1037;2013-08-19;;381;;f 11094;PAC/WEB;lug00;100;1037;2013-09-10;;1168;;1 +11111;PAC/WEB;xyz68;213;1037;2013-08-19;;401;;1 11112;PAC/WEB;mim00;100;1037;2013-09-17;;402;;1 11447;SRV/MGD;vm1093;213;1163;2014-11-28;;457;;t 19959;PAC/WEB;dph00;542;1163;2021-06-02;;574;;0 diff --git a/src/test/resources/migration/hosting/packet_component.csv b/src/test/resources/migration/hosting/packet_component.csv index ce35034f..5dee11ad 100644 --- a/src/test/resources/migration/hosting/packet_component.csv +++ b/src/test/resources/migration/hosting/packet_component.csv @@ -7,6 +7,7 @@ packet_component_id;packet_id;quantity;basecomponent_code;created;cancelled 46121;11112;20;TRAFFIC;2017-03-27; 46122;11112;5;MULTI;2017-03-27; 46123;11112;3072;QUOTA;2017-03-27; +46124;11111;3072;QUOTA;2017-03-27; 143133;11094;1;SLABASIC;2017-09-01; 143483;11112;1;SLABASIC;2017-09-01; 757383;11112;0;SLAEXT24H;; diff --git a/src/test/resources/migration/hosting/unixuser.csv b/src/test/resources/migration/hosting/unixuser.csv index cd044e0a..739899d2 100644 --- a/src/test/resources/migration/hosting/unixuser.csv +++ b/src/test/resources/migration/hosting/unixuser.csv @@ -9,6 +9,7 @@ unixuser_id;name;comment;shell;homedir;locked;packet_id;userid;quota_softlimit;q 5835;lug00-test;Test;/usr/bin/passwd;/home/pacs/lug00/users/test;0;11094;102106;2000000;4000000;20;0 6705;hsh00-mim;Michael Mellis;/bin/false;/home/pacs/hsh00/users/mi;0;10630;10003;0;0;0;0 +5961;xyz68;Monitoring h68;/bin/bash;/home/pacs/xyz68;0;11111;102141;0;0;0;0 5964;mim00;Michael Mellis;/bin/bash;/home/pacs/mim00;0;11112;102147;0;0;0;0 5966;mim00-1981;Jahrgangstreffen 1981;/bin/bash;/home/pacs/mim00/users/1981;0;11112;102148;128;256;0;0 5990;mim00-mail;Mailbox;/bin/bash;/home/pacs/mim00/users/mail;0;11112;102160;0;0;0;0