Compare commits

..

No commits in common. "99a93586796acc28b97a664ed7a9e97a3620234e" and "e1fda412aeea4834e25084e4ca898c53f4f0fe01" have entirely different histories.

18 changed files with 68 additions and 284 deletions

View File

@ -38,8 +38,8 @@ class HsManagedWebspaceBookingItemValidator extends HsBookingItemEntityValidator
); );
} }
private static TriFunction<HsBookingItemEntity, IntegerProperty<?>, Integer, List<String>> unixUsers() { private static TriFunction<HsBookingItemEntity, IntegerProperty, Integer, List<String>> unixUsers() {
return (final HsBookingItemEntity entity, final IntegerProperty<?> prop, final Integer factor) -> { return (final HsBookingItemEntity entity, final IntegerProperty prop, final Integer factor) -> {
final var unixUserCount = ofNullable(entity.getRelatedHostingAsset()) final var unixUserCount = ofNullable(entity.getRelatedHostingAsset())
.map(ha -> ha.getSubHostingAssets().stream() .map(ha -> ha.getSubHostingAssets().stream()
.filter(subAsset -> subAsset.getType() == UNIX_USER) .filter(subAsset -> subAsset.getType() == UNIX_USER)
@ -53,8 +53,8 @@ class HsManagedWebspaceBookingItemValidator extends HsBookingItemEntityValidator
}; };
} }
private static TriFunction<HsBookingItemEntity, IntegerProperty<?>, Integer, List<String>> databaseUsers() { private static TriFunction<HsBookingItemEntity, IntegerProperty, Integer, List<String>> databaseUsers() {
return (final HsBookingItemEntity entity, final IntegerProperty<?> prop, final Integer factor) -> { return (final HsBookingItemEntity entity, final IntegerProperty prop, final Integer factor) -> {
final var dbUserCount = ofNullable(entity.getRelatedHostingAsset()) final var dbUserCount = ofNullable(entity.getRelatedHostingAsset())
.map(ha -> ha.getSubHostingAssets().stream() .map(ha -> ha.getSubHostingAssets().stream()
.filter(bi -> bi.getType() == PGSQL_USER || bi.getType() == MARIADB_USER ) .filter(bi -> bi.getType() == PGSQL_USER || bi.getType() == MARIADB_USER )
@ -68,8 +68,8 @@ class HsManagedWebspaceBookingItemValidator extends HsBookingItemEntityValidator
}; };
} }
private static TriFunction<HsBookingItemEntity, IntegerProperty<?>, Integer, List<String>> databases() { private static TriFunction<HsBookingItemEntity, IntegerProperty, Integer, List<String>> databases() {
return (final HsBookingItemEntity entity, final IntegerProperty<?> prop, final Integer factor) -> { return (final HsBookingItemEntity entity, final IntegerProperty prop, final Integer factor) -> {
final var unixUserCount = ofNullable(entity.getRelatedHostingAsset()) final var unixUserCount = ofNullable(entity.getRelatedHostingAsset())
.map(ha -> ha.getSubHostingAssets().stream() .map(ha -> ha.getSubHostingAssets().stream()
.filter(bi -> bi.getType()==PGSQL_USER || bi.getType()==MARIADB_USER ) .filter(bi -> bi.getType()==PGSQL_USER || bi.getType()==MARIADB_USER )
@ -85,8 +85,8 @@ class HsManagedWebspaceBookingItemValidator extends HsBookingItemEntityValidator
}; };
} }
private static TriFunction<HsBookingItemEntity, IntegerProperty<?>, Integer, List<String>> eMailAddresses() { private static TriFunction<HsBookingItemEntity, IntegerProperty, Integer, List<String>> eMailAddresses() {
return (final HsBookingItemEntity entity, final IntegerProperty<?> prop, final Integer factor) -> { return (final HsBookingItemEntity entity, final IntegerProperty prop, final Integer factor) -> {
final var unixUserCount = ofNullable(entity.getRelatedHostingAsset()) final var unixUserCount = ofNullable(entity.getRelatedHostingAsset())
.map(ha -> ha.getSubHostingAssets().stream() .map(ha -> ha.getSubHostingAssets().stream()
.filter(bi -> bi.getType() == DOMAIN_MBOX_SETUP) .filter(bi -> bi.getType() == DOMAIN_MBOX_SETUP)

View File

@ -72,7 +72,7 @@ public class HsHostingAssetController implements HsHostingAssetsApi {
final var entity = mapper.map(body, HsHostingAssetEntity.class, RESOURCE_TO_ENTITY_POSTMAPPER); final var entity = mapper.map(body, HsHostingAssetEntity.class, RESOURCE_TO_ENTITY_POSTMAPPER);
final var mapped = new HostingAssetEntitySaveProcessor(em, entity) final var mapped = new HostingAssetEntitySaveProcessor(entity)
.preprocessEntity() .preprocessEntity()
.validateEntity() .validateEntity()
.prepareForSave() .prepareForSave()
@ -133,7 +133,7 @@ public class HsHostingAssetController implements HsHostingAssetsApi {
new HsHostingAssetEntityPatcher(em, entity).apply(body); new HsHostingAssetEntityPatcher(em, entity).apply(body);
final var mapped = new HostingAssetEntitySaveProcessor(em, entity) final var mapped = new HostingAssetEntitySaveProcessor(entity)
.preprocessEntity() .preprocessEntity()
.validateEntity() .validateEntity()
.prepareForSave() .prepareForSave()
@ -162,5 +162,5 @@ public class HsHostingAssetController implements HsHostingAssetsApi {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final BiConsumer<HsHostingAssetEntity, HsHostingAssetResource> ENTITY_TO_RESOURCE_POSTMAPPER = (entity, resource) final BiConsumer<HsHostingAssetEntity, HsHostingAssetResource> ENTITY_TO_RESOURCE_POSTMAPPER = (entity, resource)
-> resource.setConfig(HostingAssetEntityValidatorRegistry.forType(entity.getType()) -> resource.setConfig(HostingAssetEntityValidatorRegistry.forType(entity.getType())
.revampProperties(em, entity, (Map<String, Object>) resource.getConfig())); .revampProperties(entity, (Map<String, Object>) resource.getConfig()));
} }

View File

@ -5,7 +5,6 @@ import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity;
import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.model.HsHostingAssetResource; import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.model.HsHostingAssetResource;
import net.hostsharing.hsadminng.hs.validation.HsEntityValidator; import net.hostsharing.hsadminng.hs.validation.HsEntityValidator;
import jakarta.persistence.EntityManager;
import java.util.Map; import java.util.Map;
import java.util.function.Function; import java.util.function.Function;
@ -16,12 +15,10 @@ public class HostingAssetEntitySaveProcessor {
private final HsEntityValidator<HsHostingAssetEntity> validator; private final HsEntityValidator<HsHostingAssetEntity> validator;
private String expectedStep = "preprocessEntity"; private String expectedStep = "preprocessEntity";
private final EntityManager em;
private HsHostingAssetEntity entity; private HsHostingAssetEntity entity;
private HsHostingAssetResource resource; private HsHostingAssetResource resource;
public HostingAssetEntitySaveProcessor(final EntityManager em, final HsHostingAssetEntity entity) { public HostingAssetEntitySaveProcessor(final HsHostingAssetEntity entity) {
this.em = em;
this.entity = entity; this.entity = entity;
this.validator = HostingAssetEntityValidatorRegistry.forType(entity.getType()); this.validator = HostingAssetEntityValidatorRegistry.forType(entity.getType());
} }
@ -44,7 +41,7 @@ public class HostingAssetEntitySaveProcessor {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public HostingAssetEntitySaveProcessor prepareForSave() { public HostingAssetEntitySaveProcessor prepareForSave() {
step("prepareForSave", "saveUsing"); step("prepareForSave", "saveUsing");
validator.prepareProperties(em, entity); validator.prepareProperties(entity);
return this; return this;
} }
@ -73,7 +70,7 @@ public class HostingAssetEntitySaveProcessor {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public HsHostingAssetResource revampProperties() { public HsHostingAssetResource revampProperties() {
step("revampProperties", null); step("revampProperties", null);
final var revampedProps = validator.revampProperties(em, entity, (Map<String, Object>) resource.getConfig()); final var revampedProps = validator.revampProperties(entity, (Map<String, Object>) resource.getConfig());
resource.setConfig(revampedProps); resource.setConfig(revampedProps);
return resource; return resource;
} }

View File

@ -11,7 +11,7 @@ import static net.hostsharing.hsadminng.hs.validation.StringProperty.stringPrope
class HsEMailAddressHostingAssetValidator extends HostingAssetEntityValidator { class HsEMailAddressHostingAssetValidator extends HostingAssetEntityValidator {
private static final String UNIX_USER_REGEX = "^[a-z][a-z0-9]{2}[0-9]{2}(-[a-z0-9][a-z0-9\\.-]*)?$"; // also accepts legacy pac-names private static final String UNIX_USER_REGEX = "^[a-z][a-z0-9]{2}[0-9]{2}(-[a-z0-9]+)?$"; // also accepts legacy pac-names
private static final String EMAIL_ADDRESS_LOCAL_PART_REGEX = "[a-zA-Z0-9_!#$%&'*+/=?`{|}~^.-]+"; // RFC 5322 private static final String EMAIL_ADDRESS_LOCAL_PART_REGEX = "[a-zA-Z0-9_!#$%&'*+/=?`{|}~^.-]+"; // RFC 5322
private static final String EMAIL_ADDRESS_DOMAIN_PART_REGEX = "[a-zA-Z0-9.-]+"; private static final String EMAIL_ADDRESS_DOMAIN_PART_REGEX = "[a-zA-Z0-9.-]+";
private static final String EMAIL_ADDRESS_FULL_REGEX = "^" + EMAIL_ADDRESS_LOCAL_PART_REGEX + "@" + EMAIL_ADDRESS_DOMAIN_PART_REGEX + "$"; private static final String EMAIL_ADDRESS_FULL_REGEX = "^" + EMAIL_ADDRESS_LOCAL_PART_REGEX + "@" + EMAIL_ADDRESS_DOMAIN_PART_REGEX + "$";

View File

@ -10,10 +10,8 @@ import static net.hostsharing.hsadminng.hs.validation.StringProperty.stringPrope
class HsEMailAliasHostingAssetValidator extends HostingAssetEntityValidator { class HsEMailAliasHostingAssetValidator extends HostingAssetEntityValidator {
private static final String UNIX_USER_REGEX = "^[a-z][a-z0-9]{2}[0-9]{2}(-[a-z0-9][a-z0-9\\.-]*)?$"; // also accepts legacy pac-names private static final String UNIX_USER_REGEX = "^[a-z][a-z0-9]{2}[0-9]{2}(-[a-z0-9]+)?$"; // also accepts legacy pac-names
private static final String EMAIL_ADDRESS_REGEX = "^[a-zA-Z0-9_!#$%&'*+/=?`{|}~^.-]+@[a-zA-Z0-9.-]+$"; // RFC 5322 private static final String EMAIL_ADDRESS_REGEX = "^[a-zA-Z0-9_!#$%&'*+/=?`{|}~^.-]+@[a-zA-Z0-9.-]+$"; // RFC 5322
private static final String INCLUDE_REGEX = "^:include:/.*$";
private static final String PIPE_REGEX = "^|.*$";
public static final int EMAIL_ADDRESS_MAX_LENGTH = 320; // according to RFC 5321 and RFC 5322 public static final int EMAIL_ADDRESS_MAX_LENGTH = 320; // according to RFC 5321 and RFC 5322
HsEMailAliasHostingAssetValidator() { HsEMailAliasHostingAssetValidator() {
@ -21,13 +19,13 @@ class HsEMailAliasHostingAssetValidator extends HostingAssetEntityValidator {
AlarmContact.isOptional(), AlarmContact.isOptional(),
arrayOf( arrayOf(
stringProperty("target").maxLength(EMAIL_ADDRESS_MAX_LENGTH).matchesRegEx(UNIX_USER_REGEX, EMAIL_ADDRESS_REGEX, INCLUDE_REGEX, PIPE_REGEX) stringProperty("target").maxLength(EMAIL_ADDRESS_MAX_LENGTH).matchesRegEx(UNIX_USER_REGEX, EMAIL_ADDRESS_REGEX)
).required().minLength(1)); ).required().minLength(1));
} }
@Override @Override
protected Pattern identifierPattern(final HsHostingAssetEntity assetEntity) { protected Pattern identifierPattern(final HsHostingAssetEntity assetEntity) {
final var webspaceIdentifier = assetEntity.getParentAsset().getIdentifier(); final var webspaceIdentifier = assetEntity.getParentAsset().getIdentifier();
return Pattern.compile("^"+webspaceIdentifier+"$|^"+webspaceIdentifier+"-[a-z0-9][a-z0-9\\.-]*$"); return Pattern.compile("^"+webspaceIdentifier+"$|^"+webspaceIdentifier+"-[a-z0-9]+$");
} }
} }

View File

@ -7,7 +7,6 @@ import net.hostsharing.hsadminng.hs.validation.PropertiesProvider;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import static net.hostsharing.hsadminng.hs.validation.BooleanProperty.booleanProperty;
import static net.hostsharing.hsadminng.hs.validation.EnumerationProperty.enumerationProperty; 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.IntegerProperty.integerProperty;
import static net.hostsharing.hsadminng.hs.validation.PasswordProperty.passwordProperty; import static net.hostsharing.hsadminng.hs.validation.PasswordProperty.passwordProperty;
@ -22,26 +21,23 @@ class HsUnixUserHostingAssetValidator extends HostingAssetEntityValidator {
HsHostingAssetType.UNIX_USER, HsHostingAssetType.UNIX_USER,
AlarmContact.isOptional(), AlarmContact.isOptional(),
booleanProperty("locked").readOnly(), integerProperty("SSD hard quota").unit("GB").maxFrom("SSD").optional(),
integerProperty("userid").readOnly().computedBy(HsUnixUserHostingAssetValidator::computeUserId), integerProperty("SSD soft quota").unit("GB").maxFrom("SSD hard quota").optional(),
integerProperty("HDD hard quota").unit("GB").maxFrom("HDD").optional(),
integerProperty("SSD hard quota").unit("MB").maxFrom("SSD").withFactor(1024).optional(), integerProperty("HDD soft quota").unit("GB").maxFrom("HDD hard quota").optional(),
integerProperty("SSD soft quota").unit("MB").maxFrom("SSD hard quota").optional(),
integerProperty("HDD hard quota").unit("MB").maxFrom("HDD").withFactor(1024).optional(),
integerProperty("HDD soft quota").unit("MB").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().computedBy(HsUnixUserHostingAssetValidator::computeHomedir), stringProperty("homedir").readOnly().computedBy(HsUnixUserHostingAssetValidator::computeHomedir),
stringProperty("totpKey").matchesRegEx("^0x([0-9A-Fa-f]{2})+$").minLength(20).maxLength(256).undisclosed().writeOnly().optional(), stringProperty("totpKey").matchesRegEx("^0x([0-9A-Fa-f]{2})+$").minLength(20).maxLength(256).undisclosed().writeOnly().optional(),
passwordProperty("password").minLength(8).maxLength(40).hashedUsing(HashGenerator.Algorithm.LINUX_SHA512).writeOnly()); passwordProperty("password").minLength(8).maxLength(40).hashedUsing(HashGenerator.Algorithm.LINUX_SHA512).writeOnly());
// TODO.spec: public SSH keys? (only if hsadmin-ng is only accessible with 2FA) // TODO.spec: public SSH keys?
} }
@Override @Override
protected Pattern identifierPattern(final HsHostingAssetEntity assetEntity) { protected Pattern identifierPattern(final HsHostingAssetEntity assetEntity) {
final var webspaceIdentifier = assetEntity.getParentAsset().getIdentifier(); final var webspaceIdentifier = assetEntity.getParentAsset().getIdentifier();
return Pattern.compile("^"+webspaceIdentifier+"$|^"+webspaceIdentifier+"-[a-z0-9\\.-]+$"); return Pattern.compile("^"+webspaceIdentifier+"$|^"+webspaceIdentifier+"-[a-z0-9]+$");
} }
private static String computeHomedir(final PropertiesProvider propertiesProvider) { private static String computeHomedir(final PropertiesProvider propertiesProvider) {
@ -50,8 +46,4 @@ class HsUnixUserHostingAssetValidator extends HostingAssetEntityValidator {
return "/home/pacs/" + webspaceName return "/home/pacs/" + webspaceName
+ "/users/" + entity.getIdentifier().substring(webspaceName.length()+DASH_LENGTH); + "/users/" + entity.getIdentifier().substring(webspaceName.length()+DASH_LENGTH);
} }
private static Integer computeUserId(PropertiesProvider propertiesProvider) {
return 0; // FIXME: from a specific numeric rage and unique per hive?
}
} }

View File

@ -2,7 +2,6 @@ package net.hostsharing.hsadminng.hs.validation;
import jakarta.persistence.EntityManager;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
@ -107,21 +106,21 @@ public abstract class HsEntityValidator<E extends PropertiesProvider> {
throw new IllegalArgumentException("Integer value (or null) expected, but got " + value); throw new IllegalArgumentException("Integer value (or null) expected, but got " + value);
} }
public void prepareProperties(final EntityManager em, final E entity) { public void prepareProperties(final E entity) {
stream(propertyValidators).forEach(p -> { stream(propertyValidators).forEach(p -> {
if ( p.isWriteOnly() && p.isComputed()) { if ( p.isWriteOnly() && p.isComputed()) {
entity.directProps().put(p.propertyName, p.compute(em, entity)); entity.directProps().put(p.propertyName, p.compute(entity));
} }
}); });
} }
public Map<String, Object> revampProperties(final EntityManager em, final E entity, final Map<String, Object> config) { public Map<String, Object> revampProperties(final E entity, final Map<String, Object> config) {
final var copy = new HashMap<>(config); final var copy = new HashMap<>(config);
stream(propertyValidators).forEach(p -> { stream(propertyValidators).forEach(p -> {
if (p.isWriteOnly()) { if (p.isWriteOnly()) {
copy.remove(p.propertyName); copy.remove(p.propertyName);
} else if (p.isReadOnly() && p.isComputed()) { } else if (p.isReadOnly() && p.isComputed()) {
copy.put(p.propertyName, p.compute(em, entity)); copy.put(p.propertyName, p.compute(entity));
} }
}); });
return copy; return copy;

View File

@ -7,7 +7,7 @@ import org.apache.commons.lang3.Validate;
import java.util.List; import java.util.List;
@Setter @Setter
public class IntegerProperty<P extends IntegerProperty<P>> extends ValidatableProperty<P, Integer> { public class IntegerProperty extends ValidatableProperty<IntegerProperty, Integer> {
private final static String[] KEY_ORDER = Array.join( private final static String[] KEY_ORDER = Array.join(
ValidatableProperty.KEY_ORDER_HEAD, ValidatableProperty.KEY_ORDER_HEAD,
@ -19,11 +19,10 @@ public class IntegerProperty<P extends IntegerProperty<P>> extends ValidatablePr
private String minFrom; private String minFrom;
private Integer max; private Integer max;
private String maxFrom; private String maxFrom;
private Integer factor;
private Integer step; private Integer step;
public static IntegerProperty<?> integerProperty(final String propertyName) { public static IntegerProperty integerProperty(final String propertyName) {
return new IntegerProperty<>(propertyName); return new IntegerProperty(propertyName);
} }
private IntegerProperty(final String propertyName) { private IntegerProperty(final String propertyName) {
@ -36,19 +35,14 @@ public class IntegerProperty<P extends IntegerProperty<P>> extends ValidatablePr
Validate.isTrue(max == null || maxFrom == null, "max and maxFrom are exclusive, but both are given"); Validate.isTrue(max == null || maxFrom == null, "max and maxFrom are exclusive, but both are given");
} }
public P minFrom(final String propertyName) { public IntegerProperty minFrom(final String propertyName) {
minFrom = propertyName; minFrom = propertyName;
return self(); return this;
} }
public P maxFrom(final String propertyName) { public IntegerProperty maxFrom(final String propertyName) {
maxFrom = propertyName; maxFrom = propertyName;
return self(); return this;
}
public P withFactor(final int factor) {
this.factor = factor;
return self();
} }
@Override @Override
@ -68,10 +62,10 @@ public class IntegerProperty<P extends IntegerProperty<P>> extends ValidatablePr
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) { if (minFrom != null) {
validateMin(result, propertyName, propValue, propProvider.getContextValue(minFrom, Integer.class) * ((factor != null) ? factor : 1)); validateMin(result, propertyName, propValue, propProvider.getContextValue(minFrom, Integer.class));
} }
if (maxFrom != null) { if (maxFrom != null) {
validateMax(result, propertyName, propValue, propProvider.getContextValue(maxFrom, Integer.class, 0) * ((factor != null) ? factor : 1)); validateMax(result, propertyName, propValue, propProvider.getContextValue(maxFrom, Integer.class, 0));
} }
} }

View File

@ -9,7 +9,6 @@ import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity;
import net.hostsharing.hsadminng.mapper.Array; import net.hostsharing.hsadminng.mapper.Array;
import org.apache.commons.lang3.function.TriFunction; import org.apache.commons.lang3.function.TriFunction;
import jakarta.persistence.EntityManager;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
@ -138,8 +137,8 @@ protected void setDeferredInit(final Function<ValidatableProperty<?, ?>[], T[]>
if (asTotalLimitValidators == null) { if (asTotalLimitValidators == null) {
asTotalLimitValidators = new ArrayList<>(); asTotalLimitValidators = new ArrayList<>();
} }
final TriFunction<HsBookingItemEntity, IntegerProperty<?>, Integer, List<String>> validator = final TriFunction<HsBookingItemEntity, IntegerProperty, Integer, List<String>> validator =
(final HsBookingItemEntity entity, final IntegerProperty<?> prop, final Integer factor) -> { (final HsBookingItemEntity entity, final IntegerProperty prop, final Integer factor) -> {
final var total = entity.getSubBookingItems().stream() final var total = entity.getSubBookingItems().stream()
.map(server -> server.getResources().get(propertyName)) .map(server -> server.getResources().get(propertyName))
@ -170,11 +169,11 @@ protected void setDeferredInit(final Function<ValidatableProperty<?, ?>[], T[]>
return thresholdPercentage; return thresholdPercentage;
} }
public ValidatableProperty<P, T> eachComprising(final int factor, final TriFunction<HsBookingItemEntity, IntegerProperty<?>, Integer, List<String>> validator) { public ValidatableProperty<P, T> eachComprising(final int factor, final TriFunction<HsBookingItemEntity, IntegerProperty, Integer, List<String>> validator) {
if (asTotalLimitValidators == null) { if (asTotalLimitValidators == null) {
asTotalLimitValidators = new ArrayList<>(); asTotalLimitValidators = new ArrayList<>();
} }
asTotalLimitValidators.add((final HsBookingItemEntity entity) -> validator.apply(entity, (IntegerProperty<?>)this, factor)); asTotalLimitValidators.add((final HsBookingItemEntity entity) -> validator.apply(entity, (IntegerProperty)this, factor));
return this; return this;
} }
@ -308,7 +307,7 @@ protected void setDeferredInit(final Function<ValidatableProperty<?, ?>[], T[]>
return self(); return self();
} }
public <E extends PropertiesProvider> T compute(final EntityManager em, final E entity) { public <E extends PropertiesProvider> T compute(final E entity) {
return computedBy.apply(entity); return computedBy.apply(entity);
} }

View File

@ -3,7 +3,6 @@ package net.hostsharing.hsadminng.mapper;
import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.ImmutablePair;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -57,19 +56,16 @@ public class PatchableMapWrapper<T> implements Map<String, T> {
return "{\n" return "{\n"
+ ( + (
keySet().stream().sorted() keySet().stream().sorted()
.map(k -> " \"" + k + "\": " + formatted(get(k)))) .map(k -> " \"" + k + "\": " + optionallyQuoted(get(k))))
.collect(joining(",\n") .collect(joining(",\n")
) )
+ "\n}\n"; + "\n}\n";
} }
private Object formatted(final Object value) { private Object optionallyQuoted(final Object value) {
if ( value == null || value instanceof Number || value instanceof Boolean ) { if ( value instanceof Number || value instanceof Boolean ) {
return value; return value;
} }
if ( value.getClass().isArray() ) {
return "\"" + Arrays.toString( (Object[]) value) + "\"";
}
return "\"" + value + "\""; return "\"" + value + "\"";
} }

View File

@ -4,7 +4,6 @@ import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity;
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity.HsHostingAssetEntityBuilder; import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity.HsHostingAssetEntityBuilder;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import jakarta.persistence.EntityManager;
import java.util.HashMap; import java.util.HashMap;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -25,8 +24,6 @@ class HsMariaDbUserHostingAssetValidatorUnitTest {
.caption("some valid test MariaDB-Instance") .caption("some valid test MariaDB-Instance")
.build(); .build();
private EntityManager em = null; // not actually needed in these test cases
private static HsHostingAssetEntityBuilder givenValidMariaDbUserBuilder() { private static HsHostingAssetEntityBuilder givenValidMariaDbUserBuilder() {
return HsHostingAssetEntity.builder() return HsHostingAssetEntity.builder()
.type(MARIADB_USER) .type(MARIADB_USER)
@ -61,7 +58,7 @@ class HsMariaDbUserHostingAssetValidatorUnitTest {
// when // when
// HashGenerator.nextSalt("Ly3LbsArtL5u4EVt"); // not needed for mysql_native_password // HashGenerator.nextSalt("Ly3LbsArtL5u4EVt"); // not needed for mysql_native_password
validator.prepareProperties(em, givenMariaDbUserHostingAsset); validator.prepareProperties(givenMariaDbUserHostingAsset);
// then // then
assertThat(givenMariaDbUserHostingAsset.getConfig()).containsExactlyInAnyOrderEntriesOf(ofEntries( assertThat(givenMariaDbUserHostingAsset.getConfig()).containsExactlyInAnyOrderEntriesOf(ofEntries(

View File

@ -5,7 +5,6 @@ import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity;
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity.HsHostingAssetEntityBuilder; import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity.HsHostingAssetEntityBuilder;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import jakarta.persistence.EntityManager;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.Base64; import java.util.Base64;
import java.util.HashMap; import java.util.HashMap;
@ -28,8 +27,6 @@ class HsPostgreSqlUserHostingAssetValidatorUnitTest {
.caption("some valid test PgSql-Instance") .caption("some valid test PgSql-Instance")
.build(); .build();
private EntityManager em = null; // not actually needed in these test cases
private static HsHostingAssetEntityBuilder givenValidMariaDbUserBuilder() { private static HsHostingAssetEntityBuilder givenValidMariaDbUserBuilder() {
return HsHostingAssetEntity.builder() return HsHostingAssetEntity.builder()
.type(PGSQL_USER) .type(PGSQL_USER)
@ -64,7 +61,7 @@ class HsPostgreSqlUserHostingAssetValidatorUnitTest {
// when // when
HashGenerator.nextSalt(new String(Base64.getDecoder().decode("L1QxSVNyTU81b3NZS1djNg=="), Charset.forName("latin1"))); HashGenerator.nextSalt(new String(Base64.getDecoder().decode("L1QxSVNyTU81b3NZS1djNg=="), Charset.forName("latin1")));
validator.prepareProperties(em, givenMariaDbUserHostingAsset); validator.prepareProperties(givenMariaDbUserHostingAsset);
// then // then
assertThat(givenMariaDbUserHostingAsset.getConfig()).containsExactlyInAnyOrderEntriesOf(ofEntries( assertThat(givenMariaDbUserHostingAsset.getConfig()).containsExactlyInAnyOrderEntriesOf(ofEntries(

View File

@ -5,7 +5,6 @@ import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity;
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType; import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import jakarta.persistence.EntityManager;
import java.util.HashMap; import java.util.HashMap;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -44,8 +43,6 @@ class HsUnixUserHostingAssetValidatorUnitTest {
))) )))
.build(); .build();
private EntityManager em = null; // not actually needed in these test cases
@Test @Test
void preparesUnixUser() { void preparesUnixUser() {
// given // given
@ -54,7 +51,7 @@ class HsUnixUserHostingAssetValidatorUnitTest {
// when // when
HashGenerator.nextSalt("Ly3LbsArtL5u4EVt"); HashGenerator.nextSalt("Ly3LbsArtL5u4EVt");
validator.prepareProperties(em, unixUserHostingAsset); validator.prepareProperties(unixUserHostingAsset);
// then // then
assertThat(unixUserHostingAsset.getConfig()).containsExactlyInAnyOrderEntriesOf(ofEntries( assertThat(unixUserHostingAsset.getConfig()).containsExactlyInAnyOrderEntriesOf(ofEntries(
@ -145,7 +142,7 @@ class HsUnixUserHostingAssetValidatorUnitTest {
// when // when
HashGenerator.nextSalt("Ly3LbsArtL5u4EVt"); HashGenerator.nextSalt("Ly3LbsArtL5u4EVt");
final var result = validator.revampProperties(em, unixUserHostingAsset, unixUserHostingAsset.getConfig()); final var result = validator.revampProperties(unixUserHostingAsset, unixUserHostingAsset.getConfig());
// then // then
assertThat(result).containsExactlyInAnyOrderEntriesOf(ofEntries( assertThat(result).containsExactlyInAnyOrderEntriesOf(ofEntries(

View File

@ -3,7 +3,6 @@ package net.hostsharing.hsadminng.hs.migration;
import com.opencsv.CSVParserBuilder; import com.opencsv.CSVParserBuilder;
import com.opencsv.CSVReader; import com.opencsv.CSVReader;
import com.opencsv.CSVReaderBuilder; import com.opencsv.CSVReaderBuilder;
import lombok.SneakyThrows;
import net.hostsharing.hsadminng.rbac.context.ContextBasedTest; import net.hostsharing.hsadminng.rbac.context.ContextBasedTest;
import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject; import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
import net.hostsharing.hsadminng.rbac.test.JpaAttempt; import net.hostsharing.hsadminng.rbac.test.JpaAttempt;
@ -38,7 +37,6 @@ import static java.lang.Boolean.parseBoolean;
import static java.util.Arrays.stream; import static java.util.Arrays.stream;
import static java.util.Objects.requireNonNull; import static java.util.Objects.requireNonNull;
import static java.util.Optional.ofNullable; import static java.util.Optional.ofNullable;
import static net.hostsharing.hsadminng.mapper.Array.emptyArray;
import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assumptions.assumeThat; import static org.assertj.core.api.Assumptions.assumeThat;
@ -115,14 +113,6 @@ public class CsvDataImport extends ContextBasedTest {
return records.subList(1, records.size()); return records.subList(1, records.size());
} }
@SneakyThrows
public static String[] parseCsvLine(final String csvLine) {
try (final var reader = new CSVReader(new StringReader(csvLine))) {
return ofNullable(reader.readNext()).orElse(emptyArray(String.class));
}
}
String[] trimAll(final String[] record) { String[] trimAll(final String[] record) {
for (int i = 0; i < record.length; ++i) { for (int i = 0; i < record.length; ++i) {
if (record[i] != null) { if (record[i] != null) {

View File

@ -23,23 +23,18 @@ import org.springframework.test.annotation.Commit;
import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext;
import java.io.Reader; import java.io.Reader;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function; import java.util.function.Function;
import static java.util.Arrays.stream; import static java.util.Arrays.stream;
import static java.util.Map.entry;
import static java.util.Optional.ofNullable; import static java.util.Optional.ofNullable;
import static java.util.stream.Collectors.toMap; import static java.util.stream.Collectors.toMap;
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.CLOUD_SERVER; import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.CLOUD_SERVER;
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.EMAIL_ALIAS;
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.IPV4_NUMBER; import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.IPV4_NUMBER;
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_SERVER; import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_SERVER;
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_WEBSPACE; import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_WEBSPACE;
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.UNIX_USER;
import static net.hostsharing.hsadminng.mapper.PostgresDateRange.toPostgresDateRange; import static net.hostsharing.hsadminng.mapper.PostgresDateRange.toPostgresDateRange;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assumptions.assumeThat; import static org.assertj.core.api.Assumptions.assumeThat;
@ -96,7 +91,6 @@ public class ImportHostingAssets extends ImportOfficeData {
static final Integer IP_NUMBER_ID_OFFSET = 1000000; static final Integer IP_NUMBER_ID_OFFSET = 1000000;
static final Integer HIVE_ID_OFFSET = 2000000; static final Integer HIVE_ID_OFFSET = 2000000;
static final Integer PACKET_ID_OFFSET = 3000000; static final Integer PACKET_ID_OFFSET = 3000000;
static final Integer UNIXUSER_ID_OFFSET = 4000000;
record Hive(int hive_id, String hive_name, int inet_addr_id, AtomicReference<HsHostingAssetEntity> serverRef) {} record Hive(int hive_id, String hive_name, int inet_addr_id, AtomicReference<HsHostingAssetEntity> serverRef) {}
@ -267,74 +261,6 @@ public class ImportHostingAssets extends ImportOfficeData {
"""); """);
} }
@Test
@Order(14010)
void importUnixUsers() {
try (Reader reader = resourceReader(MIGRATION_DATA_PATH + "/hosting/unixuser.csv")) {
final var lines = readAllLines(reader);
importUnixUsers(justHeader(lines), withoutHeader(lines));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Test
@Order(14019)
void verifyUnixUsers() {
assumeThatWeAreImportingControlledTestData();
// no contacts yet => mostly null values
assertThat(firstOfEachType(15, UNIX_USER)).isEqualToIgnoringWhitespace("""
{
4005803=HsHostingAssetEntity(UNIX_USER, lug00, LUGs, MANAGED_WEBSPACE:lug00, { "HDD hard quota": 0, "HDD soft quota": 0, "SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "shell": "/bin/bash", "userid": 102090}),
4005805=HsHostingAssetEntity(UNIX_USER, lug00-wla.1, Paul Klemm, MANAGED_WEBSPACE:lug00, { "HDD hard quota": 0, "HDD soft quota": 0, "SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "shell": "/bin/bash", "userid": 102091}),
4005809=HsHostingAssetEntity(UNIX_USER, lug00-wla.2, Walter Müller, MANAGED_WEBSPACE:lug00, { "HDD hard quota": 0, "HDD soft quota": 0, "SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "shell": "/bin/bash", "userid": 102093}),
4005811=HsHostingAssetEntity(UNIX_USER, lug00-ola.a, LUG OLA - POP a, MANAGED_WEBSPACE:lug00, { "HDD hard quota": 0, "HDD soft quota": 0, "SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "shell": "/usr/bin/passwd", "userid": 102094}),
4005813=HsHostingAssetEntity(UNIX_USER, lug00-ola.b, LUG OLA - POP b, MANAGED_WEBSPACE:lug00, { "HDD hard quota": 0, "HDD soft quota": 0, "SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "shell": "/usr/bin/passwd", "userid": 102095}),
4005835=HsHostingAssetEntity(UNIX_USER, lug00-test, Test, MANAGED_WEBSPACE:lug00, { "HDD hard quota": 0, "HDD soft quota": 0, "SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "shell": "/usr/bin/passwd", "userid": 102106}),
4005964=HsHostingAssetEntity(UNIX_USER, mim00, Michael Mellis, MANAGED_WEBSPACE:mim00, { "HDD hard quota": 0, "HDD soft quota": 0, "SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "shell": "/bin/bash", "userid": 102147}),
4005966=HsHostingAssetEntity(UNIX_USER, mim00-1981, Jahrgangstreffen 1981, MANAGED_WEBSPACE:mim00, { "HDD hard quota": 0, "HDD soft quota": 0, "SSD hard quota": 256, "SSD soft quota": 128, "locked": false, "shell": "/bin/bash", "userid": 102148}),
4005990=HsHostingAssetEntity(UNIX_USER, mim00-mail, Mailbox, MANAGED_WEBSPACE:mim00, { "HDD hard quota": 0, "HDD soft quota": 0, "SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "shell": "/bin/bash", "userid": 102160}),
4100705=HsHostingAssetEntity(UNIX_USER, hsh00-mim, Michael Mellis, MANAGED_WEBSPACE:hsh00, { "HDD hard quota": 0, "HDD soft quota": 0, "SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "shell": "/bin/false", "userid": 10003}),
4100824=HsHostingAssetEntity(UNIX_USER, hsh00, Hostsharing Paket, MANAGED_WEBSPACE:hsh00, { "HDD hard quota": 0, "HDD soft quota": 0, "SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "shell": "/bin/bash", "userid": 10000}),
4167846=HsHostingAssetEntity(UNIX_USER, hsh00-dph, hsh00-uph, MANAGED_WEBSPACE:hsh00, { "HDD hard quota": 0, "HDD soft quota": 0, "SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "shell": "/bin/false", "userid": 110568}),
4169546=HsHostingAssetEntity(UNIX_USER, dph00, Reinhard Wiese, MANAGED_WEBSPACE:dph00, { "HDD hard quota": 0, "HDD soft quota": 0, "SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "shell": "/bin/bash", "userid": 110593}),
4169596=HsHostingAssetEntity(UNIX_USER, dph00-uph, Domain admin, MANAGED_WEBSPACE:dph00, { "HDD hard quota": 0, "HDD soft quota": 0, "SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "shell": "/bin/bash", "userid": 110594})
}
""");
}
@Test
@Order(14020)
void importEmailAliases() {
try (Reader reader = resourceReader(MIGRATION_DATA_PATH + "/hosting/emailalias.csv")) {
final var lines = readAllLines(reader);
importEmailAliases(justHeader(lines), withoutHeader(lines));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Test
@Order(14029)
void verifyEmailAliases() {
assumeThatWeAreImportingControlledTestData();
// no contacts yet => mostly null values
assertThat(firstOfEachType(15, EMAIL_ALIAS)).isEqualToIgnoringWhitespace("""
{
4002403=HsHostingAssetEntity(EMAIL_ALIAS, lug00, lug00, MANAGED_WEBSPACE:lug00, { "target": "[michael.mellis@example.com]"}),
4002405=HsHostingAssetEntity(EMAIL_ALIAS, lug00-wla-listar, lug00-wla-listar, MANAGED_WEBSPACE:lug00, { "target": "[|/home/pacs/lug00/users/in/mailinglist/listar]"}),
4002429=HsHostingAssetEntity(EMAIL_ALIAS, mim00, mim00, MANAGED_WEBSPACE:mim00, { "target": "[mim12-mi@mim12.hostsharing.net]"}),
4002431=HsHostingAssetEntity(EMAIL_ALIAS, mim00-abruf, mim00-abruf, MANAGED_WEBSPACE:mim00, { "target": "[michael.mellis@hostsharing.net]"}),
4002449=HsHostingAssetEntity(EMAIL_ALIAS, mim00-hhfx, mim00-hhfx, MANAGED_WEBSPACE:mim00, { "target": "[mim00-hhfx, |/usr/bin/formail -I 'Reply-To: hamburger-fx@example.net' | /usr/lib/sendmail mim00-hhfx-l]"}),
4002451=HsHostingAssetEntity(EMAIL_ALIAS, mim00-hhfx-l, mim00-hhfx-l, MANAGED_WEBSPACE:mim00, { "target": "[:include:/home/pacs/mim00/etc/hhfx.list]"})
}
""");
}
// --------------------------------------------------------------------------------------------
@Test @Test
@Order(11400) @Order(11400)
void validateBookingItems() { void validateBookingItems() {
@ -352,7 +278,7 @@ public class ImportHostingAssets extends ImportOfficeData {
void validateHostingAssets() { void validateHostingAssets() {
hostingAssets.forEach((id, ha) -> { hostingAssets.forEach((id, ha) -> {
try { try {
new HostingAssetEntitySaveProcessor(em, ha) new HostingAssetEntitySaveProcessor(ha)
.preprocessEntity() .preprocessEntity()
.validateEntity(); .validateEntity();
} catch (final Exception exc) { } catch (final Exception exc) {
@ -361,8 +287,6 @@ public class ImportHostingAssets extends ImportOfficeData {
}); });
} }
// --------------------------------------------------------------------------------------------
@Test @Test
@Order(19000) @Order(19000)
@Commit @Commit
@ -384,8 +308,6 @@ public class ImportHostingAssets extends ImportOfficeData {
persistHostingAssetsOfType(MANAGED_SERVER); persistHostingAssetsOfType(MANAGED_SERVER);
persistHostingAssetsOfType(MANAGED_WEBSPACE); persistHostingAssetsOfType(MANAGED_WEBSPACE);
persistHostingAssetsOfType(IPV4_NUMBER); persistHostingAssetsOfType(IPV4_NUMBER);
persistHostingAssetsOfType(UNIX_USER);
persistHostingAssetsOfType(EMAIL_ALIAS);
} }
@Test @Test
@ -401,14 +323,12 @@ public class ImportHostingAssets extends ImportOfficeData {
persist(key, HsBookingItemEntityValidatorRegistry.validated(bi)); persist(key, HsBookingItemEntityValidatorRegistry.validated(bi));
} }
// ============================================================================================
private void persistHostingAssetsOfType(final HsHostingAssetType hsHostingAssetType) { private void persistHostingAssetsOfType(final HsHostingAssetType hsHostingAssetType) {
jpaAttempt.transacted(() -> { jpaAttempt.transacted(() -> {
context(rbacSuperuser); context(rbacSuperuser);
hostingAssets.forEach((key, ha) -> { hostingAssets.forEach((key, ha) -> {
if (ha.getType() == hsHostingAssetType) { if (ha.getType() == hsHostingAssetType) {
new HostingAssetEntitySaveProcessor(em, ha) new HostingAssetEntitySaveProcessor(ha)
.preprocessEntity() .preprocessEntity()
.validateEntity() .validateEntity()
.prepareForSave() .prepareForSave()
@ -482,17 +402,12 @@ public class ImportHostingAssets extends ImportOfficeData {
bookingItems.put(PACKET_ID_OFFSET + packet_id, bookingItem); bookingItems.put(PACKET_ID_OFFSET + packet_id, bookingItem);
final var haType = determineHaType(basepacket_code); final var haType = determineHaType(basepacket_code);
logError(() -> assertThat(!free || haType == MANAGED_WEBSPACE || bookingItem.getRelatedProject() logError(() -> assertThat(!free || haType == MANAGED_WEBSPACE || bookingItem.getRelatedProject().getDebitor().getDefaultPrefix().equals("hsh"))
.getDebitor() .as("packet.free only supported for Hostsharing-Assets and ManagedWebspace in customer-ManagedServer, but is set for " + packet_name)
.getDefaultPrefix()
.equals("hsh"))
.as("packet.free only supported for Hostsharing-Assets and ManagedWebspace in customer-ManagedServer, but is set for "
+ packet_name)
.isTrue()); .isTrue());
final var asset = HsHostingAssetEntity.builder() final var asset = HsHostingAssetEntity.builder()
.isLoaded(haType .isLoaded(haType == MANAGED_WEBSPACE) // this turns off identifier validation to accept former default prefixes
== MANAGED_WEBSPACE) // this turns off identifier validation to accept former default prefixes
.type(haType) .type(haType)
.identifier(packet_name) .identifier(packet_name)
.bookingItem(bookingItem) .bookingItem(bookingItem)
@ -546,9 +461,9 @@ public class ImportHostingAssets extends ImportOfficeData {
case "DAEMON" -> "Daemons"; case "DAEMON" -> "Daemons";
case "MULTI" -> "Multi"; case "MULTI" -> "Multi";
case "CPU" -> "CPU"; case "CPU" -> "CPU";
case "RAM" -> returning("RAM", convert = v -> v / 1024); case "RAM" -> returning("RAM", convert = v -> v/1024);
case "QUOTA" -> returning("SSD", convert = v -> v / 1024); case "QUOTA" -> returning("SSD", convert = v -> v/1024);
case "STORAGE" -> returning("HDD", convert = v -> v / 1024); case "STORAGE" -> returning("HDD", convert = v -> v/1024);
case "TRAFFIC" -> "Traffic"; case "TRAFFIC" -> "Traffic";
case "OFFICE" -> returning("Online Office Server", convert = v -> v == 1); case "OFFICE" -> returning("Online Office Server", convert = v -> v == 1);
@ -611,7 +526,7 @@ public class ImportHostingAssets extends ImportOfficeData {
case "SLAPLAT8H" -> "EXT8H"; case "SLAPLAT8H" -> "EXT8H";
default -> throw new IllegalArgumentException("unknown basecomponent_code: " + basecomponent_code); default -> throw new IllegalArgumentException("unknown basecomponent_code: " + basecomponent_code);
}; };
if (ofNullable(asset.getBookingItem().getResources().get(name)).map("BASIC"::equals).orElse(true)) { if ( ofNullable(asset.getBookingItem().getResources().get(name)).map("BASIC"::equals).orElse(true) ) {
asset.getBookingItem().getResources().put(name, slaValue); asset.getBookingItem().getResources().put(name, slaValue);
} }
} else if (name.startsWith("SLA")) { } else if (name.startsWith("SLA")) {
@ -622,62 +537,7 @@ public class ImportHostingAssets extends ImportOfficeData {
}); });
} }
private void importUnixUsers(final String[] header, final List<String[]> records) { <V> V returning(final V value, final Object... assignments) {
final var columns = new Columns(header);
records.stream()
.map(this::trimAll)
.map(row -> new Record(columns, row))
.forEach(rec -> {
final var unixuser_id = rec.getInteger("unixuser_id");
final var packet_id = rec.getInteger("packet_id");
final var unixUserAsset = HsHostingAssetEntity.builder()
.type(UNIX_USER)
.parentAsset(hostingAssets.get(PACKET_ID_OFFSET+packet_id))
.identifier(rec.getString("name"))
.caption(rec.getString("comment"))
.config(new HashMap<>(Map.ofEntries(
entry("shell", rec.getString("shell")),
// entry("homedir", rec.getString("homedir")), do not import, it's calculated
entry("locked", rec.getBoolean("locked")),
entry("userid", rec.getInteger("userid")),
entry("SSD soft quota", rec.getInteger("quota_softlimit")),
entry("SSD hard quota", rec.getInteger("quota_hardlimit")),
entry("HDD soft quota", rec.getInteger("storage_softlimit")),
entry("HDD hard quota", rec.getInteger("storage_hardlimit"))
)))
.build();
hostingAssets.put(UNIXUSER_ID_OFFSET + unixuser_id, unixUserAsset);
});
}
private void importEmailAliases(final String[] header, final List<String[]> records) {
final var columns = new Columns(header);
records.stream()
.map(this::trimAll)
.map(row -> new Record(columns, row))
.forEach(rec -> {
final var unixuser_id = rec.getInteger("emailalias_id");
final var packet_id = rec.getInteger("pac_id");
final var targets = parseCsvLine(rec.getString("target"));
final var unixUserAsset = HsHostingAssetEntity.builder()
.type(EMAIL_ALIAS)
.parentAsset(hostingAssets.get(PACKET_ID_OFFSET+packet_id))
.identifier(rec.getString("name"))
.caption(rec.getString("name"))
.config(Map.ofEntries(
entry("target", targets)
))
.build();
hostingAssets.put(UNIXUSER_ID_OFFSET + unixuser_id, unixUserAsset);
});
}
// ============================================================================================
<V> V returning(
final V value,
@SuppressWarnings("unused") final Object... assignments // DSL-hack: just used for side effects on caller-side
) {
return value; return value;
} }
@ -722,11 +582,7 @@ public class ImportHostingAssets extends ImportOfficeData {
.filter(hae -> hae.getValue().getType() == t) .filter(hae -> hae.getValue().getType() == t)
.limit(maxCount) .limit(maxCount)
) )
.collect(toMap(Map.Entry::getKey, Map.Entry::getValue, ImportHostingAssets::uniqueKeys, TreeMap::new))); .collect(toMap(Map.Entry::getKey, Map.Entry::getValue)));
}
protected static <V> V uniqueKeys(final V v1, final V v2) {
throw new RuntimeException(String.format("Duplicate key for values %s and %s", v1, v2));
} }
private String firstOfEachType( private String firstOfEachType(

View File

@ -5,7 +5,6 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource; import org.junit.jupiter.params.provider.ValueSource;
import jakarta.persistence.EntityManager;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -20,7 +19,6 @@ class PasswordPropertyUnitTest {
private final ValidatableProperty<PasswordProperty, String> passwordProp = private final ValidatableProperty<PasswordProperty, String> passwordProp =
passwordProperty("password").minLength(8).maxLength(40).hashedUsing(LINUX_SHA512).writeOnly(); passwordProperty("password").minLength(8).maxLength(40).hashedUsing(LINUX_SHA512).writeOnly();
private final List<String> violations = new ArrayList<>(); private final List<String> violations = new ArrayList<>();
private EntityManager em = null; // not actually needed in these test cases
@ParameterizedTest @ParameterizedTest
@ValueSource(strings = { @ValueSource(strings = {
@ -101,7 +99,7 @@ class PasswordPropertyUnitTest {
void shouldComputeHash() { void shouldComputeHash() {
// when // when
final var result = passwordProp.compute(em, new PropertiesProvider() { final var result = passwordProp.compute(new PropertiesProvider() {
@Override @Override
public Map<String, Object> directProps() { public Map<String, Object> directProps() {

View File

@ -1,7 +0,0 @@
emailalias_id;pac_id;name;target
2403;1094;lug00;michael.mellis@example.com
2405;1094;lug00-wla-listar;|/home/pacs/lug00/users/in/mailinglist/listar
2429;1112;mim00;mim12-mi@mim12.hostsharing.net
2431;1112;mim00-abruf;michael.mellis@hostsharing.net
2449;1112;mim00-hhfx;"mim00-hhfx,""|/usr/bin/formail -I 'Reply-To: hamburger-fx@example.net' | /usr/lib/sendmail mim00-hhfx-l"""
2451;1112;mim00-hhfx-l;:include:/home/pacs/mim00/etc/hhfx.list
1 emailalias_id pac_id name target
2 2403 1094 lug00 michael.mellis@example.com
3 2405 1094 lug00-wla-listar |/home/pacs/lug00/users/in/mailinglist/listar
4 2429 1112 mim00 mim12-mi@mim12.hostsharing.net
5 2431 1112 mim00-abruf michael.mellis@hostsharing.net
6 2449 1112 mim00-hhfx mim00-hhfx,"|/usr/bin/formail -I 'Reply-To: hamburger-fx@example.net' | /usr/lib/sendmail mim00-hhfx-l"
7 2451 1112 mim00-hhfx-l :include:/home/pacs/mim00/etc/hhfx.list

View File

@ -1,19 +0,0 @@
unixuser_id;name;comment;shell;homedir;locked;packet_id;userid;quota_softlimit;quota_hardlimit;storage_softlimit;storage_hardlimit
100824;hsh00;Hostsharing Paket;/bin/bash;/home/pacs/hsh00;0;630;10000;0;0;0;0
5803;lug00;LUGs;/bin/bash;/home/pacs/lug00;0;1094;102090;0;0;0;0
5805;lug00-wla.1;Paul Klemm;/bin/bash;/home/pacs/lug00/users/deaf;0;1094;102091;0;0;0;0
5809;lug00-wla.2;Walter Müller;/bin/bash;/home/pacs/lug00/users/marl;0;1094;102093;0;0;0;0
5811;lug00-ola.a;LUG OLA - POP a;/usr/bin/passwd;/home/pacs/lug00/users/marl.a;1;1094;102094;0;0;0;0
5813;lug00-ola.b;LUG OLA - POP b;/usr/bin/passwd;/home/pacs/lug00/users/marl.b;1;1094;102095;0;0;0;0
5835;lug00-test;Test;/usr/bin/passwd;/home/pacs/lug00/users/test;0;1094;102106;0;0;0;0
100705;hsh00-mim;Michael Mellis;/bin/false;/home/pacs/hsh00/users/mi;0;630;10003;0;0;0;0
5964;mim00;Michael Mellis;/bin/bash;/home/pacs/mim00;0;1112;102147;0;0;0;0
5966;mim00-1981;Jahrgangstreffen 1981;/bin/bash;/home/pacs/mim00/users/1981;0;1112;102148;128;256;0;0
5990;mim00-mail;Mailbox;/bin/bash;/home/pacs/mim00/users/mail;0;1112;102160;0;0;0;0
167846;hsh00-dph;hsh00-uph;/bin/false;/home/pacs/hsh00/users/uph;0;630;110568;0;0;0;0
169546;dph00;Reinhard Wiese;/bin/bash;/home/pacs/dph00;0;19959;110593;0;0;0;0
169596;dph00-uph;Domain admin;/bin/bash;/home/pacs/dph00/users/uph;0;19959;110594;0;0;0;0
1 unixuser_id name comment shell homedir locked packet_id userid quota_softlimit quota_hardlimit storage_softlimit storage_hardlimit
2 100824 hsh00 Hostsharing Paket /bin/bash /home/pacs/hsh00 0 630 10000 0 0 0 0
3 5803 lug00 LUGs /bin/bash /home/pacs/lug00 0 1094 102090 0 0 0 0
4 5805 lug00-wla.1 Paul Klemm /bin/bash /home/pacs/lug00/users/deaf 0 1094 102091 0 0 0 0
5 5809 lug00-wla.2 Walter Müller /bin/bash /home/pacs/lug00/users/marl 0 1094 102093 0 0 0 0
6 5811 lug00-ola.a LUG OLA - POP a /usr/bin/passwd /home/pacs/lug00/users/marl.a 1 1094 102094 0 0 0 0
7 5813 lug00-ola.b LUG OLA - POP b /usr/bin/passwd /home/pacs/lug00/users/marl.b 1 1094 102095 0 0 0 0
8 5835 lug00-test Test /usr/bin/passwd /home/pacs/lug00/users/test 0 1094 102106 0 0 0 0
9 100705 hsh00-mim Michael Mellis /bin/false /home/pacs/hsh00/users/mi 0 630 10003 0 0 0 0
10 5964 mim00 Michael Mellis /bin/bash /home/pacs/mim00 0 1112 102147 0 0 0 0
11 5966 mim00-1981 Jahrgangstreffen 1981 /bin/bash /home/pacs/mim00/users/1981 0 1112 102148 128 256 0 0
12 5990 mim00-mail Mailbox /bin/bash /home/pacs/mim00/users/mail 0 1112 102160 0 0 0 0
13 167846 hsh00-dph hsh00-uph /bin/false /home/pacs/hsh00/users/uph 0 630 110568 0 0 0 0
14 169546 dph00 Reinhard Wiese /bin/bash /home/pacs/dph00 0 19959 110593 0 0 0 0
15 169596 dph00-uph Domain admin /bin/bash /home/pacs/dph00/users/uph 0 19959 110594 0 0 0 0