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 6daa8ba9..0856f866 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 @@ -17,6 +17,8 @@ import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL; import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject; import net.hostsharing.hsadminng.stringify.Stringify; import net.hostsharing.hsadminng.stringify.Stringifyable; +import org.hibernate.annotations.NotFound; +import org.hibernate.annotations.NotFoundAction; import org.hibernate.annotations.Type; import jakarta.persistence.CascadeType; @@ -30,6 +32,7 @@ import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.OneToMany; +import jakarta.persistence.OneToOne; import jakarta.persistence.Table; import jakarta.persistence.Transient; import jakarta.persistence.Version; @@ -113,9 +116,8 @@ public class HsBookingItemEntity implements Stringifyable, RbacObject { @JoinColumn(name="parentitemuuid", referencedColumnName="uuid") private List subBookingItems; - @OneToMany(cascade = CascadeType.REFRESH, orphanRemoval = true) - @JoinColumn(name="bookingitemuuid", referencedColumnName="uuid") - private List subHostingAssets; + @OneToOne(mappedBy="bookingItem") + private HsHostingAssetEntity relatedHostingAsset; @Transient private PatchableMapWrapper resourcesWrapper; diff --git a/src/main/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsManagedWebspaceBookingItemValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsManagedWebspaceBookingItemValidator.java index bf637f15..81c74b9f 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsManagedWebspaceBookingItemValidator.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsManagedWebspaceBookingItemValidator.java @@ -7,6 +7,7 @@ import org.apache.commons.lang3.function.TriFunction; import java.util.List; import static java.util.Collections.emptyList; +import static java.util.Optional.ofNullable; import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.DOMAIN_EMAIL_SETUP; import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.EMAIL_ADDRESS; import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MARIADB_DATABASE; @@ -38,10 +39,11 @@ class HsManagedWebspaceBookingItemValidator extends HsBookingItemEntityValidator private static TriFunction> unixUsers() { return (final HsBookingItemEntity entity, final IntegerProperty prop, final Integer factor) -> { - final var unixUserCount = entity.getSubHostingAssets().stream() - .flatMap(ha -> ha.getSubHostingAssets().stream()) - .filter(ha -> ha.getType() == UNIX_USER) - .count(); + final var unixUserCount = ofNullable(entity.getRelatedHostingAsset()) + .map(ha -> ha.getSubHostingAssets().stream() + .filter(subAsset -> subAsset.getType() == UNIX_USER) + .count()) + .orElse(0L); final long limitingValue = prop.getValue(entity.getResources()); if (unixUserCount > factor*limitingValue) { return List.of(prop.propertyName() + "=" + limitingValue + " allows at maximum " + limitingValue*factor + " unix users, but " + unixUserCount + " found"); @@ -52,13 +54,14 @@ class HsManagedWebspaceBookingItemValidator extends HsBookingItemEntityValidator private static TriFunction> databaseUsers() { return (final HsBookingItemEntity entity, final IntegerProperty prop, final Integer factor) -> { - final var unixUserCount = entity.getSubHostingAssets().stream() - .flatMap(ha -> ha.getSubHostingAssets().stream()) - .filter(bi -> bi.getType() == PGSQL_USER || bi.getType() == MARIADB_USER ) - .count(); + final var dbUserCount = ofNullable(entity.getRelatedHostingAsset()) + .map(ha -> ha.getSubHostingAssets().stream() + .filter(bi -> bi.getType() == PGSQL_USER || bi.getType() == MARIADB_USER ) + .count()) + .orElse(0L); final long limitingValue = prop.getValue(entity.getResources()); - if (unixUserCount > factor*limitingValue) { - return List.of(prop.propertyName() + "=" + limitingValue + " allows at maximum " + limitingValue*factor + " database users, but " + unixUserCount + " found"); + if (dbUserCount > factor*limitingValue) { + return List.of(prop.propertyName() + "=" + limitingValue + " allows at maximum " + limitingValue*factor + " database users, but " + dbUserCount + " found"); } return emptyList(); }; @@ -66,12 +69,13 @@ class HsManagedWebspaceBookingItemValidator extends HsBookingItemEntityValidator private static TriFunction> databases() { return (final HsBookingItemEntity entity, final IntegerProperty prop, final Integer factor) -> { - final var unixUserCount = entity.getSubHostingAssets().stream() - .flatMap(ha -> ha.getSubHostingAssets().stream()) - .filter(bi -> bi.getType()==PGSQL_USER || bi.getType()==MARIADB_USER ) - .flatMap(domainEMailSetup -> domainEMailSetup.getSubHostingAssets().stream() - .filter(ha -> ha.getType()==PGSQL_DATABASE || ha.getType()==MARIADB_DATABASE)) - .count(); + final var unixUserCount = ofNullable(entity.getRelatedHostingAsset()) + .map(ha -> ha.getSubHostingAssets().stream() + .filter(bi -> bi.getType()==PGSQL_USER || bi.getType()==MARIADB_USER ) + .flatMap(domainEMailSetup -> domainEMailSetup.getSubHostingAssets().stream() + .filter(subAsset -> subAsset.getType()==PGSQL_DATABASE || subAsset.getType()==MARIADB_DATABASE)) + .count()) + .orElse(0L); final long limitingValue = prop.getValue(entity.getResources()); if (unixUserCount > factor*limitingValue) { return List.of(prop.propertyName() + "=" + limitingValue + " allows at maximum " + limitingValue*factor + " databases, but " + unixUserCount + " found"); @@ -82,12 +86,13 @@ class HsManagedWebspaceBookingItemValidator extends HsBookingItemEntityValidator private static TriFunction> eMailAddresses() { return (final HsBookingItemEntity entity, final IntegerProperty prop, final Integer factor) -> { - final var unixUserCount = entity.getSubHostingAssets().stream() - .flatMap(ha -> ha.getSubHostingAssets().stream()) - .filter(bi -> bi.getType() == DOMAIN_EMAIL_SETUP) - .flatMap(domainEMailSetup -> domainEMailSetup.getSubHostingAssets().stream() - .filter(ha -> ha.getType()==EMAIL_ADDRESS)) - .count(); + final var unixUserCount = ofNullable(entity.getRelatedHostingAsset()) + .map(ha -> ha.getSubHostingAssets().stream() + .filter(bi -> bi.getType() == DOMAIN_EMAIL_SETUP) + .flatMap(domainEMailSetup -> domainEMailSetup.getSubHostingAssets().stream() + .filter(subAsset -> subAsset.getType()==EMAIL_ADDRESS)) + .count()) + .orElse(0L); final long limitingValue = prop.getValue(entity.getResources()); if (unixUserCount > factor*limitingValue) { return List.of(prop.propertyName() + "=" + limitingValue + " allows at maximum " + limitingValue*factor + " databases, but " + unixUserCount + " found"); 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 fcc290ff..b474d0c7 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 @@ -177,6 +177,9 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup "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, { CPUs: 2, RAM: 8, SSD: 500, Traffic: 500 })", "HsBookingItemEntity(D-1000212:D-1000212 default project, PRIVATE_CLOUD, [2024-04-01,), some PrivateCloud, { CPUs: 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(); } @Test diff --git a/src/test/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsManagedServerBookingItemValidatorUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsManagedServerBookingItemValidatorUnitTest.java index 1fe54a82..549b5700 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsManagedServerBookingItemValidatorUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsManagedServerBookingItemValidatorUnitTest.java @@ -139,27 +139,26 @@ class HsManagedServerBookingItemValidatorUnitTest { entry("Traffic", 1000), entry("Multi", 1) )) - .subHostingAssets(of( - HsHostingAssetEntity.builder() - .type(HsHostingAssetType.MANAGED_WEBSPACE) - .identifier("abc00") - .subHostingAssets(concat( - generate(26, HsHostingAssetType.UNIX_USER, "xyz00-%c%c"), - generateDbUsersWithDatabases(3, HsHostingAssetType.PGSQL_USER, - "xyz00_%c%c", - 1, HsHostingAssetType.PGSQL_DATABASE - ), - generateDbUsersWithDatabases(3, HsHostingAssetType.MARIADB_USER, - "xyz00_%c%c", - 2, HsHostingAssetType.MARIADB_DATABASE - ), - generateDomainEmailSetupsWithEMailAddresses(26, HsHostingAssetType.DOMAIN_EMAIL_SETUP, - "%c%c.example.com", - 10, HsHostingAssetType.EMAIL_ADDRESS - ) - )) - .build() - )) + .relatedHostingAsset(HsHostingAssetEntity.builder() + .type(HsHostingAssetType.MANAGED_WEBSPACE) + .identifier("abc00") + .subHostingAssets(concat( + generate(26, HsHostingAssetType.UNIX_USER, "xyz00-%c%c"), + generateDbUsersWithDatabases(3, HsHostingAssetType.PGSQL_USER, + "xyz00_%c%c", + 1, HsHostingAssetType.PGSQL_DATABASE + ), + generateDbUsersWithDatabases(3, HsHostingAssetType.MARIADB_USER, + "xyz00_%c%c", + 2, HsHostingAssetType.MARIADB_DATABASE + ), + generateDomainEmailSetupsWithEMailAddresses(26, HsHostingAssetType.DOMAIN_EMAIL_SETUP, + "%c%c.example.com", + 10, HsHostingAssetType.EMAIL_ADDRESS + ) + )) + .build() + ) .build(); // when