From b56e27b1a93f99b2c95dab670be1dc441fe69172 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Tue, 7 May 2024 06:27:53 +0200 Subject: [PATCH 1/7] fix rendering of permissions and target table in INSERT-Permission in runtime RBAC-diagrams --- .../rbac/rbacgrant/RbacGrantsDiagramService.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) 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 f4dc2167..2290c948 100644 --- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantsDiagramService.java +++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantsDiagramService.java @@ -8,6 +8,7 @@ import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; import jakarta.validation.constraints.NotNull; import java.io.BufferedWriter; +import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.*; @@ -25,6 +26,7 @@ public class RbacGrantsDiagramService { public static void writeToFile(final String title, final String graph, final String fileName) { + new File("doc/temp").mkdirs(); try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) { writer.write(""" ### all grants to %s @@ -192,8 +194,9 @@ public class RbacGrantsDiagramService { return "[" + roleType + "\nref:" + uuid + "]"; } if (refType.equals("perm")) { - final var roleType = idName.split(":")[1]; - return "{{" + roleType + "\nref:" + uuid + "}}"; + final var parts = idName.split(":"); + final var permType = parts[2]; + return "{{" + permType + "\nref:" + uuid + "}}"; } return ""; } @@ -205,7 +208,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(">", ":"); } -- 2.39.5 From 7e6a02717f13fa6f5439e06f03a227784bfb174f Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Tue, 7 May 2024 06:41:38 +0200 Subject: [PATCH 2/7] BookingItem reference only in directly booked HostingAssets --- .../asset/HsHostingAssetController.java | 7 ++- .../hosting/asset/HsHostingAssetEntity.java | 3 +- .../hs-hosting/hs-hosting-asset-schemas.yaml | 7 ++- .../7010-hs-hosting-asset.sql | 8 ++- .../7013-hs-hosting-asset-rbac.sql | 2 - ...sHostingAssetControllerAcceptanceTest.java | 61 +++++++++++++++++-- 6 files changed, 73 insertions(+), 15 deletions(-) diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetController.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetController.java index 384fc2e3..ae13d0c8 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetController.java @@ -16,6 +16,7 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder; +import jakarta.persistence.EntityNotFoundException; import jakarta.validation.ValidationException; import java.util.List; import java.util.UUID; @@ -130,8 +131,12 @@ public class HsHostingAssetController implements HsHostingAssetsApi { return entityToSave; } - @SuppressWarnings("unchecked") final BiConsumer RESOURCE_TO_ENTITY_POSTMAPPER = (resource, entity) -> { entity.putConfig(KeyValueMap.from(resource.getConfig())); + if (resource.getParentAssetUuid() != null) { + entity.setParentAsset(assetRepo.findByUuid(resource.getParentAssetUuid()) + .orElseThrow(() -> new EntityNotFoundException("ERROR: [400] parentAssetUuid %s not found".formatted( + resource.getParentAssetUuid())))); + } }; } 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 52466e82..af91e0db 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 @@ -40,7 +40,6 @@ import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.CaseDef.inOtherCas import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Column.dependsOnColumn; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.ColumnValue.usingCase; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.ColumnValue.usingDefaultCase; -import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NOT_NULL; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NULLABLE; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.DELETE; import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.INSERT; @@ -137,7 +136,7 @@ public class HsHostingAssetEntity implements Stringifyable, RbacObject { .importEntityAlias("bookingItem", HsBookingItemEntity.class, usingDefaultCase(), dependsOnColumn("bookingItemUuid"), directlyFetchedByDependsOnColumn(), - NOT_NULL) + NULLABLE) .switchOnColumn("type", inCaseOf(CLOUD_SERVER.name(), diff --git a/src/main/resources/api-definition/hs-hosting/hs-hosting-asset-schemas.yaml b/src/main/resources/api-definition/hs-hosting/hs-hosting-asset-schemas.yaml index 59696a23..7390c3c8 100644 --- a/src/main/resources/api-definition/hs-hosting/hs-hosting-asset-schemas.yaml +++ b/src/main/resources/api-definition/hs-hosting/hs-hosting-asset-schemas.yaml @@ -53,7 +53,11 @@ components: bookingItemUuid: type: string format: uuid - nullable: false + nullable: true + parentAssetUuid: + type: string + format: uuid + nullable: true type: $ref: '#/components/schemas/HsHostingAssetType' identifier: @@ -72,7 +76,6 @@ components: - type - identifier - caption - - debitorUuid - config additionalProperties: false diff --git a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7010-hs-hosting-asset.sql b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7010-hs-hosting-asset.sql index 57f8b866..950d01b0 100644 --- a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7010-hs-hosting-asset.sql +++ b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7010-hs-hosting-asset.sql @@ -24,13 +24,17 @@ create table if not exists hs_hosting_asset ( uuid uuid unique references RbacObject (uuid), version int not null default 0, - bookingItemUuid uuid not 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), identifier varchar(80) not null, caption varchar(80) not null, - config jsonb not null + config jsonb not null, + + constraint chk_hs_hosting_asset_has_booking_item_or_parent_asset check (bookingItemUuid is not null or parentAssetUuid is not null) ); + + --// 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 4924f25e..2495f1ea 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 @@ -39,8 +39,6 @@ begin SELECT * FROM hs_hosting_asset WHERE uuid = NEW.parentAssetUuid INTO newParentServer; SELECT * FROM hs_booking_item WHERE uuid = NEW.bookingItemUuid INTO newBookingItem; - assert newBookingItem.uuid is not null, format('newBookingItem must not be null for NEW.bookingItemUuid = %s', NEW.bookingItemUuid); - perform createRoleWithGrants( hsHostingAssetOWNER(NEW), 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 0cde4075..0d7c8dc5 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 @@ -19,6 +19,7 @@ import java.util.Map; import java.util.UUID; import static java.util.Map.entry; +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_SERVER; import static net.hostsharing.hsadminng.rbac.test.JsonMatcher.lenientlyEquals; import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.Matchers.matchesRegex; @@ -113,7 +114,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup .header("current-user", "superuser-alex@hostsharing.net") .port(port) .when() - .get("http://localhost/api/hs/hosting/assets?type=" + HsHostingAssetType.MANAGED_SERVER) + .get("http://localhost/api/hs/hosting/assets?type=" + MANAGED_SERVER) .then().log().all().assertThat() .statusCode(200) .contentType("application/json") @@ -159,7 +160,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup class AddServer { @Test - void globalAdmin_canAddAsset() { + void globalAdmin_canAddBookedAsset() { context.define("superuser-alex@hostsharing.net"); final var givenBookingItem = givenBookingItem("First", "some PrivateCloud"); @@ -173,7 +174,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup "bookingItemUuid": "%s", "type": "MANAGED_SERVER", "identifier": "vm1400", - "caption": "some new CloudServer", + "caption": "some new ManagedServer", "config": { "CPUs": 2, "RAM": 100, "SSD": 300, "Traffic": 250 } } """.formatted(givenBookingItem.getUuid())) @@ -187,7 +188,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup { "type": "MANAGED_SERVER", "identifier": "vm1400", - "caption": "some new CloudServer", + "caption": "some new ManagedServer", "config": { "CPUs": 2, "RAM": 100, "SSD": 300, "Traffic": 250 } } """)) @@ -200,6 +201,48 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup assertThat(newUserUuid).isNotNull(); } + @Test + void parentAssetAgent_canAddSubAsset() { + + context.define("superuser-alex@hostsharing.net"); + final var givenParentAsset = givenParentAsset("First", MANAGED_SERVER); + + final var location = RestAssured // @formatter:off + .given() + .header("current-user", "person-FirbySusan@example.com") + .contentType(ContentType.JSON) + .body(""" + { + "parentAssetUuid": "%s", + "type": "MANAGED_WEBSPACE", + "identifier": "xyz00", + "caption": "some new ManagedWebspace in client's ManagedServer", + "config": { "SSD": 100, "Traffic": 250 } + } + """.formatted(givenParentAsset.getUuid())) + .port(port) + .when() + .post("http://localhost/api/hs/hosting/assets") + .then().log().all().assertThat() + .statusCode(201) + .contentType(ContentType.JSON) + .body("", lenientlyEquals(""" + { + "type": "MANAGED_WEBSPACE", + "identifier": "xyz00", + "caption": "some new ManagedWebspace in client's ManagedServer", + "config": { "SSD": 100, "Traffic": 250 } + } + """)) + .header("Location", matchesRegex("http://localhost:[1-9][0-9]*/api/hs/hosting/assets/[^/]*")) + .extract().header("Location"); // @formatter:on + + // finally, the new asset can be accessed under the generated UUID + final var newUserUuid = UUID.fromString( + location.substring(location.lastIndexOf('/') + 1)); + assertThat(newUserUuid).isNotNull(); + } + @Test void additionalValidationsArePerformend_whenAddingAsset() { @@ -215,7 +258,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup "bookingItemUuid": "%s", "type": "MANAGED_SERVER", "identifier": "vm1400", - "caption": "some new CloudServer", + "caption": "some new ManagedServer", "config": { "CPUs": 0, "extra": 42 } } """.formatted(givenBookingItem.getUuid())) @@ -235,7 +278,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup } @Nested - class GetASset { + class GetAsset { @Test void globalAdmin_canGetArbitraryAsset() { @@ -412,6 +455,12 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup .findAny().orElseThrow(); } + HsHostingAssetEntity givenParentAsset(final String debitorName, final HsHostingAssetType assetType) { + final var givenDebitor = debitorRepo.findDebitorByOptionalNameLike(debitorName).stream().findAny().orElseThrow(); + final var givenAsset = assetRepo.findAllByCriteria(givenDebitor.getUuid(), null, assetType).stream().findAny().orElseThrow(); + return givenAsset; + } + private HsHostingAssetEntity givenSomeTemporaryAssetForDebitorNumber(final String identifierSuffix, final Map.Entry resources) { return jpaAttempt.transacted(() -> { -- 2.39.5 From 409f6c973cc16af86d2ba946b0efd7e64c48d4f6 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Tue, 7 May 2024 12:20:08 +0200 Subject: [PATCH 3/7] extract HsManagedWebspaceAssetValidator to separate class and validate identifier against debitor defaultPrefix --- .../HsHostingAssetPropertyValidator.java | 16 ++-- .../validator/HsHostingAssetValidator.java | 19 ++-- .../HsManagedWebspaceAssetValidator.java | 40 +++++++++ .../7010-hs-hosting-asset.sql | 2 - ...sHostingAssetControllerAcceptanceTest.java | 6 +- .../HsHostingAssetValidatorUnitTest.java | 35 ++++++++ ...anagedWebspaceAssetValidatorUnitTest.java} | 88 ++++++++++++------- 7 files changed, 151 insertions(+), 55 deletions(-) create mode 100644 src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsManagedWebspaceAssetValidator.java create mode 100644 src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsHostingAssetValidatorUnitTest.java rename src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/{HsHostingAssetValidatorUnitTest.java => validator/HsManagedWebspaceAssetValidatorUnitTest.java} (54%) diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsHostingAssetPropertyValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsHostingAssetPropertyValidator.java index 7e61845f..15936ea3 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsHostingAssetPropertyValidator.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsHostingAssetPropertyValidator.java @@ -38,7 +38,7 @@ public abstract class HsHostingAssetPropertyValidator { final var propValue = props.get(propertyName); if (propValue == null) { if (required) { - result.add("'" + propertyName + "' is required but missing"); + result.add("'config." + propertyName + "' is required but missing"); } } if (propValue != null){ @@ -46,7 +46,7 @@ public abstract class HsHostingAssetPropertyValidator { //noinspection unchecked validate(result, (T) propValue, props); } else { - result.add("'" + propertyName + "' is expected to be of type " + type + ", " + + result.add("'config." + propertyName + "' is expected to be of type " + type + ", " + "but is of type '" + propValue.getClass().getSimpleName() + "'"); } } @@ -90,13 +90,13 @@ class IntegerPropertyValidator extends HsHostingAssetPropertyValidator{ @Override protected void validate(final ArrayList result, final Integer propValue, final Map props) { if (min != null && propValue < min) { - result.add("'" + propertyName + "' is expected to be >= " + min + " but is " + propValue); + result.add("'config." + propertyName + "' is expected to be >= " + min + " but is " + propValue); } if (max != null && propValue > max) { - result.add("'" + propertyName + "' is expected to be <= " + max + " but is " + propValue); + result.add("'config." + propertyName + "' is expected to be <= " + max + " but is " + propValue); } if (step != null && propValue % step != 0) { - result.add("'" + propertyName + "' is expected to be multiple of " + step + " but is " + propValue); + result.add("'config." + propertyName + "' is expected to be multiple of " + step + " but is " + propValue); } } @@ -127,7 +127,7 @@ class EnumPropertyValidator extends HsHostingAssetPropertyValidator { @Override protected void validate(final ArrayList result, final String propValue, final Map props) { if (Arrays.stream(values).noneMatch(v -> v.equals(propValue))) { - result.add("'" + propertyName + "' is expected to be one of " + Arrays.toString(values) + " but is '" + propValue + "'"); + result.add("'config." + propertyName + "' is expected to be one of " + Arrays.toString(values) + " but is '" + propValue + "'"); } } @@ -159,8 +159,8 @@ class BooleanPropertyValidator extends HsHostingAssetPropertyValidator protected void validate(final ArrayList result, final Boolean propValue, final Map props) { if (falseIf != null && !Objects.equals(props.get(falseIf.getKey()), falseIf.getValue())) { if (propValue) { - result.add("'" + propertyName + "' is expected to be false because " + - falseIf.getKey()+ "=" + falseIf.getValue() + " but is " + propValue); + result.add("'config." + propertyName + "' is expected to be false because " + + "config." + falseIf.getKey()+ "=" + falseIf.getValue() + " but is " + propValue); } } } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsHostingAssetValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsHostingAssetValidator.java index 1389de21..d713330b 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsHostingAssetValidator.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsHostingAssetValidator.java @@ -8,6 +8,7 @@ import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -20,7 +21,7 @@ import static net.hostsharing.hsadminng.hs.hosting.asset.validator.IntegerProper public class HsHostingAssetValidator { - private static final Map validators = Map.ofEntries( + private static final Map validators = new HashMap<>(Map.ofEntries( defType(HsHostingAssetType.CLOUD_SERVER, new HsHostingAssetValidator( integerProperty("CPUs").min(1).max(32).required(), integerProperty("RAM").unit("GB").min(1).max(128).required(), @@ -39,15 +40,7 @@ public class HsHostingAssetValidator { booleanProperty("SLA-Maria").falseIf("SLA-Platform", "BASIC").optional(), booleanProperty("SLA-PgSQL").falseIf("SLA-Platform", "BASIC").optional(), booleanProperty("SLA-Office").falseIf("SLA-Platform", "BASIC").optional(), - booleanProperty("SLA-Web").falseIf("SLA-Platform", "BASIC").optional())), - defType(HsHostingAssetType.MANAGED_WEBSPACE, new HsHostingAssetValidator( - integerProperty("SSD").unit("GB").min(1).max(100).step(1).required(), - integerProperty("HDD").unit("GB").min(0).max(250).step(10).optional(), - integerProperty("Traffic").unit("GB").min(10).max(1000).step(10).required(), - enumerationProperty("SLA-Platform").values("BASIC", "EXT24H").optional(), - integerProperty("Daemons").min(0).max(10).optional(), - booleanProperty("Online Office Server").optional()) - )); + booleanProperty("SLA-Web").falseIf("SLA-Platform", "BASIC").optional())))); static { validators.entrySet().forEach(typeDef -> { stream(typeDef.getValue().propertyValidators).forEach( entry -> { @@ -57,6 +50,10 @@ public class HsHostingAssetValidator { } private final HsHostingAssetPropertyValidator[] propertyValidators; + public static void register(final HsHostingAssetType type, final HsHostingAssetValidator validator) { + validators.put(type, validator); + } + public static HsHostingAssetValidator forType(final HsHostingAssetType type) { return validators.get(type); } @@ -73,7 +70,7 @@ public class HsHostingAssetValidator { final var result = new ArrayList(); assetEntity.getConfig().keySet().forEach( givenPropName -> { if (stream(propertyValidators).map(pv -> pv.propertyName).noneMatch(propName -> propName.equals(givenPropName))) { - result.add("'" + givenPropName + "' is not expected but is '" +assetEntity.getConfig().get(givenPropName) + "'"); + result.add("'config." + givenPropName + "' is not expected but is '" +assetEntity.getConfig().get(givenPropName) + "'"); } }); stream(propertyValidators).forEach(pv -> { diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsManagedWebspaceAssetValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsManagedWebspaceAssetValidator.java new file mode 100644 index 00000000..709a3ec5 --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsManagedWebspaceAssetValidator.java @@ -0,0 +1,40 @@ +package net.hostsharing.hsadminng.hs.hosting.asset.validator; + +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; +import org.springframework.stereotype.Component; + +import java.util.List; + +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_WEBSPACE; +import static net.hostsharing.hsadminng.hs.hosting.asset.validator.BooleanPropertyValidator.booleanProperty; +import static net.hostsharing.hsadminng.hs.hosting.asset.validator.EnumPropertyValidator.enumerationProperty; +import static net.hostsharing.hsadminng.hs.hosting.asset.validator.IntegerPropertyValidator.integerProperty; + +@Component +class HsManagedWebspaceAssetValidator extends HsHostingAssetValidator { + + static { + HsHostingAssetValidator.register(MANAGED_WEBSPACE, new HsManagedWebspaceAssetValidator()); + } + + public HsManagedWebspaceAssetValidator() { + super( + integerProperty("SSD").unit("GB").min(1).max(100).step(1).required(), + integerProperty("HDD").unit("GB").min(0).max(250).step(10).optional(), + integerProperty("Traffic").unit("GB").min(10).max(1000).step(10).required(), + enumerationProperty("SLA-Platform").values("BASIC", "EXT24H").optional(), + integerProperty("Daemons").min(0).max(10).optional(), + booleanProperty("Online Office Server").optional() + ); + } + + @Override + public List validate(final HsHostingAssetEntity assetEntity) { + final var result = super.validate(assetEntity); + final var expectedIdentifierPattern = "^" + assetEntity.getParentAsset().getBookingItem().getDebitor().getDefaultPrefix() + "[0-9][0-9]$"; + if ( !assetEntity.getIdentifier().matches(expectedIdentifierPattern)) { + result.add("'identifier' expected to match '"+expectedIdentifierPattern+"', but is '" + assetEntity.getIdentifier() + "'"); + } + return result; + } +} diff --git a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7010-hs-hosting-asset.sql b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7010-hs-hosting-asset.sql index 950d01b0..4aa9e099 100644 --- a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7010-hs-hosting-asset.sql +++ b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7010-hs-hosting-asset.sql @@ -33,8 +33,6 @@ create table if not exists hs_hosting_asset constraint chk_hs_hosting_asset_has_booking_item_or_parent_asset check (bookingItemUuid is not null or parentAssetUuid is not null) ); - - --// 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 0d7c8dc5..94c4ceae 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 @@ -215,7 +215,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup { "parentAssetUuid": "%s", "type": "MANAGED_WEBSPACE", - "identifier": "xyz00", + "identifier": "fir90", "caption": "some new ManagedWebspace in client's ManagedServer", "config": { "SSD": 100, "Traffic": 250 } } @@ -229,7 +229,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup .body("", lenientlyEquals(""" { "type": "MANAGED_WEBSPACE", - "identifier": "xyz00", + "identifier": "fir90", "caption": "some new ManagedWebspace in client's ManagedServer", "config": { "SSD": 100, "Traffic": 250 } } @@ -271,7 +271,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup .body("", lenientlyEquals(""" { "statusPhrase": "Bad Request", - "message": "['extra' is not expected but is '42', 'CPUs' is expected to be >= 1 but is 0, 'RAM' is required but missing, 'SSD' is required but missing, 'Traffic' is required but missing]" + "message": "['config.extra' is not expected but is '42', 'config.CPUs' is expected to be >= 1 but is 0, 'config.RAM' is required but missing, 'config.SSD' is required but missing, 'config.Traffic' is required but missing]" } """)); // @formatter:on } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsHostingAssetValidatorUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsHostingAssetValidatorUnitTest.java new file mode 100644 index 00000000..90ff4e42 --- /dev/null +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsHostingAssetValidatorUnitTest.java @@ -0,0 +1,35 @@ +package net.hostsharing.hsadminng.hs.hosting.asset.validator; + +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static java.util.Map.entry; +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_SERVER; +import static org.assertj.core.api.Assertions.assertThat; + +class HsHostingAssetValidatorUnitTest { + + @Test + void validatesDependentProperties() { + // given + final var validator = HsHostingAssetValidator.forType(MANAGED_SERVER); + final var mangedWebspaceHostingAssetEntity = HsHostingAssetEntity.builder() + .type(MANAGED_SERVER) + .config(Map.ofEntries( + entry("CPUs", 2), + entry("RAM", 25), + entry("SSD", 25), + entry("Traffic", 250), + entry("SLA-EMail", true) + )) + .build(); + + // when + final var result = validator.validate(mangedWebspaceHostingAssetEntity); + + // then + assertThat(result).containsExactly("'config.SLA-EMail' is expected to be false because config.SLA-Platform=BASIC but is true"); + } +} diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetValidatorUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsManagedWebspaceAssetValidatorUnitTest.java similarity index 54% rename from src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetValidatorUnitTest.java rename to src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsManagedWebspaceAssetValidatorUnitTest.java index d7f21222..952498e0 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetValidatorUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsManagedWebspaceAssetValidatorUnitTest.java @@ -1,6 +1,8 @@ -package net.hostsharing.hsadminng.hs.hosting.asset; +package net.hostsharing.hsadminng.hs.hosting.asset.validator; -import net.hostsharing.hsadminng.hs.hosting.asset.validator.HsHostingAssetValidator; +import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity; +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; +import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity; import org.junit.jupiter.api.Test; import java.util.Map; @@ -11,24 +13,66 @@ import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANA import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_WEBSPACE; import static org.assertj.core.api.Assertions.assertThat; -class HsHostingAssetValidatorUnitTest { +class HsManagedWebspaceAssetValidatorUnitTest { + + @SuppressWarnings("unused") // just to make sure the class is loaded + HsHostingAssetValidator validator = new HsManagedWebspaceAssetValidator(); + + final HsBookingItemEntity managedServerBookingItem = HsBookingItemEntity.builder() + .debitor(HsOfficeDebitorEntity.builder().defaultPrefix("abc").build() + ) + .build(); + final HsHostingAssetEntity mangedServerAssetEntity = HsHostingAssetEntity.builder() + .type(MANAGED_SERVER) + .bookingItem(managedServerBookingItem) + .config(Map.ofEntries( + entry("HDD", 0), + entry("SSD", 1), + entry("Traffic", 10) + )) + .build(); + + @Test + void validatesIdentifier() { + // given + final var validator = HsHostingAssetValidator.forType(MANAGED_WEBSPACE); + final var mangedWebspaceHostingAssetEntity = HsHostingAssetEntity.builder() + .type(MANAGED_WEBSPACE) + .parentAsset(mangedServerAssetEntity) + .identifier("xyz00") + .config(Map.ofEntries( + entry("HDD", 0), + entry("SSD", 1), + entry("Traffic", 10) + )) + .build(); + + // when + final var result = validator.validate(mangedWebspaceHostingAssetEntity); + + // then + assertThat(result).containsExactly("'identifier' expected to match '^abc[0-9][0-9]$', but is 'xyz00'"); + } + @Test void validatesMissingProperties() { // given final var validator = HsHostingAssetValidator.forType(MANAGED_WEBSPACE); final var mangedWebspaceHostingAssetEntity = HsHostingAssetEntity.builder() - .type(MANAGED_WEBSPACE) - .config(emptyMap()) - .build(); + .type(MANAGED_WEBSPACE) + .parentAsset(mangedServerAssetEntity) + .identifier("abc00") + .config(emptyMap()) + .build(); // when final var result = validator.validate(mangedWebspaceHostingAssetEntity); // then assertThat(result).containsExactlyInAnyOrder( - "'SSD' is required but missing", - "'Traffic' is required but missing" + "'config.SSD' is required but missing", + "'config.Traffic' is required but missing" ); } @@ -38,6 +82,8 @@ class HsHostingAssetValidatorUnitTest { final var validator = HsHostingAssetValidator.forType(MANAGED_WEBSPACE); final var mangedWebspaceHostingAssetEntity = HsHostingAssetEntity.builder() .type(MANAGED_WEBSPACE) + .parentAsset(mangedServerAssetEntity) + .identifier("abc00") .config(Map.ofEntries( entry("HDD", 0), entry("SSD", 1), @@ -50,29 +96,7 @@ class HsHostingAssetValidatorUnitTest { final var result = validator.validate(mangedWebspaceHostingAssetEntity); // then - assertThat(result).containsExactly("'unknown' is not expected but is 'some value'"); - } - - @Test - void validatesDependentProperties() { - // given - final var validator = HsHostingAssetValidator.forType(MANAGED_SERVER); - final var mangedWebspaceHostingAssetEntity = HsHostingAssetEntity.builder() - .type(MANAGED_SERVER) - .config(Map.ofEntries( - entry("CPUs", 2), - entry("RAM", 25), - entry("SSD", 25), - entry("Traffic", 250), - entry("SLA-EMail", true) - )) - .build(); - - // when - final var result = validator.validate(mangedWebspaceHostingAssetEntity); - - // then - assertThat(result).containsExactly("'SLA-EMail' is expected to be false because SLA-Platform=BASIC but is true"); + assertThat(result).containsExactly("'config.unknown' is not expected but is 'some value'"); } @Test @@ -81,6 +105,8 @@ class HsHostingAssetValidatorUnitTest { final var validator = HsHostingAssetValidator.forType(MANAGED_WEBSPACE); final var mangedWebspaceHostingAssetEntity = HsHostingAssetEntity.builder() .type(MANAGED_WEBSPACE) + .parentAsset(mangedServerAssetEntity) + .identifier("abc00") .config(Map.ofEntries( entry("HDD", 200), entry("SSD", 25), -- 2.39.5 From 99ec74386af39cfbf140d39c905ed530c43139bc Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Tue, 7 May 2024 13:35:13 +0200 Subject: [PATCH 4/7] refactor Validator classes to package hs.validation --- .../asset/HsCloudServerAssetValidator.java | 27 +++ .../asset/HsHostingAssetController.java | 4 +- .../asset/HsHostingAssetPropsController.java | 6 +- .../asset/HsManagedServerAssetValidator.java | 33 ++++ .../HsManagedWebspaceAssetValidator.java | 14 +- .../HsHostingAssetPropertyValidator.java | 172 ------------------ .../validator/HsHostingAssetValidator.java | 96 ---------- .../validation/BooleanPropertyValidator.java | 42 +++++ .../EnumerationPropertyValidator.java | 38 ++++ .../hs/validation/HsEntityValidator.java | 72 ++++++++ .../hs/validation/HsPropertyValidator.java | 68 +++++++ .../validation/IntegerPropertyValidator.java | 42 +++++ .../validator => validation}/lombok.config | 0 ...st.java => HsEntityValidatorUnitTest.java} | 8 +- ...ManagedWebspaceAssetValidatorUnitTest.java | 14 +- 15 files changed, 345 insertions(+), 291 deletions(-) create mode 100644 src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsCloudServerAssetValidator.java create mode 100644 src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedServerAssetValidator.java rename src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/{validator => }/HsManagedWebspaceAssetValidator.java (67%) delete mode 100644 src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsHostingAssetPropertyValidator.java delete mode 100644 src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsHostingAssetValidator.java create mode 100644 src/main/java/net/hostsharing/hsadminng/hs/validation/BooleanPropertyValidator.java create mode 100644 src/main/java/net/hostsharing/hsadminng/hs/validation/EnumerationPropertyValidator.java create mode 100644 src/main/java/net/hostsharing/hsadminng/hs/validation/HsEntityValidator.java create mode 100644 src/main/java/net/hostsharing/hsadminng/hs/validation/HsPropertyValidator.java create mode 100644 src/main/java/net/hostsharing/hsadminng/hs/validation/IntegerPropertyValidator.java rename src/main/java/net/hostsharing/hsadminng/hs/{hosting/asset/validator => validation}/lombok.config (100%) rename src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/{validator/HsHostingAssetValidatorUnitTest.java => HsEntityValidatorUnitTest.java} (79%) rename src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/{validator => }/HsManagedWebspaceAssetValidatorUnitTest.java (88%) diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsCloudServerAssetValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsCloudServerAssetValidator.java new file mode 100644 index 00000000..acef7bd9 --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsCloudServerAssetValidator.java @@ -0,0 +1,27 @@ +package net.hostsharing.hsadminng.hs.hosting.asset; + +import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; +import org.springframework.stereotype.Component; + +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.CLOUD_SERVER; +import static net.hostsharing.hsadminng.hs.validation.EnumerationPropertyValidator.enumerationProperty; +import static net.hostsharing.hsadminng.hs.validation.IntegerPropertyValidator.integerProperty; + +@Component +class HsCloudServerAssetValidator extends HsEntityValidator { + + static { + HsEntityValidator.register(CLOUD_SERVER, new HsCloudServerAssetValidator()); + } + + public HsCloudServerAssetValidator() { + super( + integerProperty("CPUs").min(1).max(32).required(), + integerProperty("RAM").unit("GB").min(1).max(128).required(), + integerProperty("SSD").unit("GB").min(25).max(1000).step(25).required(), + integerProperty("HDD").unit("GB").min(0).max(4000).step(250).optional(), + integerProperty("Traffic").unit("GB").min(250).max(10000).step(250).required(), + enumerationProperty("SLA-Infrastructure").values("BASIC", "EXT8H", "EXT4H", "EXT2H").optional() + ); + } +} diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetController.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetController.java index ae13d0c8..9b8b484e 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetController.java @@ -1,6 +1,6 @@ package net.hostsharing.hsadminng.hs.hosting.asset; -import net.hostsharing.hsadminng.hs.hosting.asset.validator.HsHostingAssetValidator; +import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.api.HsHostingAssetsApi; import net.hostsharing.hsadminng.context.Context; @@ -124,7 +124,7 @@ public class HsHostingAssetController implements HsHostingAssetsApi { } private HsHostingAssetEntity valid(final HsHostingAssetEntity entityToSave) { - final var violations = HsHostingAssetValidator.forType(entityToSave.getType()).validate(entityToSave); + final var violations = HsEntityValidator.forType(entityToSave.getType()).validate(entityToSave); if (!violations.isEmpty()) { throw new ValidationException(violations.toString()); } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetPropsController.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetPropsController.java index 8a3f1523..50e236eb 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetPropsController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetPropsController.java @@ -1,6 +1,6 @@ package net.hostsharing.hsadminng.hs.hosting.asset; -import net.hostsharing.hsadminng.hs.hosting.asset.validator.HsHostingAssetValidator; +import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.api.HsHostingAssetPropsApi; import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.model.HsHostingAssetTypeResource; import org.springframework.http.ResponseEntity; @@ -15,7 +15,7 @@ public class HsHostingAssetPropsController implements HsHostingAssetPropsApi { @Override public ResponseEntity> listAssetTypes() { - final var resource = HsHostingAssetValidator.types().stream() + final var resource = HsEntityValidator.types().stream() .map(Enum::name) .toList(); return ResponseEntity.ok(resource); @@ -25,7 +25,7 @@ public class HsHostingAssetPropsController implements HsHostingAssetPropsApi { public ResponseEntity> listAssetTypeProps( final HsHostingAssetTypeResource assetType) { - final var propValidators = HsHostingAssetValidator.forType(HsHostingAssetType.of(assetType)); + final var propValidators = HsEntityValidator.forType(HsHostingAssetType.of(assetType)); final List> resource = propValidators.properties(); return ResponseEntity.ok(toListOfObjects(resource)); } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedServerAssetValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedServerAssetValidator.java new file mode 100644 index 00000000..95bbfb96 --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedServerAssetValidator.java @@ -0,0 +1,33 @@ +package net.hostsharing.hsadminng.hs.hosting.asset; + +import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; +import org.springframework.stereotype.Component; + +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_SERVER; +import static net.hostsharing.hsadminng.hs.validation.BooleanPropertyValidator.booleanProperty; +import static net.hostsharing.hsadminng.hs.validation.EnumerationPropertyValidator.enumerationProperty; +import static net.hostsharing.hsadminng.hs.validation.IntegerPropertyValidator.integerProperty; + +@Component +class HsManagedServerAssetValidator extends HsEntityValidator { + + static { + HsEntityValidator.register(MANAGED_SERVER, new HsManagedServerAssetValidator()); + } + + public HsManagedServerAssetValidator() { + super( + integerProperty("CPUs").min(1).max(32).required(), + integerProperty("RAM").unit("GB").min(1).max(128).required(), + integerProperty("SSD").unit("GB").min(25).max(1000).step(25).required(), + integerProperty("HDD").unit("GB").min(0).max(4000).step(250).optional(), + integerProperty("Traffic").unit("GB").min(250).max(10000).step(250).required(), + enumerationProperty("SLA-Platform").values("BASIC", "EXT8H", "EXT4H", "EXT2H").optional(), + booleanProperty("SLA-EMail").falseIf("SLA-Platform", "BASIC").optional(), + booleanProperty("SLA-Maria").falseIf("SLA-Platform", "BASIC").optional(), + booleanProperty("SLA-PgSQL").falseIf("SLA-Platform", "BASIC").optional(), + booleanProperty("SLA-Office").falseIf("SLA-Platform", "BASIC").optional(), + booleanProperty("SLA-Web").falseIf("SLA-Platform", "BASIC").optional() + ); + } +} diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsManagedWebspaceAssetValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceAssetValidator.java similarity index 67% rename from src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsManagedWebspaceAssetValidator.java rename to src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceAssetValidator.java index 709a3ec5..4deade19 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsManagedWebspaceAssetValidator.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceAssetValidator.java @@ -1,20 +1,20 @@ -package net.hostsharing.hsadminng.hs.hosting.asset.validator; +package net.hostsharing.hsadminng.hs.hosting.asset; -import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; +import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; import org.springframework.stereotype.Component; import java.util.List; import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_WEBSPACE; -import static net.hostsharing.hsadminng.hs.hosting.asset.validator.BooleanPropertyValidator.booleanProperty; -import static net.hostsharing.hsadminng.hs.hosting.asset.validator.EnumPropertyValidator.enumerationProperty; -import static net.hostsharing.hsadminng.hs.hosting.asset.validator.IntegerPropertyValidator.integerProperty; +import static net.hostsharing.hsadminng.hs.validation.BooleanPropertyValidator.booleanProperty; +import static net.hostsharing.hsadminng.hs.validation.EnumerationPropertyValidator.enumerationProperty; +import static net.hostsharing.hsadminng.hs.validation.IntegerPropertyValidator.integerProperty; @Component -class HsManagedWebspaceAssetValidator extends HsHostingAssetValidator { +class HsManagedWebspaceAssetValidator extends HsEntityValidator { static { - HsHostingAssetValidator.register(MANAGED_WEBSPACE, new HsManagedWebspaceAssetValidator()); + HsEntityValidator.register(MANAGED_WEBSPACE, new HsManagedWebspaceAssetValidator()); } public HsManagedWebspaceAssetValidator() { diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsHostingAssetPropertyValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsHostingAssetPropertyValidator.java deleted file mode 100644 index 15936ea3..00000000 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsHostingAssetPropertyValidator.java +++ /dev/null @@ -1,172 +0,0 @@ -package net.hostsharing.hsadminng.hs.hosting.asset.validator; - -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.RequiredArgsConstructor; -import lombok.Setter; -import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType; - -import java.util.AbstractMap.SimpleImmutableEntry; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -@RequiredArgsConstructor -public abstract class HsHostingAssetPropertyValidator { - - final Class type; - final String propertyName; - private Boolean required; - - public static Map.Entry defType(K k, V v) { - return new SimpleImmutableEntry<>(k, v); - } - - public HsHostingAssetPropertyValidator required() { - required = Boolean.TRUE; - return this; - } - - public HsHostingAssetPropertyValidator optional() { - required = Boolean.FALSE; - return this; - } - - public final List validate(final Map props) { - final var result = new ArrayList(); - final var propValue = props.get(propertyName); - if (propValue == null) { - if (required) { - result.add("'config." + propertyName + "' is required but missing"); - } - } - if (propValue != null){ - if ( type.isInstance(propValue)) { - //noinspection unchecked - validate(result, (T) propValue, props); - } else { - result.add("'config." + propertyName + "' is expected to be of type " + type + ", " + - "but is of type '" + propValue.getClass().getSimpleName() + "'"); - } - } - return result; - } - - protected abstract void validate(final ArrayList result, final T propValue, final Map props); - - public void verifyConsistency(final Map.Entry typeDef) { - if (required == null ) { - throw new IllegalStateException(typeDef.getKey() + "[" + propertyName + "] not fully initialized, please call either .required() or .optional()" ); - } - } - - public Map toMap(final ObjectMapper mapper) { - final Map map = mapper.convertValue(this, Map.class); - map.put("type", simpleTypeName()); - return map; - } - - protected abstract String simpleTypeName(); -} - -@Setter -class IntegerPropertyValidator extends HsHostingAssetPropertyValidator{ - - private String unit; - private Integer min; - private Integer max; - private Integer step; - - public static IntegerPropertyValidator integerProperty(final String propertyName) { - return new IntegerPropertyValidator(propertyName); - } - - private IntegerPropertyValidator(final String propertyName) { - super(Integer.class, propertyName); - } - - - @Override - protected void validate(final ArrayList result, final Integer propValue, final Map props) { - if (min != null && propValue < min) { - result.add("'config." + propertyName + "' is expected to be >= " + min + " but is " + propValue); - } - if (max != null && propValue > max) { - result.add("'config." + propertyName + "' is expected to be <= " + max + " but is " + propValue); - } - if (step != null && propValue % step != 0) { - result.add("'config." + propertyName + "' is expected to be multiple of " + step + " but is " + propValue); - } - } - - @Override - protected String simpleTypeName() { - return "integer"; - } -} - -@Setter -class EnumPropertyValidator extends HsHostingAssetPropertyValidator { - - private String[] values; - - private EnumPropertyValidator(final String propertyName) { - super(String.class, propertyName); - } - - public static EnumPropertyValidator enumerationProperty(final String propertyName) { - return new EnumPropertyValidator(propertyName); - } - - public HsHostingAssetPropertyValidator values(final String... values) { - this.values = values; - return this; - } - - @Override - protected void validate(final ArrayList result, final String propValue, final Map props) { - if (Arrays.stream(values).noneMatch(v -> v.equals(propValue))) { - result.add("'config." + propertyName + "' is expected to be one of " + Arrays.toString(values) + " but is '" + propValue + "'"); - } - } - - @Override - protected String simpleTypeName() { - return "enumeration"; - } -} - -@Setter -class BooleanPropertyValidator extends HsHostingAssetPropertyValidator { - - private Map.Entry falseIf; - - private BooleanPropertyValidator(final String propertyName) { - super(Boolean.class, propertyName); - } - - public static BooleanPropertyValidator booleanProperty(final String propertyName) { - return new BooleanPropertyValidator(propertyName); - } - - HsHostingAssetPropertyValidator falseIf(final String refPropertyName, final String refPropertyValue) { - this.falseIf = new SimpleImmutableEntry<>(refPropertyName, refPropertyValue); - return this; - } - - @Override - protected void validate(final ArrayList result, final Boolean propValue, final Map props) { - if (falseIf != null && !Objects.equals(props.get(falseIf.getKey()), falseIf.getValue())) { - if (propValue) { - result.add("'config." + propertyName + "' is expected to be false because " + - "config." + falseIf.getKey()+ "=" + falseIf.getValue() + " but is " + propValue); - } - } - } - - @Override - protected String simpleTypeName() { - return "boolean"; - } -} diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsHostingAssetValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsHostingAssetValidator.java deleted file mode 100644 index d713330b..00000000 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsHostingAssetValidator.java +++ /dev/null @@ -1,96 +0,0 @@ -package net.hostsharing.hsadminng.hs.hosting.asset.validator; - -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.PropertyAccessor; -import com.fasterxml.jackson.databind.ObjectMapper; -import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; -import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import static java.util.Arrays.stream; -import static net.hostsharing.hsadminng.hs.hosting.asset.validator.EnumPropertyValidator.enumerationProperty; -import static net.hostsharing.hsadminng.hs.hosting.asset.validator.HsHostingAssetPropertyValidator.defType; -import static net.hostsharing.hsadminng.hs.hosting.asset.validator.BooleanPropertyValidator.booleanProperty; -import static net.hostsharing.hsadminng.hs.hosting.asset.validator.IntegerPropertyValidator.integerProperty; - -public class HsHostingAssetValidator { - - private static final Map validators = new HashMap<>(Map.ofEntries( - defType(HsHostingAssetType.CLOUD_SERVER, new HsHostingAssetValidator( - integerProperty("CPUs").min(1).max(32).required(), - integerProperty("RAM").unit("GB").min(1).max(128).required(), - integerProperty("SSD").unit("GB").min(25).max(1000).step(25).required(), - integerProperty("HDD").unit("GB").min(0).max(4000).step(250).optional(), - integerProperty("Traffic").unit("GB").min(250).max(10000).step(250).required(), - enumerationProperty("SLA-Infrastructure").values("BASIC", "EXT8H", "EXT4H", "EXT2H").optional())), - defType(HsHostingAssetType.MANAGED_SERVER, new HsHostingAssetValidator( - integerProperty("CPUs").min(1).max(32).required(), - integerProperty("RAM").unit("GB").min(1).max(128).required(), - integerProperty("SSD").unit("GB").min(25).max(1000).step(25).required(), - integerProperty("HDD").unit("GB").min(0).max(4000).step(250).optional(), - integerProperty("Traffic").unit("GB").min(250).max(10000).step(250).required(), - enumerationProperty("SLA-Platform").values("BASIC", "EXT8H", "EXT4H", "EXT2H").optional(), - booleanProperty("SLA-EMail").falseIf("SLA-Platform", "BASIC").optional(), - booleanProperty("SLA-Maria").falseIf("SLA-Platform", "BASIC").optional(), - booleanProperty("SLA-PgSQL").falseIf("SLA-Platform", "BASIC").optional(), - booleanProperty("SLA-Office").falseIf("SLA-Platform", "BASIC").optional(), - booleanProperty("SLA-Web").falseIf("SLA-Platform", "BASIC").optional())))); - static { - validators.entrySet().forEach(typeDef -> { - stream(typeDef.getValue().propertyValidators).forEach( entry -> { - entry.verifyConsistency(typeDef); - }); - }); - } - private final HsHostingAssetPropertyValidator[] propertyValidators; - - public static void register(final HsHostingAssetType type, final HsHostingAssetValidator validator) { - validators.put(type, validator); - } - - public static HsHostingAssetValidator forType(final HsHostingAssetType type) { - return validators.get(type); - } - - HsHostingAssetValidator(final HsHostingAssetPropertyValidator... validators) { - propertyValidators = validators; - } - - public static Set types() { - return validators.keySet(); - } - - public List validate(final HsHostingAssetEntity assetEntity) { - final var result = new ArrayList(); - assetEntity.getConfig().keySet().forEach( givenPropName -> { - if (stream(propertyValidators).map(pv -> pv.propertyName).noneMatch(propName -> propName.equals(givenPropName))) { - result.add("'config." + givenPropName + "' is not expected but is '" +assetEntity.getConfig().get(givenPropName) + "'"); - } - }); - stream(propertyValidators).forEach(pv -> { - result.addAll(pv.validate(assetEntity.getConfig())); - }); - return result; - } - - public List> properties() { - final var mapper = new ObjectMapper(); - mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); - return Arrays.stream(propertyValidators) - .map(propertyValidator -> propertyValidator.toMap(mapper)) - .map(HsHostingAssetValidator::asKeyValueMap) - .toList(); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - private static Map asKeyValueMap(final Map map) { - return (Map) map; - } - -} diff --git a/src/main/java/net/hostsharing/hsadminng/hs/validation/BooleanPropertyValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/validation/BooleanPropertyValidator.java new file mode 100644 index 00000000..8b6f1232 --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/validation/BooleanPropertyValidator.java @@ -0,0 +1,42 @@ +package net.hostsharing.hsadminng.hs.validation; + +import lombok.Setter; + +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.Map; +import java.util.Objects; + +@Setter +public class BooleanPropertyValidator extends HsPropertyValidator { + + private Map.Entry falseIf; + + private BooleanPropertyValidator(final String propertyName) { + super(Boolean.class, propertyName); + } + + public static BooleanPropertyValidator booleanProperty(final String propertyName) { + return new BooleanPropertyValidator(propertyName); + } + + public HsPropertyValidator falseIf(final String refPropertyName, final String refPropertyValue) { + this.falseIf = new AbstractMap.SimpleImmutableEntry<>(refPropertyName, refPropertyValue); + return this; + } + + @Override + protected void validate(final ArrayList result, final Boolean propValue, final Map props) { + if (falseIf != null && !Objects.equals(props.get(falseIf.getKey()), falseIf.getValue())) { + if (propValue) { + result.add("'config." + propertyName + "' is expected to be false because " + + "config." + falseIf.getKey()+ "=" + falseIf.getValue() + " but is " + propValue); + } + } + } + + @Override + protected String simpleTypeName() { + return "boolean"; + } +} diff --git a/src/main/java/net/hostsharing/hsadminng/hs/validation/EnumerationPropertyValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/validation/EnumerationPropertyValidator.java new file mode 100644 index 00000000..e0d170d0 --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/validation/EnumerationPropertyValidator.java @@ -0,0 +1,38 @@ +package net.hostsharing.hsadminng.hs.validation; + +import lombok.Setter; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Map; + +@Setter +public class EnumerationPropertyValidator extends HsPropertyValidator { + + private String[] values; + + private EnumerationPropertyValidator(final String propertyName) { + super(String.class, propertyName); + } + + public static EnumerationPropertyValidator enumerationProperty(final String propertyName) { + return new EnumerationPropertyValidator(propertyName); + } + + public HsPropertyValidator values(final String... values) { + this.values = values; + return this; + } + + @Override + protected void validate(final ArrayList result, final String propValue, final Map props) { + if (Arrays.stream(values).noneMatch(v -> v.equals(propValue))) { + result.add("'config." + propertyName + "' is expected to be one of " + Arrays.toString(values) + " but is '" + propValue + "'"); + } + } + + @Override + protected String simpleTypeName() { + return "enumeration"; + } +} diff --git a/src/main/java/net/hostsharing/hsadminng/hs/validation/HsEntityValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/validation/HsEntityValidator.java new file mode 100644 index 00000000..3288b8fb --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/validation/HsEntityValidator.java @@ -0,0 +1,72 @@ +package net.hostsharing.hsadminng.hs.validation; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static java.util.Arrays.stream; +import static net.hostsharing.hsadminng.hs.validation.EnumerationPropertyValidator.enumerationProperty; +import static net.hostsharing.hsadminng.hs.validation.HsPropertyValidator.defType; +import static net.hostsharing.hsadminng.hs.validation.IntegerPropertyValidator.integerProperty; + +public class HsEntityValidator { + + private static final Map, HsEntityValidator> validators = new HashMap<>(); + private final HsPropertyValidator[] propertyValidators; + + public static void register(final Enum type, final HsEntityValidator validator) { + stream(validator.propertyValidators).forEach( entry -> { + entry.verifyConsistency(Map.entry(type, validator)); + }); + validators.put(type, validator); + } + + public static HsEntityValidator forType(final HsHostingAssetType type) { + return validators.get(type); + } + + public HsEntityValidator(final HsPropertyValidator... validators) { + propertyValidators = validators; + } + + public static Set> types() { + return validators.keySet(); + } + + public List validate(final HsHostingAssetEntity assetEntity) { + final var result = new ArrayList(); + assetEntity.getConfig().keySet().forEach( givenPropName -> { + if (stream(propertyValidators).map(pv -> pv.propertyName).noneMatch(propName -> propName.equals(givenPropName))) { + result.add("'config." + givenPropName + "' is not expected but is '" +assetEntity.getConfig().get(givenPropName) + "'"); + } + }); + stream(propertyValidators).forEach(pv -> { + result.addAll(pv.validate(assetEntity.getConfig())); + }); + return result; + } + + public List> properties() { + final var mapper = new ObjectMapper(); + mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); + return Arrays.stream(propertyValidators) + .map(propertyValidator -> propertyValidator.toMap(mapper)) + .map(HsEntityValidator::asKeyValueMap) + .toList(); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + private static Map asKeyValueMap(final Map map) { + return (Map) map; + } + +} diff --git a/src/main/java/net/hostsharing/hsadminng/hs/validation/HsPropertyValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/validation/HsPropertyValidator.java new file mode 100644 index 00000000..4408a1f3 --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/validation/HsPropertyValidator.java @@ -0,0 +1,68 @@ +package net.hostsharing.hsadminng.hs.validation; + +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.RequiredArgsConstructor; +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType; + +import java.util.AbstractMap.SimpleImmutableEntry; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@RequiredArgsConstructor +public abstract class HsPropertyValidator { + + final Class type; + final String propertyName; + private Boolean required; + + public static Map.Entry defType(K k, V v) { + return new SimpleImmutableEntry<>(k, v); + } + + public HsPropertyValidator required() { + required = Boolean.TRUE; + return this; + } + + public HsPropertyValidator optional() { + required = Boolean.FALSE; + return this; + } + + public final List validate(final Map props) { + final var result = new ArrayList(); + final var propValue = props.get(propertyName); + if (propValue == null) { + if (required) { + result.add("'config." + propertyName + "' is required but missing"); + } + } + if (propValue != null){ + if ( type.isInstance(propValue)) { + //noinspection unchecked + validate(result, (T) propValue, props); + } else { + result.add("'config." + propertyName + "' is expected to be of type " + type + ", " + + "but is of type '" + propValue.getClass().getSimpleName() + "'"); + } + } + return result; + } + + protected abstract void validate(final ArrayList result, final T propValue, final Map props); + + public void verifyConsistency(final Map.Entry, HsEntityValidator> typeDef) { + if (required == null ) { + throw new IllegalStateException(typeDef.getKey() + "[" + propertyName + "] not fully initialized, please call either .required() or .optional()" ); + } + } + + public Map toMap(final ObjectMapper mapper) { + final Map map = mapper.convertValue(this, Map.class); + map.put("type", simpleTypeName()); + return map; + } + + protected abstract String simpleTypeName(); +} diff --git a/src/main/java/net/hostsharing/hsadminng/hs/validation/IntegerPropertyValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/validation/IntegerPropertyValidator.java new file mode 100644 index 00000000..d0727dd4 --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/validation/IntegerPropertyValidator.java @@ -0,0 +1,42 @@ +package net.hostsharing.hsadminng.hs.validation; + +import lombok.Setter; + +import java.util.ArrayList; +import java.util.Map; + +@Setter +public class IntegerPropertyValidator extends HsPropertyValidator { + + private String unit; + private Integer min; + private Integer max; + private Integer step; + + public static IntegerPropertyValidator integerProperty(final String propertyName) { + return new IntegerPropertyValidator(propertyName); + } + + private IntegerPropertyValidator(final String propertyName) { + super(Integer.class, propertyName); + } + + + @Override + protected void validate(final ArrayList result, final Integer propValue, final Map props) { + if (min != null && propValue < min) { + result.add("'config." + propertyName + "' is expected to be >= " + min + " but is " + propValue); + } + if (max != null && propValue > max) { + result.add("'config." + propertyName + "' is expected to be <= " + max + " but is " + propValue); + } + if (step != null && propValue % step != 0) { + result.add("'config." + propertyName + "' is expected to be multiple of " + step + " but is " + propValue); + } + } + + @Override + protected String simpleTypeName() { + return "integer"; + } +} diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/lombok.config b/src/main/java/net/hostsharing/hsadminng/hs/validation/lombok.config similarity index 100% rename from src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/lombok.config rename to src/main/java/net/hostsharing/hsadminng/hs/validation/lombok.config diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsHostingAssetValidatorUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsEntityValidatorUnitTest.java similarity index 79% rename from src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsHostingAssetValidatorUnitTest.java rename to src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsEntityValidatorUnitTest.java index 90ff4e42..86836cec 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsHostingAssetValidatorUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsEntityValidatorUnitTest.java @@ -1,6 +1,6 @@ -package net.hostsharing.hsadminng.hs.hosting.asset.validator; +package net.hostsharing.hsadminng.hs.hosting.asset; -import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; +import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; import org.junit.jupiter.api.Test; import java.util.Map; @@ -9,12 +9,12 @@ import static java.util.Map.entry; import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_SERVER; import static org.assertj.core.api.Assertions.assertThat; -class HsHostingAssetValidatorUnitTest { +class HsManagedServerValidatorUnitTest { @Test void validatesDependentProperties() { // given - final var validator = HsHostingAssetValidator.forType(MANAGED_SERVER); + final var validator = HsEntityValidator.forType(MANAGED_SERVER); final var mangedWebspaceHostingAssetEntity = HsHostingAssetEntity.builder() .type(MANAGED_SERVER) .config(Map.ofEntries( diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsManagedWebspaceAssetValidatorUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceAssetValidatorUnitTest.java similarity index 88% rename from src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsManagedWebspaceAssetValidatorUnitTest.java rename to src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceAssetValidatorUnitTest.java index 952498e0..2bc82650 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validator/HsManagedWebspaceAssetValidatorUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceAssetValidatorUnitTest.java @@ -1,7 +1,7 @@ -package net.hostsharing.hsadminng.hs.hosting.asset.validator; +package net.hostsharing.hsadminng.hs.hosting.asset; import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity; -import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; +import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity; import org.junit.jupiter.api.Test; @@ -16,7 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat; class HsManagedWebspaceAssetValidatorUnitTest { @SuppressWarnings("unused") // just to make sure the class is loaded - HsHostingAssetValidator validator = new HsManagedWebspaceAssetValidator(); + HsEntityValidator validator = new HsManagedWebspaceAssetValidator(); final HsBookingItemEntity managedServerBookingItem = HsBookingItemEntity.builder() .debitor(HsOfficeDebitorEntity.builder().defaultPrefix("abc").build() @@ -35,7 +35,7 @@ class HsManagedWebspaceAssetValidatorUnitTest { @Test void validatesIdentifier() { // given - final var validator = HsHostingAssetValidator.forType(MANAGED_WEBSPACE); + final var validator = HsEntityValidator.forType(MANAGED_WEBSPACE); final var mangedWebspaceHostingAssetEntity = HsHostingAssetEntity.builder() .type(MANAGED_WEBSPACE) .parentAsset(mangedServerAssetEntity) @@ -58,7 +58,7 @@ class HsManagedWebspaceAssetValidatorUnitTest { @Test void validatesMissingProperties() { // given - final var validator = HsHostingAssetValidator.forType(MANAGED_WEBSPACE); + final var validator = HsEntityValidator.forType(MANAGED_WEBSPACE); final var mangedWebspaceHostingAssetEntity = HsHostingAssetEntity.builder() .type(MANAGED_WEBSPACE) .parentAsset(mangedServerAssetEntity) @@ -79,7 +79,7 @@ class HsManagedWebspaceAssetValidatorUnitTest { @Test void validatesUnknownProperties() { // given - final var validator = HsHostingAssetValidator.forType(MANAGED_WEBSPACE); + final var validator = HsEntityValidator.forType(MANAGED_WEBSPACE); final var mangedWebspaceHostingAssetEntity = HsHostingAssetEntity.builder() .type(MANAGED_WEBSPACE) .parentAsset(mangedServerAssetEntity) @@ -102,7 +102,7 @@ class HsManagedWebspaceAssetValidatorUnitTest { @Test void validatesValidProperties() { // given - final var validator = HsHostingAssetValidator.forType(MANAGED_WEBSPACE); + final var validator = HsEntityValidator.forType(MANAGED_WEBSPACE); final var mangedWebspaceHostingAssetEntity = HsHostingAssetEntity.builder() .type(MANAGED_WEBSPACE) .parentAsset(mangedServerAssetEntity) -- 2.39.5 From 6d286d18a9ac117a5730aa6a4c14459c76d48fe5 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Wed, 8 May 2024 09:47:11 +0200 Subject: [PATCH 5/7] move entity validation to domain specific packages to avoid typing problems --- .../hs/booking/item/HsBookingItemEntity.java | 8 +++- .../item/HsBookingItemEntityValidators.java | 40 ++++++++++++++++++ .../asset/HsCloudServerAssetValidator.java | 4 +- .../asset/HsHostingAssetController.java | 13 +----- .../hosting/asset/HsHostingAssetEntity.java | 8 +++- .../asset/HsHostingAssetEntityValidators.java | 41 +++++++++++++++++++ .../asset/HsHostingAssetPropsController.java | 5 +-- .../asset/HsManagedServerAssetValidator.java | 4 +- .../HsManagedWebspaceAssetValidator.java | 4 +- .../hs/validation/HsEntityValidator.java | 35 +++------------- .../hs/validation/HsPropertyValidator.java | 3 +- .../hsadminng/hs/validation/Validatable.java | 11 +++++ .../asset/HsEntityValidatorUnitTest.java | 3 +- ...ManagedWebspaceAssetValidatorUnitTest.java | 15 +++---- 14 files changed, 132 insertions(+), 62 deletions(-) create mode 100644 src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemEntityValidators.java create mode 100644 src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntityValidators.java create mode 100644 src/main/java/net/hostsharing/hsadminng/hs/validation/Validatable.java 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 5eb831de..5b8bb362 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 @@ -11,6 +11,7 @@ import lombok.NoArgsConstructor; import lombok.Setter; import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity; +import net.hostsharing.hsadminng.hs.validation.Validatable; import net.hostsharing.hsadminng.mapper.PatchableMapWrapper; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL; @@ -65,7 +66,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify; @Setter @NoArgsConstructor @AllArgsConstructor -public class HsBookingItemEntity implements Stringifyable, RbacObject { +public class HsBookingItemEntity implements Stringifyable, RbacObject, Validatable { private static Stringify stringify = stringify(HsBookingItemEntity.class) .withProp(HsBookingItemEntity::getDebitor) @@ -142,6 +143,11 @@ public class HsBookingItemEntity implements Stringifyable, RbacObject { ":" + caption; } + @Override + public Map getProperties() { + return resources; + } + public static RbacView rbac() { return rbacViewFor("bookingItem", HsBookingItemEntity.class) .withIdentityView(SQL.query(""" diff --git a/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemEntityValidators.java b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemEntityValidators.java new file mode 100644 index 00000000..36b14223 --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemEntityValidators.java @@ -0,0 +1,40 @@ +package net.hostsharing.hsadminng.hs.booking.item; + +import lombok.experimental.UtilityClass; +import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; + +import jakarta.validation.ValidationException; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import static java.util.Arrays.stream; + +@UtilityClass +public class HsBookingItemEntityValidators { + + private static final Map, HsEntityValidator> validators = new HashMap<>(); + + public static void register(final Enum type, final HsEntityValidator validator) { + stream(validator.propertyValidators).forEach( entry -> { + entry.verifyConsistency(Map.entry(type, validator)); + }); + validators.put(type, validator); + } + + public static HsEntityValidator forType(final Enum type) { + return validators.get(type); + } + + public static Set> types() { + return validators.keySet(); + } + + static HsBookingItemEntity valid(final HsBookingItemEntity entityToSave) { + final var violations = HsBookingItemEntityValidators.forType(entityToSave.getType()).validate(entityToSave); + if (!violations.isEmpty()) { + throw new ValidationException(violations.toString()); + } + return entityToSave; + } +} diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsCloudServerAssetValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsCloudServerAssetValidator.java index acef7bd9..3f9cb2a5 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsCloudServerAssetValidator.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsCloudServerAssetValidator.java @@ -8,10 +8,10 @@ import static net.hostsharing.hsadminng.hs.validation.EnumerationPropertyValidat import static net.hostsharing.hsadminng.hs.validation.IntegerPropertyValidator.integerProperty; @Component -class HsCloudServerAssetValidator extends HsEntityValidator { +class HsCloudServerAssetValidator extends HsEntityValidator { static { - HsEntityValidator.register(CLOUD_SERVER, new HsCloudServerAssetValidator()); + HsHostingAssetEntityValidators.register(CLOUD_SERVER, new HsCloudServerAssetValidator()); } public HsCloudServerAssetValidator() { diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetController.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetController.java index 9b8b484e..04221a8a 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetController.java @@ -1,6 +1,5 @@ package net.hostsharing.hsadminng.hs.hosting.asset; -import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.api.HsHostingAssetsApi; import net.hostsharing.hsadminng.context.Context; @@ -17,11 +16,11 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder; import jakarta.persistence.EntityNotFoundException; -import jakarta.validation.ValidationException; import java.util.List; import java.util.UUID; import java.util.function.BiConsumer; +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntityValidators.valid; @RestController public class HsHostingAssetController implements HsHostingAssetsApi { @@ -118,19 +117,11 @@ public class HsHostingAssetController implements HsHostingAssetsApi { new HsHostingAssetEntityPatcher(current).apply(body); - final var saved = assetRepo.save(current); + final var saved = assetRepo.save(valid(current)); final var mapped = mapper.map(saved, HsHostingAssetResource.class); return ResponseEntity.ok(mapped); } - private HsHostingAssetEntity valid(final HsHostingAssetEntity entityToSave) { - final var violations = HsEntityValidator.forType(entityToSave.getType()).validate(entityToSave); - if (!violations.isEmpty()) { - throw new ValidationException(violations.toString()); - } - return entityToSave; - } - final BiConsumer RESOURCE_TO_ENTITY_POSTMAPPER = (resource, entity) -> { entity.putConfig(KeyValueMap.from(resource.getConfig())); if (resource.getParentAssetUuid() != null) { 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 af91e0db..5571dd13 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 @@ -8,6 +8,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity; +import net.hostsharing.hsadminng.hs.validation.Validatable; import net.hostsharing.hsadminng.mapper.PatchableMapWrapper; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView; import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL; @@ -60,7 +61,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify; @Setter @NoArgsConstructor @AllArgsConstructor -public class HsHostingAssetEntity implements Stringifyable, RbacObject { +public class HsHostingAssetEntity implements Stringifyable, RbacObject, Validatable { private static Stringify stringify = stringify(HsHostingAssetEntity.class) .withProp(HsHostingAssetEntity::getType) @@ -113,6 +114,11 @@ public class HsHostingAssetEntity implements Stringifyable, RbacObject { PatchableMapWrapper.of(configWrapper, (newWrapper) -> {configWrapper = newWrapper; }, config).assign(newConfg); } + @Override + public Map getProperties() { + return config; + } + @Override public String toString() { return stringify.apply(this); diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntityValidators.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntityValidators.java new file mode 100644 index 00000000..42567993 --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntityValidators.java @@ -0,0 +1,41 @@ +package net.hostsharing.hsadminng.hs.hosting.asset; + +import lombok.experimental.UtilityClass; +import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; + +import jakarta.validation.ValidationException; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import static java.util.Arrays.stream; + +@UtilityClass +public class HsHostingAssetEntityValidators { + + private static final Map, HsEntityValidator> validators = new HashMap<>(); + + public static void register(final Enum type, final HsEntityValidator validator) { + stream(validator.propertyValidators).forEach( entry -> { + entry.verifyConsistency(Map.entry(type, validator)); + }); + validators.put(type, validator); + } + + public static HsEntityValidator forType(final Enum type) { + return validators.get(type); + } + + public static Set> types() { + return validators.keySet(); + } + + + static HsHostingAssetEntity valid(final HsHostingAssetEntity entityToSave) { + final var violations = HsHostingAssetEntityValidators.forType(entityToSave.getType()).validate(entityToSave); + if (!violations.isEmpty()) { + throw new ValidationException(violations.toString()); + } + return entityToSave; + } +} diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetPropsController.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetPropsController.java index 50e236eb..1ef68798 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetPropsController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetPropsController.java @@ -1,6 +1,5 @@ package net.hostsharing.hsadminng.hs.hosting.asset; -import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.api.HsHostingAssetPropsApi; import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.model.HsHostingAssetTypeResource; import org.springframework.http.ResponseEntity; @@ -15,7 +14,7 @@ public class HsHostingAssetPropsController implements HsHostingAssetPropsApi { @Override public ResponseEntity> listAssetTypes() { - final var resource = HsEntityValidator.types().stream() + final var resource = HsHostingAssetEntityValidators.types().stream() .map(Enum::name) .toList(); return ResponseEntity.ok(resource); @@ -25,7 +24,7 @@ public class HsHostingAssetPropsController implements HsHostingAssetPropsApi { public ResponseEntity> listAssetTypeProps( final HsHostingAssetTypeResource assetType) { - final var propValidators = HsEntityValidator.forType(HsHostingAssetType.of(assetType)); + final var propValidators = HsHostingAssetEntityValidators.forType(HsHostingAssetType.of(assetType)); final List> resource = propValidators.properties(); return ResponseEntity.ok(toListOfObjects(resource)); } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedServerAssetValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedServerAssetValidator.java index 95bbfb96..c7b35550 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedServerAssetValidator.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedServerAssetValidator.java @@ -9,10 +9,10 @@ import static net.hostsharing.hsadminng.hs.validation.EnumerationPropertyValidat import static net.hostsharing.hsadminng.hs.validation.IntegerPropertyValidator.integerProperty; @Component -class HsManagedServerAssetValidator extends HsEntityValidator { +class HsManagedServerAssetValidator extends HsEntityValidator { static { - HsEntityValidator.register(MANAGED_SERVER, new HsManagedServerAssetValidator()); + HsHostingAssetEntityValidators.register(MANAGED_SERVER, new HsManagedServerAssetValidator()); } public HsManagedServerAssetValidator() { diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceAssetValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceAssetValidator.java index 4deade19..5b898976 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceAssetValidator.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceAssetValidator.java @@ -11,10 +11,10 @@ import static net.hostsharing.hsadminng.hs.validation.EnumerationPropertyValidat import static net.hostsharing.hsadminng.hs.validation.IntegerPropertyValidator.integerProperty; @Component -class HsManagedWebspaceAssetValidator extends HsEntityValidator { +class HsManagedWebspaceAssetValidator extends HsEntityValidator { static { - HsEntityValidator.register(MANAGED_WEBSPACE, new HsManagedWebspaceAssetValidator()); + HsHostingAssetEntityValidators.register(MANAGED_WEBSPACE, new HsManagedWebspaceAssetValidator()); } public HsManagedWebspaceAssetValidator() { diff --git a/src/main/java/net/hostsharing/hsadminng/hs/validation/HsEntityValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/validation/HsEntityValidator.java index 3288b8fb..15f62916 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/validation/HsEntityValidator.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/validation/HsEntityValidator.java @@ -3,54 +3,31 @@ package net.hostsharing.hsadminng.hs.validation; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; -import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; -import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; import static java.util.Arrays.stream; -import static net.hostsharing.hsadminng.hs.validation.EnumerationPropertyValidator.enumerationProperty; -import static net.hostsharing.hsadminng.hs.validation.HsPropertyValidator.defType; -import static net.hostsharing.hsadminng.hs.validation.IntegerPropertyValidator.integerProperty; -public class HsEntityValidator { +public class HsEntityValidator, T extends Enum> { - private static final Map, HsEntityValidator> validators = new HashMap<>(); - private final HsPropertyValidator[] propertyValidators; - - public static void register(final Enum type, final HsEntityValidator validator) { - stream(validator.propertyValidators).forEach( entry -> { - entry.verifyConsistency(Map.entry(type, validator)); - }); - validators.put(type, validator); - } - - public static HsEntityValidator forType(final HsHostingAssetType type) { - return validators.get(type); - } + public final HsPropertyValidator[] propertyValidators; public HsEntityValidator(final HsPropertyValidator... validators) { propertyValidators = validators; } - public static Set> types() { - return validators.keySet(); - } - - public List validate(final HsHostingAssetEntity assetEntity) { + public List validate(final E assetEntity) { final var result = new ArrayList(); - assetEntity.getConfig().keySet().forEach( givenPropName -> { + assetEntity.getProperties().keySet().forEach( givenPropName -> { if (stream(propertyValidators).map(pv -> pv.propertyName).noneMatch(propName -> propName.equals(givenPropName))) { - result.add("'config." + givenPropName + "' is not expected but is '" +assetEntity.getConfig().get(givenPropName) + "'"); + result.add("'config." + givenPropName + "' is not expected but is '" +assetEntity.getProperties().get(givenPropName) + "'"); } }); stream(propertyValidators).forEach(pv -> { - result.addAll(pv.validate(assetEntity.getConfig())); + result.addAll(pv.validate(assetEntity.getProperties())); }); return result; } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/validation/HsPropertyValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/validation/HsPropertyValidator.java index 4408a1f3..4a7bb05e 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/validation/HsPropertyValidator.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/validation/HsPropertyValidator.java @@ -2,7 +2,6 @@ package net.hostsharing.hsadminng.hs.validation; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; -import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType; import java.util.AbstractMap.SimpleImmutableEntry; import java.util.ArrayList; @@ -52,7 +51,7 @@ public abstract class HsPropertyValidator { protected abstract void validate(final ArrayList result, final T propValue, final Map props); - public void verifyConsistency(final Map.Entry, HsEntityValidator> typeDef) { + public void verifyConsistency(final Map.Entry, ?> typeDef) { if (required == null ) { throw new IllegalStateException(typeDef.getKey() + "[" + propertyName + "] not fully initialized, please call either .required() or .optional()" ); } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/validation/Validatable.java b/src/main/java/net/hostsharing/hsadminng/hs/validation/Validatable.java new file mode 100644 index 00000000..09cf4388 --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/validation/Validatable.java @@ -0,0 +1,11 @@ +package net.hostsharing.hsadminng.hs.validation; + + +import java.util.Map; + +public interface Validatable> { + + Map getProperties(); + + Enum getType(); +} diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsEntityValidatorUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsEntityValidatorUnitTest.java index 86836cec..66e3f16d 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsEntityValidatorUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsEntityValidatorUnitTest.java @@ -1,6 +1,5 @@ package net.hostsharing.hsadminng.hs.hosting.asset; -import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; import org.junit.jupiter.api.Test; import java.util.Map; @@ -14,7 +13,7 @@ class HsManagedServerValidatorUnitTest { @Test void validatesDependentProperties() { // given - final var validator = HsEntityValidator.forType(MANAGED_SERVER); + final var validator = HsHostingAssetEntityValidators.forType(MANAGED_SERVER); final var mangedWebspaceHostingAssetEntity = HsHostingAssetEntity.builder() .type(MANAGED_SERVER) .config(Map.ofEntries( diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceAssetValidatorUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceAssetValidatorUnitTest.java index 2bc82650..73873b24 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceAssetValidatorUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceAssetValidatorUnitTest.java @@ -1,7 +1,6 @@ package net.hostsharing.hsadminng.hs.hosting.asset; import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity; -import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity; import org.junit.jupiter.api.Test; @@ -15,8 +14,10 @@ import static org.assertj.core.api.Assertions.assertThat; class HsManagedWebspaceAssetValidatorUnitTest { - @SuppressWarnings("unused") // just to make sure the class is loaded - HsEntityValidator validator = new HsManagedWebspaceAssetValidator(); + // just to make sure the class is loaded + static { + new HsManagedWebspaceAssetValidator(); + } final HsBookingItemEntity managedServerBookingItem = HsBookingItemEntity.builder() .debitor(HsOfficeDebitorEntity.builder().defaultPrefix("abc").build() @@ -35,7 +36,7 @@ class HsManagedWebspaceAssetValidatorUnitTest { @Test void validatesIdentifier() { // given - final var validator = HsEntityValidator.forType(MANAGED_WEBSPACE); + final var validator = HsHostingAssetEntityValidators.forType(MANAGED_WEBSPACE); final var mangedWebspaceHostingAssetEntity = HsHostingAssetEntity.builder() .type(MANAGED_WEBSPACE) .parentAsset(mangedServerAssetEntity) @@ -58,7 +59,7 @@ class HsManagedWebspaceAssetValidatorUnitTest { @Test void validatesMissingProperties() { // given - final var validator = HsEntityValidator.forType(MANAGED_WEBSPACE); + final var validator = HsHostingAssetEntityValidators.forType(MANAGED_WEBSPACE); final var mangedWebspaceHostingAssetEntity = HsHostingAssetEntity.builder() .type(MANAGED_WEBSPACE) .parentAsset(mangedServerAssetEntity) @@ -79,7 +80,7 @@ class HsManagedWebspaceAssetValidatorUnitTest { @Test void validatesUnknownProperties() { // given - final var validator = HsEntityValidator.forType(MANAGED_WEBSPACE); + final var validator = HsHostingAssetEntityValidators.forType(MANAGED_WEBSPACE); final var mangedWebspaceHostingAssetEntity = HsHostingAssetEntity.builder() .type(MANAGED_WEBSPACE) .parentAsset(mangedServerAssetEntity) @@ -102,7 +103,7 @@ class HsManagedWebspaceAssetValidatorUnitTest { @Test void validatesValidProperties() { // given - final var validator = HsEntityValidator.forType(MANAGED_WEBSPACE); + final var validator = HsHostingAssetEntityValidators.forType(MANAGED_WEBSPACE); final var mangedWebspaceHostingAssetEntity = HsHostingAssetEntity.builder() .type(MANAGED_WEBSPACE) .parentAsset(mangedServerAssetEntity) -- 2.39.5 From 18dd28a7e3cab491ddaae04f58006320212ab595 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Fri, 10 May 2024 09:55:30 +0200 Subject: [PATCH 6/7] working separate booking item and and hosting asset validations --- .../booking/item/HsBookingItemController.java | 5 +- .../hs/booking/item/HsBookingItemEntity.java | 5 + .../item/HsBookingItemEntityValidators.java | 10 +- .../HsCloudServerBookingItemValidator.java | 20 +++ .../HsManagedServerBookingItemValidator.java | 26 ++++ ...HsManagedWebspaceBookingItemValidator.java | 22 +++ .../asset/HsCloudServerAssetValidator.java | 27 ---- .../HsCloudServerHostingAssetValidator.java | 18 +++ .../hosting/asset/HsHostingAssetEntity.java | 5 + .../asset/HsHostingAssetEntityValidators.java | 14 +- .../asset/HsManagedServerAssetValidator.java | 33 ---- .../HsManagedServerHostingAssetValidator.java | 18 +++ ...ManagedWebspaceHostingAssetValidator.java} | 26 ++-- .../validation/BooleanPropertyValidator.java | 6 +- .../EnumerationPropertyValidator.java | 4 +- .../hs/validation/HsEntityValidator.java | 4 +- .../hs/validation/HsPropertyValidator.java | 10 +- .../validation/IntegerPropertyValidator.java | 8 +- .../hsadminng/hs/validation/Validatable.java | 4 +- .../6018-hs-booking-item-test-data.sql | 6 +- .../7018-hs-hosting-asset-test-data.sql | 6 +- ...HsBookingItemControllerAcceptanceTest.java | 115 ++++++++------ ...sBookingItemRepositoryIntegrationTest.java | 12 +- ...gedServerBookingItemValidatorUnitTest.java | 34 +++++ ...sHostingAssetControllerAcceptanceTest.java | 36 +++-- ...ingAssetPropsControllerAcceptanceTest.java | 141 ++++++------------ ...dServerHostingAssetValidatorUnitTest.java} | 20 ++- ...ebspaceHostingAssetValidatorUnitTest.java} | 6 +- 28 files changed, 363 insertions(+), 278 deletions(-) create mode 100644 src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsCloudServerBookingItemValidator.java create mode 100644 src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsManagedServerBookingItemValidator.java create mode 100644 src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsManagedWebspaceBookingItemValidator.java delete mode 100644 src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsCloudServerAssetValidator.java create mode 100644 src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsCloudServerHostingAssetValidator.java delete mode 100644 src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedServerAssetValidator.java create mode 100644 src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedServerHostingAssetValidator.java rename src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/{HsManagedWebspaceAssetValidator.java => HsManagedWebspaceHostingAssetValidator.java} (54%) create mode 100644 src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsManagedServerBookingItemValidatorUnitTest.java rename src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/{HsEntityValidatorUnitTest.java => HsManagedServerHostingAssetValidatorUnitTest.java} (50%) rename src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/{HsManagedWebspaceAssetValidatorUnitTest.java => HsManagedWebspaceHostingAssetValidatorUnitTest.java} (96%) diff --git a/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemController.java b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemController.java index bd05ad66..b278e817 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemController.java @@ -17,6 +17,7 @@ import java.util.List; import java.util.UUID; import java.util.function.BiConsumer; +import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntityValidators.valid; import static net.hostsharing.hsadminng.mapper.PostgresDateRange.toPostgresDateRange; @RestController @@ -56,7 +57,7 @@ public class HsBookingItemController implements HsBookingItemsApi { final var entityToSave = mapper.map(body, HsBookingItemEntity.class, RESOURCE_TO_ENTITY_POSTMAPPER); - final var saved = bookingItemRepo.save(entityToSave); + final var saved = bookingItemRepo.save(valid(entityToSave)); final var uri = MvcUriComponentsBuilder.fromController(getClass()) @@ -111,7 +112,7 @@ public class HsBookingItemController implements HsBookingItemsApi { new HsBookingItemEntityPatcher(current).apply(body); - final var saved = bookingItemRepo.save(current); + final var saved = bookingItemRepo.save(valid(current)); final var mapped = mapper.map(saved, HsBookingItemResource.class, ENTITY_TO_RESOURCE_POSTMAPPER); return ResponseEntity.ok(mapped); } 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 5b8bb362..60dd2935 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 @@ -143,6 +143,11 @@ public class HsBookingItemEntity implements Stringifyable, RbacObject, Validatab ":" + caption; } + @Override + public String getPropertiesName() { + return "resources"; + } + @Override public Map getProperties() { return resources; diff --git a/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemEntityValidators.java b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemEntityValidators.java index 36b14223..c85430bd 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemEntityValidators.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemEntityValidators.java @@ -9,13 +9,21 @@ import java.util.Map; import java.util.Set; import static java.util.Arrays.stream; +import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.CLOUD_SERVER; +import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.MANAGED_SERVER; +import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.MANAGED_WEBSPACE; @UtilityClass public class HsBookingItemEntityValidators { private static final Map, HsEntityValidator> validators = new HashMap<>(); + static { + register(CLOUD_SERVER, new HsCloudServerBookingItemValidator()); + register(MANAGED_SERVER, new HsManagedServerBookingItemValidator()); + register(MANAGED_WEBSPACE, new HsManagedWebspaceBookingItemValidator()); + } - public static void register(final Enum type, final HsEntityValidator validator) { + private static void register(final Enum type, final HsEntityValidator validator) { stream(validator.propertyValidators).forEach( entry -> { entry.verifyConsistency(Map.entry(type, validator)); }); diff --git a/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsCloudServerBookingItemValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsCloudServerBookingItemValidator.java new file mode 100644 index 00000000..521e9a0a --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsCloudServerBookingItemValidator.java @@ -0,0 +1,20 @@ +package net.hostsharing.hsadminng.hs.booking.item; + +import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; + +import static net.hostsharing.hsadminng.hs.validation.EnumerationPropertyValidator.enumerationProperty; +import static net.hostsharing.hsadminng.hs.validation.IntegerPropertyValidator.integerProperty; + +class HsCloudServerBookingItemValidator extends HsEntityValidator { + + HsCloudServerBookingItemValidator() { + super( + integerProperty("CPUs").min(1).max(32).required(), + integerProperty("RAM").unit("GB").min(1).max(128).required(), + integerProperty("SSD").unit("GB").min(25).max(1000).step(25).required(), + integerProperty("HDD").unit("GB").min(0).max(4000).step(250).optional(), + integerProperty("Traffic").unit("GB").min(250).max(10000).step(250).required(), + enumerationProperty("SLA-Infrastructure").values("BASIC", "EXT8H", "EXT4H", "EXT2H").optional() + ); + } +} diff --git a/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsManagedServerBookingItemValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsManagedServerBookingItemValidator.java new file mode 100644 index 00000000..ca00edc8 --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsManagedServerBookingItemValidator.java @@ -0,0 +1,26 @@ +package net.hostsharing.hsadminng.hs.booking.item; + +import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; + +import static net.hostsharing.hsadminng.hs.validation.BooleanPropertyValidator.booleanProperty; +import static net.hostsharing.hsadminng.hs.validation.EnumerationPropertyValidator.enumerationProperty; +import static net.hostsharing.hsadminng.hs.validation.IntegerPropertyValidator.integerProperty; + +class HsManagedServerBookingItemValidator extends HsEntityValidator { + + HsManagedServerBookingItemValidator() { + super( + integerProperty("CPUs").min(1).max(32).required(), + integerProperty("RAM").unit("GB").min(1).max(128).required(), + integerProperty("SSD").unit("GB").min(25).max(1000).step(25).required(), + integerProperty("HDD").unit("GB").min(0).max(4000).step(250).optional(), + integerProperty("Traffic").unit("GB").min(250).max(10000).step(250).required(), + enumerationProperty("SLA-Platform").values("BASIC", "EXT8H", "EXT4H", "EXT2H").optional(), + booleanProperty("SLA-EMail").falseIf("SLA-Platform", "BASIC").optional(), + booleanProperty("SLA-Maria").falseIf("SLA-Platform", "BASIC").optional(), + booleanProperty("SLA-PgSQL").falseIf("SLA-Platform", "BASIC").optional(), + booleanProperty("SLA-Office").falseIf("SLA-Platform", "BASIC").optional(), + booleanProperty("SLA-Web").falseIf("SLA-Platform", "BASIC").optional() + ); + } +} diff --git a/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsManagedWebspaceBookingItemValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsManagedWebspaceBookingItemValidator.java new file mode 100644 index 00000000..b6dbaf82 --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsManagedWebspaceBookingItemValidator.java @@ -0,0 +1,22 @@ +package net.hostsharing.hsadminng.hs.booking.item; + +import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; + + +import static net.hostsharing.hsadminng.hs.validation.BooleanPropertyValidator.booleanProperty; +import static net.hostsharing.hsadminng.hs.validation.EnumerationPropertyValidator.enumerationProperty; +import static net.hostsharing.hsadminng.hs.validation.IntegerPropertyValidator.integerProperty; + +class HsManagedWebspaceBookingItemValidator extends HsEntityValidator { + + public HsManagedWebspaceBookingItemValidator() { + super( + integerProperty("SSD").unit("GB").min(1).max(100).step(1).required(), + integerProperty("HDD").unit("GB").min(0).max(250).step(10).optional(), + integerProperty("Traffic").unit("GB").min(10).max(1000).step(10).required(), + enumerationProperty("SLA-Platform").values("BASIC", "EXT24H").optional(), + integerProperty("Daemons").min(0).max(10).optional(), + booleanProperty("Online Office Server").optional() + ); + } +} diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsCloudServerAssetValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsCloudServerAssetValidator.java deleted file mode 100644 index 3f9cb2a5..00000000 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsCloudServerAssetValidator.java +++ /dev/null @@ -1,27 +0,0 @@ -package net.hostsharing.hsadminng.hs.hosting.asset; - -import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; -import org.springframework.stereotype.Component; - -import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.CLOUD_SERVER; -import static net.hostsharing.hsadminng.hs.validation.EnumerationPropertyValidator.enumerationProperty; -import static net.hostsharing.hsadminng.hs.validation.IntegerPropertyValidator.integerProperty; - -@Component -class HsCloudServerAssetValidator extends HsEntityValidator { - - static { - HsHostingAssetEntityValidators.register(CLOUD_SERVER, new HsCloudServerAssetValidator()); - } - - public HsCloudServerAssetValidator() { - super( - integerProperty("CPUs").min(1).max(32).required(), - integerProperty("RAM").unit("GB").min(1).max(128).required(), - integerProperty("SSD").unit("GB").min(25).max(1000).step(25).required(), - integerProperty("HDD").unit("GB").min(0).max(4000).step(250).optional(), - integerProperty("Traffic").unit("GB").min(250).max(10000).step(250).required(), - enumerationProperty("SLA-Infrastructure").values("BASIC", "EXT8H", "EXT4H", "EXT2H").optional() - ); - } -} diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsCloudServerHostingAssetValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsCloudServerHostingAssetValidator.java new file mode 100644 index 00000000..8124df34 --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsCloudServerHostingAssetValidator.java @@ -0,0 +1,18 @@ +package net.hostsharing.hsadminng.hs.hosting.asset; + +import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; + +import static net.hostsharing.hsadminng.hs.validation.IntegerPropertyValidator.integerProperty; + +class HsCloudServerHostingAssetValidator extends HsEntityValidator { + + public HsCloudServerHostingAssetValidator() { + super( + integerProperty("CPUs").min(1).max(32).required(), + integerProperty("RAM").unit("GB").min(1).max(128).required(), + integerProperty("SSD").unit("GB").min(25).max(1000).step(25).required(), + integerProperty("HDD").unit("GB").min(0).max(4000).step(250).optional(), + integerProperty("Traffic").unit("GB").min(250).max(10000).step(250).required() + ); + } +} 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 5571dd13..1f4ec01a 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 @@ -114,6 +114,11 @@ public class HsHostingAssetEntity implements Stringifyable, RbacObject, Validata PatchableMapWrapper.of(configWrapper, (newWrapper) -> {configWrapper = newWrapper; }, config).assign(newConfg); } + @Override + public String getPropertiesName() { + return "config"; + } + @Override public Map getProperties() { return config; diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntityValidators.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntityValidators.java index 42567993..cd8157d1 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntityValidators.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntityValidators.java @@ -9,24 +9,32 @@ import java.util.Map; import java.util.Set; import static java.util.Arrays.stream; +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.CLOUD_SERVER; +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_SERVER; +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_WEBSPACE; @UtilityClass public class HsHostingAssetEntityValidators { private static final Map, HsEntityValidator> validators = new HashMap<>(); + static { + register(CLOUD_SERVER, new HsCloudServerHostingAssetValidator()); + register(MANAGED_SERVER, new HsManagedServerHostingAssetValidator()); + register(MANAGED_WEBSPACE, new HsManagedWebspaceHostingAssetValidator()); + } - public static void register(final Enum type, final HsEntityValidator validator) { + private static void register(final Enum type, final HsEntityValidator validator) { stream(validator.propertyValidators).forEach( entry -> { entry.verifyConsistency(Map.entry(type, validator)); }); validators.put(type, validator); } - public static HsEntityValidator forType(final Enum type) { + static HsEntityValidator forType(final Enum type) { return validators.get(type); } - public static Set> types() { + static Set> types() { return validators.keySet(); } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedServerAssetValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedServerAssetValidator.java deleted file mode 100644 index c7b35550..00000000 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedServerAssetValidator.java +++ /dev/null @@ -1,33 +0,0 @@ -package net.hostsharing.hsadminng.hs.hosting.asset; - -import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; -import org.springframework.stereotype.Component; - -import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_SERVER; -import static net.hostsharing.hsadminng.hs.validation.BooleanPropertyValidator.booleanProperty; -import static net.hostsharing.hsadminng.hs.validation.EnumerationPropertyValidator.enumerationProperty; -import static net.hostsharing.hsadminng.hs.validation.IntegerPropertyValidator.integerProperty; - -@Component -class HsManagedServerAssetValidator extends HsEntityValidator { - - static { - HsHostingAssetEntityValidators.register(MANAGED_SERVER, new HsManagedServerAssetValidator()); - } - - public HsManagedServerAssetValidator() { - super( - integerProperty("CPUs").min(1).max(32).required(), - integerProperty("RAM").unit("GB").min(1).max(128).required(), - integerProperty("SSD").unit("GB").min(25).max(1000).step(25).required(), - integerProperty("HDD").unit("GB").min(0).max(4000).step(250).optional(), - integerProperty("Traffic").unit("GB").min(250).max(10000).step(250).required(), - enumerationProperty("SLA-Platform").values("BASIC", "EXT8H", "EXT4H", "EXT2H").optional(), - booleanProperty("SLA-EMail").falseIf("SLA-Platform", "BASIC").optional(), - booleanProperty("SLA-Maria").falseIf("SLA-Platform", "BASIC").optional(), - booleanProperty("SLA-PgSQL").falseIf("SLA-Platform", "BASIC").optional(), - booleanProperty("SLA-Office").falseIf("SLA-Platform", "BASIC").optional(), - booleanProperty("SLA-Web").falseIf("SLA-Platform", "BASIC").optional() - ); - } -} diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedServerHostingAssetValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedServerHostingAssetValidator.java new file mode 100644 index 00000000..ce739a2f --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedServerHostingAssetValidator.java @@ -0,0 +1,18 @@ +package net.hostsharing.hsadminng.hs.hosting.asset; + +import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; + +import static net.hostsharing.hsadminng.hs.validation.IntegerPropertyValidator.integerProperty; + +class HsManagedServerHostingAssetValidator extends HsEntityValidator { + + public HsManagedServerHostingAssetValidator() { + super( + integerProperty("CPUs").min(1).max(32).required(), + integerProperty("RAM").unit("GB").min(1).max(128).required(), + integerProperty("SSD").unit("GB").min(25).max(1000).step(25).required(), + integerProperty("HDD").unit("GB").min(0).max(4000).step(250).optional(), + integerProperty("Traffic").unit("GB").min(250).max(10000).step(250).required() + ); + } +} diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceAssetValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceHostingAssetValidator.java similarity index 54% rename from src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceAssetValidator.java rename to src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceHostingAssetValidator.java index 5b898976..76ae29e9 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceAssetValidator.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceHostingAssetValidator.java @@ -1,40 +1,32 @@ package net.hostsharing.hsadminng.hs.hosting.asset; import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; -import org.springframework.stereotype.Component; import java.util.List; -import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_WEBSPACE; -import static net.hostsharing.hsadminng.hs.validation.BooleanPropertyValidator.booleanProperty; -import static net.hostsharing.hsadminng.hs.validation.EnumerationPropertyValidator.enumerationProperty; import static net.hostsharing.hsadminng.hs.validation.IntegerPropertyValidator.integerProperty; -@Component -class HsManagedWebspaceAssetValidator extends HsEntityValidator { - - static { - HsHostingAssetEntityValidators.register(MANAGED_WEBSPACE, new HsManagedWebspaceAssetValidator()); - } - - public HsManagedWebspaceAssetValidator() { +class HsManagedWebspaceHostingAssetValidator extends HsEntityValidator { + public HsManagedWebspaceHostingAssetValidator() { super( integerProperty("SSD").unit("GB").min(1).max(100).step(1).required(), integerProperty("HDD").unit("GB").min(0).max(250).step(10).optional(), - integerProperty("Traffic").unit("GB").min(10).max(1000).step(10).required(), - enumerationProperty("SLA-Platform").values("BASIC", "EXT24H").optional(), - integerProperty("Daemons").min(0).max(10).optional(), - booleanProperty("Online Office Server").optional() + integerProperty("Traffic").unit("GB").min(10).max(1000).step(10).required() ); } @Override public List validate(final HsHostingAssetEntity assetEntity) { final var result = super.validate(assetEntity); + validateIdentifierPattern(result, assetEntity); + + return result; + } + + private static void validateIdentifierPattern(final List result, final HsHostingAssetEntity assetEntity) { final var expectedIdentifierPattern = "^" + assetEntity.getParentAsset().getBookingItem().getDebitor().getDefaultPrefix() + "[0-9][0-9]$"; if ( !assetEntity.getIdentifier().matches(expectedIdentifierPattern)) { result.add("'identifier' expected to match '"+expectedIdentifierPattern+"', but is '" + assetEntity.getIdentifier() + "'"); } - return result; } } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/validation/BooleanPropertyValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/validation/BooleanPropertyValidator.java index 8b6f1232..2838e0f5 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/validation/BooleanPropertyValidator.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/validation/BooleanPropertyValidator.java @@ -26,11 +26,11 @@ public class BooleanPropertyValidator extends HsPropertyValidator { } @Override - protected void validate(final ArrayList result, final Boolean propValue, final Map props) { + protected void validate(final ArrayList result, final String propertiesName, final Boolean propValue, final Map props) { if (falseIf != null && !Objects.equals(props.get(falseIf.getKey()), falseIf.getValue())) { if (propValue) { - result.add("'config." + propertyName + "' is expected to be false because " + - "config." + falseIf.getKey()+ "=" + falseIf.getValue() + " but is " + propValue); + result.add("'"+propertiesName+"." + propertyName + "' is expected to be false because " + + propertiesName+"." + falseIf.getKey()+ "=" + falseIf.getValue() + " but is " + propValue); } } } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/validation/EnumerationPropertyValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/validation/EnumerationPropertyValidator.java index e0d170d0..329feb74 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/validation/EnumerationPropertyValidator.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/validation/EnumerationPropertyValidator.java @@ -25,9 +25,9 @@ public class EnumerationPropertyValidator extends HsPropertyValidator { } @Override - protected void validate(final ArrayList result, final String propValue, final Map props) { + protected void validate(final ArrayList result, final String propertiesName, final String propValue, final Map props) { if (Arrays.stream(values).noneMatch(v -> v.equals(propValue))) { - result.add("'config." + propertyName + "' is expected to be one of " + Arrays.toString(values) + " but is '" + propValue + "'"); + result.add("'"+propertiesName+"." + propertyName + "' is expected to be one of " + Arrays.toString(values) + " but is '" + propValue + "'"); } } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/validation/HsEntityValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/validation/HsEntityValidator.java index 15f62916..43be4d10 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/validation/HsEntityValidator.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/validation/HsEntityValidator.java @@ -23,11 +23,11 @@ public class HsEntityValidator, T extends Enum> { final var result = new ArrayList(); assetEntity.getProperties().keySet().forEach( givenPropName -> { if (stream(propertyValidators).map(pv -> pv.propertyName).noneMatch(propName -> propName.equals(givenPropName))) { - result.add("'config." + givenPropName + "' is not expected but is '" +assetEntity.getProperties().get(givenPropName) + "'"); + result.add("'"+assetEntity.getPropertiesName()+"." + givenPropName + "' is not expected but is set to '" +assetEntity.getProperties().get(givenPropName) + "'"); } }); stream(propertyValidators).forEach(pv -> { - result.addAll(pv.validate(assetEntity.getProperties())); + result.addAll(pv.validate(assetEntity.getPropertiesName(), assetEntity.getProperties())); }); return result; } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/validation/HsPropertyValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/validation/HsPropertyValidator.java index 4a7bb05e..891c8a7a 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/validation/HsPropertyValidator.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/validation/HsPropertyValidator.java @@ -29,27 +29,27 @@ public abstract class HsPropertyValidator { return this; } - public final List validate(final Map props) { + public final List validate(final String propertiesName, final Map props) { final var result = new ArrayList(); final var propValue = props.get(propertyName); if (propValue == null) { if (required) { - result.add("'config." + propertyName + "' is required but missing"); + result.add("'"+propertiesName+"." + propertyName + "' is required but missing"); } } if (propValue != null){ if ( type.isInstance(propValue)) { //noinspection unchecked - validate(result, (T) propValue, props); + validate(result, propertiesName, (T) propValue, props); } else { - result.add("'config." + propertyName + "' is expected to be of type " + type + ", " + + result.add("'"+propertiesName+"." + propertyName + "' is expected to be of type " + type + ", " + "but is of type '" + propValue.getClass().getSimpleName() + "'"); } } return result; } - protected abstract void validate(final ArrayList result, final T propValue, final Map props); + protected abstract void validate(final ArrayList result, final String propertiesName, final T propValue, final Map props); public void verifyConsistency(final Map.Entry, ?> typeDef) { if (required == null ) { diff --git a/src/main/java/net/hostsharing/hsadminng/hs/validation/IntegerPropertyValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/validation/IntegerPropertyValidator.java index d0727dd4..d6fb85f5 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/validation/IntegerPropertyValidator.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/validation/IntegerPropertyValidator.java @@ -23,15 +23,15 @@ public class IntegerPropertyValidator extends HsPropertyValidator { @Override - protected void validate(final ArrayList result, final Integer propValue, final Map props) { + protected void validate(final ArrayList result, final String propertiesName, final Integer propValue, final Map props) { if (min != null && propValue < min) { - result.add("'config." + propertyName + "' is expected to be >= " + min + " but is " + propValue); + result.add("'"+propertiesName+"." + propertyName + "' is expected to be >= " + min + " but is " + propValue); } if (max != null && propValue > max) { - result.add("'config." + propertyName + "' is expected to be <= " + max + " but is " + propValue); + result.add("'"+propertiesName+"." + propertyName + "' is expected to be <= " + max + " but is " + propValue); } if (step != null && propValue % step != 0) { - result.add("'config." + propertyName + "' is expected to be multiple of " + step + " but is " + propValue); + result.add("'"+propertiesName+"." + propertyName + "' is expected to be multiple of " + step + " but is " + propValue); } } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/validation/Validatable.java b/src/main/java/net/hostsharing/hsadminng/hs/validation/Validatable.java index 09cf4388..6f214b04 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/validation/Validatable.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/validation/Validatable.java @@ -5,7 +5,9 @@ import java.util.Map; public interface Validatable> { - Map getProperties(); Enum getType(); + + String getPropertiesName(); + Map getProperties(); } diff --git a/src/main/resources/db/changelog/6-hs-booking/601-booking-item/6018-hs-booking-item-test-data.sql b/src/main/resources/db/changelog/6-hs-booking/601-booking-item/6018-hs-booking-item-test-data.sql index 21300070..88ada16f 100644 --- a/src/main/resources/db/changelog/6-hs-booking/601-booking-item/6018-hs-booking-item-test-data.sql +++ b/src/main/resources/db/changelog/6-hs-booking/601-booking-item/6018-hs-booking-item-test-data.sql @@ -32,9 +32,9 @@ begin raise notice '- using debitor (%): %', relatedDebitor.uuid, relatedDebitor; insert into hs_booking_item (uuid, debitoruuid, type, caption, validity, resources) - values (uuid_generate_v4(), relatedDebitor.uuid, 'MANAGED_SERVER', 'some ManagedServer', daterange('20221001', null, '[]'), '{ "CPU": 2, "SDD": 512, "extra": 42 }'::jsonb), - (uuid_generate_v4(), relatedDebitor.uuid, 'CLOUD_SERVER', 'some CloudServer', daterange('20230115', '20240415', '[)'), '{ "CPU": 2, "HDD": 1024, "extra": 42 }'::jsonb), - (uuid_generate_v4(), relatedDebitor.uuid, 'PRIVATE_CLOUD', 'some PrivateCloud', daterange('20240401', null, '[]'), '{ "CPU": 10, "SDD": 10240, "HDD": 10240, "extra": 42 }'::jsonb); + values (uuid_generate_v4(), relatedDebitor.uuid, 'MANAGED_SERVER', 'some ManagedServer', daterange('20221001', null, '[]'), '{ "CPUs": 2, "RAM": 8, "SDD": 512, "Traffic": 42 }'::jsonb), + (uuid_generate_v4(), relatedDebitor.uuid, 'CLOUD_SERVER', 'some CloudServer', daterange('20230115', '20240415', '[)'), '{ "CPUs": 2, "RAM": 4, "HDD": 1024, "Traffic": 42 }'::jsonb), + (uuid_generate_v4(), relatedDebitor.uuid, 'PRIVATE_CLOUD', 'some PrivateCloud', daterange('20240401', null, '[]'), '{ "CPUs": 10, "SDD": 10240, "HDD": 10240, "Traffic": 42 }'::jsonb); end; $$; --// 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 496bea15..e8bcbc05 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 @@ -44,10 +44,10 @@ begin raise notice 'creating test hosting-asset: %', givenPartnerNumber::text || givenDebitorSuffix::text; raise notice '- using debitor (%): %', relatedDebitor.uuid, relatedDebitor; insert into hs_hosting_asset - (uuid, bookingitemuuid, type, parentAssetUuid, identifier, caption, config) + (uuid, bookingitemuuid, type, parentAssetUuid, identifier, caption, config) values (managedServerUuid, relatedPrivateCloudBookingItem.uuid, 'MANAGED_SERVER', null, 'vm10' || givenDebitorSuffix, 'some ManagedServer', '{ "CPU": 2, "SDD": 512, "extra": 42 }'::jsonb), - (uuid_generate_v4(), relatedPrivateCloudBookingItem.uuid, 'CLOUD_SERVER', null, 'vm20' || givenDebitorSuffix, 'another CloudServer', '{ "CPU": 2, "HDD": 1024, "extra": 42 }'::jsonb), - (uuid_generate_v4(), relatedManagedServerBookingItem.uuid, 'MANAGED_WEBSPACE', managedServerUuid, givenWebspacePrefix || '01', 'some Webspace', '{ "RAM": 1, "SDD": 512, "HDD": 2048, "extra": 42 }'::jsonb); + (uuid_generate_v4(), relatedPrivateCloudBookingItem.uuid, 'CLOUD_SERVER', null, 'vm20' || givenDebitorSuffix, 'another CloudServer', '{ "CPU": 2, "HDD": 1024, "extra": 42 }'::jsonb), + (uuid_generate_v4(), relatedManagedServerBookingItem.uuid, 'MANAGED_WEBSPACE', managedServerUuid, givenWebspacePrefix || '01', 'some Webspace', '{ "RAM": 1, "SDD": 512, "HDD": 2048, "extra": 42 }'::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 e29a93e1..0a92ff3f 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 @@ -21,6 +21,7 @@ import java.util.Map; import java.util.UUID; import static java.util.Map.entry; +import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.MANAGED_WEBSPACE; import static net.hostsharing.hsadminng.rbac.test.JsonMatcher.lenientlyEquals; import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.Matchers.matchesRegex; @@ -69,37 +70,42 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup .body("", lenientlyEquals(""" [ { - "caption": "some ManagedServer", - "validFrom": "2022-10-01", - "validTo": null, - "resources": { - "CPU": 2, - "SDD": 512, - "extra": 42 - } - }, - { - "caption": "some CloudServer", - "validFrom": "2023-01-15", - "validTo": "2024-04-14", - "resources": { - "CPU": 2, - "HDD": 1024, - "extra": 42 - } - }, - { - "caption": "some PrivateCloud", - "validFrom": "2024-04-01", - "validTo": null, - "resources": { - "CPU": 10, - "HDD": 10240, - "SDD": 10240, - "extra": 42 - } - } - ] + "type": "MANAGED_SERVER", + "caption": "some ManagedServer", + "validFrom": "2022-10-01", + "validTo": null, + "resources": { + "RAM": 8, + "SDD": 512, + "CPUs": 2, + "Traffic": 42 + } + }, + { + "type": "CLOUD_SERVER", + "caption": "some CloudServer", + "validFrom": "2023-01-15", + "validTo": "2024-04-14", + "resources": { + "HDD": 1024, + "RAM": 4, + "CPUs": 2, + "Traffic": 42 + } + }, + { + "type": "PRIVATE_CLOUD", + "caption": "some PrivateCloud", + "validFrom": "2024-04-01", + "validTo": null, + "resources": { + "HDD": 10240, + "SDD": 10240, + "CPUs": 10, + "Traffic": 42 + } + } + ] """)); // @formatter:on } @@ -123,7 +129,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup "debitorUuid": "%s", "type": "MANAGED_SERVER", "caption": "some new booking", - "resources": { "CPU": 12, "extra": 42 }, + "resources": { "CPUs": 12, "RAM": 4, "SSD": 100, "Traffic": 250 }, "validFrom": "2022-10-13" } """.formatted(givenDebitor.getUuid())) @@ -139,7 +145,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup "caption": "some new booking", "validFrom": "2022-10-13", "validTo": null, - "resources": { "CPU": 12 } + "resources": { "CPUs": 12, "SSD": 100, "Traffic": 250 } } """)) .header("Location", matchesRegex("http://localhost:[1-9][0-9]*/api/hs/booking/items/[^/]*")) @@ -177,7 +183,12 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup "caption": "some CloudServer", "validFrom": "2023-01-15", "validTo": "2024-04-14", - "resources": { CPU: 2, HDD: 1024 } + "resources": { + "HDD": 1024, + "RAM": 4, + "CPUs": 2, + "Traffic": 42 + } } """)); // @formatter:on } @@ -222,7 +233,12 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup "caption": "some CloudServer", "validFrom": "2023-01-15", "validTo": "2024-04-14", - "resources": { CPU: 2, HDD: 1024 } + "resources": { + "HDD": 1024, + "RAM": 4, + "CPUs": 2, + "Traffic": 42 + } } """)); // @formatter:on } @@ -234,7 +250,8 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup @Test void globalAdmin_canPatchAllUpdatablePropertiesOfBookingItem() { - final var givenBookingItem = givenSomeTemporaryBookingItemForDebitorNumber(1000111, entry("something", 1)); + final var givenBookingItem = givenSomeBookingItem(1000111, MANAGED_WEBSPACE, + resource("HDD", 100), resource("SSD", 50), resource("Traffic", 250)); RestAssured // @formatter:off .given() @@ -245,9 +262,9 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup "validFrom": "2020-06-05", "validTo": "2022-12-31", "resources": { - "CPU": "4", + "Traffic": 500, "HDD": null, - "SSD": "4096" + "SSD": 100 } } """) @@ -263,9 +280,8 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup "validFrom": "2022-11-01", "validTo": "2022-12-31", "resources": { - "CPU": "4", - "SSD": "4096", - "something": 1 + "Traffic": 500, + "SSD": 100 } } """)); // @formatter:on @@ -288,7 +304,8 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup @Test void globalAdmin_canDeleteArbitraryBookingItem() { context.define("superuser-alex@hostsharing.net"); - final var givenBookingItem = givenSomeTemporaryBookingItemForDebitorNumber(1000111, entry("something", 1)); + final var givenBookingItem = givenSomeBookingItem(1000111, MANAGED_WEBSPACE, + resource("HDD", 100), resource("SSD", 50), resource("Traffic", 250)); RestAssured // @formatter:off .given() @@ -306,7 +323,8 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup @Test void normalUser_canNotDeleteUnrelatedBookingItem() { context.define("superuser-alex@hostsharing.net"); - final var givenBookingItem = givenSomeTemporaryBookingItemForDebitorNumber(1000111, entry("something", 1)); + final var givenBookingItem = givenSomeBookingItem(1000111, MANAGED_WEBSPACE, + resource("HDD", 100), resource("SSD", 50), resource("Traffic", 250)); RestAssured // @formatter:off .given() @@ -322,15 +340,16 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup } } - private HsBookingItemEntity givenSomeTemporaryBookingItemForDebitorNumber(final int debitorNumber, - final Map.Entry resources) { + @SafeVarargs + private HsBookingItemEntity givenSomeBookingItem(final int debitorNumber, + final HsBookingItemType hsBookingItemType, final Map.Entry... resources) { return jpaAttempt.transacted(() -> { context.define("superuser-alex@hostsharing.net"); final var givenDebitor = debitorRepo.findDebitorByDebitorNumber(debitorNumber).get(0); final var newBookingItem = HsBookingItemEntity.builder() .uuid(UUID.randomUUID()) .debitor(givenDebitor) - .type(HsBookingItemType.MANAGED_WEBSPACE) + .type(hsBookingItemType) .caption("some test-booking") .resources(Map.ofEntries(resources)) .validity(Range.closedOpen( @@ -340,4 +359,8 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup return bookingItemRepo.save(newBookingItem); }).assertSuccessful().returnedValue(); } + + private Map.Entry resource(final String key, final Object value) { + return entry(key, value); + } } 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 05d9cbc0..c76d30df 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 @@ -167,9 +167,9 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup // then allTheseBookingItemsAreReturned( result, - "HsBookingItemEntity(D-1000212, MANAGED_SERVER, [2022-10-01,), some ManagedServer, { CPU: 2, SDD: 512, extra: 42 })", - "HsBookingItemEntity(D-1000212, CLOUD_SERVER, [2023-01-15,2024-04-15), some CloudServer, { CPU: 2, HDD: 1024, extra: 42 })", - "HsBookingItemEntity(D-1000212, PRIVATE_CLOUD, [2024-04-01,), some PrivateCloud, { CPU: 10, HDD: 10240, SDD: 10240, extra: 42 })"); + "HsBookingItemEntity(D-1000212, MANAGED_SERVER, [2022-10-01,), some ManagedServer, { CPUs: 2, RAM: 8, SDD: 512, Traffic: 42 })", + "HsBookingItemEntity(D-1000212, CLOUD_SERVER, [2023-01-15,2024-04-15), some CloudServer, { CPUs: 2, HDD: 1024, RAM: 4, Traffic: 42 })", + "HsBookingItemEntity(D-1000212, PRIVATE_CLOUD, [2024-04-01,), some PrivateCloud, { CPUs: 10, HDD: 10240, SDD: 10240, Traffic: 42 })"); } @Test @@ -184,9 +184,9 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup // then: exactlyTheseBookingItemsAreReturned( result, - "HsBookingItemEntity(D-1000111, MANAGED_SERVER, [2022-10-01,), some ManagedServer, { CPU: 2, SDD: 512, extra: 42 })", - "HsBookingItemEntity(D-1000111, CLOUD_SERVER, [2023-01-15,2024-04-15), some CloudServer, { CPU: 2, HDD: 1024, extra: 42 })", - "HsBookingItemEntity(D-1000111, PRIVATE_CLOUD, [2024-04-01,), some PrivateCloud, { CPU: 10, HDD: 10240, SDD: 10240, extra: 42 })"); + "HsBookingItemEntity(D-1000111, MANAGED_SERVER, [2022-10-01,), some ManagedServer, { CPUs: 2, RAM: 8, SDD: 512, Traffic: 42 })", + "HsBookingItemEntity(D-1000111, CLOUD_SERVER, [2023-01-15,2024-04-15), some CloudServer, { CPUs: 2, HDD: 1024, RAM: 4, Traffic: 42 })", + "HsBookingItemEntity(D-1000111, PRIVATE_CLOUD, [2024-04-01,), some PrivateCloud, { CPUs: 10, HDD: 10240, SDD: 10240, Traffic: 42 })"); } } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsManagedServerBookingItemValidatorUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsManagedServerBookingItemValidatorUnitTest.java new file mode 100644 index 00000000..7f51b271 --- /dev/null +++ b/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsManagedServerBookingItemValidatorUnitTest.java @@ -0,0 +1,34 @@ +package net.hostsharing.hsadminng.hs.booking.item; + +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static java.util.Map.entry; +import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.MANAGED_SERVER; +import static org.assertj.core.api.Assertions.assertThat; + +class HsManagedServerBookingItemValidatorUnitTest { + + @Test + void validatesDependentProperties() { + // given + final var validator = HsBookingItemEntityValidators.forType(MANAGED_SERVER); + final var mangedWebspaceBookingItemEntity = HsBookingItemEntity.builder() + .type(MANAGED_SERVER) + .resources(Map.ofEntries( + entry("CPUs", 2), + entry("RAM", 25), + entry("SSD", 25), + entry("Traffic", 250), + entry("SLA-EMail", true) + )) + .build(); + + // when + final var result = validator.validate(mangedWebspaceBookingItemEntity); + + // then + assertThat(result).containsExactly("'resources.SLA-EMail' is expected to be false because resources.SLA-Platform=BASIC but is true"); + } +} 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 94c4ceae..f3eb66ee 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 @@ -19,6 +19,7 @@ import java.util.Map; import java.util.UUID; 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.MANAGED_SERVER; import static net.hostsharing.hsadminng.rbac.test.JsonMatcher.lenientlyEquals; import static org.assertj.core.api.Assertions.assertThat; @@ -271,7 +272,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup .body("", lenientlyEquals(""" { "statusPhrase": "Bad Request", - "message": "['config.extra' is not expected but is '42', 'config.CPUs' is expected to be >= 1 but is 0, 'config.RAM' is required but missing, 'config.SSD' is required but missing, 'config.Traffic' is required but missing]" + "message": "['config.extra' is not expected but is set to '42', 'config.CPUs' is expected to be >= 1 but is 0, 'config.RAM' is required but missing, 'config.SSD' is required but missing, 'config.Traffic' is required but missing]" } """)); // @formatter:on } @@ -364,7 +365,8 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup @Test void globalAdmin_canPatchAllUpdatablePropertiesOfAsset() { - final var givenAsset = givenSomeTemporaryAssetForDebitorNumber("2001", entry("something", 1)); + final var givenAsset = givenSomeTemporaryHostingAsset("2001", CLOUD_SERVER, + config("CPUs", 4), config("RAM", 100), config("HDD", 100), config("Traffic", 2000)); RestAssured // @formatter:off .given() @@ -373,9 +375,9 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup .body(""" { "config": { - "CPU": "4", + "CPUs": 2, "HDD": null, - "SSD": "4096" + "SSD": 250 } } """) @@ -391,9 +393,9 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup "identifier": "vm2001", "caption": "some test-asset", "config": { - "CPU": "4", - "SSD": "4096", - "something": 1 + "CPUs": 2, + "RAM": 100, + "SSD": 250 } } """)); // @formatter:on @@ -402,7 +404,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup context.define("superuser-alex@hostsharing.net"); assertThat(assetRepo.findByUuid(givenAsset.getUuid())).isPresent().get() .matches(asset -> { - assertThat(asset.toString()).isEqualTo("HsHostingAssetEntity(CLOUD_SERVER, vm2001, some test-asset, D-1000111:some CloudServer, { CPU: 4, SSD: 4096, something: 1 })"); + assertThat(asset.toString()).isEqualTo("HsHostingAssetEntity(CLOUD_SERVER, vm2001, some test-asset, D-1000111:some CloudServer, { CPUs: 2, RAM: 100, SSD: 250, Traffic: 2000 })"); return true; }); } @@ -414,7 +416,8 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup @Test void globalAdmin_canDeleteArbitraryAsset() { context.define("superuser-alex@hostsharing.net"); - final var givenAsset = givenSomeTemporaryAssetForDebitorNumber("2002", entry("something", 1)); + final var givenAsset = givenSomeTemporaryHostingAsset("2002", CLOUD_SERVER, + config("CPUs", 4), config("RAM", 100), config("HDD", 100), config("Traffic", 2000)); RestAssured // @formatter:off .given() @@ -432,7 +435,8 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup @Test void normalUser_canNotDeleteUnrelatedAsset() { context.define("superuser-alex@hostsharing.net"); - final var givenAsset = givenSomeTemporaryAssetForDebitorNumber("2003", entry("something", 1)); + final var givenAsset = givenSomeTemporaryHostingAsset("2003", CLOUD_SERVER, + config("CPUs", 4), config("RAM", 100), config("HDD", 100), config("Traffic", 2000)); RestAssured // @formatter:off .given() @@ -461,14 +465,16 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup return givenAsset; } - private HsHostingAssetEntity givenSomeTemporaryAssetForDebitorNumber(final String identifierSuffix, - final Map.Entry resources) { + @SafeVarargs + private HsHostingAssetEntity givenSomeTemporaryHostingAsset(final String identifierSuffix, + final HsHostingAssetType hostingAssetType, + final Map.Entry... resources) { return jpaAttempt.transacted(() -> { context.define("superuser-alex@hostsharing.net"); final var newAsset = HsHostingAssetEntity.builder() .uuid(UUID.randomUUID()) .bookingItem(givenBookingItem("First", "some CloudServer")) - .type(HsHostingAssetType.CLOUD_SERVER) + .type(hostingAssetType) .identifier("vm" + identifierSuffix) .caption("some test-asset") .config(Map.ofEntries(resources)) @@ -477,4 +483,8 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup return assetRepo.save(newAsset); }).assertSuccessful().returnedValue(); } + + private Map.Entry config(final String key, final Object value) { + return entry(key, value); + } } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetPropsControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetPropsControllerAcceptanceTest.java index 58c7bf91..e6cc9acd 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetPropsControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetPropsControllerAcceptanceTest.java @@ -40,7 +40,7 @@ class HsHostingAssetPropsControllerAcceptanceTest { } @Test - void globalAdmin_canListPropertiesOfGivenAssetType() { + void anyone_canListPropertiesOfGivenAssetType() { RestAssured // @formatter:off .given() @@ -52,101 +52,50 @@ class HsHostingAssetPropsControllerAcceptanceTest { .contentType("application/json") .body("", lenientlyEquals(""" [ - { - "type": "integer", - "propertyName": "CPUs", - "required": true, - "unit": null, - "min": 1, - "max": 32, - "step": null - }, - { - "type": "integer", - "propertyName": "RAM", - "required": true, - "unit": "GB", - "min": 1, - "max": 128, - "step": null - }, - { - "type": "integer", - "propertyName": "SSD", - "required": true, - "unit": "GB", - "min": 25, - "max": 1000, - "step": 25 - }, - { - "type": "integer", - "propertyName": "HDD", - "required": false, - "unit": "GB", - "min": 0, - "max": 4000, - "step": 250 - }, - { - "type": "integer", - "propertyName": "Traffic", - "required": true, - "unit": "GB", - "min": 250, - "max": 10000, - "step": 250 - }, - { - "type": "enumeration", - "propertyName": "SLA-Platform", - "required": false, - "values": [ - "BASIC", - "EXT8H", - "EXT4H", - "EXT2H" - ] - }, - { - "type": "boolean", - "propertyName": "SLA-EMail", - "required": false, - "falseIf": { - "SLA-Platform": "BASIC" - } - }, - { - "type": "boolean", - "propertyName": "SLA-Maria", - "required": false, - "falseIf": { - "SLA-Platform": "BASIC" - } - }, - { - "type": "boolean", - "propertyName": "SLA-PgSQL", - "required": false, - "falseIf": { - "SLA-Platform": "BASIC" - } - }, - { - "type": "boolean", - "propertyName": "SLA-Office", - "required": false, - "falseIf": { - "SLA-Platform": "BASIC" - } - }, - { - "type": "boolean", - "propertyName": "SLA-Web", - "required": false, - "falseIf": { - "SLA-Platform": "BASIC" - } + { + "type": "integer", + "propertyName": "CPUs", + "required": true, + "unit": null, + "min": 1, + "max": 32, + "step": null + }, + { + "type": "integer", + "propertyName": "RAM", + "required": true, + "unit": "GB", + "min": 1, + "max": 128, + "step": null + }, + { + "type": "integer", + "propertyName": "SSD", + "required": true, + "unit": "GB", + "min": 25, + "max": 1000, + "step": 25 + }, + { + "type": "integer", + "propertyName": "HDD", + "required": false, + "unit": "GB", + "min": 0, + "max": 4000, + "step": 250 + }, + { + "type": "integer", + "propertyName": "Traffic", + "required": true, + "unit": "GB", + "min": 250, + "max": 10000, + "step": 250 } ] """)); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsEntityValidatorUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedServerHostingAssetValidatorUnitTest.java similarity index 50% rename from src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsEntityValidatorUnitTest.java rename to src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedServerHostingAssetValidatorUnitTest.java index 66e3f16d..eef3afb1 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsEntityValidatorUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedServerHostingAssetValidatorUnitTest.java @@ -8,20 +8,19 @@ import static java.util.Map.entry; import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_SERVER; import static org.assertj.core.api.Assertions.assertThat; -class HsManagedServerValidatorUnitTest { +class HsManagedServerHostingAssetValidatorUnitTest { @Test - void validatesDependentProperties() { + void validatesProperties() { // given final var validator = HsHostingAssetEntityValidators.forType(MANAGED_SERVER); final var mangedWebspaceHostingAssetEntity = HsHostingAssetEntity.builder() .type(MANAGED_SERVER) .config(Map.ofEntries( - entry("CPUs", 2), - entry("RAM", 25), - entry("SSD", 25), - entry("Traffic", 250), - entry("SLA-EMail", true) + entry("RAM", 2000), + entry("SSD", 256), + entry("Traffic", "250"), + entry("SLA-Platform", "xxx") )) .build(); @@ -29,6 +28,11 @@ class HsManagedServerValidatorUnitTest { final var result = validator.validate(mangedWebspaceHostingAssetEntity); // then - assertThat(result).containsExactly("'config.SLA-EMail' is expected to be false because config.SLA-Platform=BASIC but is true"); + assertThat(result).containsExactlyInAnyOrder( + "'config.SLA-Platform' is not expected but is set to 'xxx'", + "'config.CPUs' is required but missing", + "'config.RAM' is expected to be <= 128 but is 2000", + "'config.SSD' is expected to be multiple of 25 but is 256", + "'config.Traffic' is expected to be of type class java.lang.Integer, but is of type 'String'"); } } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceAssetValidatorUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceHostingAssetValidatorUnitTest.java similarity index 96% rename from src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceAssetValidatorUnitTest.java rename to src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceHostingAssetValidatorUnitTest.java index 73873b24..4bb24a03 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceAssetValidatorUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceHostingAssetValidatorUnitTest.java @@ -12,11 +12,11 @@ import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANA import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_WEBSPACE; import static org.assertj.core.api.Assertions.assertThat; -class HsManagedWebspaceAssetValidatorUnitTest { +class HsManagedWebspaceHostingAssetValidatorUnitTest { // just to make sure the class is loaded static { - new HsManagedWebspaceAssetValidator(); + new HsManagedWebspaceHostingAssetValidator(); } final HsBookingItemEntity managedServerBookingItem = HsBookingItemEntity.builder() @@ -97,7 +97,7 @@ class HsManagedWebspaceAssetValidatorUnitTest { final var result = validator.validate(mangedWebspaceHostingAssetEntity); // then - assertThat(result).containsExactly("'config.unknown' is not expected but is 'some value'"); + assertThat(result).containsExactly("'config.unknown' is not expected but is set to 'some value'"); } @Test -- 2.39.5 From cbcef6d3547f8ebd335e9b371affb38960437512 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Fri, 10 May 2024 17:19:29 +0200 Subject: [PATCH 7/7] introduce validators package and add tests --- .../booking/item/HsBookingItemController.java | 2 +- .../HsBookingItemEntityValidators.java | 8 ++- .../HsCloudServerBookingItemValidator.java | 4 +- .../HsManagedServerBookingItemValidator.java | 4 +- ...HsManagedWebspaceBookingItemValidator.java | 4 +- .../asset/HsHostingAssetController.java | 2 +- .../asset/HsHostingAssetPropsController.java | 1 + .../HsCloudServerHostingAssetValidator.java | 4 +- .../HsHostingAssetEntityValidators.java | 10 ++-- .../HsManagedServerHostingAssetValidator.java | 4 +- ...sManagedWebspaceHostingAssetValidator.java | 4 +- ...gedServerBookingItemValidatorUnitTest.java | 34 ----------- ...HsBookingItemEntityValidatorsUnitTest.java | 44 +++++++++++++++ ...oudServerBookingItemValidatorUnitTest.java | 51 +++++++++++++++++ ...gedServerBookingItemValidatorUnitTest.java | 56 +++++++++++++++++++ ...dWebspaceBookingItemValidatorUnitTest.java | 54 ++++++++++++++++++ ...udServerHostingAssetValidatorUnitTest.java | 55 ++++++++++++++++++ ...sHostingAssetEntityValidatorsUnitTest.java | 33 +++++++++++ ...edServerHostingAssetValidatorUnitTest.java | 6 +- ...WebspaceHostingAssetValidatorUnitTest.java | 8 +-- 20 files changed, 331 insertions(+), 57 deletions(-) rename src/main/java/net/hostsharing/hsadminng/hs/booking/item/{ => validators}/HsBookingItemEntityValidators.java (83%) rename src/main/java/net/hostsharing/hsadminng/hs/booking/item/{ => validators}/HsCloudServerBookingItemValidator.java (82%) rename src/main/java/net/hostsharing/hsadminng/hs/booking/item/{ => validators}/HsManagedServerBookingItemValidator.java (88%) rename src/main/java/net/hostsharing/hsadminng/hs/booking/item/{ => validators}/HsManagedWebspaceBookingItemValidator.java (83%) rename src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/{ => validators}/HsCloudServerHostingAssetValidator.java (79%) rename src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/{ => validators}/HsHostingAssetEntityValidators.java (78%) rename src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/{ => validators}/HsManagedServerHostingAssetValidator.java (79%) rename src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/{ => validators}/HsManagedWebspaceHostingAssetValidator.java (87%) delete mode 100644 src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsManagedServerBookingItemValidatorUnitTest.java create mode 100644 src/test/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsBookingItemEntityValidatorsUnitTest.java create mode 100644 src/test/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsCloudServerBookingItemValidatorUnitTest.java create mode 100644 src/test/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsManagedServerBookingItemValidatorUnitTest.java create mode 100644 src/test/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsManagedWebspaceBookingItemValidatorUnitTest.java create mode 100644 src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsCloudServerHostingAssetValidatorUnitTest.java create mode 100644 src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsHostingAssetEntityValidatorsUnitTest.java rename src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/{ => validators}/HsManagedServerHostingAssetValidatorUnitTest.java (80%) rename src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/{ => validators}/HsManagedWebspaceHostingAssetValidatorUnitTest.java (96%) diff --git a/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemController.java b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemController.java index b278e817..e3154f76 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemController.java @@ -17,7 +17,7 @@ import java.util.List; import java.util.UUID; import java.util.function.BiConsumer; -import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntityValidators.valid; +import static net.hostsharing.hsadminng.hs.booking.item.validators.HsBookingItemEntityValidators.valid; import static net.hostsharing.hsadminng.mapper.PostgresDateRange.toPostgresDateRange; @RestController diff --git a/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemEntityValidators.java b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsBookingItemEntityValidators.java similarity index 83% rename from src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemEntityValidators.java rename to src/main/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsBookingItemEntityValidators.java index c85430bd..1f4493e2 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemEntityValidators.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsBookingItemEntityValidators.java @@ -1,6 +1,8 @@ -package net.hostsharing.hsadminng.hs.booking.item; +package net.hostsharing.hsadminng.hs.booking.item.validators; import lombok.experimental.UtilityClass; +import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity; +import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType; import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; import jakarta.validation.ValidationException; @@ -34,11 +36,11 @@ public class HsBookingItemEntityValidators { return validators.get(type); } - public static Set> types() { + public static Set> types() { return validators.keySet(); } - static HsBookingItemEntity valid(final HsBookingItemEntity entityToSave) { + public static HsBookingItemEntity valid(final HsBookingItemEntity entityToSave) { final var violations = HsBookingItemEntityValidators.forType(entityToSave.getType()).validate(entityToSave); if (!violations.isEmpty()) { throw new ValidationException(violations.toString()); diff --git a/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsCloudServerBookingItemValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsCloudServerBookingItemValidator.java similarity index 82% rename from src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsCloudServerBookingItemValidator.java rename to src/main/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsCloudServerBookingItemValidator.java index 521e9a0a..fa09f2c3 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsCloudServerBookingItemValidator.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsCloudServerBookingItemValidator.java @@ -1,5 +1,7 @@ -package net.hostsharing.hsadminng.hs.booking.item; +package net.hostsharing.hsadminng.hs.booking.item.validators; +import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity; +import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType; import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; import static net.hostsharing.hsadminng.hs.validation.EnumerationPropertyValidator.enumerationProperty; diff --git a/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsManagedServerBookingItemValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsManagedServerBookingItemValidator.java similarity index 88% rename from src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsManagedServerBookingItemValidator.java rename to src/main/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsManagedServerBookingItemValidator.java index ca00edc8..79c41070 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsManagedServerBookingItemValidator.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsManagedServerBookingItemValidator.java @@ -1,5 +1,7 @@ -package net.hostsharing.hsadminng.hs.booking.item; +package net.hostsharing.hsadminng.hs.booking.item.validators; +import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity; +import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType; import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; import static net.hostsharing.hsadminng.hs.validation.BooleanPropertyValidator.booleanProperty; diff --git a/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsManagedWebspaceBookingItemValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsManagedWebspaceBookingItemValidator.java similarity index 83% rename from src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsManagedWebspaceBookingItemValidator.java rename to src/main/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsManagedWebspaceBookingItemValidator.java index b6dbaf82..482d0900 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/booking/item/HsManagedWebspaceBookingItemValidator.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsManagedWebspaceBookingItemValidator.java @@ -1,5 +1,7 @@ -package net.hostsharing.hsadminng.hs.booking.item; +package net.hostsharing.hsadminng.hs.booking.item.validators; +import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity; +import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType; import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetController.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetController.java index 04221a8a..57e91ec5 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetController.java @@ -20,7 +20,7 @@ import java.util.List; import java.util.UUID; import java.util.function.BiConsumer; -import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntityValidators.valid; +import static net.hostsharing.hsadminng.hs.hosting.asset.validators.HsHostingAssetEntityValidators.valid; @RestController public class HsHostingAssetController implements HsHostingAssetsApi { diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetPropsController.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetPropsController.java index 1ef68798..47852310 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetPropsController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetPropsController.java @@ -1,5 +1,6 @@ package net.hostsharing.hsadminng.hs.hosting.asset; +import net.hostsharing.hsadminng.hs.hosting.asset.validators.HsHostingAssetEntityValidators; import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.api.HsHostingAssetPropsApi; import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.model.HsHostingAssetTypeResource; import org.springframework.http.ResponseEntity; diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsCloudServerHostingAssetValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsCloudServerHostingAssetValidator.java similarity index 79% rename from src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsCloudServerHostingAssetValidator.java rename to src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsCloudServerHostingAssetValidator.java index 8124df34..8c43dd43 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsCloudServerHostingAssetValidator.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsCloudServerHostingAssetValidator.java @@ -1,5 +1,7 @@ -package net.hostsharing.hsadminng.hs.hosting.asset; +package net.hostsharing.hsadminng.hs.hosting.asset.validators; +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType; import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; import static net.hostsharing.hsadminng.hs.validation.IntegerPropertyValidator.integerProperty; diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntityValidators.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsHostingAssetEntityValidators.java similarity index 78% rename from src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntityValidators.java rename to src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsHostingAssetEntityValidators.java index cd8157d1..c4eaef0f 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetEntityValidators.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsHostingAssetEntityValidators.java @@ -1,6 +1,8 @@ -package net.hostsharing.hsadminng.hs.hosting.asset; +package net.hostsharing.hsadminng.hs.hosting.asset.validators; import lombok.experimental.UtilityClass; +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType; import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; import jakarta.validation.ValidationException; @@ -30,16 +32,16 @@ public class HsHostingAssetEntityValidators { validators.put(type, validator); } - static HsEntityValidator forType(final Enum type) { + public static HsEntityValidator forType(final Enum type) { return validators.get(type); } - static Set> types() { + public static Set> types() { return validators.keySet(); } - static HsHostingAssetEntity valid(final HsHostingAssetEntity entityToSave) { + public static HsHostingAssetEntity valid(final HsHostingAssetEntity entityToSave) { final var violations = HsHostingAssetEntityValidators.forType(entityToSave.getType()).validate(entityToSave); if (!violations.isEmpty()) { throw new ValidationException(violations.toString()); diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedServerHostingAssetValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsManagedServerHostingAssetValidator.java similarity index 79% rename from src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedServerHostingAssetValidator.java rename to src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsManagedServerHostingAssetValidator.java index ce739a2f..aee10839 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedServerHostingAssetValidator.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsManagedServerHostingAssetValidator.java @@ -1,5 +1,7 @@ -package net.hostsharing.hsadminng.hs.hosting.asset; +package net.hostsharing.hsadminng.hs.hosting.asset.validators; +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType; import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; import static net.hostsharing.hsadminng.hs.validation.IntegerPropertyValidator.integerProperty; diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceHostingAssetValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsManagedWebspaceHostingAssetValidator.java similarity index 87% rename from src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceHostingAssetValidator.java rename to src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsManagedWebspaceHostingAssetValidator.java index 76ae29e9..452bb116 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceHostingAssetValidator.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsManagedWebspaceHostingAssetValidator.java @@ -1,5 +1,7 @@ -package net.hostsharing.hsadminng.hs.hosting.asset; +package net.hostsharing.hsadminng.hs.hosting.asset.validators; +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType; import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; import java.util.List; diff --git a/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsManagedServerBookingItemValidatorUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsManagedServerBookingItemValidatorUnitTest.java deleted file mode 100644 index 7f51b271..00000000 --- a/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsManagedServerBookingItemValidatorUnitTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package net.hostsharing.hsadminng.hs.booking.item; - -import org.junit.jupiter.api.Test; - -import java.util.Map; - -import static java.util.Map.entry; -import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.MANAGED_SERVER; -import static org.assertj.core.api.Assertions.assertThat; - -class HsManagedServerBookingItemValidatorUnitTest { - - @Test - void validatesDependentProperties() { - // given - final var validator = HsBookingItemEntityValidators.forType(MANAGED_SERVER); - final var mangedWebspaceBookingItemEntity = HsBookingItemEntity.builder() - .type(MANAGED_SERVER) - .resources(Map.ofEntries( - entry("CPUs", 2), - entry("RAM", 25), - entry("SSD", 25), - entry("Traffic", 250), - entry("SLA-EMail", true) - )) - .build(); - - // when - final var result = validator.validate(mangedWebspaceBookingItemEntity); - - // then - assertThat(result).containsExactly("'resources.SLA-EMail' is expected to be false because resources.SLA-Platform=BASIC but is true"); - } -} diff --git a/src/test/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsBookingItemEntityValidatorsUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsBookingItemEntityValidatorsUnitTest.java new file mode 100644 index 00000000..741d7c1e --- /dev/null +++ b/src/test/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsBookingItemEntityValidatorsUnitTest.java @@ -0,0 +1,44 @@ +package net.hostsharing.hsadminng.hs.booking.item.validators; + +import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity; +import org.junit.jupiter.api.Test; + +import jakarta.validation.ValidationException; + +import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.MANAGED_SERVER; +import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.MANAGED_WEBSPACE; +import static net.hostsharing.hsadminng.hs.booking.item.validators.HsBookingItemEntityValidators.valid; +import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.CLOUD_SERVER; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; + +class HsBookingItemEntityValidatorsUnitTest { + + @Test + void validThrowsException() { + // given + final var cloudServerBookingItemEntity = HsBookingItemEntity.builder() + .type(CLOUD_SERVER) + .build(); + + // when + final var result = catchThrowable( ()-> valid(cloudServerBookingItemEntity) ); + + // then + assertThat(result).isInstanceOf(ValidationException.class) + .hasMessageContaining( + "'resources.CPUs' is required but missing", + "'resources.RAM' is required but missing", + "'resources.SSD' is required but missing", + "'resources.Traffic' is required but missing"); + } + + @Test + void listsTypes() { + // when + final var result = HsBookingItemEntityValidators.types(); + + // then + assertThat(result).containsExactlyInAnyOrder(CLOUD_SERVER, MANAGED_SERVER, MANAGED_WEBSPACE); + } +} diff --git a/src/test/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsCloudServerBookingItemValidatorUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsCloudServerBookingItemValidatorUnitTest.java new file mode 100644 index 00000000..e15b95d7 --- /dev/null +++ b/src/test/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsCloudServerBookingItemValidatorUnitTest.java @@ -0,0 +1,51 @@ +package net.hostsharing.hsadminng.hs.booking.item.validators; + +import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static java.util.Map.entry; +import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.CLOUD_SERVER; +import static net.hostsharing.hsadminng.hs.booking.item.validators.HsBookingItemEntityValidators.forType; +import static org.assertj.core.api.Assertions.assertThat; + +class HsCloudServerBookingItemValidatorUnitTest { + + @Test + void validatesProperties() { + // given + final var validator = HsBookingItemEntityValidators.forType(CLOUD_SERVER); + final var cloudServerBookingItemEntity = HsBookingItemEntity.builder() + .type(CLOUD_SERVER) + .resources(Map.ofEntries( + entry("CPUs", 2), + entry("RAM", 25), + entry("SSD", 25), + entry("Traffic", 250), + entry("SLA-EMail", true) + )) + .build(); + + // when + final var result = validator.validate(cloudServerBookingItemEntity); + + // then + assertThat(result).containsExactly("'resources.SLA-EMail' is not expected but is set to 'true'"); + } + + @Test + void containsAllValidations() { + // when + final var validator = forType(CLOUD_SERVER); + + // then + assertThat(validator.properties()).map(Map::toString).containsExactlyInAnyOrder( + "{type=integer, propertyName=CPUs, required=true, unit=null, min=1, max=32, step=null}", + "{type=integer, propertyName=RAM, required=true, unit=GB, min=1, max=128, step=null}", + "{type=integer, propertyName=SSD, required=true, unit=GB, min=25, max=1000, step=25}", + "{type=integer, propertyName=HDD, required=false, unit=GB, min=0, max=4000, step=250}", + "{type=integer, propertyName=Traffic, required=true, unit=GB, min=250, max=10000, step=250}", + "{type=enumeration, propertyName=SLA-Infrastructure, required=false, values=[BASIC, EXT8H, EXT4H, EXT2H]}"); + } +} 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 new file mode 100644 index 00000000..5f2bdfc3 --- /dev/null +++ b/src/test/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsManagedServerBookingItemValidatorUnitTest.java @@ -0,0 +1,56 @@ +package net.hostsharing.hsadminng.hs.booking.item.validators; + +import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static java.util.Map.entry; +import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.MANAGED_SERVER; +import static net.hostsharing.hsadminng.hs.booking.item.validators.HsBookingItemEntityValidators.forType; +import static org.assertj.core.api.Assertions.assertThat; + +class HsManagedServerBookingItemValidatorUnitTest { + + @Test + void validatesProperties() { + // given + final var validator = HsBookingItemEntityValidators.forType(MANAGED_SERVER); + final var mangedServerBookingItemEntity = HsBookingItemEntity.builder() + .type(MANAGED_SERVER) + .resources(Map.ofEntries( + entry("CPUs", 2), + entry("RAM", 25), + entry("SSD", 25), + entry("Traffic", 250), + entry("SLA-EMail", true) + )) + .build(); + + // when + final var result = validator.validate(mangedServerBookingItemEntity); + + // then + assertThat(result).containsExactly("'resources.SLA-EMail' is expected to be false because resources.SLA-Platform=BASIC but is true"); + } + + @Test + void containsAllValidations() { + // when + final var validator = forType(MANAGED_SERVER); + + // then + assertThat(validator.properties()).map(Map::toString).containsExactlyInAnyOrder( + "{type=integer, propertyName=CPUs, required=true, unit=null, min=1, max=32, step=null}", + "{type=integer, propertyName=RAM, required=true, unit=GB, min=1, max=128, step=null}", + "{type=integer, propertyName=SSD, required=true, unit=GB, min=25, max=1000, step=25}", + "{type=integer, propertyName=HDD, required=false, unit=GB, min=0, max=4000, step=250}", + "{type=integer, propertyName=Traffic, required=true, unit=GB, min=250, max=10000, step=250}", + "{type=enumeration, propertyName=SLA-Platform, required=false, values=[BASIC, EXT8H, EXT4H, EXT2H]}", + "{type=boolean, propertyName=SLA-EMail, required=false, falseIf={SLA-Platform=BASIC}}", + "{type=boolean, propertyName=SLA-Maria, required=false, falseIf={SLA-Platform=BASIC}}", + "{type=boolean, propertyName=SLA-PgSQL, required=false, falseIf={SLA-Platform=BASIC}}", + "{type=boolean, propertyName=SLA-Office, required=false, falseIf={SLA-Platform=BASIC}}", + "{type=boolean, propertyName=SLA-Web, required=false, falseIf={SLA-Platform=BASIC}}"); + } +} diff --git a/src/test/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsManagedWebspaceBookingItemValidatorUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsManagedWebspaceBookingItemValidatorUnitTest.java new file mode 100644 index 00000000..8a278850 --- /dev/null +++ b/src/test/java/net/hostsharing/hsadminng/hs/booking/item/validators/HsManagedWebspaceBookingItemValidatorUnitTest.java @@ -0,0 +1,54 @@ +package net.hostsharing.hsadminng.hs.booking.item.validators; + +import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static java.util.Map.entry; +import static net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType.MANAGED_WEBSPACE; +import static net.hostsharing.hsadminng.hs.booking.item.validators.HsBookingItemEntityValidators.forType; +import static org.assertj.core.api.Assertions.assertThat; + +class HsManagedWebspaceBookingItemValidatorUnitTest { + + @Test + void validatesProperties() { + // given + final var mangedServerBookingItemEntity = HsBookingItemEntity.builder() + .type(MANAGED_WEBSPACE) + .resources(Map.ofEntries( + entry("CPUs", 2), + entry("RAM", 25), + entry("SSD", 25), + entry("Traffic", 250), + entry("SLA-EMail", true) + )) + .build(); + final var validator = forType(mangedServerBookingItemEntity.getType()); + + // when + final var result = validator.validate(mangedServerBookingItemEntity); + + // then + assertThat(result).containsExactlyInAnyOrder( + "'resources.CPUs' is not expected but is set to '2'", + "'resources.SLA-EMail' is not expected but is set to 'true'", + "'resources.RAM' is not expected but is set to '25'"); + } + + @Test + void containsAllValidations() { + // when + final var validator = forType(MANAGED_WEBSPACE); + + // then + assertThat(validator.properties()).map(Map::toString).containsExactlyInAnyOrder( + "{type=integer, propertyName=SSD, required=true, unit=GB, min=1, max=100, step=1}", + "{type=integer, propertyName=HDD, required=false, unit=GB, min=0, max=250, step=10}", + "{type=integer, propertyName=Traffic, required=true, unit=GB, min=10, max=1000, step=10}", + "{type=enumeration, propertyName=SLA-Platform, required=false, values=[BASIC, EXT24H]}", + "{type=integer, propertyName=Daemons, required=false, unit=null, min=0, max=10, step=null}", + "{type=boolean, propertyName=Online Office Server, required=false, falseIf=null}"); + } +} diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsCloudServerHostingAssetValidatorUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsCloudServerHostingAssetValidatorUnitTest.java new file mode 100644 index 00000000..ee77c565 --- /dev/null +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsCloudServerHostingAssetValidatorUnitTest.java @@ -0,0 +1,55 @@ +package net.hostsharing.hsadminng.hs.hosting.asset.validators; + +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; +import org.junit.jupiter.api.Test; + +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.validators.HsHostingAssetEntityValidators.forType; +import static org.assertj.core.api.Assertions.assertThat; + +class HsCloudServerHostingAssetValidatorUnitTest { + + @Test + void validatesProperties() { + // given + final var cloudServerHostingAssetEntity = HsHostingAssetEntity.builder() + .type(CLOUD_SERVER) + .config(Map.ofEntries( + entry("RAM", 2000), + entry("SSD", 256), + entry("Traffic", "250"), + entry("SLA-Platform", "xxx") + )) + .build(); + final var validator = forType(cloudServerHostingAssetEntity.getType()); + + + // when + final var result = validator.validate(cloudServerHostingAssetEntity); + + // then + assertThat(result).containsExactlyInAnyOrder( + "'config.SLA-Platform' is not expected but is set to 'xxx'", + "'config.CPUs' is required but missing", + "'config.RAM' is expected to be <= 128 but is 2000", + "'config.SSD' is expected to be multiple of 25 but is 256", + "'config.Traffic' is expected to be of type class java.lang.Integer, but is of type 'String'"); + } + + @Test + void containsAllValidations() { + // when + final var validator = forType(CLOUD_SERVER); + + // then + assertThat(validator.properties()).map(Map::toString).containsExactlyInAnyOrder( + "{type=integer, propertyName=CPUs, required=true, unit=null, min=1, max=32, step=null}", + "{type=integer, propertyName=RAM, required=true, unit=GB, min=1, max=128, step=null}", + "{type=integer, propertyName=SSD, required=true, unit=GB, min=25, max=1000, step=25}", + "{type=integer, propertyName=HDD, required=false, unit=GB, min=0, max=4000, step=250}", + "{type=integer, propertyName=Traffic, required=true, unit=GB, min=250, max=10000, step=250}"); + } +} diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsHostingAssetEntityValidatorsUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsHostingAssetEntityValidatorsUnitTest.java new file mode 100644 index 00000000..07eb7517 --- /dev/null +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsHostingAssetEntityValidatorsUnitTest.java @@ -0,0 +1,33 @@ +package net.hostsharing.hsadminng.hs.hosting.asset.validators; + +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; +import org.junit.jupiter.api.Test; + +import jakarta.validation.ValidationException; + +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.CLOUD_SERVER; +import static net.hostsharing.hsadminng.hs.hosting.asset.validators.HsHostingAssetEntityValidators.valid; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; + +class HsHostingAssetEntityValidatorsUnitTest { + + @Test + void validThrowsException() { + // given + final var cloudServerHostingAssetEntity = HsHostingAssetEntity.builder() + .type(CLOUD_SERVER) + .build(); + + // when + final var result = catchThrowable( ()-> valid(cloudServerHostingAssetEntity) ); + + // then + assertThat(result).isInstanceOf(ValidationException.class) + .hasMessageContaining( + "'config.CPUs' is required but missing", + "'config.RAM' is required but missing", + "'config.SSD' is required but missing", + "'config.Traffic' is required but missing"); + } +} diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedServerHostingAssetValidatorUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsManagedServerHostingAssetValidatorUnitTest.java similarity index 80% rename from src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedServerHostingAssetValidatorUnitTest.java rename to src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsManagedServerHostingAssetValidatorUnitTest.java index eef3afb1..a9ee1433 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedServerHostingAssetValidatorUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsManagedServerHostingAssetValidatorUnitTest.java @@ -1,11 +1,13 @@ -package net.hostsharing.hsadminng.hs.hosting.asset; +package net.hostsharing.hsadminng.hs.hosting.asset.validators; +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; import org.junit.jupiter.api.Test; import java.util.Map; import static java.util.Map.entry; import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_SERVER; +import static net.hostsharing.hsadminng.hs.hosting.asset.validators.HsHostingAssetEntityValidators.forType; import static org.assertj.core.api.Assertions.assertThat; class HsManagedServerHostingAssetValidatorUnitTest { @@ -13,7 +15,6 @@ class HsManagedServerHostingAssetValidatorUnitTest { @Test void validatesProperties() { // given - final var validator = HsHostingAssetEntityValidators.forType(MANAGED_SERVER); final var mangedWebspaceHostingAssetEntity = HsHostingAssetEntity.builder() .type(MANAGED_SERVER) .config(Map.ofEntries( @@ -23,6 +24,7 @@ class HsManagedServerHostingAssetValidatorUnitTest { entry("SLA-Platform", "xxx") )) .build(); + final var validator = forType(mangedWebspaceHostingAssetEntity.getType()); // when final var result = validator.validate(mangedWebspaceHostingAssetEntity); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceHostingAssetValidatorUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsManagedWebspaceHostingAssetValidatorUnitTest.java similarity index 96% rename from src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceHostingAssetValidatorUnitTest.java rename to src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsManagedWebspaceHostingAssetValidatorUnitTest.java index 4bb24a03..e0397036 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsManagedWebspaceHostingAssetValidatorUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsManagedWebspaceHostingAssetValidatorUnitTest.java @@ -1,6 +1,7 @@ -package net.hostsharing.hsadminng.hs.hosting.asset; +package net.hostsharing.hsadminng.hs.hosting.asset.validators; import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity; +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity; import org.junit.jupiter.api.Test; @@ -14,11 +15,6 @@ import static org.assertj.core.api.Assertions.assertThat; class HsManagedWebspaceHostingAssetValidatorUnitTest { - // just to make sure the class is loaded - static { - new HsManagedWebspaceHostingAssetValidator(); - } - final HsBookingItemEntity managedServerBookingItem = HsBookingItemEntity.builder() .debitor(HsOfficeDebitorEntity.builder().defaultPrefix("abc").build() ) -- 2.39.5