Compare commits

...

3 Commits

Author SHA1 Message Date
Michael Hoennig
03184f6e58 also import groupid 2024-08-30 18:36:18 +02:00
Michael Hoennig
f9309451aa set webspace groupid to main user userid 2024-08-30 17:32:50 +02:00
Michael Hoennig
ce81c4a0c1 create webspace main user for new webspaces 2024-08-30 17:18:38 +02:00
6 changed files with 86 additions and 8 deletions

View File

@ -34,6 +34,7 @@ import jakarta.persistence.OneToOne;
import jakarta.persistence.PostLoad; import jakarta.persistence.PostLoad;
import jakarta.persistence.Transient; import jakarta.persistence.Transient;
import jakarta.persistence.Version; import jakarta.persistence.Version;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -115,6 +116,13 @@ public abstract class HsHostingAsset implements Stringifyable, BaseEntity<HsHost
this.isLoaded = true; this.isLoaded = true;
} }
public List<HsHostingAssetRealEntity> getSubHostingAssets() {
if (subHostingAssets == null) {
subHostingAssets = new ArrayList<>();
}
return subHostingAssets;
}
public PatchableMapWrapper<Object> getConfig() { public PatchableMapWrapper<Object> getConfig() {
return PatchableMapWrapper.of(configWrapper, (newWrapper) -> {configWrapper = newWrapper;}, config); return PatchableMapWrapper.of(configWrapper, (newWrapper) -> {configWrapper = newWrapper;}, config);
} }

View File

@ -66,6 +66,8 @@ public class HostingAssetEntitySaveProcessor {
public HostingAssetEntitySaveProcessor saveUsing(final Function<HsHostingAsset, HsHostingAsset> saveFunction) { public HostingAssetEntitySaveProcessor saveUsing(final Function<HsHostingAsset, HsHostingAsset> saveFunction) {
step("saveUsing", "validateContext"); step("saveUsing", "validateContext");
entity = saveFunction.apply(entity); entity = saveFunction.apply(entity);
em.flush(); // makes RbacEntity available as RealEntity if needed
validator.postPersist(em, entity);
return this; return this;
} }

View File

@ -1,17 +1,22 @@
package net.hostsharing.hsadminng.hs.hosting.asset.validators; package net.hostsharing.hsadminng.hs.hosting.asset.validators;
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAsset; import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAsset;
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetRealEntity;
import jakarta.persistence.EntityManager;
import java.util.regex.Pattern; import java.util.regex.Pattern;
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.hs.validation.IntegerProperty.integerProperty;
class HsManagedWebspaceHostingAssetValidator extends HostingAssetEntityValidator { class HsManagedWebspaceHostingAssetValidator extends HostingAssetEntityValidator {
public HsManagedWebspaceHostingAssetValidator() { public HsManagedWebspaceHostingAssetValidator() {
super( super(
MANAGED_WEBSPACE, MANAGED_WEBSPACE,
AlarmContact.isOptional(), AlarmContact.isOptional(),
NO_EXTRA_PROPERTIES); // TODO.impl: groupid missing, should be equal to main user integerProperty("groupid").readOnly()
);
} }
@Override @Override
@ -22,4 +27,33 @@ class HsManagedWebspaceHostingAssetValidator extends HostingAssetEntityValidator
: "[a-z][a-z0-9][a-z0-9]"; : "[a-z][a-z0-9][a-z0-9]";
return Pattern.compile("^" + prefixPattern + "[0-9][0-9]$"); return Pattern.compile("^" + prefixPattern + "[0-9][0-9]$");
} }
@Override
public void postPersist(final EntityManager em, final HsHostingAsset webspaceAsset) {
if (!webspaceAsset.isLoaded()) {
final var unixUserAsset = HsHostingAssetRealEntity.builder()
.type(UNIX_USER)
.parentAsset(em.find(HsHostingAssetRealEntity.class, webspaceAsset.getUuid()))
.identifier(webspaceAsset.getIdentifier())
.caption(webspaceAsset.getIdentifier() + " webspace user")
.build();
webspaceAsset.getSubHostingAssets().add(unixUserAsset);
final var emw = new EntityManagerWrapper(em);
new HostingAssetEntitySaveProcessor(em, unixUserAsset)
.preprocessEntity()
.validateEntity()
.prepareForSave()
.saveUsing(emw::persist)
.validateContext();
webspaceAsset.getConfig().put("groupid", unixUserAsset.getConfig().get("userid"));
}
}
}
record EntityManagerWrapper(EntityManager em) {
HsHostingAsset persist(HsHostingAsset hsHostingAsset) {
em.persist(hsHostingAsset);
return hsHostingAsset;
}
} }

View File

@ -160,4 +160,7 @@ public abstract class HsEntityValidator<E extends PropertiesProvider> {
public ValidatableProperty<?, ?> getProperty(final String propertyName) { public ValidatableProperty<?, ?> getProperty(final String propertyName) {
return stream(propertyValidators).filter(pv -> pv.propertyName().equals(propertyName)).findFirst().orElse(null); return stream(propertyValidators).filter(pv -> pv.propertyName().equals(propertyName)).findFirst().orElse(null);
} }
public void postPersist(final EntityManager em, final E entity) {
}
} }

View File

