This is an automated email from the ASF dual-hosted git repository. btellier pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
commit abaa0021c6c9f2d17d84f84052b77f0959c984d0 Author: Benoit Tellier <[email protected]> AuthorDate: Mon May 13 17:50:40 2019 +0700 JAMES-2149 Domain routes should handle aliases Add the following CRUD routes and their unit tests: GET /domains/domain.tld/aliases PUT /domains/domain.tld/aliases/alias.domain.tld DELETE /domains/domain.tld/aliases/alias.domain.tld --- .../james/webadmin/dto/DomainAliasResponse.java | 51 ++++ .../james/webadmin/routes/DomainsRoutes.java | 162 +++++++++++-- .../webadmin/dto/DomainAliasResponseTest.java | 31 +++ .../james/webadmin/routes/DomainsRoutesTest.java | 257 ++++++++++++++++++++- 4 files changed, 479 insertions(+), 22 deletions(-) diff --git a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/DomainAliasResponse.java b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/DomainAliasResponse.java new file mode 100644 index 0000000..141faf9 --- /dev/null +++ b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/DomainAliasResponse.java @@ -0,0 +1,51 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.webadmin.dto; + +import java.util.Objects; + +import org.apache.james.rrt.lib.MappingSource; + +public class DomainAliasResponse { + private final MappingSource source; + + public DomainAliasResponse(MappingSource source) { + this.source = source; + } + + public String getSource() { + return source.getFixedDomain(); + } + + @Override + public final boolean equals(Object o) { + if (o instanceof DomainAliasResponse) { + DomainAliasResponse that = (DomainAliasResponse) o; + + return Objects.equals(this.source, that.source); + } + return false; + } + + @Override + public final int hashCode() { + return Objects.hash(source); + } +} diff --git a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/DomainsRoutes.java b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/DomainsRoutes.java index 321b2c7..8625498 100644 --- a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/DomainsRoutes.java +++ b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/DomainsRoutes.java @@ -34,8 +34,13 @@ import javax.ws.rs.Produces; import org.apache.james.core.Domain; import org.apache.james.domainlist.api.DomainList; import org.apache.james.domainlist.api.DomainListException; +import org.apache.james.rrt.api.RecipientRewriteTable; +import org.apache.james.rrt.api.RecipientRewriteTableException; +import org.apache.james.rrt.lib.Mapping; +import org.apache.james.rrt.lib.MappingSource; import org.apache.james.webadmin.Constants; import org.apache.james.webadmin.Routes; +import org.apache.james.webadmin.dto.DomainAliasResponse; import org.apache.james.webadmin.utils.ErrorResponder; import org.apache.james.webadmin.utils.ErrorResponder.ErrorType; import org.apache.james.webadmin.utils.JsonTransformer; @@ -43,13 +48,18 @@ import org.eclipse.jetty.http.HttpStatus; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.github.steveash.guavate.Guavate; import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; + import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; +import spark.HaltException; import spark.Request; import spark.Response; import spark.Service; @@ -58,22 +68,31 @@ import spark.Service; @Path(DomainsRoutes.DOMAINS) @Produces("application/json") public class DomainsRoutes implements Routes { - - private static final String DOMAIN_NAME = ":domainName"; - private static final Logger LOGGER = LoggerFactory.getLogger(DomainsRoutes.class); + @FunctionalInterface + interface MappingOperation { + void perform(MappingSource mappingSource, Mapping mapping) throws RecipientRewriteTableException; + } public static final String DOMAINS = "/domains"; - public static final String SPECIFIC_DOMAIN = DOMAINS + SEPARATOR + DOMAIN_NAME; - public static final int MAXIMUM_DOMAIN_SIZE = 256; - + private static final Logger LOGGER = LoggerFactory.getLogger(DomainsRoutes.class); + private static final String DOMAIN_NAME = ":domainName"; + private static final String SOURCE_DOMAIN = ":sourceDomain"; + private static final String DESTINATION_DOMAIN = ":destinationDomain"; + private static final String SPECIFIC_DOMAIN = DOMAINS + SEPARATOR + DOMAIN_NAME; + private static final String ALIASES = "aliases"; + private static final String DOMAIN_ALIASES = SPECIFIC_DOMAIN + SEPARATOR + ALIASES; + private static final String SPECIFIC_ALIAS = DOMAINS + SEPARATOR + DESTINATION_DOMAIN + SEPARATOR + ALIASES + SEPARATOR + SOURCE_DOMAIN; + private static final int MAXIMUM_DOMAIN_SIZE = 256; private final DomainList domainList; + private final RecipientRewriteTable recipientRewriteTable; private final JsonTransformer jsonTransformer; private Service service; @Inject - public DomainsRoutes(DomainList domainList, JsonTransformer jsonTransformer) { + public DomainsRoutes(DomainList domainList, RecipientRewriteTable recipientRewriteTable, JsonTransformer jsonTransformer) { this.domainList = domainList; + this.recipientRewriteTable = recipientRewriteTable; this.jsonTransformer = jsonTransformer; } @@ -86,13 +105,16 @@ public class DomainsRoutes implements Routes { public void define(Service service) { this.service = service; + // Domain endpoints defineGetDomains(); - defineDomainExists(); - defineAddDomain(); - defineDeleteDomain(); + + // Domain aliases endpoints + defineListAliases(service); + defineAddAlias(service); + defineRemoveAlias(service); } @DELETE @@ -156,9 +178,59 @@ public class DomainsRoutes implements Routes { jsonTransformer); } + @GET + @Path("/{domainName}/aliases") + @ApiOperation(value = "Getting all aliases for a domain") + @ApiImplicitParams({ + @ApiImplicitParam(required = true, dataType = "string", name = "domainName", paramType = "path") + }) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.OK_200, message = "OK", response = List.class), + @ApiResponse(code = HttpStatus.NOT_FOUND_404, message = "The domain does not exist."), + @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, + message = "Internal server error - Something went bad on the server side.") + }) + public void defineListAliases(Service service) { + service.get(DOMAIN_ALIASES, this::listDomainAliases, jsonTransformer); + } + + @DELETE + @Path("/{destinationDomain}/aliases/{sourceDomain}") + @ApiOperation(value = "Remove an alias for a specific domain") + @ApiImplicitParams({ + @ApiImplicitParam(required = true, dataType = "string", name = "sourceDomain", paramType = "path"), + @ApiImplicitParam(required = true, dataType = "string", name = "destinationDomain", paramType = "path") + }) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.NO_CONTENT_204, message = "OK", response = List.class), + @ApiResponse(code = HttpStatus.NOT_FOUND_404, message = "The domain does not exist."), + @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, + message = "Internal server error - Something went bad on the server side.") + }) + public void defineRemoveAlias(Service service) { + service.delete(SPECIFIC_ALIAS, this::removeDomainAlias, jsonTransformer); + } + + @PUT + @Path("/{destinationDomain}/aliases/{sourceDomain}") + @ApiOperation(value = "Add an alias for a specific domain") + @ApiImplicitParams({ + @ApiImplicitParam(required = true, dataType = "string", name = "sourceDomain", paramType = "path"), + @ApiImplicitParam(required = true, dataType = "string", name = "destinationDomain", paramType = "path") + }) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.NO_CONTENT_204, message = "OK", response = List.class), + @ApiResponse(code = HttpStatus.NOT_FOUND_404, message = "The domain does not exist."), + @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, + message = "Internal server error - Something went bad on the server side.") + }) + public void defineAddAlias(Service service) { + service.put(SPECIFIC_ALIAS, this::addDomainAlias, jsonTransformer); + } + private String removeDomain(Request request, Response response) { try { - Domain domain = checkValidDomain(request); + Domain domain = checkValidDomain(request.params(DOMAIN_NAME)); domainList.removeDomain(domain); } catch (DomainListException e) { LOGGER.info("{} did not exists", request.params(DOMAIN_NAME)); @@ -168,7 +240,7 @@ public class DomainsRoutes implements Routes { } private String addDomain(Request request, Response response) { - Domain domain = checkValidDomain(request); + Domain domain = checkValidDomain(request.params(DOMAIN_NAME)); try { addDomain(domain); response.status(204); @@ -192,8 +264,7 @@ public class DomainsRoutes implements Routes { return Constants.EMPTY_BODY; } - private Domain checkValidDomain(Request request) { - String domainName = request.params(DOMAIN_NAME); + private Domain checkValidDomain(String domainName) { try { return Domain.of(domainName); } catch (IllegalArgumentException e) { @@ -212,16 +283,67 @@ public class DomainsRoutes implements Routes { } private Response exists(Request request, Response response) throws DomainListException { - Domain domain = checkValidDomain(request); + Domain domain = checkValidDomain(request.params(DOMAIN_NAME)); + if (!domainList.containsDomain(domain)) { - throw ErrorResponder.builder() - .statusCode(HttpStatus.NOT_FOUND_404) - .type(ErrorType.INVALID_ARGUMENT) - .message("The domain list does not contain: " + domain.name()) - .haltError(); + throw domainNotFound(domain); } else { response.status(HttpStatus.NO_CONTENT_204); return response; } } + + private ImmutableSet<DomainAliasResponse> listDomainAliases(Request request, Response response) throws DomainListException, RecipientRewriteTableException { + Domain domain = checkValidDomain(request.params(DOMAIN_NAME)); + + if (!hasAliases(domain)) { + throw domainHasNoAliases(domain); + } else { + return recipientRewriteTable.listSources(Mapping.domain(domain)) + .map(DomainAliasResponse::new) + .collect(Guavate.toImmutableSet()); + } + } + + private String addDomainAlias(Request request, Response response) throws DomainListException, RecipientRewriteTableException { + return performOperationOnAlias(request, response, recipientRewriteTable::addMapping); + } + + private String removeDomainAlias(Request request, Response response) throws DomainListException, RecipientRewriteTableException { + return performOperationOnAlias(request, response, recipientRewriteTable::removeMapping); + } + + private String performOperationOnAlias(Request request, Response response, MappingOperation operation) throws DomainListException, RecipientRewriteTableException { + Domain sourceDomain = checkValidDomain(request.params(SOURCE_DOMAIN)); + Domain destinationDomain = checkValidDomain(request.params(DESTINATION_DOMAIN)); + + if (!domainList.containsDomain(sourceDomain)) { + throw domainNotFound(sourceDomain); + } + + operation.perform(MappingSource.fromDomain(sourceDomain), Mapping.domain(destinationDomain)); + response.status(HttpStatus.NO_CONTENT_204); + return Constants.EMPTY_BODY; + } + + private boolean hasAliases(Domain domain) throws DomainListException, RecipientRewriteTableException { + return domainList.containsDomain(domain) + || recipientRewriteTable.listSources(Mapping.domain(domain)).findFirst().isPresent(); + } + + private HaltException domainNotFound(Domain domain) { + return ErrorResponder.builder() + .statusCode(HttpStatus.NOT_FOUND_404) + .type(ErrorType.INVALID_ARGUMENT) + .message("The domain list does not contain: " + domain.name()) + .haltError(); + } + + private HaltException domainHasNoAliases(Domain domain) { + return ErrorResponder.builder() + .statusCode(HttpStatus.NOT_FOUND_404) + .type(ErrorType.INVALID_ARGUMENT) + .message("The following domain is not in the domain list and has no registered local aliases: " + domain.name()) + .haltError(); + } } diff --git a/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/dto/DomainAliasResponseTest.java b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/dto/DomainAliasResponseTest.java new file mode 100644 index 0000000..f8fb107 --- /dev/null +++ b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/dto/DomainAliasResponseTest.java @@ -0,0 +1,31 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.webadmin.dto; + +import org.junit.jupiter.api.Test; + +import nl.jqno.equalsverifier.EqualsVerifier; + +class DomainAliasResponseTest { + @Test + void shouldMatchBeanContract() { + EqualsVerifier.forClass(DomainAliasResponse.class).verify(); + } +} \ No newline at end of file diff --git a/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/DomainsRoutesTest.java b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/DomainsRoutesTest.java index 82b7dde..d5f28bd 100644 --- a/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/DomainsRoutesTest.java +++ b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/DomainsRoutesTest.java @@ -25,6 +25,9 @@ import static io.restassured.RestAssured.with; import static org.apache.james.webadmin.Constants.SEPARATOR; import static org.apache.james.webadmin.WebAdminServer.NO_CONFIGURATION; import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.hasSize; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; @@ -40,6 +43,7 @@ import org.apache.james.domainlist.api.DomainList; import org.apache.james.domainlist.api.DomainListException; import org.apache.james.domainlist.memory.MemoryDomainList; import org.apache.james.metrics.logger.DefaultMetricFactory; +import org.apache.james.rrt.memory.MemoryRecipientRewriteTable; import org.apache.james.webadmin.WebAdminServer; import org.apache.james.webadmin.WebAdminUtils; import org.apache.james.webadmin.utils.JsonTransformer; @@ -54,14 +58,17 @@ import io.restassured.http.ContentType; public class DomainsRoutesTest { - public static final String DOMAIN = "domain"; + private static final String DOMAIN = "domain"; + private static final String ALIAS_DOMAIN = "alias.domain"; + private static final String ALIAS_DOMAIN_2 = "alias.domain.bis"; + public static final String EXTERNAL_DOMAIN = "external.domain.tld"; private WebAdminServer webAdminServer; private void createServer(DomainList domainList) throws Exception { webAdminServer = WebAdminUtils.createWebAdminServer( new DefaultMetricFactory(), - new DomainsRoutes(domainList, new JsonTransformer())); + new DomainsRoutes(domainList, new MemoryRecipientRewriteTable(), new JsonTransformer())); webAdminServer.configure(NO_CONFIGURATION); webAdminServer.await(); @@ -255,6 +262,252 @@ public class DomainsRoutesTest { .statusCode(HttpStatus.NOT_FOUND_404); } + @Nested + class DomainAlias{ + @Test + void getAliasesShouldReturnNotFoundWhenDomainDoesNotExist() { + when() + .get(DOMAIN + "/aliases") + .then() + .contentType(ContentType.JSON) + .statusCode(HttpStatus.NOT_FOUND_404) + .body("statusCode", is(HttpStatus.NOT_FOUND_404)) + .body("type", is("InvalidArgument")) + .body("message", is("The following domain is not in the domain list and has no registered local aliases: domain")); + } + + @Test + void getAliasesShouldReturnEmptyWhenNone() { + with().put(DOMAIN); + + when() + .get(DOMAIN + "/aliases") + .then() + .contentType(ContentType.JSON) + .statusCode(HttpStatus.OK_200) + .body(".", hasSize(0)); + } + + @Test + void getAliasesShouldReturnCreatedAliases() { + with().put(DOMAIN); + with().put(ALIAS_DOMAIN); + with().put(ALIAS_DOMAIN_2); + + with().put(DOMAIN + "/aliases/" + ALIAS_DOMAIN); + with().put(DOMAIN + "/aliases/" + ALIAS_DOMAIN_2); + + when() + .get(DOMAIN + "/aliases") + .then() + .contentType(ContentType.JSON) + .statusCode(HttpStatus.OK_200) + .body("source", containsInAnyOrder(ALIAS_DOMAIN, ALIAS_DOMAIN_2)); + } + + @Test + void putShouldBeIdempotent() { + with().put(DOMAIN); + with().put(ALIAS_DOMAIN); + + with().put(DOMAIN + "/aliases/" + ALIAS_DOMAIN); + with().put(DOMAIN + "/aliases/" + ALIAS_DOMAIN); + + when() + .get(DOMAIN + "/aliases") + .then() + .contentType(ContentType.JSON) + .statusCode(HttpStatus.OK_200) + .body("source", containsInAnyOrder(ALIAS_DOMAIN)); + } + + @Test + void deleteShouldNotFailOnNonExistingEvents() { + with().put(DOMAIN); + with().put(ALIAS_DOMAIN); + + with().delete(DOMAIN + "/aliases/" + ALIAS_DOMAIN); + + when() + .get(DOMAIN + "/aliases") + .then() + .contentType(ContentType.JSON) + .statusCode(HttpStatus.OK_200) + .body("", hasSize(0)); + } + + @Test + void putShouldLowercaseDomain() { + with().put(DOMAIN); + with().put(ALIAS_DOMAIN); + + with().put(DOMAIN + "/aliases/" + "Alias.Domain"); + + when() + .get(DOMAIN + "/aliases") + .then() + .contentType(ContentType.JSON) + .statusCode(HttpStatus.OK_200) + .body("source", containsInAnyOrder(ALIAS_DOMAIN)); + } + + @Test + void getAliasesShouldNotReturnDeletedAliases() { + with().put(DOMAIN); + with().put(ALIAS_DOMAIN); + + with().put(DOMAIN + "/aliases/" + ALIAS_DOMAIN); + with().delete(DOMAIN + "/aliases/" + ALIAS_DOMAIN); + + when() + .get(DOMAIN + "/aliases") + .then() + .contentType(ContentType.JSON) + .statusCode(HttpStatus.OK_200) + .body(".", hasSize(0)); + } + + @Test + void deleteShouldReturnNotFoundWhenAliasDomainDoesNotExist() { + with().put(DOMAIN); + + when() + .delete(DOMAIN + "/aliases/" + ALIAS_DOMAIN) + .then() + .contentType(ContentType.JSON) + .statusCode(HttpStatus.NOT_FOUND_404) + .body("statusCode", is(HttpStatus.NOT_FOUND_404)) + .body("type", is("InvalidArgument")) + .body("message", is("The domain list does not contain: " + ALIAS_DOMAIN)); + } + + @Test + void putShouldReturnNotFoundWhenAliasDomainDoesNotExist() { + with().put(DOMAIN); + + when() + .put(DOMAIN + "/aliases/" + ALIAS_DOMAIN) + .then() + .contentType(ContentType.JSON) + .statusCode(HttpStatus.NOT_FOUND_404) + .body("statusCode", is(HttpStatus.NOT_FOUND_404)) + .body("type", is("InvalidArgument")) + .body("message", is("The domain list does not contain: " + ALIAS_DOMAIN)); + } + + @Test + void putShouldNotFailOnExternalDomainAlias() { + with().put(DOMAIN); + + when() + .put(EXTERNAL_DOMAIN + "/aliases/" + DOMAIN).prettyPeek() + .then() + .contentType(ContentType.JSON) + .statusCode(HttpStatus.NO_CONTENT_204); + } + + @Test + void deleteShouldNotFailOnExternalDomainDestinationForAnAlias() { + with().put(DOMAIN); + + when() + .delete(EXTERNAL_DOMAIN + "/aliases/" + DOMAIN) + .then() + .contentType(ContentType.JSON) + .statusCode(HttpStatus.NO_CONTENT_204); + } + + @Test + void getAliasesShouldListAliasesForExternalDomains() { + with().put(DOMAIN); + + with().put(EXTERNAL_DOMAIN + "/aliases/" + DOMAIN); + + when() + .get(EXTERNAL_DOMAIN + "/aliases") + .then() + .contentType(ContentType.JSON) + .statusCode(HttpStatus.OK_200) + .body("source", containsInAnyOrder(DOMAIN)); + } + + @Test + void deleteShouldRemoveExternalDomainAlias() { + with().put(DOMAIN); + + with().put(EXTERNAL_DOMAIN + "/aliases/" + DOMAIN); + + with().delete(EXTERNAL_DOMAIN + "/aliases/" + DOMAIN); + + when() + .get(DOMAIN + "/aliases") + .then() + .contentType(ContentType.JSON) + .statusCode(HttpStatus.OK_200) + .body("source", hasSize(0)); + } + + @Test + void putShouldReturnBadRequestWhenDestinationDomainIsInvalid() { + when() + .put("invalid@domain/aliases/" + ALIAS_DOMAIN) + .then() + .contentType(ContentType.JSON) + .statusCode(HttpStatus.BAD_REQUEST_400) + .body("statusCode", is(HttpStatus.BAD_REQUEST_400)) + .body("type", is("InvalidArgument")) + .body("message", is("Invalid request for domain creation invalid@domain")); + } + + @Test + void putShouldReturnBadRequestWhenSourceDomainIsInvalid() { + when() + .put("domain/aliases/[email protected]") + .then() + .contentType(ContentType.JSON) + .statusCode(HttpStatus.BAD_REQUEST_400) + .body("statusCode", is(HttpStatus.BAD_REQUEST_400)) + .body("type", is("InvalidArgument")) + .body("message", is("Invalid request for domain creation [email protected]")); + } + + @Test + void deleteShouldReturnBadRequestWhenDestinationDomainIsInvalid() { + when() + .delete("invalid@domain/aliases/" + ALIAS_DOMAIN) + .then() + .contentType(ContentType.JSON) + .statusCode(HttpStatus.BAD_REQUEST_400) + .body("statusCode", is(HttpStatus.BAD_REQUEST_400)) + .body("type", is("InvalidArgument")) + .body("message", is("Invalid request for domain creation invalid@domain")); + } + + @Test + void deleteShouldReturnBadRequestWhenSourceDomainIsInvalid() { + when() + .delete("domain/aliases/[email protected]") + .then() + .contentType(ContentType.JSON) + .statusCode(HttpStatus.BAD_REQUEST_400) + .body("statusCode", is(HttpStatus.BAD_REQUEST_400)) + .body("type", is("InvalidArgument")) + .body("message", is("Invalid request for domain creation [email protected]")); + } + + @Test + void getAliasesShouldReturnBadRequestWhenDomainIsInvalid() { + when() + .get("invalid@domain/aliases") + .then() + .contentType(ContentType.JSON) + .statusCode(HttpStatus.BAD_REQUEST_400) + .body("statusCode", is(HttpStatus.BAD_REQUEST_400)) + .body("type", is("InvalidArgument")) + .body("message", is("Invalid request for domain creation invalid@domain")); + } + } + } @Nested --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
