Repository: james-project Updated Branches: refs/heads/master d926a617a -> dc59e58bf
JAMES-2149 Create domain mappings via webadmin Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/dc59e58b Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/dc59e58b Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/dc59e58b Branch: refs/heads/master Commit: dc59e58bf0ddc6c50ca0259bff19b90864613aba Parents: d926a61 Author: Edgar Asatryan <[email protected]> Authored: Sat Jun 9 16:15:02 2018 +0400 Committer: Matthieu Baechler <[email protected]> Committed: Thu Jun 21 15:56:18 2018 +0200 ---------------------------------------------------------------------- .../james/modules/server/DataRoutesModules.java | 2 + .../org/apache/james/rrt/lib/MappingsImpl.java | 7 +- server/protocols/webadmin/webadmin-data/pom.xml | 6 +- .../webadmin/routes/DomainMappingsRoutes.java | 206 ++++++++++ .../routes/DomainMappingsRoutesTest.java | 386 +++++++++++++++++++ 5 files changed, 605 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/dc59e58b/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/DataRoutesModules.java ---------------------------------------------------------------------- diff --git a/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/DataRoutesModules.java b/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/DataRoutesModules.java index 2ae64ec..ef695fa 100644 --- a/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/DataRoutesModules.java +++ b/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/DataRoutesModules.java @@ -20,6 +20,7 @@ package org.apache.james.modules.server; import org.apache.james.webadmin.Routes; +import org.apache.james.webadmin.routes.DomainMappingsRoutes; import org.apache.james.webadmin.routes.DomainsRoutes; import org.apache.james.webadmin.routes.ForwardRoutes; import org.apache.james.webadmin.routes.GroupsRoutes; @@ -34,6 +35,7 @@ public class DataRoutesModules extends AbstractModule { protected void configure() { Multibinder<Routes> routesMultibinder = Multibinder.newSetBinder(binder(), Routes.class); routesMultibinder.addBinding().to(DomainsRoutes.class); + routesMultibinder.addBinding().to(DomainMappingsRoutes.class); routesMultibinder.addBinding().to(ForwardRoutes.class); routesMultibinder.addBinding().to(GroupsRoutes.class); routesMultibinder.addBinding().to(UserRoutes.class); http://git-wip-us.apache.org/repos/asf/james-project/blob/dc59e58b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingsImpl.java ---------------------------------------------------------------------- diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingsImpl.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingsImpl.java index 6c042ff..c633307 100644 --- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingsImpl.java +++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/MappingsImpl.java @@ -22,6 +22,7 @@ package org.apache.james.rrt.lib; import java.io.Serializable; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Comparator; import java.util.Iterator; @@ -86,7 +87,11 @@ public class MappingsImpl implements Mappings, Serializable { public static MappingsImpl fromRawString(String raw) { return fromCollection(mappingToCollection(raw)); } - + + public static MappingsImpl fromMappings(Mapping... mappings) { + return fromMappings(Arrays.stream(mappings)); + } + private static ArrayList<String> mappingToCollection(String rawMapping) { ArrayList<String> map = new ArrayList<>(); StringTokenizer tokenizer = new StringTokenizer(rawMapping, RecipientRewriteTableUtil.getSeparator(rawMapping)); http://git-wip-us.apache.org/repos/asf/james-project/blob/dc59e58b/server/protocols/webadmin/webadmin-data/pom.xml ---------------------------------------------------------------------- diff --git a/server/protocols/webadmin/webadmin-data/pom.xml b/server/protocols/webadmin/webadmin-data/pom.xml index f4b1d20..c007063 100644 --- a/server/protocols/webadmin/webadmin-data/pom.xml +++ b/server/protocols/webadmin/webadmin-data/pom.xml @@ -19,7 +19,6 @@ --> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> - <parent> <groupId>org.apache.james</groupId> <artifactId>james-server</artifactId> @@ -119,6 +118,11 @@ <scope>test</scope> </dependency> <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-params</artifactId> + <scope>test</scope> + </dependency> + <dependency> <groupId>org.junit.platform</groupId> <artifactId>junit-platform-launcher</artifactId> <scope>test</scope> http://git-wip-us.apache.org/repos/asf/james-project/blob/dc59e58b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/DomainMappingsRoutes.java ---------------------------------------------------------------------- diff --git a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/DomainMappingsRoutes.java b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/DomainMappingsRoutes.java new file mode 100644 index 0000000..2502fa7 --- /dev/null +++ b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/DomainMappingsRoutes.java @@ -0,0 +1,206 @@ +/**************************************************************** + * 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.routes; + +import static org.apache.james.webadmin.Constants.SEPARATOR; +import static org.apache.james.webadmin.routes.DomainMappingsRoutes.DOMAIN_MAPPINGS; +import static spark.Spark.halt; + +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; + +import javax.inject.Inject; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; + +import org.apache.james.core.Domain; +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.rrt.lib.Mappings; +import org.apache.james.webadmin.Routes; +import org.apache.james.webadmin.utils.ErrorResponder; +import org.apache.james.webadmin.utils.JsonTransformer; +import org.eclipse.jetty.http.HttpStatus; + +import com.github.fge.lambdas.consumers.ThrowingBiConsumer; +import com.github.steveash.guavate.Guavate; + +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; + +@Api(tags = "Domain Mappings") +@Path(DOMAIN_MAPPINGS) +@Produces("application/json") +public class DomainMappingsRoutes implements Routes { + static final String DOMAIN_MAPPINGS = "/domainMappings"; + private static final String FROM_DOMAIN = "fromDomain"; + private static final String SPECIFIC_MAPPING_PATH = SEPARATOR + "/{" + FROM_DOMAIN + "}"; + private static final String SPECIFIC_MAPPING = DOMAIN_MAPPINGS + SEPARATOR + ":" + FROM_DOMAIN; + + private final RecipientRewriteTable recipientRewriteTable; + private final JsonTransformer jsonTransformer; + + @Inject + public DomainMappingsRoutes(final RecipientRewriteTable recipientRewriteTable, final JsonTransformer jsonTransformer) { + this.recipientRewriteTable = recipientRewriteTable; + this.jsonTransformer = jsonTransformer; + } + + @Override + public void define(final Service service) { + service.get(DOMAIN_MAPPINGS, this::getAllMappings, jsonTransformer); + service.get(SPECIFIC_MAPPING, this::getMapping, jsonTransformer); + service.put(SPECIFIC_MAPPING, this::addDomainMapping); + service.delete(SPECIFIC_MAPPING, this::removeDomainMapping); + } + + @PUT + @Path(SPECIFIC_MAPPING_PATH) + @ApiOperation(value = "Creating domain mapping between source and destination domains.") + @ApiImplicitParams({ + @ApiImplicitParam(required = true, dataType = "string", name = FROM_DOMAIN, paramType = "path") + }) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.NO_CONTENT_204, message = "Ok"), + @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "Domain name is invalid"), + @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, + message = "Internal server error - Something went bad on the server side.") + }) + public HaltException addDomainMapping(Request request, Response response) { + doMapping(request, recipientRewriteTable::addAliasDomainMapping); + return halt(HttpStatus.NO_CONTENT_204); + } + + @DELETE + @Path(SPECIFIC_MAPPING_PATH) + @ApiOperation(value = "Removes domain mapping between source and destination domains.") + @ApiImplicitParams({ + @ApiImplicitParam(required = true, dataType = "string", name = FROM_DOMAIN, paramType = "path") + }) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.NO_CONTENT_204, message = "Ok"), + @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "Domain name is invalid"), + @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, + message = "Internal server error - Something went bad on the server side.") + }) + public HaltException removeDomainMapping(Request request, Response response) { + doMapping(request, recipientRewriteTable::removeAliasDomainMapping); + return halt(HttpStatus.NO_CONTENT_204); + } + + @GET + @Path(DOMAIN_MAPPINGS) + @ApiOperation(value = "Lists all domain mappings.") + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.OK_200, message = "Domain mappings.", responseContainer = "Map"), + @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, + message = "Internal server error - Something went bad on the server side.") + }) + public Map<String, List<String>> getAllMappings(Request request, Response response) throws RecipientRewriteTableException { + return recipientRewriteTable.getAllMappings() + .entrySet() + .stream() + .filter(mappingsEntry -> !mappingsEntry.getValue().isEmpty()) + .filter(mappingsEntry -> mappingsEntry.getValue().contains(Mapping.Type.Domain)) + .collect(Guavate.toImmutableMap( + mappingsEntry -> mappingsEntry.getKey().getFixedDomain(), + mappingsEntry -> toDomainList(mappingsEntry.getValue()) + )); + } + + @GET + @Path(SPECIFIC_MAPPING_PATH) + @ApiOperation(value = "Lists mappings for specific domain.") + @ApiImplicitParams({ + @ApiImplicitParam(required = true, dataType = "string", name = FROM_DOMAIN, paramType = "path") + }) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.OK_200, message = "Domain mappings.", responseContainer = "List"), + @ApiResponse(code = HttpStatus.NOT_FOUND_404, message = "Not existing mappings."), + @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, + message = "Internal server error - Something went bad on the server side.") + }) + public List<String> getMapping(Request request, Response response) throws RecipientRewriteTableException { + MappingSource mappingSource = mappingSourceFrom(request); + + return Optional.ofNullable(recipientRewriteTable.getUserDomainMappings(mappingSource).select(Mapping.Type.Domain)) + .filter(mappings -> !mappings.isEmpty()) + .filter(mappings -> mappings.contains(Mapping.Type.Domain)) + .map(this::toDomainList) + .orElseThrow(() -> ErrorResponder.builder() + .statusCode(HttpStatus.NOT_FOUND_404) + .type(ErrorResponder.ErrorType.NOT_FOUND) + .message(String.format("Cannot find mappings for %s", mappingSource.getFixedDomain())) + .haltError()); + } + + private MappingSource mappingSourceFrom(final Request request) { + return createDomainOrThrow() + .andThen(MappingSource::fromDomain) + .apply(request.params(FROM_DOMAIN)); + } + + private void doMapping(Request request, ThrowingBiConsumer<MappingSource, Domain> mappingOperation) { + MappingSource fromDomain = mappingSourceFrom(request); + + Domain toDomain = createDomainOrThrow().apply(request.body()); + + mappingOperation.accept(fromDomain, toDomain); + } + + private Function<String, Domain> createDomainOrThrow() { + return candidate -> { + try { + return Domain.of(candidate.trim()); + } catch (IllegalArgumentException e) { + throw ErrorResponder.builder() + .statusCode(HttpStatus.BAD_REQUEST_400) + .type(ErrorResponder.ErrorType.INVALID_ARGUMENT) + .message(String.format("The domain %s is invalid.", candidate)) + .cause(e) + .haltError(); + } + }; + } + + private List<String> toDomainList(Mappings mappings) { + return mappings + .select(Mapping.Type.Domain) + .asStream() + .map(Mapping::asString) + .map(Mapping.Type.Domain::withoutPrefix) + .collect(Guavate.toImmutableList()); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/dc59e58b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/DomainMappingsRoutesTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/DomainMappingsRoutesTest.java b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/DomainMappingsRoutesTest.java new file mode 100644 index 0000000..b41c1ba --- /dev/null +++ b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/DomainMappingsRoutesTest.java @@ -0,0 +1,386 @@ +/**************************************************************** + * 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.routes; + +import static com.jayway.restassured.RestAssured.delete; +import static com.jayway.restassured.RestAssured.given; +import static com.jayway.restassured.RestAssured.put; +import static com.jayway.restassured.RestAssured.when; +import static org.apache.james.webadmin.WebAdminServer.NO_CONFIGURATION; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.entry; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.Matchers.isEmptyString; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import java.util.List; +import java.util.Map; +import java.util.function.Function; + +import org.apache.james.core.Domain; +import org.apache.james.metrics.logger.DefaultMetricFactory; +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.rrt.lib.Mappings; +import org.apache.james.rrt.lib.MappingsImpl; +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.ErrorResponder; +import org.apache.james.webadmin.utils.JsonTransformer; +import org.eclipse.jetty.http.HttpStatus; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.jayway.restassured.RestAssured; +import com.jayway.restassured.filter.log.LogDetail; +import com.jayway.restassured.http.ContentType; +import com.jayway.restassured.response.Response; +import com.jayway.restassured.specification.RequestSpecification; + +class DomainMappingsRoutesTest { + private RecipientRewriteTable recipientRewriteTable; + private WebAdminServer webAdminServer; + + private void createServer(DomainMappingsRoutes domainMappingsRoutes) throws Exception { + webAdminServer = WebAdminUtils.createWebAdminServer(new DefaultMetricFactory(), domainMappingsRoutes); + webAdminServer.configure(NO_CONFIGURATION); + webAdminServer.await(); + + RestAssured.requestSpecification = WebAdminUtils.buildRequestSpecification(webAdminServer) + .setBasePath("/domainMappings") + .log(LogDetail.METHOD) + .build(); + } + + @BeforeEach + void setUp() throws Exception { + recipientRewriteTable = spy(new MemoryRecipientRewriteTable()); + + createServer(new DomainMappingsRoutes(recipientRewriteTable, new JsonTransformer())); + } + + @AfterEach + void tearDown() { + webAdminServer.destroy(); + } + + @Nested + class NormalBehaviour { + + @Test + void addDomainMappingShouldRespondWithNoContent() { + given() + .body("to.com") + .when() + .put("from.com") + .then() + .statusCode(HttpStatus.NO_CONTENT_204) + .body(isEmptyString()); + } + + @Test + void getDomainMappingsShouldReturnAllDomainMappings() throws RecipientRewriteTableException { + String alias1 = "to_1.com"; + String alias2 = "to_2.com"; + String alias3 = "to_3.com"; + + Domain expectedDomain = Domain.of("abc.com"); + MappingSource mappingSource = MappingSource.fromDomain(expectedDomain); + + recipientRewriteTable.addAliasDomainMapping(mappingSource, Domain.of(alias1)); + recipientRewriteTable.addAliasDomainMapping(mappingSource, Domain.of(alias2)); + recipientRewriteTable.addAliasDomainMapping(mappingSource, Domain.of(alias3)); + + Map<String, List<String>> map = + when() + .get() + .then() + .contentType(ContentType.JSON) + .statusCode(HttpStatus.OK_200) + .extract() + .body() + .jsonPath() + .getMap("."); + + assertThat(map) + .containsOnly(entry(expectedDomain.name(), ImmutableList.of(alias1, alias2, alias3))); + } + + @Test + void getDomainMappingsEmptyMappingsAreFilteredOut() throws RecipientRewriteTableException { + MappingSource nonEmptyMapping = MappingSource.fromDomain(Domain.of("abc.com")); + MappingSource emptyMapping = MappingSource.fromDomain(Domain.of("def.com")); + + Map<MappingSource, Mappings> mappings = ImmutableMap.of( + nonEmptyMapping, MappingsImpl.fromRawString("domain:a.com"), + emptyMapping, MappingsImpl.empty() + ); + + when(recipientRewriteTable.getAllMappings()).thenReturn(mappings); + + Map<String, List<String>> map = + when() + .get() + .then() + .contentType(ContentType.JSON) + .statusCode(HttpStatus.OK_200) + .extract() + .body() + .jsonPath() + .getMap("."); + + assertThat(map) + .containsKey(nonEmptyMapping.asString()) + .doesNotContainKey(emptyMapping.asString()); + } + + @Test + void getDomainMappingsShouldFilterNonDomainMappings() throws RecipientRewriteTableException { + MappingSource mappingSource = MappingSource.fromDomain(Domain.of("abc.com")); + String address = "[email protected]"; + + recipientRewriteTable.addAddressMapping(mappingSource, address); + recipientRewriteTable.addForwardMapping(mappingSource, address); + recipientRewriteTable.addErrorMapping(mappingSource, address); + recipientRewriteTable.addGroupMapping(mappingSource, address); + recipientRewriteTable.addRegexMapping(mappingSource, address); + + when() + .get() + .then() + .contentType(ContentType.JSON) + .statusCode(HttpStatus.OK_200) + .body(is("{}")); + } + + @Test + void getDomainMappingsShouldBeEmptyByDefault() { + when() + .get() + .then() + .contentType(ContentType.JSON) + .statusCode(HttpStatus.OK_200) + .body(is("{}")); + } + + @Test + void deleteDomainMappingShouldRespondWithNoContent() { + given() + .body("to.com") + .when() + .delete("from.com") + .then() + .statusCode(HttpStatus.NO_CONTENT_204) + .body(isEmptyString()); + } + + @Test + void deleteDomainMappingShouldRemoveMapping() throws RecipientRewriteTableException { + MappingSource mappingSource = MappingSource.fromDomain(Domain.of("from.com")); + String alias = "to.com"; + + recipientRewriteTable.addAliasDomainMapping(mappingSource, Domain.of(alias)); + + Assumptions.assumeTrue(recipientRewriteTable.getUserDomainMappings(mappingSource) != null); + + given() + .body("to.com") + .when() + .delete("from.com") + .then() + .body(isEmptyString()); + + assertThat(recipientRewriteTable.getAllMappings()).isEmpty(); + } + + @Test + void getSpecificDomainMappingShouldRespondWithNotFoundWhenHasNoAliases() throws RecipientRewriteTableException { + String domain = "from.com"; + + when(recipientRewriteTable.getUserDomainMappings(any())).thenReturn(MappingsImpl.empty()); + + when() + .get(domain) + .then() + .contentType(ContentType.JSON) + .statusCode(HttpStatus.NOT_FOUND_404) + .body("type", is(ErrorResponder.ErrorType.NOT_FOUND.getType())) + .body("statusCode", is(HttpStatus.NOT_FOUND_404)) + .body("message", is("Cannot find mappings for " + domain)); + } + + @Test + void getSpecificDomainMappingShouldRespondWithNotFoundWhenHasEmptyAliases() throws RecipientRewriteTableException { + String domain = "from.com"; + + when(recipientRewriteTable.getUserDomainMappings(any())).thenReturn(MappingsImpl.empty()); + + when() + .get(domain) + .then() + .contentType(ContentType.JSON) + .statusCode(HttpStatus.NOT_FOUND_404) + .body("type", is(ErrorResponder.ErrorType.NOT_FOUND.getType())) + .body("statusCode", is(HttpStatus.NOT_FOUND_404)) + .body("message", is("Cannot find mappings for " + domain)); + } + + @Test + void getSpecificDomainMappingShouldFilterOutNonDomainMappings() throws RecipientRewriteTableException { + String domain = "from.com"; + String aliasDomain = "to.com"; + final MappingSource mappingSource = MappingSource.fromDomain(Domain.of(domain)); + + recipientRewriteTable.addRegexMapping(mappingSource, "(.*)@localhost"); + recipientRewriteTable.addGroupMapping(mappingSource, "[email protected]"); + recipientRewriteTable.addForwardMapping(mappingSource, "[email protected]"); + recipientRewriteTable.addErrorMapping(mappingSource, "disabled"); + recipientRewriteTable.addAliasDomainMapping(mappingSource, Domain.of(aliasDomain)); + + List<String> body = + when() + .get(domain) + .then() + .contentType(ContentType.JSON) + .statusCode(HttpStatus.OK_200) + .extract() + .jsonPath() + .getList("."); + + assertThat(body).containsOnly(aliasDomain); + } + + @Test + void getSpecificDomainMappingShouldReturnDomainMappings() throws RecipientRewriteTableException { + String domain = "abc.com"; + String aliasDomain = "a.com"; + Mappings mappings = MappingsImpl.fromMappings(Mapping.domain(Domain.of(aliasDomain))); + + when(recipientRewriteTable.getUserDomainMappings(any())).thenReturn(mappings); + + List<String> body = + when() + .get(domain) + .then() + .contentType(ContentType.JSON) + .statusCode(HttpStatus.OK_200) + .extract() + .jsonPath() + .getList("."); + + assertThat(body).contains(aliasDomain); + } + } + + @Nested + class IllegalInputs { + @Test + void addDomainMappingShouldRespondWithNotFound() { + when() + .put("") + .then() + .statusCode(HttpStatus.NOT_FOUND_404); + } + + @Test + void deleteDomainMappingShouldRespondWithNotFound() { + when() + .delete("") + .then() + .statusCode(HttpStatus.NOT_FOUND_404); + } + + @Test + void addDomainMappingWithInvalidDomainInBody() { + assertBadRequest("[email protected]", spec -> put("domain.com")); + } + + @Test + void deleteDomainMappingWithInvalidDomainInBody() { + assertBadRequest("[email protected]", spec -> put("domain.com")); + } + + @Test + void addDomainMappingWithInvalidDomainInPath() { + assertBadRequest("domain.com", spec -> put("[email protected]")); + } + + @Test + void deleteDomainMappingWithInvalidDomainInPath() { + assertBadRequest("domain.com", spec -> put("[email protected]")); + } + + @Test + void addDomainMappingWithEmptyAliasDomain() { + assertBadRequest("", spec -> put("domain.com")); + } + + @Test + void deleteDomainMappingWithEmptyAliasDomain() { + assertBadRequest("", spec -> delete("domain.com")); + } + + + @Test + void addSpecificDomainMappingWithInvalidDomainInPath() { + Map<String, Object> errors = + when() + .get("[email protected]") + .then() + .statusCode(HttpStatus.BAD_REQUEST_400) + .contentType(ContentType.JSON) + .extract() + .body() + .jsonPath() + .getMap("."); + + assertThat(errors) + .containsEntry("statusCode", HttpStatus.BAD_REQUEST_400) + .containsEntry("type", "InvalidArgument") + .hasEntrySatisfying("message", o -> assertThat((String) o).matches("^The domain .* is invalid\\.$")); + } + + private void assertBadRequest(String toDomain, Function<RequestSpecification, Response> op) { + Map<String, Object> errors = op.apply(given().body(toDomain).when()) + .then() + .statusCode(HttpStatus.BAD_REQUEST_400) + .contentType(ContentType.JSON) + .extract() + .body() + .jsonPath() + .getMap("."); + + assertThat(errors) + .containsEntry("statusCode", HttpStatus.BAD_REQUEST_400) + .containsEntry("type", "InvalidArgument") + .hasEntrySatisfying("message", o -> assertThat((String) o).matches("^The domain .* is invalid\\.$")); + } + } +} \ No newline at end of file --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
