import-unix-user-and-email-aliases #81
@ -32,6 +32,7 @@ import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.OneToOne;
|
||||
import jakarta.persistence.PostLoad;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.Transient;
|
||||
import jakarta.persistence.Version;
|
||||
@ -124,6 +125,14 @@ public class HsBookingItemEntity implements Stringifyable, RbacObject<HsBookingI
|
||||
@Transient
|
||||
private PatchableMapWrapper<Object> resourcesWrapper;
|
||||
|
||||
@Transient
|
||||
private boolean isLoaded;
|
||||
|
||||
@PostLoad
|
||||
public void markAsLoaded() {
|
||||
this.isLoaded = true;
|
||||
}
|
||||
|
||||
public PatchableMapWrapper<Object> getResources() {
|
||||
return PatchableMapWrapper.of(resourcesWrapper, (newWrapper) -> {resourcesWrapper = newWrapper; }, resources );
|
||||
}
|
||||
|
@ -40,6 +40,17 @@ public class HostingAssetEntitySaveProcessor {
|
||||
return this;
|
||||
}
|
||||
|
||||
/// validates the entity itself including its properties, but ignoring some error messages for import of legacy data
|
||||
public HostingAssetEntitySaveProcessor validateEntityIgnoring(final String ignoreRegExp) {
|
||||
step("validateEntity", "prepareForSave");
|
||||
MultiValidationException.throwIfNotEmpty(
|
||||
validator.validateEntity(entity).stream()
|
||||
.filter(errorMsg -> !errorMsg.matches(ignoreRegExp))
|
||||
.toList()
|
||||
);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// hashing passwords etc.
|
||||
@SuppressWarnings("unchecked")
|
||||
public HostingAssetEntitySaveProcessor prepareForSave() {
|
||||
|
@ -18,7 +18,7 @@ import static net.hostsharing.hsadminng.hs.validation.StringProperty.stringPrope
|
||||
class HsDomainDnsSetupHostingAssetValidator extends HostingAssetEntityValidator {
|
||||
|
||||
// according to RFC 1035 (section 5) and RFC 1034
|
||||
static final String RR_REGEX_NAME = "([a-z0-9\\._-]+|@)\\s+";
|
||||
static final String RR_REGEX_NAME = "([a-z0-9\\.-]+|@)\\s+";
|
||||
static final String RR_REGEX_TTL = "(([1-9][0-9]*[mMhHdDwW]{0,1})+\\s+)*";
|
||||
static final String RR_REGEX_IN = "IN\\s+"; // record class IN for Internet
|
||||
static final String RR_RECORD_TYPE = "[A-Z]+\\s+";
|
||||
|
@ -9,7 +9,6 @@ import jakarta.persistence.EntityManager;
|
||||
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.IntegerProperty.integerProperty;
|
||||
import static net.hostsharing.hsadminng.hs.validation.PasswordProperty.passwordProperty;
|
||||
import static net.hostsharing.hsadminng.hs.validation.StringProperty.stringProperty;
|
||||
@ -24,16 +23,17 @@ class HsUnixUserHostingAssetValidator extends HostingAssetEntityValidator {
|
||||
AlarmContact.isOptional(),
|
||||
|
||||
booleanProperty("locked").readOnly(),
|
||||
integerProperty("userid").computedBy(HsUnixUserHostingAssetValidator::computeUserId),
|
||||
integerProperty("userid").readOnly().initializedBy(HsUnixUserHostingAssetValidator::computeUserId),
|
||||
|
||||
integerProperty("SSD hard quota").unit("MB").maxFrom("SSD").withFactor(1024).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(),
|
||||
stringProperty("shell")
|
||||
// TODO.spec: do we want to change them all to /usr/bin/, also in import?
|
||||
.provided("/bin/false", "/bin/bash", "/bin/csh", "/bin/dash", "/usr/bin/tcsh", "/usr/bin/zsh", "/usr/bin/passwd")
|
||||
.withDefault("/bin/false"),
|
||||
stringProperty("homedir").readOnly().computedBy(HsUnixUserHostingAssetValidator::computeHomedir),
|
||||
stringProperty("homedir").readOnly().renderedBy(HsUnixUserHostingAssetValidator::computeHomedir),
|
||||
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());
|
||||
// TODO.spec: public SSH keys? (only if hsadmin-ng is only accessible with 2FA)
|
||||
|
@ -14,6 +14,9 @@ import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.Arrays.stream;
|
||||
import static java.util.Collections.emptyList;
|
||||
import static net.hostsharing.hsadminng.hs.validation.ValidatableProperty.ComputeMode.IN_INIT;
|
||||
import static net.hostsharing.hsadminng.hs.validation.ValidatableProperty.ComputeMode.IN_PREP;
|
||||
import static net.hostsharing.hsadminng.hs.validation.ValidatableProperty.ComputeMode.IN_REVAMP;
|
||||
|
||||
// TODO.refa: rename to HsEntityProcessor, also subclasses
|
||||
public abstract class HsEntityValidator<E extends PropertiesProvider> {
|
||||
@ -109,7 +112,7 @@ public abstract class HsEntityValidator<E extends PropertiesProvider> {
|
||||
|
||||
public void prepareProperties(final EntityManager em, final E entity) {
|
||||
stream(propertyValidators).forEach(p -> {
|
||||
if (!p.isReadOnly() && p.isComputed()) {
|
||||
if (p.isComputed(IN_PREP) || p.isComputed(IN_INIT) && !entity.isLoaded() ) {
|
||||
entity.directProps().put(p.propertyName, p.compute(em, entity));
|
||||
}
|
||||
});
|
||||
@ -120,7 +123,7 @@ public abstract class HsEntityValidator<E extends PropertiesProvider> {
|
||||
stream(propertyValidators).forEach(p -> {
|
||||
if (p.isWriteOnly()) {
|
||||
copy.remove(p.propertyName);
|
||||
} else if (p.isReadOnly() && p.isComputed()) {
|
||||
} else if (p.isComputed(IN_REVAMP)) {
|
||||
copy.put(p.propertyName, p.compute(em, entity));
|
||||
}
|
||||
});
|
||||
|
@ -1,8 +1,8 @@
|
||||
package net.hostsharing.hsadminng.hs.validation;
|
||||
|
||||
import lombok.Setter;
|
||||
import net.hostsharing.hsadminng.hash.HashGenerator;
|
||||
import net.hostsharing.hsadminng.hash.HashGenerator.Algorithm;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
@ -13,7 +13,10 @@ import static net.hostsharing.hsadminng.mapper.Array.insertNewEntriesAfterExisti
|
||||
@Setter
|
||||
public class PasswordProperty extends StringProperty<PasswordProperty> {
|
||||
|
||||
private static final String[] KEY_ORDER = insertNewEntriesAfterExistingEntry(StringProperty.KEY_ORDER, "computed", "hashedUsing");
|
||||
private static final String[] KEY_ORDER = insertNewEntriesAfterExistingEntry(
|
||||
StringProperty.KEY_ORDER,
|
||||
"computed",
|
||||
hsh-michaelhoennig marked this conversation as resolved
|
||||
"hashedUsing");
|
||||
|
||||
private Algorithm hashedUsing;
|
||||
|
||||
@ -34,10 +37,11 @@ public class PasswordProperty extends StringProperty<PasswordProperty> {
|
||||
|
||||
public PasswordProperty hashedUsing(final Algorithm algorithm) {
|
||||
this.hashedUsing = algorithm;
|
||||
computedBy((em, entity)
|
||||
-> ofNullable(entity.getDirectValue(propertyName, String.class))
|
||||
.map(password -> HashGenerator.using(algorithm).withRandomSalt().hash(password))
|
||||
.orElse(null));
|
||||
computedBy(
|
||||
ComputeMode.IN_PREP,
|
||||
(em, entity) -> ofNullable(entity.getDirectValue(propertyName, String.class))
|
||||
.map(password -> HashGenerator.using(algorithm).withRandomSalt().hash(password))
|
||||
.orElse(null));
|
||||
return self();
|
||||
}
|
||||
|
||||
@ -69,9 +73,10 @@ public class PasswordProperty extends StringProperty<PasswordProperty> {
|
||||
}
|
||||
}
|
||||
|
||||
final long groupsCovered = Stream.of(hasLowerCase, hasUpperCase, hasDigit, hasSpecialChar).filter(v->v).count();
|
||||
if ( groupsCovered < 3) {
|
||||
result.add(propertyName + "' must contain at least one character of at least 3 of the following groups: upper case letters, lower case letters, digits, special characters");
|
||||
final long groupsCovered = Stream.of(hasLowerCase, hasUpperCase, hasDigit, hasSpecialChar).filter(v -> v).count();
|
||||
if (groupsCovered < 3) {
|
||||
result.add(propertyName
|
||||
+ "' must contain at least one character of at least 3 of the following groups: upper case letters, lower case letters, digits, special characters");
|
||||
}
|
||||
if (containsColon) {
|
||||
result.add(propertyName + "' must not contain colon (':')");
|
||||
|
@ -4,6 +4,7 @@ import java.util.Map;
|
||||
|
||||
public interface PropertiesProvider {
|
||||
|
||||
boolean isLoaded();
|
||||
Map<String, Object> directProps();
|
||||
Object getContextValue(final String propName);
|
||||
|
||||
@ -11,6 +12,10 @@ public interface PropertiesProvider {
|
||||
return cast(propName, directProps().get(propName), clazz, null);
|
||||
}
|
||||
|
||||
default <T> T getDirectValue(final String propName, final Class<T> clazz, final T defaultValue) {
|
||||
return cast(propName, directProps().get(propName), clazz, defaultValue);
|
||||
}
|
||||
|
||||
default <T> T getContextValue(final String propName, final Class<T> clazz) {
|
||||
return cast(propName, getContextValue(propName), clazz, null);
|
||||
}
|
||||
|
@ -48,11 +48,17 @@ public abstract class ValidatableProperty<P extends ValidatableProperty<?, ?>, T
|
||||
private Set<String> requiresAtMaxOneOf;
|
||||
private T defaultValue;
|
||||
|
||||
protected enum ComputeMode {
|
||||
IN_INIT,
|
||||
IN_PREP,
|
||||
IN_REVAMP
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
private BiFunction<EntityManager, PropertiesProvider, T> computedBy;
|
||||
|
||||
@Accessors(makeFinal = true, chain = true, fluent = false)
|
||||
private boolean computed; // used in descriptor, because computedBy cannot be rendered to a text string
|
||||
private ComputeMode computed; // name 'computed' instead 'computeMode' for better readability in property description
|
||||
|
||||
@Accessors(makeFinal = true, chain = true, fluent = false)
|
||||
private boolean readOnly;
|
||||
@ -77,7 +83,7 @@ public abstract class ValidatableProperty<P extends ValidatableProperty<?, ?>, T
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void setDeferredInit(final Function<ValidatableProperty<?, ?>[], T[]> function) {
|
||||
protected void setDeferredInit(final Function<ValidatableProperty<?, ?>[], T[]> function) {
|
||||
this.deferredInit = function;
|
||||
}
|
||||
|
||||
@ -236,8 +242,8 @@ protected void setDeferredInit(final Function<ValidatableProperty<?, ?>[], T[]>
|
||||
protected abstract void validate(final List<String> result, final T propValue, final PropertiesProvider propProvider);
|
||||
|
||||
public void verifyConsistency(final Map.Entry<? extends Enum<?>, ?> typeDef) {
|
||||
if (required == null && requiresAtLeastOneOf == null && requiresAtMaxOneOf == null && !readOnly && !computed) {
|
||||
throw new IllegalStateException(typeDef.getKey() + "[" + propertyName + "] not fully initialized, please call either .computed(...), .readOnly(), .required(), .optional(), .withDefault(...), .requiresAtLeastOneOf(...) or .requiresAtMaxOneOf(...)" );
|
||||
if (required == null && requiresAtLeastOneOf == null && requiresAtMaxOneOf == null && !readOnly && defaultValue == null) {
|
||||
throw new IllegalStateException(typeDef.getKey() + "[" + propertyName + "] not fully initialized, please call either .readOnly(), .required(), .optional(), .withDefault(...), .requiresAtLeastOneOf(...) or .requiresAtMaxOneOf(...)" );
|
||||
}
|
||||
}
|
||||
|
||||
@ -302,12 +308,24 @@ protected void setDeferredInit(final Function<ValidatableProperty<?, ?>[], T[]>
|
||||
.toList();
|
||||
}
|
||||
|
||||
public P computedBy(final BiFunction<EntityManager, PropertiesProvider, T> compute) {
|
||||
public P initializedBy(final BiFunction<EntityManager, PropertiesProvider, T> compute) {
|
||||
return computedBy(ComputeMode.IN_INIT, compute);
|
||||
}
|
||||
|
||||
public P renderedBy(final BiFunction<EntityManager, PropertiesProvider, T> compute) {
|
||||
return computedBy(ComputeMode.IN_REVAMP, compute);
|
||||
}
|
||||
|
||||
protected P computedBy(final ComputeMode computeMode, final BiFunction<EntityManager, PropertiesProvider, T> compute) {
|
||||
this.computedBy = compute;
|
||||
this.computed = true;
|
||||
this.computed = computeMode;
|
||||
return self();
|
||||
}
|
||||
|
||||
public boolean isComputed(final ComputeMode computeMode) {
|
||||
return computed == computeMode;
|
||||
}
|
||||
|
||||
public <E extends PropertiesProvider> T compute(final EntityManager em, final E entity) {
|
||||
return computedBy.apply(em, entity);
|
||||
}
|
||||
|
@ -26,6 +26,8 @@ import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
@ -230,7 +232,7 @@ public class CsvDataImport extends ContextBasedTest {
|
||||
}
|
||||
|
||||
void logErrors() {
|
||||
assumeThat(errors).isEmpty();
|
||||
assertThat(errors).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@ -298,12 +300,17 @@ class Record {
|
||||
}
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface ContinueOnFailure {
|
||||
}
|
||||
|
||||
class OrderedDependedTestsExtension implements TestWatcher, BeforeEachCallback {
|
||||
|
||||
private static boolean previousTestsPassed = true;
|
||||
|
||||
public void testFailed(ExtensionContext context, Throwable cause) {
|
||||
previousTestsPassed = false;
|
||||
@Override
|
||||
public void testFailed(final ExtensionContext context, final Throwable cause) {
|
||||
previousTestsPassed = previousTestsPassed && context.getElement().map(e -> e.isAnnotationPresent(ContinueOnFailure.class)).orElse(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -287,20 +287,20 @@ public class ImportHostingAssets extends ImportOfficeData {
|
||||
// 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}),
|
||||
4005803=HsHostingAssetEntity(UNIX_USER, lug00, LUGs, MANAGED_WEBSPACE:lug00, { "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, { "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, { "SSD hard quota": 8, "SSD soft quota": 4, "locked": false, "shell": "/bin/bash", "userid": 102093}),
|
||||
4005811=HsHostingAssetEntity(UNIX_USER, lug00-ola.a, LUG OLA - POP a, MANAGED_WEBSPACE:lug00, { "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, { "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, { "SSD hard quota": 1024, "SSD soft quota": 1024, "locked": false, "shell": "/usr/bin/passwd", "userid": 102106}),
|
||||
4005964=HsHostingAssetEntity(UNIX_USER, mim00, Michael Mellis, MANAGED_WEBSPACE:mim00, { "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, { "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, { "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})
|
||||
4169546=HsHostingAssetEntity(UNIX_USER, dph00, Reinhard Wiese, MANAGED_WEBSPACE:dph00, { "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, { "SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "shell": "/bin/bash", "userid": 110594})
|
||||
}
|
||||
""");
|
||||
}
|
||||
@ -324,12 +324,16 @@ public class ImportHostingAssets extends ImportOfficeData {
|
||||
// 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]"})
|
||||
5002403=HsHostingAssetEntity(EMAIL_ALIAS, lug00, lug00, MANAGED_WEBSPACE:lug00, { "target": "[michael.mellis@example.com]"}),
|
||||
5002405=HsHostingAssetEntity(EMAIL_ALIAS, lug00-wla-listar, lug00-wla-listar, MANAGED_WEBSPACE:lug00, { "target": "[|/home/pacs/lug00/users/in/mailinglist/listar]"}),
|
||||
5002429=HsHostingAssetEntity(EMAIL_ALIAS, mim00, mim00, MANAGED_WEBSPACE:mim00, { "target": "[mim12-mi@mim12.hostsharing.net]"}),
|
||||
5002431=HsHostingAssetEntity(EMAIL_ALIAS, mim00-abruf, mim00-abruf, MANAGED_WEBSPACE:mim00, { "target": "[michael.mellis@hostsharing.net]"}),
|
||||
5002449=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]"}),
|
||||
5002451=HsHostingAssetEntity(EMAIL_ALIAS, mim00-hhfx-l, mim00-hhfx-l, MANAGED_WEBSPACE:mim00, { "target": "[:include:/home/pacs/mim00/etc/hhfx.list]"}),
|
||||
5002452=HsHostingAssetEntity(EMAIL_ALIAS, mim00-empty, mim00-empty, MANAGED_WEBSPACE:mim00, { "target": "[]"}),
|
||||
5002453=HsHostingAssetEntity(EMAIL_ALIAS, mim00-0_entries, mim00-0_entries, MANAGED_WEBSPACE:mim00, { "target": "[]"}),
|
||||
5002454=HsHostingAssetEntity(EMAIL_ALIAS, mim00-dev.null, mim00-dev.null, MANAGED_WEBSPACE:mim00, { "target": "[/dev/null]"}),
|
||||
5002455=HsHostingAssetEntity(EMAIL_ALIAS, mim00-1_with_space, mim00-1_with_space, MANAGED_WEBSPACE:mim00, { "target": "[|/home/pacs/mim00/install/corpslistar/listar]"})
|
||||
}
|
||||
""");
|
||||
}
|
||||
@ -337,7 +341,7 @@ public class ImportHostingAssets extends ImportOfficeData {
|
||||
// --------------------------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
@Order(11400)
|
||||
@Order(18010)
|
||||
void validateBookingItems() {
|
||||
bookingItems.forEach((id, bi) -> {
|
||||
try {
|
||||
@ -349,19 +353,27 @@ public class ImportHostingAssets extends ImportOfficeData {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(11410)
|
||||
@Order(18020)
|
||||
void validateHostingAssets() {
|
||||
hostingAssets.forEach((id, ha) -> {
|
||||
try {
|
||||
new HostingAssetEntitySaveProcessor(em, ha)
|
||||
.preprocessEntity()
|
||||
.validateEntity();
|
||||
.validateEntityIgnoring("'EMAIL_ALIAS:.*\\.config\\.target' .*")
|
||||
.prepareForSave();
|
||||
} catch (final Exception exc) {
|
||||
errors.add("validation failed for id:" + id + "( " + ha + "): " + exc.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(18999)
|
||||
@ContinueOnFailure
|
||||
void logValidationErrors() {
|
||||
super.logErrors();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
@ -389,30 +401,28 @@ public class ImportHostingAssets extends ImportOfficeData {
|
||||
persistHostingAssetsOfType(EMAIL_ALIAS);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Order(19010)
|
||||
void verifyPersistedUnixUsersWithUserId() {
|
||||
assumeThatWeAreImportingControlledTestData();
|
||||
|
||||
// no contacts yet => mostly null value
|
||||
// FIXME: keep original userids
|
||||
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, "password": null, "shell": "/bin/bash", "userid": 100000000}),
|
||||
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, "password": null, "shell": "/bin/bash", "userid": 100000001}),
|
||||
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, "password": null, "shell": "/bin/bash", "userid": 100000002}),
|
||||
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, "password": null, "shell": "/usr/bin/passwd", "userid": 100000003}),
|
||||
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, "password": null, "shell": "/usr/bin/passwd", "userid": 100000004}),
|
||||
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, "password": null, "shell": "/usr/bin/passwd", "userid": 100000005}),
|
||||
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, "password": null, "shell": "/bin/bash", "userid": 100000006}),
|
||||
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, "password": null, "shell": "/bin/bash", "userid": 100000007}),
|
||||
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, "password": null, "shell": "/bin/bash", "userid": 100000008}),
|
||||
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, "password": null, "shell": "/bin/false", "userid": 100000009}),
|
||||
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, "password": null, "shell": "/bin/bash", "userid": 100000010}),
|
||||
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, "password": null, "shell": "/bin/false", "userid": 100000011}),
|
||||
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, "password": null, "shell": "/bin/bash", "userid": 100000012}),
|
||||
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, "password": null, "shell": "/bin/bash", "userid": 100000013})
|
||||
4005803=HsHostingAssetEntity(UNIX_USER, lug00, LUGs, MANAGED_WEBSPACE:lug00, { "SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "password": null, "shell": "/bin/bash", "userid": 102090}),
|
||||
4005805=HsHostingAssetEntity(UNIX_USER, lug00-wla.1, Paul Klemm, MANAGED_WEBSPACE:lug00, { "SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "password": null, "shell": "/bin/bash", "userid": 102091}),
|
||||
4005809=HsHostingAssetEntity(UNIX_USER, lug00-wla.2, Walter Müller, MANAGED_WEBSPACE:lug00, { "SSD hard quota": 8, "SSD soft quota": 4, "locked": false, "password": null, "shell": "/bin/bash", "userid": 102093}),
|
||||
4005811=HsHostingAssetEntity(UNIX_USER, lug00-ola.a, LUG OLA - POP a, MANAGED_WEBSPACE:lug00, { "SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "password": null, "shell": "/usr/bin/passwd", "userid": 102094}),
|
||||
4005813=HsHostingAssetEntity(UNIX_USER, lug00-ola.b, LUG OLA - POP b, MANAGED_WEBSPACE:lug00, { "SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "password": null, "shell": "/usr/bin/passwd", "userid": 102095}),
|
||||
4005835=HsHostingAssetEntity(UNIX_USER, lug00-test, Test, MANAGED_WEBSPACE:lug00, { "SSD hard quota": 1024, "SSD soft quota": 1024, "locked": false, "password": null, "shell": "/usr/bin/passwd", "userid": 102106}),
|
||||
4005964=HsHostingAssetEntity(UNIX_USER, mim00, Michael Mellis, MANAGED_WEBSPACE:mim00, { "SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "password": null, "shell": "/bin/bash", "userid": 102147}),
|
||||
4005966=HsHostingAssetEntity(UNIX_USER, mim00-1981, Jahrgangstreffen 1981, MANAGED_WEBSPACE:mim00, { "SSD hard quota": 256, "SSD soft quota": 128, "locked": false, "password": null, "shell": "/bin/bash", "userid": 102148}),
|
||||
4005990=HsHostingAssetEntity(UNIX_USER, mim00-mail, Mailbox, MANAGED_WEBSPACE:mim00, { "SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "password": null, "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, "password": null, "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, "password": null, "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, "password": null, "shell": "/bin/false", "userid": 110568}),
|
||||
4169546=HsHostingAssetEntity(UNIX_USER, dph00, Reinhard Wiese, MANAGED_WEBSPACE:dph00, { "SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "password": null, "shell": "/bin/bash", "userid": 110593}),
|
||||
4169596=HsHostingAssetEntity(UNIX_USER, dph00-uph, Domain admin, MANAGED_WEBSPACE:dph00, { "SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "password": null, "shell": "/bin/bash", "userid": 110594})
|
||||
}
|
||||
""");
|
||||
}
|
||||
@ -436,12 +446,12 @@ public class ImportHostingAssets extends ImportOfficeData {
|
||||
|
||||
private void persistHostingAssetsOfType(final HsHostingAssetType hsHostingAssetType) {
|
||||
jpaAttempt.transacted(() -> {
|
||||
context(rbacSuperuser);
|
||||
hostingAssets.forEach((key, ha) -> {
|
||||
context(rbacSuperuser);
|
||||
if (ha.getType() == hsHostingAssetType) {
|
||||
new HostingAssetEntitySaveProcessor(em, ha)
|
||||
.preprocessEntity()
|
||||
.validateEntity()
|
||||
.validateEntityIgnoring("'EMAIL_ALIAS:.*\\.config\\.target' .*")
|
||||
.prepareForSave()
|
||||
.saveUsing(entity -> persist(key, entity))
|
||||
.validateContext();
|
||||
@ -522,8 +532,8 @@ public class ImportHostingAssets extends ImportOfficeData {
|
||||
.isTrue());
|
||||
|
||||
final var asset = HsHostingAssetEntity.builder()
|
||||
.isLoaded(haType
|
||||
== MANAGED_WEBSPACE) // this turns off identifier validation to accept former default prefixes
|
||||
// this turns off identifier validation to accept former default prefixes
|
||||
.isLoaded(haType == MANAGED_WEBSPACE)
|
||||
.type(haType)
|
||||
.identifier(packet_name)
|
||||
.bookingItem(bookingItem)
|
||||
@ -663,9 +673,10 @@ public class ImportHostingAssets extends ImportOfficeData {
|
||||
final var packet_id = rec.getInteger("packet_id");
|
||||
final var unixUserAsset = HsHostingAssetEntity.builder()
|
||||
.type(UNIX_USER)
|
||||
.parentAsset(hostingAssets.get(PACKET_ID_OFFSET+packet_id))
|
||||
.parentAsset(hostingAssets.get(PACKET_ID_OFFSET + packet_id))
|
||||
.identifier(rec.getString("name"))
|
||||
.caption(rec.getString("comment"))
|
||||
.isLoaded(true) // avoid overwriting imported userids with generated ids
|
||||
.config(new HashMap<>(Map.ofEntries(
|
||||
entry("shell", rec.getString("shell")),
|
||||
// entry("homedir", rec.getString("homedir")), do not import, it's calculated
|
||||
@ -677,6 +688,33 @@ public class ImportHostingAssets extends ImportOfficeData {
|
||||
entry("HDD hard quota", rec.getInteger("storage_hardlimit"))
|
||||
)))
|
||||
.build();
|
||||
|
||||
// TODO.spec: crop SSD+HDD limits if > booked
|
||||
if (unixUserAsset.getDirectValue("SSD hard quota", Integer.class, 0)
|
||||
> 1024*unixUserAsset.getContextValue("SSD", Integer.class, 0)) {
|
||||
unixUserAsset.getConfig().put("SSD hard quota", unixUserAsset.getContextValue("SSD", Integer.class, 0)*1024);
|
||||
}
|
||||
if (unixUserAsset.getDirectValue("HDD hard quota", Integer.class, 0)
|
||||
> 1024*unixUserAsset.getContextValue("HDD", Integer.class, 0)) {
|
||||
unixUserAsset.getConfig().put("HDD hard quota", unixUserAsset.getContextValue("HDD", Integer.class, 0)*1024);
|
||||
}
|
||||
|
||||
// TODO.spec: does `softlimit<hardlimit?` even make sense? Fix it in this or the other direction?
|
||||
if (unixUserAsset.getDirectValue("SSD soft quota", Integer.class, 0)
|
||||
> unixUserAsset.getDirectValue("SSD hard quota", Integer.class, 0)) {
|
||||
unixUserAsset.getConfig().put("SSD soft quota", unixUserAsset.getConfig().get("SSD hard quota"));
|
||||
}
|
||||
if (unixUserAsset.getDirectValue("HDD soft quota", Integer.class, 0)
|
||||
> unixUserAsset.getDirectValue("HDD hard quota", Integer.class, 0)) {
|
||||
unixUserAsset.getConfig().put("HDD soft quota", unixUserAsset.getConfig().get("HDD hard quota"));
|
||||
}
|
||||
|
||||
// TODO.spec: remove HDD limits if no HDD storage is booked
|
||||
if (unixUserAsset.getContextValue("HDD", Integer.class, 0) == 0) {
|
||||
unixUserAsset.getConfig().remove("HDD hard quota");
|
||||
unixUserAsset.getConfig().remove("HDD soft quota");
|
||||
}
|
||||
|
||||
hostingAssets.put(UNIXUSER_ID_OFFSET + unixuser_id, unixUserAsset);
|
||||
});
|
||||
}
|
||||
@ -692,7 +730,7 @@ public class ImportHostingAssets extends ImportOfficeData {
|
||||
final var targets = parseCsvLine(rec.getString("target"));
|
||||
final var unixUserAsset = HsHostingAssetEntity.builder()
|
||||
.type(EMAIL_ALIAS)
|
||||
.parentAsset(hostingAssets.get(PACKET_ID_OFFSET+packet_id))
|
||||
.parentAsset(hostingAssets.get(PACKET_ID_OFFSET + packet_id))
|
||||
.identifier(rec.getString("name"))
|
||||
.caption(rec.getString("name"))
|
||||
.config(Map.ofEntries(
|
||||
|
@ -103,6 +103,11 @@ class PasswordPropertyUnitTest {
|
||||
// when
|
||||
final var result = passwordProp.compute(em, new PropertiesProvider() {
|
||||
|
||||
@Override
|
||||
public boolean isLoaded() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> directProps() {
|
||||
return Map.ofEntries(
|
||||
|
@ -5,3 +5,7 @@ emailalias_id;pac_id;name;target
|
||||
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
|
||||
2452;1112;mim00-empty;
|
||||
2453;1112;mim00-0_entries;""
|
||||
2454;1112;mim00-dev.null; /dev/null
|
||||
2455;1112;mim00-1_with_space;" ""|/home/pacs/mim00/install/corpslistar/listar"""
|
||||
|
|
@ -2,11 +2,11 @@ unixuser_id;name;comment;shell;homedir;locked;packet_id;userid;quota_softlimit;q
|
||||
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
|
||||
5805;lug00-wla.1;Paul Klemm;/bin/bash;/home/pacs/lug00/users/deaf;0;1094;102091;4;0;0;0
|
||||
5809;lug00-wla.2;Walter Müller;/bin/bash;/home/pacs/lug00/users/marl;0;1094;102093;4;8;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
|
||||
5835;lug00-test;Test;/usr/bin/passwd;/home/pacs/lug00/users/test;0;1094;102106;2000000;4000000;20;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
|
||||
|
|
Loading…
Reference in New Issue
Block a user
computed muss raus
computed muss doch in die Ausgabe, also z.B. als computed=IN_PREP weil ja die intializedBy und renderedBy Lambdas sind, also Code, den ich gar nicht ausgeben kann. Nur hashedBy kann ausgeben werden, nämlich der Name des Hash-Algorithmus.