add UnixUser HostingAsset property validation config
This commit is contained in:
parent
de88f1d842
commit
cf6bcc0b94
@ -47,7 +47,7 @@ public abstract class HsHostingAssetEntityValidator extends HsEntityValidator<Hs
|
||||
@Override
|
||||
public List<String> validate(final HsHostingAssetEntity assetEntity) {
|
||||
return sequentiallyValidate(
|
||||
() -> validateEntityReferences(assetEntity),
|
||||
() -> validateEntityReferencesAndProperties(assetEntity),
|
||||
() -> validateIdentifierPattern(assetEntity), // might need proper parentAsset or billingItem
|
||||
() -> optionallyValidate(assetEntity.getBookingItem()),
|
||||
() -> optionallyValidate(assetEntity.getParentAsset()),
|
||||
@ -55,7 +55,7 @@ public abstract class HsHostingAssetEntityValidator extends HsEntityValidator<Hs
|
||||
);
|
||||
}
|
||||
|
||||
private List<String> validateEntityReferences(final HsHostingAssetEntity assetEntity) {
|
||||
private List<String> validateEntityReferencesAndProperties(final HsHostingAssetEntity assetEntity) {
|
||||
return Stream.of(
|
||||
validateReferencedEntity(assetEntity, "bookingItem", bookingItemValidation::validate),
|
||||
validateReferencedEntity(assetEntity, "parentAsset", parentAssetValidation::validate),
|
||||
|
@ -5,14 +5,28 @@ import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static net.hostsharing.hsadminng.hs.validation.EnumerationProperty.enumerationProperty;
|
||||
import static net.hostsharing.hsadminng.hs.validation.IntegerProperty.integerProperty;
|
||||
import static net.hostsharing.hsadminng.hs.validation.StringProperty.stringProperty;
|
||||
|
||||
class HsUnixUserHostingAssetValidator extends HsHostingAssetEntityValidator {
|
||||
|
||||
HsUnixUserHostingAssetValidator() {
|
||||
super( BookingItem.mustBeNull(),
|
||||
ParentAsset.mustBeOfType(HsHostingAssetType.MANAGED_WEBSPACE),
|
||||
AssignedToAsset.mustBeNull(),
|
||||
AlarmContact.isOptional(), // TODO.spec: for quota notifications
|
||||
NO_EXTRA_PROPERTIES); // TODO.spec: yet to be specified
|
||||
AlarmContact.isOptional(),
|
||||
|
||||
integerProperty("SSD hard quota").unit("GB").maxFrom("SSD").optional(),
|
||||
integerProperty("SSD soft quota").unit("GB").minFrom("SSD hard quota").optional(),
|
||||
integerProperty("HDD hard quota").unit("GB").maxFrom("HDD").optional(),
|
||||
integerProperty("HDD soft quota").unit("GB").minFrom("HDD hard quota").optional(),
|
||||
enumerationProperty("shell")
|
||||
.values("/bin/false", "/bin/bash", "/bin/csh", "/bin/dash", "/usr/bin/tcsh", "/usr/bin/zsh", "/usr/bin/passwd")
|
||||
.withDefault("/bin/false"),
|
||||
stringProperty("homedir").readOnly(),
|
||||
stringProperty("totpKey").matchesRegEx("^0x\\([0-9A-Fa-f][0-9A-Fa-f]\\)+$").minLength(12).maxLength(32).writeOnly().optional(),
|
||||
stringProperty("password").minLength(8).maxLength(40).writeOnly()); // FIXME: spec
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -35,7 +35,7 @@ public class EnumerationProperty extends ValidatableProperty<String> {
|
||||
public void deferredInit(final ValidatableProperty<?>[] allProperties) {
|
||||
if (deferredInit != null) {
|
||||
if (this.values != null) {
|
||||
throw new IllegalStateException("property " + toString() + " already has values");
|
||||
throw new IllegalStateException("property " + this + " already has values");
|
||||
}
|
||||
this.values = deferredInit.apply(allProperties);
|
||||
}
|
||||
|
@ -40,14 +40,19 @@ public abstract class HsEntityValidator<E> {
|
||||
|
||||
protected ArrayList<String> validateProperties(final Map<String, Object> properties) {
|
||||
final var result = new ArrayList<String>();
|
||||
|
||||
// verify that all actually given properties are specified
|
||||
properties.keySet().forEach( givenPropName -> {
|
||||
if (stream(propertyValidators).map(pv -> pv.propertyName).noneMatch(propName -> propName.equals(givenPropName))) {
|
||||
result.add(givenPropName + "' is not expected but is set to '" + properties.get(givenPropName) + "'");
|
||||
}
|
||||
});
|
||||
|
||||
// run all property validators
|
||||
stream(propertyValidators).forEach(pv -> {
|
||||
result.addAll(pv.validate(properties));
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,9 @@ public class IntegerProperty extends ValidatableProperty<Integer> {
|
||||
|
||||
private String unit;
|
||||
private Integer min;
|
||||
private String minFrom;
|
||||
private Integer max;
|
||||
private String maxFrom;
|
||||
private Integer step;
|
||||
|
||||
public static IntegerProperty integerProperty(final String propertyName) {
|
||||
@ -27,6 +29,16 @@ public class IntegerProperty extends ValidatableProperty<Integer> {
|
||||
super(Integer.class, propertyName, KEY_ORDER);
|
||||
}
|
||||
|
||||
public IntegerProperty minFrom(final String propertyName) {
|
||||
minFrom = propertyName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public IntegerProperty maxFrom(final String propertyName) {
|
||||
maxFrom = propertyName;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String unit() {
|
||||
return unit;
|
||||
|
@ -0,0 +1,76 @@
|
||||
package net.hostsharing.hsadminng.hs.validation;
|
||||
|
||||
import lombok.Setter;
|
||||
import net.hostsharing.hsadminng.mapper.Array;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
@Setter
|
||||
public class StringProperty extends ValidatableProperty<String> {
|
||||
|
||||
private static final String[] KEY_ORDER = Array.join(
|
||||
ValidatableProperty.KEY_ORDER_HEAD,
|
||||
Array.of("values"),
|
||||
ValidatableProperty.KEY_ORDER_TAIL);
|
||||
private Pattern regExPattern;
|
||||
private Integer minLength;
|
||||
private Integer maxLength;
|
||||
private boolean writeOnly;
|
||||
private boolean readOnly;
|
||||
|
||||
private StringProperty(final String propertyName) {
|
||||
super(String.class, propertyName, KEY_ORDER);
|
||||
}
|
||||
|
||||
public static StringProperty stringProperty(final String propertyName) {
|
||||
return new StringProperty(propertyName);
|
||||
}
|
||||
|
||||
public StringProperty minLength(final int minLength) {
|
||||
this.minLength = minLength;
|
||||
return this;
|
||||
}
|
||||
|
||||
public StringProperty maxLength(final int maxLength) {
|
||||
this.maxLength = maxLength;
|
||||
return this;
|
||||
}
|
||||
|
||||
public StringProperty matchesRegEx(final String regExPattern) {
|
||||
this.regExPattern = Pattern.compile(regExPattern);
|
||||
return this;
|
||||
}
|
||||
|
||||
public StringProperty writeOnly() {
|
||||
this.writeOnly = true;
|
||||
super.optional();
|
||||
return this;
|
||||
}
|
||||
|
||||
public StringProperty readOnly() {
|
||||
this.readOnly = true;
|
||||
super.optional();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validate(final ArrayList<String> result, final String propValue, final Map<String, Object> props) {
|
||||
if (minLength != null && propValue.length()<minLength) {
|
||||
result.add(propertyName + "' length is expected to be at min " + minLength + " but length of '" + propValue+ "' is " + propValue.length());
|
||||
}
|
||||
if (maxLength != null && propValue.length()>maxLength) {
|
||||
result.add(propertyName + "' length is expected to be at max " + maxLength + " but length of '" + propValue+ "' is " + propValue.length());
|
||||
}
|
||||
if (regExPattern != null && !regExPattern.matcher(propValue).matches()) {
|
||||
result.add(propertyName + "' is expected to be match " + regExPattern + " but '" + propValue+ "' does not match");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String simpleTypeName() {
|
||||
return "string";
|
||||
}
|
||||
}
|
@ -12,21 +12,35 @@ import static net.hostsharing.hsadminng.hs.booking.project.TestHsBookingProject.
|
||||
@UtilityClass
|
||||
public class TestHsBookingItem {
|
||||
|
||||
public static final HsBookingItemEntity TEST_MANAGED_SERVER_BOOKING_ITEM = HsBookingItemEntity.builder()
|
||||
.project(TEST_PROJECT)
|
||||
.type(HsBookingItemType.MANAGED_SERVER)
|
||||
.caption("test project booking item")
|
||||
.resources(Map.ofEntries(
|
||||
entry("someThing", 1),
|
||||
entry("anotherThing", "blue")
|
||||
))
|
||||
.validity(Range.closedInfinite(LocalDate.of(2020, 1, 15)))
|
||||
.build();
|
||||
|
||||
public static final HsBookingItemEntity TEST_CLOUD_SERVER_BOOKING_ITEM = HsBookingItemEntity.builder()
|
||||
.project(TEST_PROJECT)
|
||||
.type(HsBookingItemType.CLOUD_SERVER)
|
||||
.caption("test cloud server booking item")
|
||||
.validity(Range.closedInfinite(LocalDate.of(2020, 1, 15)))
|
||||
.build();
|
||||
|
||||
public static final HsBookingItemEntity TEST_MANAGED_SERVER_BOOKING_ITEM = HsBookingItemEntity.builder()
|
||||
.project(TEST_PROJECT)
|
||||
.type(HsBookingItemType.MANAGED_SERVER)
|
||||
.caption("test project booking item")
|
||||
.resources(Map.ofEntries(
|
||||
entry("CPUs", 2),
|
||||
entry("RAM", 4),
|
||||
entry("SSD", 50),
|
||||
entry("Traffic", 250)
|
||||
))
|
||||
.validity(Range.closedInfinite(LocalDate.of(2020, 1, 15)))
|
||||
.build();
|
||||
|
||||
public static final HsBookingItemEntity TEST_MANAGED_WEBSPACE_BOOKING_ITEM = HsBookingItemEntity.builder()
|
||||
.parentItem(TEST_MANAGED_SERVER_BOOKING_ITEM)
|
||||
.type(HsBookingItemType.MANAGED_WEBSPACE)
|
||||
.caption("test managed webspace item")
|
||||
.resources(Map.ofEntries(
|
||||
entry("SSD", 25),
|
||||
entry("Traffic", 250)
|
||||
))
|
||||
.validity(Range.closedInfinite(LocalDate.of(2020, 1, 15)))
|
||||
.build();
|
||||
|
||||
}
|
||||
|
@ -1,14 +1,78 @@
|
||||
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 org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static net.hostsharing.hsadminng.hs.booking.item.TestHsBookingItem.TEST_MANAGED_SERVER_BOOKING_ITEM;
|
||||
import static net.hostsharing.hsadminng.hs.booking.item.TestHsBookingItem.TEST_MANAGED_WEBSPACE_BOOKING_ITEM;
|
||||
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_WEBSPACE;
|
||||
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.UNIX_USER;
|
||||
import static net.hostsharing.hsadminng.mapper.PatchMap.entry;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class HsUnixUserHostingAssetValidatorUnitTest {
|
||||
|
||||
private final HsHostingAssetEntity TEST_MANAGED_SERVER_HOSTING_ASSET = HsHostingAssetEntity.builder()
|
||||
.type(HsHostingAssetType.MANAGED_SERVER)
|
||||
.identifier("vm1234")
|
||||
.caption("some managed server")
|
||||
.bookingItem(TEST_MANAGED_SERVER_BOOKING_ITEM)
|
||||
.build();
|
||||
private HsHostingAssetEntity TEST_MANAGED_WEBSPACE_HOSTING_ASSET = HsHostingAssetEntity.builder()
|
||||
.type(MANAGED_WEBSPACE)
|
||||
.bookingItem(TEST_MANAGED_WEBSPACE_BOOKING_ITEM)
|
||||
.parentAsset(TEST_MANAGED_SERVER_HOSTING_ASSET)
|
||||
.identifier("abc00")
|
||||
.build();;
|
||||
|
||||
@Test
|
||||
void validatesValidUnixUser() {
|
||||
// given
|
||||
final var unixUserHostingAsset = HsHostingAssetEntity.builder()
|
||||
.type(UNIX_USER)
|
||||
.parentAsset(TEST_MANAGED_WEBSPACE_HOSTING_ASSET)
|
||||
.identifier("abc00-temp")
|
||||
.caption("some valid test UnixUser")
|
||||
.build();
|
||||
final var validator = HsHostingAssetEntityValidatorRegistry.forType(unixUserHostingAsset.getType());
|
||||
|
||||
// when
|
||||
final var result = validator.validate(unixUserHostingAsset);
|
||||
|
||||
// then
|
||||
assertThat(result).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void validatesUnixUserProperties() {
|
||||
// given
|
||||
final var unixUserHostingAsset = HsHostingAssetEntity.builder()
|
||||
.type(UNIX_USER)
|
||||
.parentAsset(TEST_MANAGED_WEBSPACE_HOSTING_ASSET)
|
||||
.identifier("abc00-temp")
|
||||
.caption("some test UnixUser with invalid properties")
|
||||
.config(Map.ofEntries(
|
||||
entry("SSD hard quota", 1000),
|
||||
entry("SSD soft quota", 2000),
|
||||
entry("HDD hard quota", 1000),
|
||||
entry("HDD soft quota", 2000),
|
||||
entry("homedir", "/is/read-only"),
|
||||
entry("totpKey", "should be a hex number"),
|
||||
entry("password", "should be a hex number")
|
||||
))
|
||||
.build();
|
||||
final var validator = HsHostingAssetEntityValidatorRegistry.forType(unixUserHostingAsset.getType());
|
||||
|
||||
// when
|
||||
final var result = validator.validate(unixUserHostingAsset);
|
||||
|
||||
// then
|
||||
assertThat(result).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void validatesInvalidIdentifier() {
|
||||
// given
|
||||
@ -19,7 +83,6 @@ class HsUnixUserHostingAssetValidatorUnitTest {
|
||||
.build();
|
||||
final var validator = HsHostingAssetEntityValidatorRegistry.forType(unixUserHostingAsset.getType());
|
||||
|
||||
|
||||
// when
|
||||
final var result = validator.validate(unixUserHostingAsset);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user