@ -176,17 +176,31 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
"type": "MANAGED_WEBSPACE", "type": "MANAGED_WEBSPACE",
"identifier": "fir10", "identifier": "fir10",
"caption": "some separate ManagedWebspace HA", "caption": "some separate ManagedWebspace HA",
"config": {} "config": {
"groupid": 1000000
}
} }
""")) """))
.header("Location", matchesRegex("http://localhost:[1-9][0-9]*/api/hs/hosting/assets/[^/]*")) .header("Location", matchesRegex("http://localhost:[1-9][0-9]*/api/hs/hosting/assets/[^/]*"))
.extract().header("Location"); // @formatter:on .extract().header("Location"); // @formatter:on
// finally, the new asset can be accessed under the generated UUID // the new asset can be accessed under the generated UUID
final var newWebspace = UUID.fromString( final var newWebspaceUuid = UUID.fromString(
location.substring(location.lastIndexOf('/') + 1)); location.substring(location.lastIndexOf('/') + 1));
assertThat(newWebspace).isNotNull(); assertThat(newWebspaceUuid).isNotNull();
toCleanup(HsHostingAssetRbacEntity.class, newWebspace); toCleanup(HsHostingAssetRbacEntity.class, newWebspaceUuid);
// and a default user got created
final var webspaceUnixUser = em.createQuery("SELECT ha FROM HsHostingAssetRealEntity ha WHERE ha.parentAsset.uuid=:webspaceUUID")
.setParameter("webspaceUUID", newWebspaceUuid)
.getSingleResult();
assertThat(webspaceUnixUser).isNotNull().extracting(Object::toString)
.isEqualTo("""
HsHostingAsset(UNIX_USER, fir10, fir10 webspace user, MANAGED_WEBSPACE:fir10, {
"password" : null,
"userid" : 1000000
})
""".trim());
} }
@Test @Test
@ -325,7 +339,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
jpaAttempt.transacted(() -> { jpaAttempt.transacted(() -> {
context.define("superuser-alex@hostsharing.net"); context.define("superuser-alex@hostsharing.net");
for (int n = 0; n < UNIX_USER_PER_MULTI_OPTION -preExistingUnixUserCount+1; ++n) { for (int n = 0; n < UNIX_USER_PER_MULTI_OPTION-preExistingUnixUserCount; ++n) {
toCleanup(realAssetRepo.save( toCleanup(realAssetRepo.save(
HsHostingAssetRealEntity.builder() HsHostingAssetRealEntity.builder()
.type(UNIX_USER) .type(UNIX_USER)

View File

@ -350,6 +350,18 @@ public class ImportHostingAssets extends BaseOfficeDataImport {
9596=HsHostingAsset(UNIX_USER, dph00-dph, Domain admin, MANAGED_WEBSPACE:dph00, {"SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "shell": "/bin/bash", "userid": 110594}) 9596=HsHostingAsset(UNIX_USER, dph00-dph, Domain admin, MANAGED_WEBSPACE:dph00, {"SSD hard quota": 0, "SSD soft quota": 0, "locked": false, "shell": "/bin/bash", "userid": 110594})
} }
"""); """);
// now with groupids
assertThat(firstOfEach(5, packetAssets, MANAGED_WEBSPACE))
.isEqualToIgnoringWhitespace("""
{
10630=HsHostingAsset(MANAGED_WEBSPACE, hsh00, HA hsh00, MANAGED_SERVER:vm1050, D-1000000:hsh default project:BI hsh00, {"groupid": 6824}),
11094=HsHostingAsset(MANAGED_WEBSPACE, lug00, HA lug00, MANAGED_SERVER:vm1068, D-1000300:mim default project:BI lug00, {"groupid": 5803}),
11111=HsHostingAsset(MANAGED_WEBSPACE, xyz68, HA xyz68, MANAGED_SERVER:vm1068, D-1000000:vm1068 Monitor:BI xyz68, {"groupid": 5961}),
11112=HsHostingAsset(MANAGED_WEBSPACE, mim00, HA mim00, MANAGED_SERVER:vm1068, D-1000300:mim default project:BI mim00, {"groupid": 5964}),
19959=HsHostingAsset(MANAGED_WEBSPACE, dph00, HA dph00, MANAGED_SERVER:vm1093, D-1101900:dph default project:BI dph00, {"groupid": 9546})
}
""");
} }
@Test @Test
@ -1235,9 +1247,10 @@ public class ImportHostingAssets extends BaseOfficeDataImport {
.forEach(rec -> { .forEach(rec -> {
final var unixuser_id = rec.getInteger("unixuser_id"); final var unixuser_id = rec.getInteger("unixuser_id");
final var packet_id = rec.getInteger("packet_id"); final var packet_id = rec.getInteger("packet_id");
final var parentWebspaceAsset = packetAssets.get(packet_id);
final var unixUserAsset = HsHostingAssetRealEntity.builder() final var unixUserAsset = HsHostingAssetRealEntity.builder()
.type(UNIX_USER) .type(UNIX_USER)
.parentAsset(packetAssets.get(packet_id)) .parentAsset(parentWebspaceAsset)
.identifier(rec.getString("name")) .identifier(rec.getString("name"))
.caption(rec.getString("comment")) .caption(rec.getString("comment"))
.isLoaded(true) // avoid overwriting imported userids with generated ids .isLoaded(true) // avoid overwriting imported userids with generated ids
@ -1253,6 +1266,10 @@ public class ImportHostingAssets extends BaseOfficeDataImport {
))) )))
.build(); .build();
if (unixUserAsset.getIdentifier().equals(parentWebspaceAsset.getIdentifier())) {
parentWebspaceAsset.getConfig().put("groupid", unixuser_id);
}
// TODO.spec: crop SSD+HDD limits if > booked // TODO.spec: crop SSD+HDD limits if > booked
if (unixUserAsset.getDirectValue("SSD hard quota", Integer.class, 0) if (unixUserAsset.getDirectValue("SSD hard quota", Integer.class, 0)
> 1024 * unixUserAsset.getContextValue("SSD", Integer.class, 0)) { > 1024 * unixUserAsset.getContextValue("SSD", Integer.class, 0)) {