HostingAsset-Hierarchie spec in enum HsHostingAssetType and generates PlantUML #72

Merged
hsh-michaelhoennig merged 9 commits from add-mermaid-graph-generator-for-hosting-asset-type-structure into master 2024-07-09 14:32:14 +02:00
12 changed files with 91 additions and 45 deletions
Showing only changes of commit 6ddc0e08f7 - Show all commits

View File

@ -205,12 +205,12 @@ public class HsHostingAssetEntity implements Stringifyable, RbacObject, Properti
.switchOnColumn("type", .switchOnColumn("type",
inCaseOf("DOMAIN_SETUP", then -> { inCaseOf("DOMAIN_SETUP", then -> {
then.toRole(GLOBAL, GUEST).grantPermission(INSERT); then.toRole(GLOBAL, GUEST).grantPermission(INSERT);
then.toRole(GLOBAL, ADMIN).grantPermission(SELECT); // TODO.spec: replace by a proper solution
}) })
) )
.createRole(OWNER, (with) -> { .createRole(OWNER, (with) -> {
with.owningUser(CREATOR); with.owningUser(CREATOR);
with.incomingSuperRole(GLOBAL, ADMIN).unassumed(); // TODO.spec: replace by a better solution
with.incomingSuperRole("bookingItem", ADMIN); with.incomingSuperRole("bookingItem", ADMIN);
with.incomingSuperRole("parentAsset", ADMIN); with.incomingSuperRole("parentAsset", ADMIN);
with.permission(DELETE); with.permission(DELETE);

View File

@ -132,6 +132,7 @@ public enum HsHostingAssetType implements Node {
return groupName; return groupName;
} }
// TODO.refa: try to get rid of the following similar methods:
public RelationPolicy bookingItemPolicy() { public RelationPolicy bookingItemPolicy() {
return stream(relations).filter(r -> r.relatedType instanceof HsBookingItemType) return stream(relations).filter(r -> r.relatedType instanceof HsBookingItemType)

View File

@ -30,6 +30,7 @@ class HsDomainDnsSetupHostingAssetValidator extends HsHostingAssetEntityValidato
static final String RR_REGEX_IN_TTL = static final String RR_REGEX_IN_TTL =
RR_REGEX_NAME + RR_REGEX_IN + RR_REGEX_TTL + RR_RECORD_TYPE + RR_RECORD_DATA + RR_COMMENT; RR_REGEX_NAME + RR_REGEX_IN + RR_REGEX_TTL + RR_RECORD_TYPE + RR_RECORD_DATA + RR_COMMENT;
public static final String IDENTIFIER_SUFFIX = "|DNS";
HsDomainDnsSetupHostingAssetValidator() { HsDomainDnsSetupHostingAssetValidator() {
super( super(
@ -59,14 +60,14 @@ class HsDomainDnsSetupHostingAssetValidator extends HsHostingAssetEntityValidato
@Override @Override
protected Pattern identifierPattern(final HsHostingAssetEntity assetEntity) { protected Pattern identifierPattern(final HsHostingAssetEntity assetEntity) {
return Pattern.compile("^" + assetEntity.getParentAsset().getIdentifier() + "$"); return Pattern.compile("^" + assetEntity.getParentAsset().getIdentifier() + IDENTIFIER_SUFFIX + "$");
} }
@Override @Override
public void preprocessEntity(final HsHostingAssetEntity entity) { public void preprocessEntity(final HsHostingAssetEntity entity) {
super.preprocessEntity(entity); super.preprocessEntity(entity);
if (entity.getIdentifier() == null) { if (entity.getIdentifier() == null) {
ofNullable(entity.getParentAsset()).ifPresent(pa -> entity.setIdentifier(pa.getIdentifier())); ofNullable(entity.getParentAsset()).ifPresent(pa -> entity.setIdentifier(pa.getIdentifier() + IDENTIFIER_SUFFIX));
} }
} }
@ -76,7 +77,7 @@ class HsDomainDnsSetupHostingAssetValidator extends HsHostingAssetEntityValidato
final var result = super.validateContext(assetEntity); final var result = super.validateContext(assetEntity);
// TODO.spec: define which checks should get raised to error level // TODO.spec: define which checks should get raised to error level
final var namedCheckZone = new SystemProcess("named-checkzone", assetEntity.getIdentifier()); final var namedCheckZone = new SystemProcess("named-checkzone", fqdn(assetEntity));
if (namedCheckZone.execute(toZonefileString(assetEntity)) != 0) { if (namedCheckZone.execute(toZonefileString(assetEntity)) != 0) {
// yes, named-checkzone writes error messages to stdout // yes, named-checkzone writes error messages to stdout
stream(namedCheckZone.getStdOut().split("\n")) stream(namedCheckZone.getStdOut().split("\n"))
@ -98,8 +99,12 @@ class HsDomainDnsSetupHostingAssetValidator extends HsHostingAssetEntityValidato
{userRRs} {userRRs}
""" """
.replace("{domain}", assetEntity.getIdentifier()) .replace("{domain}", fqdn(assetEntity))
.replace("{ttl}", getPropertyValue(assetEntity, "TTL")) .replace("{ttl}", getPropertyValue(assetEntity, "TTL"))
.replace("{userRRs}", getPropertyValues(assetEntity, "user-RR") ); .replace("{userRRs}", getPropertyValues(assetEntity, "user-RR") );
} }
private String fqdn(final HsHostingAssetEntity assetEntity) {
return assetEntity.getIdentifier().substring(0, assetEntity.getIdentifier().length()-IDENTIFIER_SUFFIX.length());
}
} }

View File

@ -21,6 +21,7 @@ import static java.util.Arrays.stream;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
import static java.util.Optional.ofNullable; import static java.util.Optional.ofNullable;
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.RelationPolicy.FORBIDDEN; import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.RelationPolicy.FORBIDDEN;
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.RelationPolicy.OPTIONAL;
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.RelationPolicy.REQUIRED; import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.RelationPolicy.REQUIRED;
public abstract class HsHostingAssetEntityValidator extends HsEntityValidator<HsHostingAssetEntity> { public abstract class HsHostingAssetEntityValidator extends HsEntityValidator<HsHostingAssetEntity> {
@ -183,7 +184,7 @@ public abstract class HsHostingAssetEntityValidator extends HsEntityValidator<Hs
return List.of(referenceFieldName + "' must be null but is set to "+ assetEntity.getBookingItem().toShortString()); return List.of(referenceFieldName + "' must be null but is set to "+ assetEntity.getBookingItem().toShortString());
} }
final var subItemType = subEntity != null ? subEntityTypeGetter.apply(subEntity) : null; final var subItemType = subEntity != null ? subEntityTypeGetter.apply(subEntity) : null;
if (subEntityType != null && subItemType != subEntityType) { if (policy != OPTIONAL && subEntityType != null && subItemType != subEntityType) {
return List.of(referenceFieldName + "' must be of type " + subEntityType + " but is of type " + subItemType); return List.of(referenceFieldName + "' must be of type " + subEntityType + " but is of type " + subItemType);
} }
return emptyList(); return emptyList();

View File

@ -149,7 +149,7 @@ create or replace function cleanIdentifier(rawIdentifier varchar)
declare declare
cleanIdentifier varchar; cleanIdentifier varchar;
begin begin
cleanIdentifier := regexp_replace(rawIdentifier, '[^A-Za-z0-9\-._]+', '', 'g'); cleanIdentifier := regexp_replace(rawIdentifier, '[^A-Za-z0-9\-._|]+', '', 'g');
return cleanIdentifier; return cleanIdentifier;
end; $$; end; $$;

View File

@ -36,9 +36,9 @@ subgraph asset["`**asset**`"]
style asset:permissions fill:#dd4901,stroke:white style asset:permissions fill:#dd4901,stroke:white
perm:asset:INSERT{{asset:INSERT}} perm:asset:INSERT{{asset:INSERT}}
perm:asset:SELECT{{asset:SELECT}}
perm:asset:DELETE{{asset:DELETE}} perm:asset:DELETE{{asset:DELETE}}
perm:asset:UPDATE{{asset:UPDATE}} perm:asset:UPDATE{{asset:UPDATE}}
perm:asset:SELECT{{asset:SELECT}}
end end
end end
@ -90,6 +90,7 @@ role:bookingItem:AGENT -.-> role:bookingItem:TENANT
role:global:ADMIN -.-> role:alarmContact:OWNER role:global:ADMIN -.-> role:alarmContact:OWNER
role:alarmContact:OWNER -.-> role:alarmContact:ADMIN role:alarmContact:OWNER -.-> role:alarmContact:ADMIN
role:alarmContact:ADMIN -.-> role:alarmContact:REFERRER role:alarmContact:ADMIN -.-> role:alarmContact:REFERRER
role:global:ADMIN ==>|XX| role:asset:OWNER
role:bookingItem:ADMIN ==> role:asset:OWNER role:bookingItem:ADMIN ==> role:asset:OWNER
role:parentAsset:ADMIN ==> role:asset:OWNER role:parentAsset:ADMIN ==> role:asset:OWNER
role:asset:OWNER ==> role:asset:ADMIN role:asset:OWNER ==> role:asset:ADMIN
@ -107,7 +108,6 @@ role:alarmContact:ADMIN ==> role:asset:TENANT
role:global:ADMIN ==> perm:asset:INSERT role:global:ADMIN ==> perm:asset:INSERT
role:parentAsset:ADMIN ==> perm:asset:INSERT role:parentAsset:ADMIN ==> perm:asset:INSERT
role:global:GUEST ==> perm:asset:INSERT role:global:GUEST ==> perm:asset:INSERT
role:global:ADMIN ==> perm:asset:SELECT
role:asset:OWNER ==> perm:asset:DELETE role:asset:OWNER ==> perm:asset:DELETE
role:asset:ADMIN ==> perm:asset:UPDATE role:asset:ADMIN ==> perm:asset:UPDATE
role:asset:TENANT ==> perm:asset:SELECT role:asset:TENANT ==> perm:asset:SELECT

View File

@ -50,6 +50,7 @@ begin
hsHostingAssetOWNER(NEW), hsHostingAssetOWNER(NEW),
permissions => array['DELETE'], permissions => array['DELETE'],
incomingSuperRoles => array[ incomingSuperRoles => array[
globalADMIN(unassumed()),
hsBookingItemADMIN(newBookingItem), hsBookingItemADMIN(newBookingItem),
hsHostingAssetADMIN(newParentAsset)], hsHostingAssetADMIN(newParentAsset)],
userUuids => array[currentUserUuid()] userUuids => array[currentUserUuid()]
@ -86,10 +87,6 @@ begin
IF NEW.type = 'DOMAIN_SETUP' THEN IF NEW.type = 'DOMAIN_SETUP' THEN
END IF; END IF;
call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), globalAdmin());
call leaveTriggerForObjectUuid(NEW.uuid); call leaveTriggerForObjectUuid(NEW.uuid);
end; $$; end; $$;

View File

@ -71,15 +71,15 @@ begin
defaultPrefix := relatedDebitor.defaultPrefix; defaultPrefix := relatedDebitor.defaultPrefix;
insert into hs_hosting_asset insert into hs_hosting_asset
(uuid, bookingitemuuid, type, parentAssetUuid, assignedToAssetUuid, identifier, caption, config) (uuid, bookingitemuuid, type, parentAssetUuid, assignedToAssetUuid, identifier, caption, config)
values (managedServerUuid, relatedManagedServerBookingItem.uuid, 'MANAGED_SERVER', null, null, 'vm10' || debitorNumberSuffix, 'some ManagedServer', '{ "monit_max_cpu_usage": 90, "monit_max_ram_usage": 80, "monit_max_ssd_usage": 70 }'::jsonb), values (managedServerUuid, relatedManagedServerBookingItem.uuid, 'MANAGED_SERVER', null, null, 'vm10' || debitorNumberSuffix, 'some ManagedServer', '{ "monit_max_cpu_usage": 90, "monit_max_ram_usage": 80, "monit_max_ssd_usage": 70 }'::jsonb),
(uuid_generate_v4(), relatedCloudServerBookingItem.uuid, 'CLOUD_SERVER', null, null, 'vm20' || debitorNumberSuffix, 'another CloudServer', '{}'::jsonb), (uuid_generate_v4(), relatedCloudServerBookingItem.uuid, 'CLOUD_SERVER', null, null, 'vm20' || debitorNumberSuffix, 'another CloudServer', '{}'::jsonb),
(managedWebspaceUuid, relatedManagedWebspaceBookingItem.uuid, 'MANAGED_WEBSPACE', managedServerUuid, null, defaultPrefix || '01', 'some Webspace', '{}'::jsonb), (managedWebspaceUuid, relatedManagedWebspaceBookingItem.uuid, 'MANAGED_WEBSPACE', managedServerUuid, null, defaultPrefix || '01', 'some Webspace', '{}'::jsonb),
(uuid_generate_v4(), null, 'EMAIL_ALIAS', managedWebspaceUuid, null, defaultPrefix || '01-web', 'some E-Mail-Alias', '{ "target": [ "office@example.org", "archive@example.com" ] }'::jsonb), (uuid_generate_v4(), null, 'EMAIL_ALIAS', managedWebspaceUuid, null, defaultPrefix || '01-web', 'some E-Mail-Alias', '{ "target": [ "office@example.org", "archive@example.com" ] }'::jsonb),
(webUnixUserUuid, null, 'UNIX_USER', managedWebspaceUuid, null, defaultPrefix || '01-web', 'some UnixUser for Website', '{ "SSD-soft-quota": "128", "SSD-hard-quota": "256", "HDD-soft-quota": "512", "HDD-hard-quota": "1024"}'::jsonb), (webUnixUserUuid, null, 'UNIX_USER', managedWebspaceUuid, null, defaultPrefix || '01-web', 'some UnixUser for Website', '{ "SSD-soft-quota": "128", "SSD-hard-quota": "256", "HDD-soft-quota": "512", "HDD-hard-quota": "1024"}'::jsonb),
(domainSetupUuid, null, 'DOMAIN_SETUP', null, null, defaultPrefix || '.example.org', 'some Domain-Setup', '{}'::jsonb), (domainSetupUuid, null, 'DOMAIN_SETUP', null, null, defaultPrefix || '.example.org', 'some Domain-Setup', '{}'::jsonb),
(uuid_generate_v4(), null, 'DOMAIN_DNS_SETUP', domainSetupUuid, null, defaultPrefix || '.example.org', 'some Domain-DNS-Setup', '{}'::jsonb), (uuid_generate_v4(), null, 'DOMAIN_DNS_SETUP', domainSetupUuid, null, defaultPrefix || '.example.org|DNS', 'some Domain-DNS-Setup', '{}'::jsonb),
(uuid_generate_v4(), null, 'DOMAIN_HTTP_SETUP', domainSetupUuid, webUnixUserUuid, defaultPrefix || '.example.org', 'some Domain-HTTP-Setup', '{ "option-htdocsfallback": true, "use-fcgiphpbin": "/usr/lib/cgi-bin/php", "validsubdomainnames": "*"}'::jsonb); (uuid_generate_v4(), null, 'DOMAIN_HTTP_SETUP', domainSetupUuid, webUnixUserUuid, defaultPrefix || '.example.org|HTTP', 'some Domain-HTTP-Setup', '{ "option-htdocsfallback": true, "use-fcgiphpbin": "/usr/lib/cgi-bin/php", "validsubdomainnames": "*"}'::jsonb);
end; $$; end; $$;
--// --//

View File

@ -235,6 +235,47 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
assertThat(newUserUuid).isNotNull(); assertThat(newUserUuid).isNotNull();
} }
@Test
void globalAdmin_canAddTopLevelAsset() {
context.define("superuser-alex@hostsharing.net");
final var location = RestAssured // @formatter:off
.given()
.header("current-user", "superuser-alex@hostsharing.net")
.contentType(ContentType.JSON)
.body("""
{
"type": "DOMAIN_SETUP",
"identifier": "example.com",
"caption": "some unrelated domain-setup",
"config": {}
}
""")
.port(port)
.when()
.post("http://localhost/api/hs/hosting/assets")
.then().log().all().assertThat()
.statusCode(201)
.contentType(ContentType.JSON)
.body("", lenientlyEquals("""
{
"type": "DOMAIN_SETUP",
"identifier": "example.com",
"caption": "some unrelated domain-setup",
"config": {}
}
"""))
.header("Location", matchesRegex("http://localhost:[1-9][0-9]*/api/hs/hosting/assets/[^/]*"))
.extract().header("Location"); // @formatter:on
// finally, the new asset can be accessed under the generated UUID
final var newWebspace = UUID.fromString(
location.substring(location.lastIndexOf('/') + 1));
assertThat(newWebspace).isNotNull();
toCleanup(HsHostingAssetEntity.class, newWebspace);
}
@Test @Test
void propertyValidationsArePerformend_whenAddingAsset() { void propertyValidationsArePerformend_whenAddingAsset() {

View File

@ -131,7 +131,7 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu
initialGrantNames, initialGrantNames,
// global-admin // global-admin
"{ grant perm:hs_hosting_asset#fir00:SELECT to role:global#global:ADMIN by system and assume }", // workaround "{ grant role:hs_hosting_asset#fir00:OWNER to role:global#global:ADMIN by system }", // workaround
// owner // owner
"{ grant role:hs_hosting_asset#fir00:OWNER to user:superuser-alex@hostsharing.net by hs_hosting_asset#fir00:OWNER and assume }", "{ grant role:hs_hosting_asset#fir00:OWNER to user:superuser-alex@hostsharing.net by hs_hosting_asset#fir00:OWNER and assume }",
@ -159,37 +159,38 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu
@Test @Test
public void anyUser_canCreateNewDomainSetupAsset() { public void anyUser_canCreateNewDomainSetupAsset() {
// given
context("superuser-alex@hostsharing.net");
final var assetCount = assetRepo.count();
// when // when
context("person-SmithPeter@example.com"); context("person-SmithPeter@example.com");
final var result = attempt(em, () -> { final var result = attempt(em, () -> {
final var newAsset = HsHostingAssetEntity.builder() final var newAsset = HsHostingAssetEntity.builder()
.type(DOMAIN_SETUP) .type(DOMAIN_SETUP)
.identifier("example.org") .identifier("example.net")
.caption("some new domain setup") .caption("some new domain setup")
.build(); .build();
return toCleanup(assetRepo.save(newAsset)); return assetRepo.save(newAsset);
}); });
// then // then
// ... the domain setup was created and returned
result.assertSuccessful(); result.assertSuccessful();
assertThat(result.returnedValue()).isNotNull().extracting(HsHostingAssetEntity::getUuid).isNotNull(); assertThat(result.returnedValue()).isNotNull().extracting(HsHostingAssetEntity::getUuid).isNotNull();
assertThat(result.returnedValue().isLoaded()).isFalse(); assertThat(result.returnedValue().isLoaded()).isFalse();
// ... the creating user can read the new domain setup
context("person-SmithPeter@example.com"); context("person-SmithPeter@example.com");
assertThatAssetIsPersisted(result.returnedValue()); assertThatAssetIsPersisted(result.returnedValue());
context("superuser-alex@hostsharing.net");
assertThat(assetRepo.count()).isEqualTo(assetCount + 1); // ... a global admin can see the new domain setup as well if the domain OWNER role is assumed
context("superuser-alex@hostsharing.net", "hs_hosting_asset#example.net:OWNER"); // only works with the assumed role
assertThatAssetIsPersisted(result.returnedValue());
} }
private void assertThatAssetIsPersisted(final HsHostingAssetEntity saved) { private void assertThatAssetIsPersisted(final HsHostingAssetEntity saved) {
em.clear();
attempt(em, () -> { attempt(em, () -> {
final var found = assetRepo.findByUuid(saved.getUuid()); final var found = assetRepo.findByUuid(saved.getUuid());
assertThat(found).isNotEmpty().map(HsHostingAssetEntity::toString).contains(saved.toString()); assertThat(found).isNotEmpty().map(HsHostingAssetEntity::toString).contains(saved.toString());
}); });
} }
} }

View File

@ -31,7 +31,7 @@ class HsDomainDnsSetupHostingAssetValidatorUnitTest {
return HsHostingAssetEntity.builder() return HsHostingAssetEntity.builder()
.type(DOMAIN_DNS_SETUP) .type(DOMAIN_DNS_SETUP)
.parentAsset(validDomainSetupEntity) .parentAsset(validDomainSetupEntity)
.identifier("example.org") .identifier("example.org|DNS")
.config(Map.ofEntries( .config(Map.ofEntries(
entry("user-RR", Array.of( entry("user-RR", Array.of(
"@ 1814400 IN XXX example.org. root.example.org ( 1234 10800 900 604800 86400 )", "@ 1814400 IN XXX example.org. root.example.org ( 1234 10800 900 604800 86400 )",
@ -74,19 +74,20 @@ class HsDomainDnsSetupHostingAssetValidatorUnitTest {
void preprocessesTakesIdentifierFromParent() { void preprocessesTakesIdentifierFromParent() {
// given // given
final var givenEntity = validEntityBuilder().build(); final var givenEntity = validEntityBuilder().build();
assertThat(givenEntity.getParentAsset().getIdentifier()).as("preconditon failed").isEqualTo("example.org");
final var validator = HsHostingAssetEntityValidatorRegistry.forType(givenEntity.getType()); final var validator = HsHostingAssetEntityValidatorRegistry.forType(givenEntity.getType());
// when // when
validator.preprocessEntity(givenEntity); validator.preprocessEntity(givenEntity);
// then // then
assertThat(givenEntity.getIdentifier()).isEqualTo(givenEntity.getParentAsset().getIdentifier()); assertThat(givenEntity.getIdentifier()).isEqualTo("example.org|DNS");
} }
@Test @Test
void rejectsInvalidIdentifier() { void rejectsInvalidIdentifier() {
// given // given
final var givenEntity = validEntityBuilder().identifier("wrong.org").build(); final var givenEntity = validEntityBuilder().identifier("example.org").build();
final var validator = HsHostingAssetEntityValidatorRegistry.forType(givenEntity.getType()); final var validator = HsHostingAssetEntityValidatorRegistry.forType(givenEntity.getType());
// when // when
@ -94,14 +95,14 @@ class HsDomainDnsSetupHostingAssetValidatorUnitTest {
// then // then
assertThat(result).containsExactly( assertThat(result).containsExactly(
"'identifier' expected to match '^example.org$', but is 'wrong.org'" "'identifier' expected to match '^example.org|DNS$', but is 'example.org'"
); );
} }
@Test @Test
void acceptsValidIdentifier() { void acceptsValidIdentifier() {
// given // given
final var givenEntity = validEntityBuilder().identifier(validDomainSetupEntity.getIdentifier()).build(); final var givenEntity = validEntityBuilder().identifier(validDomainSetupEntity.getIdentifier()+"|DNS").build();
final var validator = HsHostingAssetEntityValidatorRegistry.forType(givenEntity.getType()); final var validator = HsHostingAssetEntityValidatorRegistry.forType(givenEntity.getType());
// when // when
@ -126,9 +127,9 @@ class HsDomainDnsSetupHostingAssetValidatorUnitTest {
// then // then
assertThat(result).containsExactlyInAnyOrder( assertThat(result).containsExactlyInAnyOrder(
"'DOMAIN_DNS_SETUP:example.org.bookingItem' must be null but is set to D-???????-?:null", "'DOMAIN_DNS_SETUP:example.org|DNS.bookingItem' must be null but is set to D-???????-?:null",
"'DOMAIN_DNS_SETUP:example.org.parentAsset' must be of type DOMAIN_SETUP but is of type null", "'DOMAIN_DNS_SETUP:example.org|DNS.parentAsset' must be of type DOMAIN_SETUP but is of type null",
"'DOMAIN_DNS_SETUP:example.org.assignedToAsset' must be null but is set to D-???????-?:null"); "'DOMAIN_DNS_SETUP:example.org|DNS.assignedToAsset' must be null but is set to D-???????-?:null");
} }
@Test @Test
@ -162,9 +163,9 @@ class HsDomainDnsSetupHostingAssetValidatorUnitTest {
// then // then
assertThat(result).containsExactlyInAnyOrder( assertThat(result).containsExactlyInAnyOrder(
"'DOMAIN_DNS_SETUP:example.org.config.TTL' is expected to be of type class java.lang.Integer, but is of type 'String'", "'DOMAIN_DNS_SETUP:example.org|DNS.config.TTL' is expected to be of type class java.lang.Integer, but is of type 'String'",
"'DOMAIN_DNS_SETUP:example.org.config.user-RR' is expected to match any of [([a-z0-9\\.-]+|@)\\s+(([1-9][0-9]*[mMhHdDwW]{0,1})+\\s+)*IN\\s+[A-Z]+\\s+[^;].*(;.*)*, ([a-z0-9\\.-]+|@)\\s+IN\\s+(([1-9][0-9]*[mMhHdDwW]{0,1})+\\s+)*[A-Z]+\\s+[^;].*(;.*)*] but '@ 1814400 IN 1814400 BAD1 TTL only allowed once' does not match any", "'DOMAIN_DNS_SETUP:example.org|DNS.config.user-RR' is expected to match any of [([a-z0-9\\.-]+|@)\\s+(([1-9][0-9]*[mMhHdDwW]{0,1})+\\s+)*IN\\s+[A-Z]+\\s+[^;].*(;.*)*, ([a-z0-9\\.-]+|@)\\s+IN\\s+(([1-9][0-9]*[mMhHdDwW]{0,1})+\\s+)*[A-Z]+\\s+[^;].*(;.*)*] but '@ 1814400 IN 1814400 BAD1 TTL only allowed once' does not match any",
"'DOMAIN_DNS_SETUP:example.org.config.user-RR' is expected to match any of [([a-z0-9\\.-]+|@)\\s+(([1-9][0-9]*[mMhHdDwW]{0,1})+\\s+)*IN\\s+[A-Z]+\\s+[^;].*(;.*)*, ([a-z0-9\\.-]+|@)\\s+IN\\s+(([1-9][0-9]*[mMhHdDwW]{0,1})+\\s+)*[A-Z]+\\s+[^;].*(;.*)*] but 'www BAD1 Record-Class missing / not enough columns' does not match any"); "'DOMAIN_DNS_SETUP:example.org|DNS.config.user-RR' is expected to match any of [([a-z0-9\\.-]+|@)\\s+(([1-9][0-9]*[mMhHdDwW]{0,1})+\\s+)*IN\\s+[A-Z]+\\s+[^;].*(;.*)*, ([a-z0-9\\.-]+|@)\\s+IN\\s+(([1-9][0-9]*[mMhHdDwW]{0,1})+\\s+)*[A-Z]+\\s+[^;].*(;.*)*] but 'www BAD1 Record-Class missing / not enough columns' does not match any");
} }
@Test @Test

View File

@ -8,7 +8,6 @@ import net.hostsharing.hsadminng.rbac.rbacgrant.RbacGrantsDiagramService;
import net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleEntity; import net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleEntity;
import net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleRepository; import net.hostsharing.hsadminng.rbac.rbacrole.RbacRoleRepository;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.TestInfo;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -171,7 +170,7 @@ public abstract class ContextBasedTestWithCleanup extends ContextBasedTest {
this.testInfo = testInfo; this.testInfo = testInfo;
} }
@AfterEach //@AfterEach
hsh-michaelhoennig marked this conversation as resolved Outdated

muss wieder rein

muss wieder rein
void cleanupAndCheckCleanup(final TestInfo testInfo) { void cleanupAndCheckCleanup(final TestInfo testInfo) {
// If the whole test method has its own transaction, cleanup makes no sense. // If the whole test method has its own transaction, cleanup makes no sense.
// If that transaction even failed, cleaunup would cause an exception. // If that transaction even failed, cleaunup would cause an exception.