import-unix-user-and-email-aliases #81
@ -5,6 +5,7 @@ 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 net.hostsharing.hsadminng.hs.validation.PropertiesProvider;
|
import net.hostsharing.hsadminng.hs.validation.PropertiesProvider;
|
||||||
|
|
||||||
|
import jakarta.persistence.EntityManager;
|
||||||
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.BooleanProperty.booleanProperty;
|
||||||
@ -23,7 +24,7 @@ class HsUnixUserHostingAssetValidator extends HostingAssetEntityValidator {
|
|||||||
AlarmContact.isOptional(),
|
AlarmContact.isOptional(),
|
||||||
|
|
||||||
booleanProperty("locked").readOnly(),
|
booleanProperty("locked").readOnly(),
|
||||||
integerProperty("userid").readOnly().computedBy(HsUnixUserHostingAssetValidator::computeUserId),
|
integerProperty("userid").computedBy(HsUnixUserHostingAssetValidator::computeUserId),
|
||||||
|
|
||||||
integerProperty("SSD hard quota").unit("MB").maxFrom("SSD").withFactor(1024).optional(),
|
integerProperty("SSD hard quota").unit("MB").maxFrom("SSD").withFactor(1024).optional(),
|
||||||
integerProperty("SSD soft quota").unit("MB").maxFrom("SSD hard quota").optional(),
|
integerProperty("SSD soft quota").unit("MB").maxFrom("SSD hard quota").optional(),
|
||||||
@ -44,14 +45,14 @@ class HsUnixUserHostingAssetValidator extends HostingAssetEntityValidator {
|
|||||||
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 EntityManager em, final PropertiesProvider propertiesProvider) {
|
||||||
final var entity = (HsHostingAssetEntity) propertiesProvider;
|
final var entity = (HsHostingAssetEntity) propertiesProvider;
|
||||||
final var webspaceName = entity.getParentAsset().getIdentifier();
|
final var webspaceName = entity.getParentAsset().getIdentifier();
|
||||||
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) {
|
private static Integer computeUserId(final EntityManager em, final PropertiesProvider propertiesProvider) {
|
||||||
return 0; // FIXME: from a specific numeric rage and unique per hive?
|
return Math.toIntExact((Long) em.createNativeQuery("SELECT nextval('hs_hosting_asset_unixuser_system_id_seq')").getSingleResult());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,7 @@ public abstract class HsEntityValidator<E extends PropertiesProvider> {
|
|||||||
|
|
||||||
public void prepareProperties(final EntityManager em, final E entity) {
|
public void prepareProperties(final EntityManager em, final E entity) {
|
||||||
stream(propertyValidators).forEach(p -> {
|
stream(propertyValidators).forEach(p -> {
|
||||||
if ( p.isWriteOnly() && p.isComputed()) {
|
if (!p.isReadOnly() && p.isComputed()) {
|
||||||
entity.directProps().put(p.propertyName, p.compute(em, entity));
|
entity.directProps().put(p.propertyName, p.compute(em, entity));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -34,7 +34,7 @@ public class PasswordProperty extends StringProperty<PasswordProperty> {
|
|||||||
|
|
||||||
public PasswordProperty hashedUsing(final Algorithm algorithm) {
|
public PasswordProperty hashedUsing(final Algorithm algorithm) {
|
||||||
this.hashedUsing = algorithm;
|
this.hashedUsing = algorithm;
|
||||||
computedBy((entity)
|
computedBy((em, entity)
|
||||||
-> ofNullable(entity.getDirectValue(propertyName, String.class))
|
-> ofNullable(entity.getDirectValue(propertyName, String.class))
|
||||||
.map(password -> HashGenerator.using(algorithm).withRandomSalt().hash(password))
|
.map(password -> HashGenerator.using(algorithm).withRandomSalt().hash(password))
|
||||||
.orElse(null));
|
.orElse(null));
|
||||||
|
@ -20,6 +20,7 @@ import java.util.Map;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import static java.lang.Boolean.FALSE;
|
import static java.lang.Boolean.FALSE;
|
||||||
@ -48,7 +49,7 @@ public abstract class ValidatableProperty<P extends ValidatableProperty<?, ?>, T
|
|||||||
private T defaultValue;
|
private T defaultValue;
|
||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
private Function<PropertiesProvider, T> computedBy;
|
private BiFunction<EntityManager, PropertiesProvider, T> computedBy;
|
||||||
|
|
||||||
@Accessors(makeFinal = true, chain = true, fluent = false)
|
@Accessors(makeFinal = true, chain = true, fluent = false)
|
||||||
private boolean computed; // used in descriptor, because computedBy cannot be rendered to a text string
|
private boolean computed; // used in descriptor, because computedBy cannot be rendered to a text string
|
||||||
@ -96,7 +97,6 @@ protected void setDeferredInit(final Function<ValidatableProperty<?, ?>[], T[]>
|
|||||||
|
|
||||||
public P readOnly() {
|
public P readOnly() {
|
||||||
this.readOnly = true;
|
this.readOnly = true;
|
||||||
optional();
|
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,8 +236,8 @@ protected void setDeferredInit(final Function<ValidatableProperty<?, ?>[], T[]>
|
|||||||
protected abstract void validate(final List<String> result, final T propValue, final PropertiesProvider propProvider);
|
protected abstract void validate(final List<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 && requiresAtLeastOneOf == null && requiresAtMaxOneOf == null) {
|
if (required == null && requiresAtLeastOneOf == null && requiresAtMaxOneOf == null && !readOnly && !computed) {
|
||||||
throw new IllegalStateException(typeDef.getKey() + "[" + propertyName + "] not fully initialized, please call either .required(), .optional(), .withDefault(...), .requiresAtLeastOneOf(...) or .requiresAtMaxOneOf(...)" );
|
throw new IllegalStateException(typeDef.getKey() + "[" + propertyName + "] not fully initialized, please call either .computed(...), .readOnly(), .required(), .optional(), .withDefault(...), .requiresAtLeastOneOf(...) or .requiresAtMaxOneOf(...)" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,14 +302,14 @@ protected void setDeferredInit(final Function<ValidatableProperty<?, ?>[], T[]>
|
|||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public P computedBy(final Function<PropertiesProvider, T> compute) {
|
public P computedBy(final BiFunction<EntityManager, PropertiesProvider, T> compute) {
|
||||||
this.computedBy = compute;
|
this.computedBy = compute;
|
||||||
this.computed = true;
|
this.computed = true;
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public <E extends PropertiesProvider> T compute(final EntityManager em, final E entity) {
|
public <E extends PropertiesProvider> T compute(final EntityManager em, final E entity) {
|
||||||
return computedBy.apply(entity);
|
return computedBy.apply(em, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -111,6 +111,21 @@ create trigger hs_hosting_asset_type_hierarchy_check_tg
|
|||||||
--//
|
--//
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
--changeset hosting-asset-system-sequences:1 endDelimiter:--//
|
||||||
|
-- ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
CREATE SEQUENCE IF NOT EXISTS hs_hosting_asset_unixuser_system_id_seq
|
||||||
|
AS integer
|
||||||
|
MINVALUE 100000000
|
||||||
|
MAXVALUE 199999999
|
||||||
|
NO CYCLE
|
||||||
|
OWNED BY NONE;
|
||||||
|
|
||||||
|
--//
|
||||||
|
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset hosting-asset-BOOKING-ITEM-HIERARCHY-CHECK:1 endDelimiter:--//
|
--changeset hosting-asset-BOOKING-ITEM-HIERARCHY-CHECK:1 endDelimiter:--//
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
|
@ -388,6 +388,35 @@ public class ImportHostingAssets extends ImportOfficeData {
|
|||||||
persistHostingAssetsOfType(EMAIL_ALIAS);
|
persistHostingAssetsOfType(EMAIL_ALIAS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(19010)
|
||||||
|
void verifyPersistedUnixUsersWithUserId() {
|
||||||
|
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, "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})
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ============================================================================================
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Order(99999)
|
@Order(99999)
|
||||||
void logErrors() {
|
void logErrors() {
|
||||||
|
Loading…
Reference in New Issue
Block a user