You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by ma...@apache.org on 2018/06/21 13:57:23 UTC
james-project git commit: JAMES-2149 Create domain mappings via
webadmin
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 <ns...@gmail.com>
Authored: Sat Jun 9 16:15:02 2018 +0400
Committer: Matthieu Baechler <ma...@apache.org>
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 = "addr@domain.com";
+
+ 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, "user@domain.com");
+ recipientRewriteTable.addForwardMapping(mappingSource, "user@domain.com");
+ 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("abc@domain.com", spec -> put("domain.com"));
+ }
+
+ @Test
+ void deleteDomainMappingWithInvalidDomainInBody() {
+ assertBadRequest("abc@domain.com", spec -> put("domain.com"));
+ }
+
+ @Test
+ void addDomainMappingWithInvalidDomainInPath() {
+ assertBadRequest("domain.com", spec -> put("abc@domain.com"));
+ }
+
+ @Test
+ void deleteDomainMappingWithInvalidDomainInPath() {
+ assertBadRequest("domain.com", spec -> put("abc@domain.com"));
+ }
+
+ @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("abc@domain.com")
+ .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: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org