minFrom/maxFrom validations against context properties
This commit is contained in:
parent
cf6bcc0b94
commit
330ae92c05
@ -11,6 +11,7 @@ import lombok.NoArgsConstructor;
|
|||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import net.hostsharing.hsadminng.hs.booking.project.HsBookingProjectEntity;
|
import net.hostsharing.hsadminng.hs.booking.project.HsBookingProjectEntity;
|
||||||
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity;
|
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity;
|
||||||
|
import net.hostsharing.hsadminng.hs.validation.PropertiesProvider;
|
||||||
import net.hostsharing.hsadminng.mapper.PatchableMapWrapper;
|
import net.hostsharing.hsadminng.mapper.PatchableMapWrapper;
|
||||||
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
|
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
|
||||||
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL;
|
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL;
|
||||||
@ -42,6 +43,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static java.util.Collections.emptyMap;
|
||||||
import static java.util.Optional.ofNullable;
|
import static java.util.Optional.ofNullable;
|
||||||
import static net.hostsharing.hsadminng.mapper.PostgresDateRange.lowerInclusiveFromPostgresDateRange;
|
import static net.hostsharing.hsadminng.mapper.PostgresDateRange.lowerInclusiveFromPostgresDateRange;
|
||||||
import static net.hostsharing.hsadminng.mapper.PostgresDateRange.toPostgresDateRange;
|
import static net.hostsharing.hsadminng.mapper.PostgresDateRange.toPostgresDateRange;
|
||||||
@ -68,7 +70,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
|
|||||||
@Setter
|
@Setter
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class HsBookingItemEntity implements Stringifyable, RbacObject {
|
public class HsBookingItemEntity implements Stringifyable, RbacObject, PropertiesProvider {
|
||||||
|
|
||||||
private static Stringify<HsBookingItemEntity> stringify = stringify(HsBookingItemEntity.class)
|
private static Stringify<HsBookingItemEntity> stringify = stringify(HsBookingItemEntity.class)
|
||||||
.withProp(HsBookingItemEntity::getProject)
|
.withProp(HsBookingItemEntity::getProject)
|
||||||
@ -146,6 +148,23 @@ public class HsBookingItemEntity implements Stringifyable, RbacObject {
|
|||||||
return upperInclusiveFromPostgresDateRange(getValidity());
|
return upperInclusiveFromPostgresDateRange(getValidity());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> directProps() {
|
||||||
|
return resources;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getContextValue(final String propName) {
|
||||||
|
final var v = resources.get(propName);
|
||||||
|
if (v!= null) {
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
if (parentItem!=null) {
|
||||||
|
return parentItem.getResources().get(propName);
|
||||||
|
}
|
||||||
|
return emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return stringify.apply(this);
|
return stringify.apply(this);
|
||||||
|
@ -29,7 +29,7 @@ public class HsBookingItemEntityValidator extends HsEntityValidator<HsBookingIte
|
|||||||
}
|
}
|
||||||
|
|
||||||
private List<String> validateProperties(final HsBookingItemEntity bookingItem) {
|
private List<String> validateProperties(final HsBookingItemEntity bookingItem) {
|
||||||
return enrich(prefix(bookingItem.toShortString(), "resources"), validateProperties(bookingItem.getResources()));
|
return enrich(prefix(bookingItem.toShortString(), "resources"), super.validateProperties(bookingItem));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<String> optionallyValidate(final HsBookingItemEntity bookingItem) {
|
private static List<String> optionallyValidate(final HsBookingItemEntity bookingItem) {
|
||||||
|
@ -9,6 +9,7 @@ import lombok.NoArgsConstructor;
|
|||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity;
|
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
||||||
|
import net.hostsharing.hsadminng.hs.validation.PropertiesProvider;
|
||||||
import net.hostsharing.hsadminng.mapper.PatchableMapWrapper;
|
import net.hostsharing.hsadminng.mapper.PatchableMapWrapper;
|
||||||
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
|
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
|
||||||
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL;
|
import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL;
|
||||||
@ -39,6 +40,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static java.util.Collections.emptyMap;
|
||||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Column.dependsOnColumn;
|
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Column.dependsOnColumn;
|
||||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.ColumnValue.usingDefaultCase;
|
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.ColumnValue.usingDefaultCase;
|
||||||
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.GLOBAL;
|
import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.GLOBAL;
|
||||||
@ -63,7 +65,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
|
|||||||
@Setter
|
@Setter
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class HsHostingAssetEntity implements Stringifyable, RbacObject {
|
public class HsHostingAssetEntity implements Stringifyable, RbacObject, PropertiesProvider {
|
||||||
|
|
||||||
private static Stringify<HsHostingAssetEntity> stringify = stringify(HsHostingAssetEntity.class)
|
private static Stringify<HsHostingAssetEntity> stringify = stringify(HsHostingAssetEntity.class)
|
||||||
.withProp(HsHostingAssetEntity::getType)
|
.withProp(HsHostingAssetEntity::getType)
|
||||||
@ -122,7 +124,7 @@ public class HsHostingAssetEntity implements Stringifyable, RbacObject {
|
|||||||
private PatchableMapWrapper<Object> configWrapper;
|
private PatchableMapWrapper<Object> configWrapper;
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
private boolean isLoaded = false;
|
private boolean isLoaded;
|
||||||
|
|
||||||
@PostLoad
|
@PostLoad
|
||||||
public void markAsLoaded() {
|
public void markAsLoaded() {
|
||||||
@ -137,6 +139,28 @@ public class HsHostingAssetEntity implements Stringifyable, RbacObject {
|
|||||||
PatchableMapWrapper.of(configWrapper, (newWrapper) -> {configWrapper = newWrapper; }, config).assign(newConfig);
|
PatchableMapWrapper.of(configWrapper, (newWrapper) -> {configWrapper = newWrapper; }, config).assign(newConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> directProps() {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getContextValue(final String propName) {
|
||||||
|
final var v = config.get(propName);
|
||||||
|
if (v!= null) {
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bookingItem!=null) {
|
||||||
|
return bookingItem.getResources().get(propName);
|
||||||
|
}
|
||||||
|
if (parentAsset!=null && parentAsset.getBookingItem()!=null) {
|
||||||
|
return parentAsset.getBookingItem().getResources().get(propName);
|
||||||
|
}
|
||||||
|
return emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return stringify.apply(this);
|
return stringify.apply(this);
|
||||||
|
@ -76,7 +76,7 @@ public abstract class HsHostingAssetEntityValidator extends HsEntityValidator<Hs
|
|||||||
}
|
}
|
||||||
|
|
||||||
private List<String> validateProperties(final HsHostingAssetEntity assetEntity) {
|
private List<String> validateProperties(final HsHostingAssetEntity assetEntity) {
|
||||||
return enrich(prefix(assetEntity.toShortString(), "config"), validateProperties(assetEntity.getConfig()));
|
return enrich(prefix(assetEntity.toShortString(), "config"), super.validateProperties(assetEntity));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<String> optionallyValidate(final HsHostingAssetEntity assetEntity) {
|
private static List<String> optionallyValidate(final HsHostingAssetEntity assetEntity) {
|
||||||
|
@ -18,14 +18,14 @@ class HsUnixUserHostingAssetValidator extends HsHostingAssetEntityValidator {
|
|||||||
AlarmContact.isOptional(),
|
AlarmContact.isOptional(),
|
||||||
|
|
||||||
integerProperty("SSD hard quota").unit("GB").maxFrom("SSD").optional(),
|
integerProperty("SSD hard quota").unit("GB").maxFrom("SSD").optional(),
|
||||||
integerProperty("SSD soft quota").unit("GB").minFrom("SSD hard quota").optional(),
|
integerProperty("SSD soft quota").unit("GB").maxFrom("SSD hard quota").optional(),
|
||||||
integerProperty("HDD hard quota").unit("GB").maxFrom("HDD").optional(),
|
integerProperty("HDD hard quota").unit("GB").maxFrom("HDD").optional(),
|
||||||
integerProperty("HDD soft quota").unit("GB").minFrom("HDD hard quota").optional(),
|
integerProperty("HDD soft quota").unit("GB").maxFrom("HDD hard quota").optional(),
|
||||||
enumerationProperty("shell")
|
enumerationProperty("shell")
|
||||||
.values("/bin/false", "/bin/bash", "/bin/csh", "/bin/dash", "/usr/bin/tcsh", "/usr/bin/zsh", "/usr/bin/passwd")
|
.values("/bin/false", "/bin/bash", "/bin/csh", "/bin/dash", "/usr/bin/tcsh", "/usr/bin/zsh", "/usr/bin/passwd")
|
||||||
.withDefault("/bin/false"),
|
.withDefault("/bin/false"),
|
||||||
stringProperty("homedir").readOnly(),
|
stringProperty("homedir").readOnly(),
|
||||||
stringProperty("totpKey").matchesRegEx("^0x\\([0-9A-Fa-f][0-9A-Fa-f]\\)+$").minLength(12).maxLength(32).writeOnly().optional(),
|
stringProperty("totpKey").matchesRegEx("^0x([0-9A-Fa-f]{2})+$").minLength(20).maxLength(256).writeOnly().optional(),
|
||||||
stringProperty("password").minLength(8).maxLength(40).writeOnly()); // FIXME: spec
|
stringProperty("password").minLength(8).maxLength(40).writeOnly()); // FIXME: spec
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,9 +29,9 @@ public class BooleanProperty extends ValidatableProperty<Boolean> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void validate(final ArrayList<String> result, final Boolean propValue, final Map<String, Object> props) {
|
protected void validate(final ArrayList<String> result, final Boolean propValue, final PropertiesProvider propProvider) {
|
||||||
if (falseIf != null && propValue) {
|
if (falseIf != null && propValue) {
|
||||||
final Object referencedValue = props.get(falseIf.getKey());
|
final Object referencedValue = propProvider.directProps().get(falseIf.getKey());
|
||||||
if (Objects.equals(referencedValue, falseIf.getValue())) {
|
if (Objects.equals(referencedValue, falseIf.getValue())) {
|
||||||
result.add(propertyName + "' is expected to be false because " +
|
result.add(propertyName + "' is expected to be false because " +
|
||||||
falseIf.getKey() + "=" + referencedValue + " but is " + propValue);
|
falseIf.getKey() + "=" + referencedValue + " but is " + propValue);
|
||||||
|
@ -5,7 +5,6 @@ import net.hostsharing.hsadminng.mapper.Array;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import static java.util.Arrays.stream;
|
import static java.util.Arrays.stream;
|
||||||
|
|
||||||
@ -51,7 +50,7 @@ public class EnumerationProperty extends ValidatableProperty<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void validate(final ArrayList<String> result, final String propValue, final Map<String, Object> props) {
|
protected void validate(final ArrayList<String> result, final String propValue, final PropertiesProvider propProvider) {
|
||||||
if (stream(values).noneMatch(v -> v.equals(propValue))) {
|
if (stream(values).noneMatch(v -> v.equals(propValue))) {
|
||||||
result.add(propertyName + "' is expected to be one of " + Arrays.toString(values) + " but is '" + propValue + "'");
|
result.add(propertyName + "' is expected to be one of " + Arrays.toString(values) + " but is '" + propValue + "'");
|
||||||
}
|
}
|
||||||
|
@ -38,10 +38,11 @@ public abstract class HsEntityValidator<E> {
|
|||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ArrayList<String> validateProperties(final Map<String, Object> properties) {
|
protected ArrayList<String> validateProperties(final PropertiesProvider propsProvider) {
|
||||||
final var result = new ArrayList<String>();
|
final var result = new ArrayList<String>();
|
||||||
|
|
||||||
// verify that all actually given properties are specified
|
// verify that all actually given properties are specified
|
||||||
|
final var properties = propsProvider.directProps();
|
||||||
properties.keySet().forEach( givenPropName -> {
|
properties.keySet().forEach( givenPropName -> {
|
||||||
if (stream(propertyValidators).map(pv -> pv.propertyName).noneMatch(propName -> propName.equals(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) + "'");
|
result.add(givenPropName + "' is not expected but is set to '" + properties.get(givenPropName) + "'");
|
||||||
@ -50,7 +51,7 @@ public abstract class HsEntityValidator<E> {
|
|||||||
|
|
||||||
// run all property validators
|
// run all property validators
|
||||||
stream(propertyValidators).forEach(pv -> {
|
stream(propertyValidators).forEach(pv -> {
|
||||||
result.addAll(pv.validate(properties));
|
result.addAll(pv.validate(propsProvider));
|
||||||
});
|
});
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -2,9 +2,9 @@ package net.hostsharing.hsadminng.hs.validation;
|
|||||||
|
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import net.hostsharing.hsadminng.mapper.Array;
|
import net.hostsharing.hsadminng.mapper.Array;
|
||||||
|
import org.apache.commons.lang3.Validate;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Setter
|
@Setter
|
||||||
public class IntegerProperty extends ValidatableProperty<Integer> {
|
public class IntegerProperty extends ValidatableProperty<Integer> {
|
||||||
@ -29,6 +29,12 @@ public class IntegerProperty extends ValidatableProperty<Integer> {
|
|||||||
super(Integer.class, propertyName, KEY_ORDER);
|
super(Integer.class, propertyName, KEY_ORDER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deferredInit(final ValidatableProperty<?>[] allProperties) {
|
||||||
|
Validate.isTrue(min == null || minFrom == null, "min and minFrom are exclusive, but both are given");
|
||||||
|
Validate.isTrue(max == null || maxFrom == null, "max and maxFrom are exclusive, but both are given");
|
||||||
|
}
|
||||||
|
|
||||||
public IntegerProperty minFrom(final String propertyName) {
|
public IntegerProperty minFrom(final String propertyName) {
|
||||||
minFrom = propertyName;
|
minFrom = propertyName;
|
||||||
return this;
|
return this;
|
||||||
@ -49,20 +55,34 @@ public class IntegerProperty extends ValidatableProperty<Integer> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void validate(final ArrayList<String> result, final Integer propValue, final Map<String, Object> props) {
|
protected void validate(final ArrayList<String> result, final Integer propValue, final PropertiesProvider propProvider) {
|
||||||
if (min != null && propValue < min) {
|
validateMin(result, propertyName, propValue, min);
|
||||||
result.add(propertyName + "' is expected to be >= " + min + " but is " + propValue);
|
validateMax(result, propertyName, propValue, max);
|
||||||
}
|
|
||||||
if (max != null && propValue > max) {
|
|
||||||
result.add(propertyName + "' is expected to be <= " + max + " but is " + propValue);
|
|
||||||
}
|
|
||||||
if (step != null && propValue % step != 0) {
|
if (step != null && propValue % step != 0) {
|
||||||
result.add(propertyName + "' is expected to be multiple of " + step + " but is " + propValue);
|
result.add(propertyName + "' is expected to be multiple of " + step + " but is " + propValue);
|
||||||
}
|
}
|
||||||
|
if (minFrom != null) {
|
||||||
|
validateMin(result, propertyName, propValue, propProvider.getContextValue(minFrom, Integer.class));
|
||||||
|
}
|
||||||
|
if (maxFrom != null) {
|
||||||
|
validateMax(result, propertyName, propValue, propProvider.getContextValue(maxFrom, Integer.class, 0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String simpleTypeName() {
|
protected String simpleTypeName() {
|
||||||
return "integer";
|
return "integer";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void validateMin(final ArrayList<String> result, final String propertyName, final Integer propValue, final Integer min) {
|
||||||
|
if (min != null && propValue < min) {
|
||||||
|
result.add(propertyName + "' is expected to be at least " + min + " but is " + propValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void validateMax(final ArrayList<String> result, final String propertyName, final Integer propValue, final Integer max) {
|
||||||
|
if (max != null && propValue > max) {
|
||||||
|
result.add(propertyName + "' is expected to be at most " + max + " but is " + propValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ import lombok.Setter;
|
|||||||
import net.hostsharing.hsadminng.mapper.Array;
|
import net.hostsharing.hsadminng.mapper.Array;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
|
||||||
@ -57,7 +56,7 @@ public class StringProperty extends ValidatableProperty<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void validate(final ArrayList<String> result, final String propValue, final Map<String, Object> props) {
|
protected void validate(final ArrayList<String> result, final String propValue, final PropertiesProvider propProvider) {
|
||||||
if (minLength != null && propValue.length()<minLength) {
|
if (minLength != null && propValue.length()<minLength) {
|
||||||
result.add(propertyName + "' length is expected to be at min " + minLength + " but length of '" + propValue+ "' is " + propValue.length());
|
result.add(propertyName + "' length is expected to be at min " + minLength + " but length of '" + propValue+ "' is " + propValue.length());
|
||||||
}
|
}
|
||||||
@ -67,6 +66,9 @@ public class StringProperty extends ValidatableProperty<String> {
|
|||||||
if (regExPattern != null && !regExPattern.matcher(propValue).matches()) {
|
if (regExPattern != null && !regExPattern.matcher(propValue).matches()) {
|
||||||
result.add(propertyName + "' is expected to be match " + regExPattern + " but '" + propValue+ "' does not match");
|
result.add(propertyName + "' is expected to be match " + regExPattern + " but '" + propValue+ "' does not match");
|
||||||
}
|
}
|
||||||
|
if (readOnly && propValue != null) {
|
||||||
|
result.add(propertyName + "' is readonly but given as '" + propValue+ "'");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -116,8 +116,9 @@ public abstract class ValidatableProperty<T> {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final List<String> validate(final Map<String, Object> props) {
|
public final List<String> validate(final PropertiesProvider propsProvider) {
|
||||||
final var result = new ArrayList<String>();
|
final var result = new ArrayList<String>();
|
||||||
|
final var props = propsProvider.directProps();
|
||||||
final var propValue = props.get(propertyName);
|
final var propValue = props.get(propertyName);
|
||||||
if (propValue == null) {
|
if (propValue == null) {
|
||||||
if (required) {
|
if (required) {
|
||||||
@ -127,7 +128,7 @@ public abstract class ValidatableProperty<T> {
|
|||||||
if (propValue != null){
|
if (propValue != null){
|
||||||
if ( type.isInstance(propValue)) {
|
if ( type.isInstance(propValue)) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
validate(result, (T) propValue, props);
|
validate(result, (T) propValue, propsProvider);
|
||||||
} else {
|
} else {
|
||||||
result.add(propertyName + "' is expected to be of type " + type + ", " +
|
result.add(propertyName + "' is expected to be of type " + type + ", " +
|
||||||
"but is of type '" + propValue.getClass().getSimpleName() + "'");
|
"but is of type '" + propValue.getClass().getSimpleName() + "'");
|
||||||
@ -136,7 +137,7 @@ public abstract class ValidatableProperty<T> {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void validate(final ArrayList<String> result, final T propValue, final Map<String, Object> props);
|
protected abstract void validate(final ArrayList<String> result, final T propValue, final PropertiesProvider propProvider);
|
||||||
|
|
||||||
public void verifyConsistency(final Map.Entry<? extends Enum<?>, ?> typeDef) {
|
public void verifyConsistency(final Map.Entry<? extends Enum<?>, ?> typeDef) {
|
||||||
if (required == null ) {
|
if (required == null ) {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package net.hostsharing.hsadminng.mapper;
|
package net.hostsharing.hsadminng.mapper;
|
||||||
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -43,4 +44,8 @@ public class Array {
|
|||||||
.toArray(String[]::new);
|
.toArray(String[]::new);
|
||||||
return joined;
|
return joined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <T> T[] emptyArray() {
|
||||||
|
return of();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ public class TestHsBookingItem {
|
|||||||
.type(HsBookingItemType.MANAGED_WEBSPACE)
|
.type(HsBookingItemType.MANAGED_WEBSPACE)
|
||||||
.caption("test managed webspace item")
|
.caption("test managed webspace item")
|
||||||
.resources(Map.ofEntries(
|
.resources(Map.ofEntries(
|
||||||
entry("SSD", 25),
|
entry("SSD", 50),
|
||||||
entry("Traffic", 250)
|
entry("Traffic", 250)
|
||||||
))
|
))
|
||||||
.validity(Range.closedInfinite(LocalDate.of(2020, 1, 15)))
|
.validity(Range.closedInfinite(LocalDate.of(2020, 1, 15)))
|
||||||
|
@ -292,8 +292,8 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
"statusPhrase": "Bad Request",
|
"statusPhrase": "Bad Request",
|
||||||
"message": "[
|
"message": "[
|
||||||
<<<'MANAGED_SERVER:vm1400.config.extra' is not expected but is set to '42',
|
<<<'MANAGED_SERVER:vm1400.config.extra' is not expected but is set to '42',
|
||||||
<<<'MANAGED_SERVER:vm1400.config.monit_max_cpu_usage' is expected to be <= 100 but is 101,
|
<<<'MANAGED_SERVER:vm1400.config.monit_max_cpu_usage' is expected to be at most 100 but is 101,
|
||||||
<<<'MANAGED_SERVER:vm1400.config.monit_max_ssd_usage' is expected to be >= 10 but is 0
|
<<<'MANAGED_SERVER:vm1400.config.monit_max_ssd_usage' is expected to be at least 10 but is 0
|
||||||
<<<]"
|
<<<]"
|
||||||
}
|
}
|
||||||
""".replaceAll(" +<<<", ""))); // @formatter:on
|
""".replaceAll(" +<<<", ""))); // @formatter:on
|
||||||
|
@ -37,8 +37,8 @@ class HsManagedServerHostingAssetValidatorUnitTest {
|
|||||||
assertThat(result).containsExactlyInAnyOrder(
|
assertThat(result).containsExactlyInAnyOrder(
|
||||||
"'MANAGED_SERVER:vm1234.parentAsset' must be null but is set to D-???????-?:null",
|
"'MANAGED_SERVER:vm1234.parentAsset' must be null but is set to D-???????-?:null",
|
||||||
"'MANAGED_SERVER:vm1234.assignedToAsset' must be null but is set to D-???????-?:null",
|
"'MANAGED_SERVER:vm1234.assignedToAsset' must be null but is set to D-???????-?:null",
|
||||||
"'MANAGED_SERVER:vm1234.config.monit_max_cpu_usage' is expected to be >= 10 but is 2",
|
"'MANAGED_SERVER:vm1234.config.monit_max_cpu_usage' is expected to be at least 10 but is 2",
|
||||||
"'MANAGED_SERVER:vm1234.config.monit_max_ram_usage' is expected to be <= 100 but is 101",
|
"'MANAGED_SERVER:vm1234.config.monit_max_ram_usage' is expected to be at most 100 but is 101",
|
||||||
"'MANAGED_SERVER:vm1234.config.monit_max_hdd_usage' is expected to be of type class java.lang.Integer, but is of type 'String'");
|
"'MANAGED_SERVER:vm1234.config.monit_max_hdd_usage' is expected to be of type class java.lang.Integer, but is of type 'String'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +36,12 @@ class HsUnixUserHostingAssetValidatorUnitTest {
|
|||||||
.parentAsset(TEST_MANAGED_WEBSPACE_HOSTING_ASSET)
|
.parentAsset(TEST_MANAGED_WEBSPACE_HOSTING_ASSET)
|
||||||
.identifier("abc00-temp")
|
.identifier("abc00-temp")
|
||||||
.caption("some valid test UnixUser")
|
.caption("some valid test UnixUser")
|
||||||
|
.config(Map.ofEntries(
|
||||||
|
entry("SSD hard quota", 50),
|
||||||
|
entry("SSD soft quota", 40),
|
||||||
|
entry("totpKey", "0x123456789abcdef01234"),
|
||||||
|
entry("password", "Hallo Computer, lass mich rein!")
|
||||||
|
))
|
||||||
.build();
|
.build();
|
||||||
final var validator = HsHostingAssetEntityValidatorRegistry.forType(unixUserHostingAsset.getType());
|
final var validator = HsHostingAssetEntityValidatorRegistry.forType(unixUserHostingAsset.getType());
|
||||||
|
|
||||||
@ -55,13 +61,14 @@ class HsUnixUserHostingAssetValidatorUnitTest {
|
|||||||
.identifier("abc00-temp")
|
.identifier("abc00-temp")
|
||||||
.caption("some test UnixUser with invalid properties")
|
.caption("some test UnixUser with invalid properties")
|
||||||
.config(Map.ofEntries(
|
.config(Map.ofEntries(
|
||||||
entry("SSD hard quota", 1000),
|
entry("SSD hard quota", 100),
|
||||||
entry("SSD soft quota", 2000),
|
entry("SSD soft quota", 200),
|
||||||
entry("HDD hard quota", 1000),
|
entry("HDD hard quota", 100),
|
||||||
entry("HDD soft quota", 2000),
|
entry("HDD soft quota", 200),
|
||||||
|
entry("shell", "/is/invalid"),
|
||||||
entry("homedir", "/is/read-only"),
|
entry("homedir", "/is/read-only"),
|
||||||
entry("totpKey", "should be a hex number"),
|
entry("totpKey", "should be a hex number"),
|
||||||
entry("password", "should be a hex number")
|
entry("password", "short")
|
||||||
))
|
))
|
||||||
.build();
|
.build();
|
||||||
final var validator = HsHostingAssetEntityValidatorRegistry.forType(unixUserHostingAsset.getType());
|
final var validator = HsHostingAssetEntityValidatorRegistry.forType(unixUserHostingAsset.getType());
|
||||||
@ -70,7 +77,16 @@ class HsUnixUserHostingAssetValidatorUnitTest {
|
|||||||
final var result = validator.validate(unixUserHostingAsset);
|
final var result = validator.validate(unixUserHostingAsset);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(result).isEmpty();
|
assertThat(result).containsExactlyInAnyOrder(
|
||||||
|
"'UNIX_USER:abc00-temp.config.SSD hard quota' is expected to be at most 50 but is 100",
|
||||||
|
"'UNIX_USER:abc00-temp.config.SSD soft quota' is expected to be at most 100 but is 200",
|
||||||
|
"'UNIX_USER:abc00-temp.config.HDD hard quota' is expected to be at most 0 but is 100",
|
||||||
|
"'UNIX_USER:abc00-temp.config.HDD soft quota' is expected to be at most 100 but is 200",
|
||||||
|
"'UNIX_USER:abc00-temp.config.shell' is expected to be one of [/bin/false, /bin/bash, /bin/csh, /bin/dash, /usr/bin/tcsh, /usr/bin/zsh, /usr/bin/passwd] but is '/is/invalid'",
|
||||||
|
"'UNIX_USER:abc00-temp.config.homedir' is readonly but given as '/is/read-only'",
|
||||||
|
"'UNIX_USER:abc00-temp.config.totpKey' is expected to be match ^0x([0-9A-Fa-f]{2})+$ but 'should be a hex number' does not match",
|
||||||
|
"'UNIX_USER:abc00-temp.config.password' length is expected to be at min 8 but length of 'short' is 5"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Loading…
Reference in New Issue
Block a user