From e9b6ca3d9c1b8af5c7eac180ee4954e544ff68f8 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Wed, 14 Aug 2024 12:30:46 +0200 Subject: [PATCH] make EMail-Addresses visible to webspace agent by granting asset:AGENT to assignedToAsset:AGENT --- ...e-cte-experiments-for-accessible-uuids.sql | 38 +++++++---------- .../hosting/asset/HsHostingAssetEntity.java | 4 +- .../hs/hosting/asset/HsHostingAssetType.java | 2 +- .../rbacgrant/RbacGrantsDiagramService.java | 2 +- .../7013-hs-hosting-asset-rbac.md | 8 ++-- .../7013-hs-hosting-asset-rbac.sql | 13 ++---- .../7018-hs-hosting-asset-test-data.sql | 7 +++- ...sHostingAssetControllerAcceptanceTest.java | 4 +- ...HostingAssetRepositoryIntegrationTest.java | 42 +++++++++++++++---- .../hs/migration/ImportHostingAssets.java | 10 +---- 10 files changed, 69 insertions(+), 61 deletions(-) diff --git a/sql/recursive-cte-experiments-for-accessible-uuids.sql b/sql/recursive-cte-experiments-for-accessible-uuids.sql index ae6f27dc..f8795961 100644 --- a/sql/recursive-cte-experiments-for-accessible-uuids.sql +++ b/sql/recursive-cte-experiments-for-accessible-uuids.sql @@ -123,26 +123,20 @@ select from one_path; commit transaction; - - - -select * from -( - select uuid, roleidname as name from rbacrole_ev - union all - select uuid, p.optablename || ':' || p.objectuuid || ':' || p.op as name from rbacpermission p -) united - where uuid in ( - '4157915c-a09b-490c-9430-00005fcfbb4f', - '046f2da0-66d5-4e6a-af17-d41fba617b30', - '6239ca11-5224-401d-9780-1af7f5cbf35a', - '70004958-39c7-4d32-8ba6-d78145f3ad32', - '7065fbc1-c605-4da3-97dd-f40fe1b90b4c', - 'd551551b-b1dd-414a-a0ed-a07712f15e62', - 'f1f0fc3e-020a-48fe-b9c1-ac495cc21fdf', - '63ad71f3-214c-411e-8b0b-a859e54af770', - '561bbe75-b8f2-4e4b-86ac-02a72ab9a6e8', - '379e99b3-b53f-421d-a53e-2e81c464fbf2', - '5cb1ecb2-7962-47e0-b8bf-67974da45208' - ); +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/hosting/asset/HsHostingAssetEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntity.java index 0b28197c..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); }) @@ -192,9 +193,6 @@ public class HsHostingAssetEntity implements HsHostingAsset { with.outgoingSubRole("bookingItem", TENANT); with.outgoingSubRole("parentAsset", TENANT); with.incomingSuperRole("alarmContact", ADMIN); - }) - .createSubRole(REFERRER, (with) -> { - with.incomingSuperRole("assignedToAsset", AGENT); with.permission(SELECT); }) 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/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 926ff65d..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 @@ -30,7 +30,6 @@ subgraph asset["`**asset**`"] role:asset:ADMIN[[asset:ADMIN]] role:asset:AGENT[[asset:AGENT]] role:asset:TENANT[[asset:TENANT]] - role:asset:REFERRER[[asset:REFERRER]] end subgraph asset:permissions[ ] @@ -50,8 +49,8 @@ subgraph assignedToAsset["`**assignedToAsset**`"] subgraph assignedToAsset:roles[ ] style assignedToAsset:roles fill:#99bcdb,stroke:white - role:assignedToAsset:TENANT[[assignedToAsset:TENANT]] role:assignedToAsset:AGENT[[assignedToAsset:AGENT]] + role:assignedToAsset:TENANT[[assignedToAsset:TENANT]] end end @@ -99,14 +98,13 @@ 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 role:asset:TENANT ==> role:bookingItem:TENANT role:asset:TENANT ==> role:parentAsset:TENANT role:alarmContact:ADMIN ==> role:asset:TENANT -role:asset:TENANT ==> role:asset:REFERRER -role:assignedToAsset:AGENT ==> role:asset:REFERRER %% granting permissions to roles role:global:ADMIN ==> perm:asset:INSERT @@ -114,6 +112,6 @@ role:parentAsset:ADMIN ==> perm:asset:INSERT role:global:GUEST ==> perm:asset:INSERT role:asset:OWNER ==> perm:asset:DELETE role:asset:ADMIN ==> perm:asset:UPDATE -role:asset:REFERRER ==> perm:asset:SELECT +role:asset:TENANT ==> perm:asset:SELECT ``` 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 987b3cc3..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)] @@ -75,6 +77,7 @@ begin perform createRoleWithGrants( hsHostingAssetTENANT(NEW), + permissions => array['SELECT'], incomingSuperRoles => array[ hsHostingAssetAGENT(NEW), hsOfficeContactADMIN(newAlarmContact)], @@ -83,14 +86,6 @@ begin hsHostingAssetTENANT(newParentAsset)] ); - perform createRoleWithGrants( - hsHostingAssetREFERRER(NEW), - permissions => array['SELECT'], - incomingSuperRoles => array[ - hsHostingAssetAGENT(newAssignedToAsset), - hsHostingAssetTENANT(NEW)] - ); - IF NEW.type = 'DOMAIN_SETUP' THEN END IF; 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/hosting/asset/HsHostingAssetControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetControllerAcceptanceTest.java index d84c0815..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) 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 e5695746..a2c96772 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 @@ -6,6 +6,7 @@ import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemRepository; import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType; import net.hostsharing.hsadminng.hs.booking.project.HsBookingProjectRepository; import net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantRepository; +import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantsDiagramService; import net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleRepository; import net.hostsharing.hsadminng.mapper.Array; import net.hostsharing.hsadminng.rbac.test.ContextBasedTestWithCleanup; @@ -28,6 +29,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; @@ -125,8 +127,7 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu "hs_hosting_asset#fir00:ADMIN", "hs_hosting_asset#fir00:AGENT", "hs_hosting_asset#fir00:OWNER", - "hs_hosting_asset#fir00:TENANT", - "hs_hosting_asset#fir00:REFERRER")); + "hs_hosting_asset#fir00:TENANT")); assertThat(distinctGrantDisplaysOf(rawGrantRepo.findAll())) .containsExactlyInAnyOrder(fromFormatted( initialGrantNames, @@ -153,10 +154,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 }", - - // referrer - "{ grant perm:hs_hosting_asset#fir00:SELECT to role:hs_hosting_asset#fir00:REFERRER by system and assume }", - "{ grant role:hs_hosting_asset#fir00:REFERRER 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 }", null)); } @@ -199,7 +197,7 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu } @Nested - class FindByDebitorUuid { + class FindAssets { @Test public void globalAdmin_withoutAssumedRole_canViewArbitraryAssetsOfAllDebitors() { @@ -218,7 +216,7 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu } @Test - public void normalUser_canViewOnlyRelatedAsset() { + public void normalUser_canViewOnlyRelatedAssets() { // given: context("person-FirbySusan@example.com", "hs_booking_project#D-1000111-D-1000111defaultproject:AGENT"); final var projectUuid = projectRepo.findByCaption("D-1000111 default project").stream() @@ -235,7 +233,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() @@ -253,6 +251,32 @@ 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"); + // FIXME: remove +// final var parentAssetUuid = assetRepo.findByIdentifier("vm1012").stream() +// .filter(ha -> ha.getType() == MANAGED_SERVER) +// .findAny().orElseThrow().getUuid(); + + // when +// context("superuser-alex@hostsharing.net", "hs_hosting_asset#vm1012:AGENT"); + context("superuser-alex@hostsharing.net", "hs_hosting_asset#sec01:AGENT"); + // FIXME: cleanup +// context("superuser-alex@hostsharing.net", "hs_hosting_asset#sec.example.org|MBOX:AGENT"); +// context("superuser-alex@hostsharing.net", "hs_booking_project#D-1000212-D-1000212defaultproject:AGENT"); + + generateRbacDiagramForCurrentSubjects(RbacGrantsDiagramService.Include.ALL_NON_TEST_ENTITY_RELATED, "should-contain-email-addresses"); + + 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 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 f69ef8d0..0b96a8a9 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/migration/ImportHostingAssets.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/migration/ImportHostingAssets.java @@ -928,17 +928,11 @@ public class ImportHostingAssets extends ImportOfficeData { assumeThatWeAreImportingControlledTestData(); final var haCount = jpaAttempt.transacted(() -> { - context(rbacSuperuser); - // final var roles = em.createNativeQuery("select * from rbacrole_ev where roleidname like 'hs_office_relation%with-DEBITOR%'").getResultList(); - final var roles = em.createNativeQuery("select * from rbacrole_ev where roleidname like 'hs_booking_project#D-10003%'").getResultList(); - //context(rbacSuperuser, "hs_booking_project#D-1000300-mimdefaultproject:ADMIN"); context(rbacSuperuser, "hs_booking_project#D-1000300-mimdefaultproject:AGENT"); - final var result = em.createNativeQuery("select * from hs_hosting_asset where type='EMAIL_ADDRESS'") - .getResultList(); - return (Integer) em.createNativeQuery("select count(*) from hs_hosting_asset where type='EMAIL_ADDRESS'", Integer.class) + return (Integer) em.createNativeQuery("select count(*) from hs_hosting_asset_rv where type='EMAIL_ADDRESS'", Integer.class) .getSingleResult(); }).assertSuccessful().returnedValue(); - assertThat(haCount).isEqualTo(71); + assertThat(haCount).isEqualTo(68); } // ============================================================================================