add DomainSetup-HostingAssets for new BookingItem via created-event #111
@ -15,11 +15,9 @@ import net.hostsharing.hsadminng.persistence.EntityManagerWrapper;
|
||||
import jakarta.validation.ValidationException;
|
||||
import java.net.IDN;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static java.util.Optional.ofNullable;
|
||||
import static net.hostsharing.hsadminng.hs.booking.generated.api.v1.model.HsHostingAssetTypeResource.DOMAIN_DNS_SETUP;
|
||||
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.DOMAIN_DNS_SETUP;
|
||||
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.DOMAIN_HTTP_SETUP;
|
||||
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.DOMAIN_MBOX_SETUP;
|
||||
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.DOMAIN_SMTP_SETUP;
|
||||
@ -37,33 +35,62 @@ public class DomainSetupHostingAssetFactory extends HostingAssetFactory {
|
||||
@Override
|
||||
protected HsHostingAsset create() {
|
||||
final var domainSetupAsset = createDomainSetupAsset(getDomainName());
|
||||
final var subHostingAssets = domainSetupAsset.getSubHostingAssets();
|
||||
|
||||
// TODO.legacy: as long as we need to be compatible, we always do all technical domain-setups
|
||||
|
||||
final var subHostingAssetResources = getSubHostingAssetResources();
|
||||
|
||||
subHostingAssets.add(
|
||||
createDomainSubSetupAssetEntity(
|
||||
domainSetupAsset,
|
||||
DOMAIN_HTTP_SETUP,
|
||||
builder -> builder
|
||||
.assignedToAsset(assignedToUnixUserAsset.getParentAsset())
|
||||
.identifier(getDomainName() + "|MBOX")
|
||||
.caption("HTTP-Setup für " + IDN.toUnicode(getDomainName())))
|
||||
);
|
||||
|
||||
domainHttpSetupAsset.setParentAsset(domainSetupAsset);
|
||||
final var assignedToUnixUserAsset =
|
||||
emw.find(HsHostingAssetRealEntity.class, domainHttpSetupAssetResource.getAssignedToAssetUuid());
|
||||
domainHttpSetupAsset.setAssignedToAsset(assignedToUnixUserAsset);
|
||||
|
||||
|
||||
final var domainHttpSetupAsset = createDomainHttpSetupAssetEntity(
|
||||
subHostingAssetResources,
|
||||
getDomainName(),
|
||||
domainSetupAsset);
|
||||
final var assignedToUnixUserAsset = domainHttpSetupAsset.getAssignedToAsset();
|
||||
|
||||
// TODO.legacy: don't create DNS setup as long as we need to remain support legacy web-ui etc.
|
||||
assertDomainDnsSetupAssetNotSupplied(domainSetupAsset);
|
||||
|
||||
// do not add to subHostingAssets, in compatibility mode, DNS setup works via file system
|
||||
createDomainSubSetupAssetEntity(
|
||||
domainSetupAsset,
|
||||
DOMAIN_MBOX_SETUP,
|
||||
DOMAIN_DNS_SETUP,
|
||||
builder -> builder
|
||||
.assignedToAsset(assignedToUnixUserAsset.getParentAsset())
|
||||
.identifier(getDomainName() + "|MBOX")
|
||||
.identifier(getDomainName() + "|DNS")
|
||||
.caption("HTTP-Setup für " + IDN.toUnicode(getDomainName())));
|
||||
|
||||
createDomainSubSetupAssetEntity(
|
||||
domainSetupAsset,
|
||||
DOMAIN_SMTP_SETUP,
|
||||
builder -> builder
|
||||
.assignedToAsset(assignedToUnixUserAsset.getParentAsset())
|
||||
.identifier(getDomainName() + "|SMTP")
|
||||
.caption("HTTP-Setup für " + IDN.toUnicode(getDomainName())));
|
||||
subHostingAssets.add(
|
||||
createDomainSubSetupAssetEntity(
|
||||
domainSetupAsset,
|
||||
DOMAIN_MBOX_SETUP,
|
||||
builder -> builder
|
||||
.assignedToAsset(assignedToUnixUserAsset.getParentAsset())
|
||||
.identifier(getDomainName() + "|MBOX")
|
||||
.caption("HTTP-Setup für " + IDN.toUnicode(getDomainName())))
|
||||
);
|
||||
|
||||
subHostingAssets.add(
|
||||
createDomainSubSetupAssetEntity(
|
||||
domainSetupAsset,
|
||||
DOMAIN_SMTP_SETUP,
|
||||
builder -> builder
|
||||
.assignedToAsset(assignedToUnixUserAsset.getParentAsset())
|
||||
.identifier(getDomainName() + "|SMTP")
|
||||
.caption("HTTP-Setup für " + IDN.toUnicode(getDomainName())))
|
||||
);
|
||||
|
||||
return domainSetupAsset;
|
||||
}
|
||||
@ -75,68 +102,41 @@ public class DomainSetupHostingAssetFactory extends HostingAssetFactory {
|
||||
.identifier(domainName)
|
||||
.caption(asset.getCaption() != null ? asset.getCaption() : domainName)
|
||||
.alarmContact(ref(HsOfficeContactRealEntity.class, asset.getAlarmContactUuid()))
|
||||
.subHostingAssets( // FIXME: is this even used?
|
||||
standardMapper.mapList(getSubHostingAssetResources(), HsHostingAssetRealEntity.class)
|
||||
)
|
||||
// the sub-hosting-assets get added later
|
||||
.build();
|
||||
}
|
||||
|
||||
private HsHostingAssetRealEntity createDomainHttpSetupAssetEntity(
|
||||
final List<HsHostingAssetSubInsertResource> subHostingAssetResources,
|
||||
final String domainName,
|
||||
final HsHostingAssetRealEntity domainSetupAsset) {
|
||||
final var domainHttpSetupAssetResource = subHostingAssetResources.stream()
|
||||
.filter(ha -> ha.getType() == HsHostingAssetTypeResource.DOMAIN_HTTP_SETUP)
|
||||
.findFirst().orElseThrow(() -> new ValidationException(
|
||||
domainName + ": missing target unix user (assignedToHostingAssetUuid) for DOMAIN_HTTP_SETUP "));
|
||||
final var domainHttpSetupAsset = domainSetupAsset.getSubHostingAssets()
|
||||
.stream()
|
||||
.filter(sha -> sha.getType() == DOMAIN_HTTP_SETUP)
|
||||
.findFirst()
|
||||
.orElseThrow();
|
||||
domainHttpSetupAsset.setParentAsset(domainSetupAsset);
|
||||
final var assignedToUnixUserAsset =
|
||||
emw.find(HsHostingAssetRealEntity.class, domainHttpSetupAssetResource.getAssignedToAssetUuid());
|
||||
domainHttpSetupAsset.setAssignedToAsset(assignedToUnixUserAsset);
|
||||
return domainHttpSetupAsset;
|
||||
}
|
||||
|
||||
private void assertDomainDnsSetupAssetNotSupplied(final HsHostingAssetRealEntity domainSetupAsset) {
|
||||
if (getSubHostingAssetResources().stream().anyMatch(ha -> ha.getType() == DOMAIN_DNS_SETUP)) {
|
||||
throw new ValidationException("domain DNS setup not allowed for legacy compatibility");
|
||||
}
|
||||
}
|
||||
|
||||
private void createDomainSubSetupAssetEntity(
|
||||
private HsHostingAssetRealEntity createDomainSubSetupAssetEntity(
|
||||
final HsHostingAssetRealEntity domainSetupAsset,
|
||||
final HsHostingAssetType subAssetType,
|
||||
final Function<HsHostingAssetRealEntity.HsHostingAssetRealEntityBuilder<?, ?>, HsHostingAssetRealEntity.HsHostingAssetRealEntityBuilder<?, ?>> builderTransformer) {
|
||||
final var resourceType = HsHostingAssetTypeResource.valueOf(subAssetType.name());
|
||||
final var subAssetResource = getSubHostingAssetResources().stream()
|
||||
|
||||
final var subAssetResourceOptional = getSubHostingAssetResources().stream()
|
||||
.filter(ha -> ha.getType() == resourceType)
|
||||
.reduce(Reducer::toSingleElement);
|
||||
final var subAssetEntity = builderTransformer.apply(
|
||||
|
||||
subAssetResourceOptional.ifPresentOrElse(
|
||||
subAssetResource -> verifyNotOverspecified(subAssetResource),
|
||||
() -> { throw new ValidationException("sub-asset of type " + resourceType.name() + " required in legacy mode, but missing"); }
|
||||
);
|
||||
|
||||
return builderTransformer.apply(
|
||||
HsHostingAssetRealEntity.builder()
|
||||
.type(subAssetType)
|
||||
.parentAsset(domainSetupAsset))
|
||||
.build();
|
||||
domainSetupAsset.getSubHostingAssets().add(subAssetEntity);
|
||||
subAssetResource.ifPresent(
|
||||
res -> {
|
||||
ofNullable(res.getAssignedToAssetUuid())
|
||||
.map(uuid -> emw.find(HsHostingAssetRealEntity.class, uuid))
|
||||
.ifPresent(subAssetEntity::setAssignedToAsset);
|
||||
ofNullable(res.getAlarmContactUuid())
|
||||
.map(uuid -> emw.find(HsOfficeContactRealEntity.class, uuid))
|
||||
.ifPresent(subAssetEntity::setAlarmContact);
|
||||
ofNullable(res.getIdentifier()).ifPresent(subAssetEntity::setIdentifier);
|
||||
ofNullable(res.getCaption()).ifPresent(subAssetEntity::setCaption);
|
||||
res.getConfig();
|
||||
res.get
|
||||
}
|
||||
|
||||
// TODO.legacy: while we need to stay compatible, only default values can be used, thus only the type can be specified
|
||||
private void verifyNotOverspecified(final HsHostingAssetSubInsertResource givenSubAssetResource) {
|
||||
final var convert = new ToStringConverter().ignoring("assignedToAssetUuid");
|
||||
final var expectedSubAssetResource = new HsHostingAssetSubInsertResource();
|
||||
expectedSubAssetResource.setType(givenSubAssetResource.getType());
|
||||
hsh-michaelhoennig marked this conversation as resolved
Outdated
|
||||
if ( !convert.from(givenSubAssetResource).equals(convert.from(expectedSubAssetResource)) ) {
|
||||
throw new ValidationException("sub asset " + givenSubAssetResource.getType() + " is over-specified, in compatibilty mode, only default values allowed");
|
||||
}
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private String getDomainName() {
|
||||
|
@ -0,0 +1,39 @@
|
||||
package net.hostsharing.hsadminng.hs.hosting.asset.factories;
|
||||
import net.hostsharing.hsadminng.mapper.Array;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.stream.Collectors.joining;
|
||||
|
||||
public class ToStringConverter {
|
||||
|
||||
final public Set<String> ignoredFields = new HashSet<>();
|
||||
|
||||
public ToStringConverter ignoring(final String fieldName) {
|
||||
ignoredFields.add(fieldName);
|
||||
return this;
|
||||
}
|
||||
|
||||
public String from(Object obj) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
return "{ " +
|
||||
Arrays.stream(obj.getClass().getDeclaredFields())
|
||||
.filter(f -> !ignoredFields.contains(f.getName()))
|
||||
.map(field -> {
|
||||
try {
|
||||
field.setAccessible(true);
|
||||
return field.getName() + ": " + field.get(obj);
|
||||
} catch (IllegalAccessException e) {
|
||||
// ignore inaccessible fields
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.collect(joining(", "))
|
||||
+ " }";
|
||||
}
|
||||
}
|
@ -201,33 +201,33 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
||||
.header("current-subject", "superuser-alex@hostsharing.net")
|
||||
.contentType(ContentType.JSON)
|
||||
.body("""
|
||||
{
|
||||
"projectUuid": "{projectUuid}",
|
||||
"type": "DOMAIN_SETUP",
|
||||
"caption": "Domain-Setup for example.org",
|
||||
"resources": {
|
||||
"domainName": "example.org",
|
||||
"verificationCode": "just-a-fake-verification-code"
|
||||
},
|
||||
"asset": { // FIXME: rename to hostingAsset
|
||||
"identifier": "example.org", // also as default for all subAssets
|
||||
"subHostingAssets": [
|
||||
{
|
||||
"type": "DOMAIN_DNS_SETUP"
|
||||
},
|
||||
{
|
||||
"type": "DOMAIN_HTTP_SETUP",
|
||||
"assignedToAssetUuid": "{unixUserUuid}"
|
||||
},
|
||||
{
|
||||
"type": "DOMAIN_MBOX_SETUP"
|
||||
},
|
||||
{
|
||||
"type": "DOMAIN_SMTP_SETUP"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
{
|
||||
"projectUuid": "{projectUuid}",
|
||||
"type": "DOMAIN_SETUP",
|
||||
"caption": "Domain-Setup for example.org",
|
||||
"resources": {
|
||||
"domainName": "example.org",
|
||||
"verificationCode": "just-a-fake-verification-code"
|
||||
},
|
||||
"asset": { // FIXME: rename to hostingAsset
|
||||
"identifier": "example.org", // also as default for all subAssets
|
||||
"subHostingAssets": [
|
||||
{
|
||||
"type": "DOMAIN_DNS_SETUP"
|
||||
},
|
||||
{
|
||||
"type": "DOMAIN_HTTP_SETUP",
|
||||
"assignedToAssetUuid": "{unixUserUuid}"
|
||||
},
|
||||
{
|
||||
"type": "DOMAIN_MBOX_SETUP"
|
||||
},
|
||||
{
|
||||
"type": "DOMAIN_SMTP_SETUP"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
"""
|
||||
.replace("{projectUuid}", givenProject.getUuid().toString())
|
||||
.replace("{unixUserUuid}", givenUnixUser.getUuid().toString())
|
||||
|
Loading…
Reference in New Issue
Block a user
i fehlt in compatibility mode