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 bt...@apache.org on 2017/04/03 08:34:25 UTC
[2/7] james-project git commit: JAMES-1983 Split WebAdmin to match
orthogonal Guice architecture
http://git-wip-us.apache.org/repos/asf/james-project/blob/cca0f398/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/utils/JsonExtractorTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/utils/JsonExtractorTest.java b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/utils/JsonExtractorTest.java
new file mode 100644
index 0000000..ff5f2cb
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/utils/JsonExtractorTest.java
@@ -0,0 +1,114 @@
+/****************************************************************
+ * 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.utils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.base.Preconditions;
+
+public class JsonExtractorTest {
+
+ private JsonExtractor<Request> jsonExtractor;
+
+ @Before
+ public void setUp() {
+ jsonExtractor = new JsonExtractor<>(Request.class);
+ }
+
+ @Test
+ public void parseShouldThrowOnNullInput() throws Exception {
+ assertThatThrownBy(() -> jsonExtractor.parse(null)).isInstanceOf(NullPointerException.class);
+ }
+
+ @Test
+ public void parseShouldThrowOnEmptyInput() throws Exception {
+ assertThatThrownBy(() -> jsonExtractor.parse("")).isInstanceOf(JsonExtractException.class);
+ }
+
+ @Test
+ public void parseShouldThrowOnBrokenJson() throws Exception {
+ assertThatThrownBy(() -> jsonExtractor.parse("{\"field1\":\"broken")).isInstanceOf(JsonExtractException.class);
+ }
+
+ @Test
+ public void parseShouldThrowOnEmptyJson() throws Exception {
+ assertThatThrownBy(() -> jsonExtractor.parse("{}")).isInstanceOf(JsonExtractException.class);
+ }
+
+ @Test
+ public void parseShouldThrowOnMissingMandatoryField() throws Exception {
+ assertThatThrownBy(() -> jsonExtractor.parse("{\"field1\":\"any\"}")).isInstanceOf(JsonExtractException.class);
+ }
+
+ @Test
+ public void parseShouldThrowOnValidationProblemIllegalArgumentException() throws Exception {
+ assertThatThrownBy(() -> jsonExtractor.parse("{\"field1\":\"\",\"field2\":\"any\"}")).isInstanceOf(JsonExtractException.class);
+ }
+
+ @Test
+ public void parseShouldThrowOnValidationProblemNPE() throws Exception {
+ assertThatThrownBy(() -> jsonExtractor.parse("{\"field1\":null,\"field2\":\"any\"}")).isInstanceOf(JsonExtractException.class);
+ }
+
+ @Test
+ public void parseShouldThrowOnExtraFiled() throws Exception {
+ assertThatThrownBy(() -> jsonExtractor.parse("{\"field1\":\"value\",\"field2\":\"any\",\"extra\":\"extra\"}")).isInstanceOf(JsonExtractException.class);
+ }
+
+ @Test
+ public void parseShouldInstantiateDestinationClass() throws Exception {
+ String field1 = "value1";
+ String field2 = "value2";
+ Request request = jsonExtractor.parse("{\"field1\":\"" + field1 + "\",\"field2\":\"" + field2 + "\"}");
+
+ assertThat(request.getField1()).isEqualTo(field1);
+ assertThat(request.getField2()).isEqualTo(field2);
+ }
+
+ static class Request {
+ private final String field1;
+ private final String field2;
+
+ @JsonCreator
+ public Request(@JsonProperty("field1") String field1,
+ @JsonProperty("field2") String field2) {
+ Preconditions.checkNotNull(field1);
+ Preconditions.checkNotNull(field2);
+ Preconditions.checkArgument(!field1.isEmpty());
+ this.field1 = field1;
+ this.field2 = field2;
+ }
+
+ public String getField1() {
+ return field1;
+ }
+
+ public String getField2() {
+ return field2;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/cca0f398/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
new file mode 100644
index 0000000..781baff
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-data/pom.xml
@@ -0,0 +1,280 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<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>
+ <artifactId>james-server</artifactId>
+ <groupId>org.apache.james</groupId>
+ <version>3.0.0-beta6-SNAPSHOT</version>
+ <relativePath>../../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>james-server-webadmin-data</artifactId>
+ <packaging>jar</packaging>
+
+ <name>Apache James :: Server :: Web Admin :: data</name>
+
+ <profiles>
+ <profile>
+ <id>noTest</id>
+ <activation>
+ <os>
+ <family>windows</family>
+ </os>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skipTests>true</skipTests>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>disable-build-for-older-jdk</id>
+ <activation>
+ <jdk>(,1.8)</jdk>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>default-jar</id>
+ <phase>none</phase>
+ </execution>
+ <execution>
+ <id>jar</id>
+ <phase>none</phase>
+ </execution>
+ <execution>
+ <id>test-jar</id>
+ <phase>none</phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>default-compile</id>
+ <phase>none</phase>
+ </execution>
+ <execution>
+ <id>default-testCompile</id>
+ <phase>none</phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>default-test</id>
+ <phase>none</phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-source-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <phase>none</phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-install-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>default-install</id>
+ <phase>none</phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>default-resources</id>
+ <phase>none</phase>
+ </execution>
+ <execution>
+ <id>default-testResources</id>
+ <phase>none</phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-site-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-descriptor</id>
+ <phase>none</phase>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>build-for-jdk-8</id>
+ <activation>
+ <jdk>[1.8,)</jdk>
+ </activation>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.james</groupId>
+ <artifactId>james-server-util-java8</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.james</groupId>
+ <artifactId>james-server-data-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.james</groupId>
+ <artifactId>james-server-data-memory</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.james</groupId>
+ <artifactId>james-server-webadmin-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.james</groupId>
+ <artifactId>metrics-logger</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.jayway.restassured</groupId>
+ <artifactId>rest-assured</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>de.bechte.junit</groupId>
+ <artifactId>junit-hierarchicalcontextrunner</artifactId>
+ <version>4.11.3</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.inject</groupId>
+ <artifactId>javax.inject</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ <version>${assertj-3.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>java-hamcrest</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifest>
+ <mainClass>fully.qualified.MainClass</mainClass>
+ </manifest>
+ </archive>
+ <descriptorRefs>
+ <descriptorRef>jar-with-dependencies</descriptorRef>
+ </descriptorRefs>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>animal-sniffer-java-8</id>
+ <activation>
+ <jdk>[1.8,)</jdk>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>animal-sniffer-maven-plugin</artifactId>
+ <configuration>
+ <signature>
+ <groupId>org.codehaus.mojo.signature</groupId>
+ <artifactId>java18</artifactId>
+ <version>1.0</version>
+ </signature>
+ </configuration>
+ <executions>
+ <execution>
+ <id>check_java_8</id>
+ <phase>test</phase>
+ <goals>
+ <goal>check</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project>
http://git-wip-us.apache.org/repos/asf/james-project/blob/cca0f398/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/AddUserRequest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/AddUserRequest.java b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/AddUserRequest.java
new file mode 100644
index 0000000..1d102c2
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/AddUserRequest.java
@@ -0,0 +1,39 @@
+/****************************************************************
+ * 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 com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.base.Preconditions;
+
+public class AddUserRequest {
+
+ private final char[] password;
+
+ @JsonCreator
+ public AddUserRequest(@JsonProperty("password") char[] password) {
+ Preconditions.checkNotNull(password);
+ this.password = password;
+ }
+
+ public char[] getPassword() {
+ return password;
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/cca0f398/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/UserResponse.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/UserResponse.java b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/UserResponse.java
new file mode 100644
index 0000000..5fe1846
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/UserResponse.java
@@ -0,0 +1,33 @@
+/****************************************************************
+ * 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;
+
+public class UserResponse {
+
+ private final String username;
+
+ public UserResponse(String username) {
+ this.username = username;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/cca0f398/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/DomainRoutes.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/DomainRoutes.java b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/DomainRoutes.java
new file mode 100644
index 0000000..2008278
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/DomainRoutes.java
@@ -0,0 +1,118 @@
+/****************************************************************
+ * 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 javax.inject.Inject;
+
+import org.apache.james.domainlist.api.DomainList;
+import org.apache.james.domainlist.api.DomainListException;
+import org.apache.james.webadmin.Constants;
+import org.apache.james.webadmin.Routes;
+import org.apache.james.webadmin.utils.JsonTransformer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+
+import spark.Request;
+import spark.Response;
+import spark.Service;
+
+public class DomainRoutes implements Routes {
+
+ private static final String DOMAIN_NAME = ":domainName";
+ private static final Logger LOGGER = LoggerFactory.getLogger(DomainRoutes.class);
+
+ 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 final DomainList domainList;
+ private final JsonTransformer jsonTransformer;
+
+ @Inject
+ public DomainRoutes(DomainList domainList, JsonTransformer jsonTransformer) {
+ this.domainList = domainList;
+ this.jsonTransformer = jsonTransformer;
+ }
+
+ @Override
+ public void define(Service service) {
+ service.get(DOMAINS,
+ (request, response) -> domainList.getDomains(),
+ jsonTransformer);
+
+ service.get(SPECIFIC_DOMAIN, this::exists);
+
+ service.put(SPECIFIC_DOMAIN, this::addDomain);
+
+ service.delete(SPECIFIC_DOMAIN, this::removeDomain);
+ }
+
+ private String removeDomain(Request request, Response response) {
+ try {
+ String domain = request.params(DOMAIN_NAME);
+ removeDomain(domain);
+ } catch (DomainListException e) {
+ LOGGER.info("{} did not exists", request.params(DOMAIN_NAME));
+ }
+ response.status(204);
+ return Constants.EMPTY_BODY;
+ }
+
+ private void removeDomain(String domain) throws DomainListException {
+ Preconditions.checkArgument(!Strings.isNullOrEmpty(domain));
+ domainList.removeDomain(domain);
+ }
+
+ private String addDomain(Request request, Response response) {
+ try {
+ addDomain(request.params(DOMAIN_NAME));
+ response.status(204);
+ } catch (DomainListException e) {
+ LOGGER.info("{} already exists", request.params(DOMAIN_NAME));
+ response.status(204);
+ } catch (IllegalArgumentException e) {
+ LOGGER.info("Invalid request for domain creation");
+ response.status(400);
+ }
+ return Constants.EMPTY_BODY;
+ }
+
+ private void addDomain(String domain) throws DomainListException {
+ Preconditions.checkArgument(!Strings.isNullOrEmpty(domain));
+ Preconditions.checkArgument(!domain.contains("@"));
+ Preconditions.checkArgument(domain.length() < MAXIMUM_DOMAIN_SIZE);
+ domainList.addDomain(domain);
+ }
+
+ private String exists(Request request, Response response) throws DomainListException {
+ if (!domainList.containsDomain(request.params(DOMAIN_NAME))) {
+ response.status(404);
+ } else {
+ response.status(204);
+ }
+ return Constants.EMPTY_BODY;
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/cca0f398/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/UserRoutes.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/UserRoutes.java b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/UserRoutes.java
new file mode 100644
index 0000000..0ead90a
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/UserRoutes.java
@@ -0,0 +1,104 @@
+/****************************************************************
+ * 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 javax.inject.Inject;
+
+import org.apache.james.user.api.UsersRepositoryException;
+import org.apache.james.webadmin.Constants;
+import org.apache.james.webadmin.Routes;
+import org.apache.james.webadmin.dto.AddUserRequest;
+import org.apache.james.webadmin.service.UserService;
+import org.apache.james.webadmin.utils.JsonExtractException;
+import org.apache.james.webadmin.utils.JsonExtractor;
+import org.apache.james.webadmin.utils.JsonTransformer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import spark.Request;
+import spark.Response;
+import spark.Service;
+
+public class UserRoutes implements Routes {
+
+ private static final String USER_NAME = ":userName";
+ private static final Logger LOGGER = LoggerFactory.getLogger(UserRoutes.class);
+
+ public static final String USERS = "/users";
+
+ private final UserService userService;
+ private final JsonTransformer jsonTransformer;
+ private final JsonExtractor<AddUserRequest> jsonExtractor;
+
+ @Inject
+ public UserRoutes(UserService userService, JsonTransformer jsonTransformer) {
+ this.userService = userService;
+ this.jsonTransformer = jsonTransformer;
+ this.jsonExtractor = new JsonExtractor<>(AddUserRequest.class);
+ }
+
+ @Override
+ public void define(Service service) {
+ service.get(USERS,
+ (request, response) -> userService.getUsers(),
+ jsonTransformer);
+
+ service.put(USERS + SEPARATOR + USER_NAME, this::upsertUser);
+
+ service.delete(USERS + SEPARATOR + USER_NAME, this::removeUser);
+ }
+
+ private String removeUser(Request request, Response response) {
+ String username = request.params(USER_NAME);
+ try {
+ userService.removeUser(username);
+ response.status(204);
+ return Constants.EMPTY_BODY;
+ } catch (UsersRepositoryException e) {
+ response.status(204);
+ return "The user " + username + " does not exists";
+ } catch (IllegalArgumentException e) {
+ LOGGER.info("Invalid user path", e);
+ response.status(400);
+ return Constants.EMPTY_BODY;
+ }
+ }
+
+ private String upsertUser(Request request, Response response) throws UsersRepositoryException {
+ try {
+ return userService.upsertUser(request.params(USER_NAME),
+ jsonExtractor.parse(request.body()).getPassword(),
+ response);
+ } catch (JsonExtractException e) {
+ LOGGER.info("Error while deserializing addUser request", e);
+ response.status(400);
+ return Constants.EMPTY_BODY;
+ } catch (IllegalArgumentException e) {
+ LOGGER.info("Invalid user path", e);
+ response.status(400);
+ return Constants.EMPTY_BODY;
+ }
+ }
+
+
+
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/cca0f398/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/service/UserService.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/service/UserService.java b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/service/UserService.java
new file mode 100644
index 0000000..ee0952d
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/service/UserService.java
@@ -0,0 +1,94 @@
+/****************************************************************
+ * 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.service;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import javax.inject.Inject;
+
+import org.apache.james.user.api.UsersRepository;
+import org.apache.james.user.api.UsersRepositoryException;
+import org.apache.james.user.api.model.User;
+import org.apache.james.util.streams.Iterators;
+import org.apache.james.webadmin.dto.UserResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.github.steveash.guavate.Guavate;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+
+import spark.Response;
+
+public class UserService {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(UserService.class);
+ private static final String EMPTY_BODY = "";
+ public static final int MAXIMUM_MAIL_ADDRESS_LENGTH = 255;
+
+ private final UsersRepository usersRepository;
+
+ @Inject
+ public UserService(UsersRepository usersRepository) {
+ this.usersRepository = usersRepository;
+ }
+
+ public List<UserResponse> getUsers() throws UsersRepositoryException {
+ return Optional.ofNullable(usersRepository.list())
+ .map(Iterators::toStream)
+ .orElse(Stream.of())
+ .map(UserResponse::new)
+ .collect(Guavate.toImmutableList());
+ }
+
+ public void removeUser(String username) throws UsersRepositoryException {
+ usernamePreconditions(username);
+ usersRepository.removeUser(username);
+ }
+
+ public String upsertUser(String username, char[] password, Response response) throws UsersRepositoryException {
+ usernamePreconditions(username);
+ User user = usersRepository.getUserByName(username);
+ try {
+ upsert(user, username, password);
+ response.status(204);
+ } catch (UsersRepositoryException e) {
+ LOGGER.info("Error creating or updating user : {}", e.getMessage());
+ response.status(409);
+ }
+ return EMPTY_BODY;
+ }
+
+ private void usernamePreconditions(String username) {
+ Preconditions.checkArgument(!Strings.isNullOrEmpty(username));
+ Preconditions.checkArgument(username.length() < MAXIMUM_MAIL_ADDRESS_LENGTH);
+ }
+
+ private void upsert(User user, String username, char[] password) throws UsersRepositoryException {
+ if (user == null) {
+ usersRepository.addUser(username, new String(password));
+ } else {
+ user.setPassword(new String(password));
+ usersRepository.updateUser(user);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/cca0f398/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/DomainRoutesTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/DomainRoutesTest.java b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/DomainRoutesTest.java
new file mode 100644
index 0000000..1df89d2
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/DomainRoutesTest.java
@@ -0,0 +1,326 @@
+/****************************************************************
+ * 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.given;
+import static com.jayway.restassured.RestAssured.when;
+import static com.jayway.restassured.RestAssured.with;
+import static com.jayway.restassured.config.EncoderConfig.encoderConfig;
+import static com.jayway.restassured.config.RestAssuredConfig.newConfig;
+import static org.apache.james.webadmin.Constants.SEPARATOR;
+import static org.apache.james.webadmin.WebAdminServer.NO_CONFIGURATION;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.is;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.net.InetAddress;
+
+import org.apache.james.dnsservice.api.DNSService;
+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.webadmin.WebAdminServer;
+import org.apache.james.webadmin.utils.JsonTransformer;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Charsets;
+import com.jayway.restassured.RestAssured;
+import com.jayway.restassured.builder.RequestSpecBuilder;
+import com.jayway.restassured.http.ContentType;
+
+import de.bechte.junit.runners.context.HierarchicalContextRunner;
+
+@RunWith(HierarchicalContextRunner.class)
+public class DomainRoutesTest {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(DomainRoutesTest.class);
+ public static final String DOMAIN = "domain";
+
+ private WebAdminServer webAdminServer;
+
+ private void createServer(DomainList domainList) throws Exception {
+ webAdminServer = new WebAdminServer(
+ new DefaultMetricFactory(),
+ new DomainRoutes(domainList, new JsonTransformer()));
+ webAdminServer.configure(NO_CONFIGURATION);
+ webAdminServer.await();
+
+ RestAssured.requestSpecification = new RequestSpecBuilder()
+ .setContentType(ContentType.JSON)
+ .setAccept(ContentType.JSON)
+ .setConfig(newConfig().encoderConfig(encoderConfig().defaultContentCharset(Charsets.UTF_8)))
+ .setPort(webAdminServer.getPort().toInt())
+ .setBasePath(DomainRoutes.DOMAINS)
+ .build();
+
+ }
+
+ @After
+ public void stop() {
+ webAdminServer.destroy();
+ }
+
+ public class NormalBehaviour {
+
+ @Before
+ public void setUp() throws Exception {
+ DNSService dnsService = mock(DNSService.class);
+ when(dnsService.getHostName(any())).thenReturn("localhost");
+ when(dnsService.getLocalHost()).thenReturn(InetAddress.getByName("localhost"));
+
+ MemoryDomainList domainList = new MemoryDomainList();
+ domainList.setDNSService(dnsService);
+ domainList.setLog(LOGGER);
+ domainList.setAutoDetectIP(false);
+ createServer(domainList);
+ }
+
+ @Test
+ public void getDomainsShouldBeEmptyByDefault() {
+ given()
+ .get()
+ .then()
+ .statusCode(200)
+ .body(is("[]"));
+ }
+
+ @Test
+ public void putShouldReturnErrorWhenUsedWithEmptyDomain() {
+ given()
+ .put(SEPARATOR)
+ .then()
+ .statusCode(404);
+ }
+
+ @Test
+ public void deleteShouldReturnErrorWhenUsedWithEmptyDomain() {
+ given()
+ .delete(SEPARATOR)
+ .then()
+ .statusCode(404);
+ }
+
+ @Test
+ public void putShouldBeOk() {
+ given()
+ .put(DOMAIN)
+ .then()
+ .statusCode(204);
+ }
+
+ @Test
+ public void getDomainsShouldDisplayAddedDomains() {
+ with()
+ .put(DOMAIN);
+
+ when()
+ .get()
+ .then()
+ .statusCode(200)
+ .body(containsString(DOMAIN));
+ }
+
+ @Test
+ public void putShouldReturnUserErrorWhenNameContainsAT() {
+ when()
+ .put(DOMAIN + "@" + DOMAIN)
+ .then()
+ .statusCode(400);
+ }
+
+ @Test
+ public void putShouldReturnUserErrorWhenNameContainsUrlSeparator() {
+ when()
+ .put(DOMAIN + "/" + DOMAIN)
+ .then()
+ .statusCode(404);
+ }
+
+ @Test
+ public void putShouldReturnUserErrorWhenNameIsTooLong() {
+ when()
+ .put(DOMAIN + "0123456789.0123456789.0123456789.0123456789.0123456789.0123456789.0123456789.0123456789.0123456789.0123456789." +
+ "0123456789.0123456789.0123456789.0123456789.0123456789.0123456789.0123456789.0123456789.0123456789.0123456789." +
+ "0123456789.0123456789.0123456789.")
+ .then()
+ .statusCode(400);
+ }
+
+ @Test
+ public void putShouldWorkOnTheSecondTimeForAGivenValue() {
+ with()
+ .put(DOMAIN);
+
+ when()
+ .put(DOMAIN)
+ .then()
+ .statusCode(204);
+ }
+
+ @Test
+ public void deleteShouldRemoveTheGivenDomain() {
+ with()
+ .put(DOMAIN);
+
+ when()
+ .delete(DOMAIN)
+ .then()
+ .statusCode(204);
+
+ when()
+ .get()
+ .then()
+ .statusCode(200)
+ .body(is("[]"));
+ }
+
+ @Test
+ public void deleteShouldBeOkWhenTheDomainIsNotPresent() {
+ given()
+ .delete(DOMAIN)
+ .then()
+ .statusCode(204);
+ }
+
+ @Test
+ public void getDomainShouldReturnOkWhenTheDomainIsPresent() {
+ with()
+ .put(DOMAIN);
+
+ when()
+ .get(DOMAIN)
+ .then()
+ .statusCode(204);
+ }
+
+ @Test
+ public void getDomainShouldReturnNotFoundWhenTheDomainIsAbsent() {
+ given()
+ .get(DOMAIN)
+ .then()
+ .statusCode(404);
+ }
+
+ }
+
+ public class ExceptionHandling {
+
+ private DomainList domainList;
+ private String domain;
+
+ @Before
+ public void setUp() throws Exception {
+ domainList = mock(DomainList.class);
+ createServer(domainList);
+ domain = "domain";
+ }
+
+ @Test
+ public void deleteShouldReturnErrorOnUnknownException() throws Exception {
+ doThrow(new RuntimeException()).when(domainList).removeDomain(domain);
+
+ when()
+ .delete(DOMAIN)
+ .then()
+ .statusCode(500);
+ }
+
+ @Test
+ public void putShouldReturnErrorOnUnknownException() throws Exception {
+ doThrow(new RuntimeException()).when(domainList).addDomain(domain);
+
+ when()
+ .put(DOMAIN)
+ .then()
+ .statusCode(500);
+ }
+
+ @Test
+ public void getDomainShouldReturnErrorOnUnknownException() throws Exception {
+ when(domainList.containsDomain(domain)).thenThrow(new RuntimeException());
+
+ when()
+ .get(DOMAIN)
+ .then()
+ .statusCode(500);
+ }
+
+ @Test
+ public void getDomainsShouldReturnErrorOnUnknownException() throws Exception {
+ when(domainList.getDomains()).thenThrow(new RuntimeException());
+
+ when()
+ .get()
+ .then()
+ .statusCode(500);
+ }
+
+ @Test
+ public void deleteShouldReturnOkWhenDomainListException() throws Exception {
+ doThrow(new DomainListException("message")).when(domainList).removeDomain(domain);
+
+ when()
+ .delete(DOMAIN)
+ .then()
+ .statusCode(204);
+ }
+
+ @Test
+ public void putShouldReturnOkWhenDomainListException() throws Exception {
+ doThrow(new DomainListException("message")).when(domainList).addDomain(domain);
+
+ when()
+ .put(DOMAIN)
+ .then()
+ .statusCode(204);
+ }
+
+ @Test
+ public void getDomainShouldReturnErrorOnDomainListException() throws Exception {
+ when(domainList.containsDomain(domain)).thenThrow(new DomainListException("message"));
+
+ when()
+ .get(DOMAIN)
+ .then()
+ .statusCode(500);
+ }
+
+ @Test
+ public void getDomainsShouldReturnErrorOnDomainListException() throws Exception {
+ when(domainList.getDomains()).thenThrow(new DomainListException("message"));
+
+ when()
+ .get()
+ .then()
+ .statusCode(500);
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/cca0f398/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/UsersRoutesTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/UsersRoutesTest.java b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/UsersRoutesTest.java
new file mode 100644
index 0000000..684ea9b
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/UsersRoutesTest.java
@@ -0,0 +1,422 @@
+/****************************************************************
+ * 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.given;
+import static com.jayway.restassured.RestAssured.when;
+import static com.jayway.restassured.RestAssured.with;
+import static com.jayway.restassured.config.EncoderConfig.encoderConfig;
+import static com.jayway.restassured.config.RestAssuredConfig.newConfig;
+import static org.apache.james.webadmin.WebAdminServer.NO_CONFIGURATION;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.apache.james.domainlist.api.DomainList;
+import org.apache.james.metrics.logger.DefaultMetricFactory;
+import org.apache.james.user.api.UsersRepository;
+import org.apache.james.user.api.UsersRepositoryException;
+import org.apache.james.user.api.model.User;
+import org.apache.james.user.memory.MemoryUsersRepository;
+import org.apache.james.webadmin.WebAdminServer;
+import org.apache.james.webadmin.service.UserService;
+import org.apache.james.webadmin.utils.JsonTransformer;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.google.common.base.Charsets;
+import com.jayway.restassured.RestAssured;
+import com.jayway.restassured.builder.RequestSpecBuilder;
+import com.jayway.restassured.http.ContentType;
+
+import de.bechte.junit.runners.context.HierarchicalContextRunner;
+
+@RunWith(HierarchicalContextRunner.class)
+public class UsersRoutesTest {
+
+ public static final String DOMAIN = "domain";
+ public static final String USERNAME = "username@" + DOMAIN;
+ private WebAdminServer webAdminServer;
+
+ private void createServer(UsersRepository usersRepository) throws Exception {
+ webAdminServer = new WebAdminServer(
+ new DefaultMetricFactory(),
+ new UserRoutes(new UserService(usersRepository), new JsonTransformer()));
+ webAdminServer.configure(NO_CONFIGURATION);
+ webAdminServer.await();
+
+ RestAssured.requestSpecification = new RequestSpecBuilder()
+ .setContentType(ContentType.JSON)
+ .setAccept(ContentType.JSON)
+ .setConfig(newConfig().encoderConfig(encoderConfig().defaultContentCharset(Charsets.UTF_8)))
+ .setPort(webAdminServer.getPort().toInt())
+ .setBasePath(UserRoutes.USERS)
+ .build();
+ }
+
+ @After
+ public void stop() {
+ webAdminServer.destroy();
+ }
+
+ public class NormalBehaviour {
+
+ @Before
+ public void setUp() throws Exception {
+ DomainList domainList = mock(DomainList.class);
+ when(domainList.containsDomain(DOMAIN)).thenReturn(true);
+
+ MemoryUsersRepository usersRepository = MemoryUsersRepository.withVirtualHosting();
+ usersRepository.setDomainList(domainList);
+
+ createServer(usersRepository);
+ }
+
+ @Test
+ public void getUsersShouldBeEmptyByDefault() {
+ when()
+ .get()
+ .then()
+ .statusCode(200)
+ .body(is("[]"));
+ }
+
+ @Test
+ public void putShouldReturnUserErrorWhenNoBody() {
+ when()
+ .put(USERNAME)
+ .then()
+ .statusCode(400);
+ }
+
+ @Test
+ public void postShouldReturnUserErrorWhenEmptyJsonBody() {
+ given()
+ .body("{}")
+ .when()
+ .put(USERNAME)
+ .then()
+ .statusCode(400);
+ }
+
+ @Test
+ public void postShouldReturnUserErrorWhenWrongJsonBody() {
+ given()
+ .body("{\"bad\":\"any\"}")
+ .when()
+ .put(USERNAME)
+ .then()
+ .statusCode(400);
+ }
+
+ @Test
+ public void postShouldReturnOkWhenValidJsonBody() {
+ given()
+ .body("{\"password\":\"password\"}")
+ .when()
+ .put(USERNAME)
+ .then()
+ .statusCode(204);
+ }
+
+ @Test
+ public void postShouldReturnRequireNonNullPassword() {
+ given()
+ .body("{\"password\":null}")
+ .when()
+ .put(USERNAME)
+ .then()
+ .statusCode(400);
+ }
+
+ @Test
+ public void postShouldAddTheUser() {
+ with()
+ .body("{\"password\":\"password\"}")
+ .put(USERNAME);
+
+ when()
+ .get()
+ .then()
+ .statusCode(200)
+ .body(equalTo("[{\"username\":\"" + USERNAME + "\"}]"));
+ }
+
+ @Test
+ public void postingTwoTimesShouldBeAllowed() {
+ // Given
+ with()
+ .body("{\"password\":\"password\"}")
+ .put(USERNAME);
+
+ // When
+ given()
+ .body("{\"password\":\"password\"}")
+ .when()
+ .put(USERNAME)
+ .then()
+ .statusCode(204);
+
+ // Then
+ when()
+ .get()
+ .then()
+ .statusCode(200)
+ .body(equalTo("[{\"username\":\"" + USERNAME + "\"}]"));
+ }
+
+ @Test
+ public void deleteShouldReturnOk() {
+ when()
+ .delete(USERNAME)
+ .then()
+ .statusCode(204);
+ }
+
+ @Test
+ public void deleteShouldReturnBadRequestWhenEmptyUserName() {
+ when()
+ .delete("/")
+ .then()
+ .statusCode(404);
+ }
+
+ @Test
+ public void deleteShouldReturnBadRequestWhenUsernameIsTooLong() {
+ when()
+ .delete(USERNAME + "0123456789.0123456789.0123456789.0123456789.0123456789.0123456789.0123456789.0123456789.0123456789.0123456789." +
+ "0123456789.0123456789.0123456789.0123456789.0123456789.0123456789.0123456789.0123456789.0123456789.0123456789." +
+ "0123456789.0123456789.0123456789.")
+ .then()
+ .statusCode(400);
+ }
+
+ @Test
+ public void deleteShouldReturnNotFoundWhenUsernameContainsSlash() {
+ given()
+ .body("{\"password\":\"password\"}")
+ .when()
+ .put(USERNAME + "/" + USERNAME)
+ .then()
+ .statusCode(404);
+ }
+
+ @Test
+ public void putShouldReturnBadRequestWhenEmptyUserName() {
+ given()
+ .body("{\"password\":\"password\"}")
+ .when()
+ .put("/")
+ .then()
+ .statusCode(404);
+ }
+
+ @Test
+ public void putShouldReturnBadRequestWhenUsernameIsTooLong() {
+ given()
+ .body("{\"password\":\"password\"}")
+ .when()
+ .put(USERNAME + "0123456789.0123456789.0123456789.0123456789.0123456789.0123456789.0123456789.0123456789.0123456789.0123456789." +
+ "0123456789.0123456789.0123456789.0123456789.0123456789.0123456789.0123456789.0123456789.0123456789.0123456789." +
+ "0123456789.0123456789.0123456789.")
+ .then()
+ .statusCode(400);
+ }
+
+ @Test
+ public void putShouldReturnNotFoundWhenUsernameContainsSlash() {
+ given()
+ .body("{\"password\":\"password\"}")
+ .when()
+ .put(USERNAME + "/" + USERNAME)
+ .then()
+ .statusCode(404);
+ }
+
+ @Test
+ public void deleteShouldRemoveAssociatedUser() {
+ // Given
+ with()
+ .body("{\"password\":\"password\"}")
+ .put(USERNAME);
+
+ // When
+ when()
+ .delete(USERNAME)
+ .then()
+ .statusCode(204);
+
+ // Then
+ when()
+ .get()
+ .then()
+ .statusCode(200)
+ .body(equalTo("[]"));
+ }
+
+ @Test
+ public void deleteShouldStillBeValidWithExtraBody() {
+ given()
+ .body("{\"bad\":\"any\"}")
+ .when()
+ .delete(USERNAME)
+ .then()
+ .statusCode(204);
+ }
+ }
+
+ public class ErrorHandling {
+
+ private UsersRepository usersRepository;
+ private String username;
+ private String password;
+
+ @Before
+ public void setUp() throws Exception {
+ usersRepository = mock(UsersRepository.class);
+ createServer(usersRepository);
+ username = "username@domain";
+ password = "password";
+ }
+
+ @Test
+ public void deleteShouldStillBeOkWhenNoUser() throws Exception {
+ doThrow(new UsersRepositoryException("message")).when(usersRepository).removeUser(username);
+
+ when()
+ .delete(USERNAME)
+ .then()
+ .statusCode(204);
+ }
+
+ @Test
+ public void getShouldFailOnRepositoryException() throws Exception {
+ when(usersRepository.list()).thenThrow(new UsersRepositoryException("message"));
+
+ when()
+ .get()
+ .then()
+ .statusCode(500);
+ }
+
+ @Test
+ public void postShouldFailOnRepositoryExceptionOnGetUserByName() throws Exception {
+ when(usersRepository.getUserByName(username)).thenThrow(new UsersRepositoryException("message"));
+
+ given()
+ .body("{\"password\":\"password\"}")
+ .when()
+ .put(USERNAME)
+ .then()
+ .statusCode(500);
+ }
+
+ @Test
+ public void postShouldNotFailOnRepositoryExceptionOnAddUser() throws Exception {
+ when(usersRepository.getUserByName(username)).thenReturn(null);
+ doThrow(new UsersRepositoryException("message")).when(usersRepository).addUser(username, password);
+
+ given()
+ .body("{\"password\":\"password\"}")
+ .when()
+ .put(USERNAME)
+ .then()
+ .statusCode(409);
+ }
+
+ @Test
+ public void postShouldFailOnRepositoryExceptionOnUpdateUser() throws Exception {
+ when(usersRepository.getUserByName(username)).thenReturn(mock(User.class));
+ doThrow(new UsersRepositoryException("message")).when(usersRepository).updateUser(any());
+
+ given()
+ .body("{\"password\":\"password\"}")
+ .when()
+ .put(USERNAME)
+ .then()
+ .statusCode(409);
+ }
+
+
+ @Test
+ public void deleteShouldFailOnUnknownException() throws Exception {
+ doThrow(new RuntimeException()).when(usersRepository).removeUser(username);
+
+ when()
+ .delete(USERNAME)
+ .then()
+ .statusCode(500);
+ }
+
+ @Test
+ public void getShouldFailOnUnknownException() throws Exception {
+ when(usersRepository.list()).thenThrow(new RuntimeException());
+
+ when()
+ .get()
+ .then()
+ .statusCode(500);
+ }
+
+ @Test
+ public void postShouldFailOnUnknownExceptionOnGetUserByName() throws Exception {
+ when(usersRepository.getUserByName(username)).thenThrow(new RuntimeException());
+
+ given()
+ .body("{\"password\":\"password\"}")
+ .when()
+ .put(USERNAME)
+ .then()
+ .statusCode(500);
+ }
+
+ @Test
+ public void postShouldFailOnUnknownExceptionOnAddUser() throws Exception {
+ when(usersRepository.getUserByName(username)).thenReturn(null);
+ doThrow(new RuntimeException()).when(usersRepository).addUser(username, password);
+
+ given()
+ .body("{\"password\":\"password\"}")
+ .when()
+ .put(USERNAME)
+ .then()
+ .statusCode(500);
+ }
+
+ @Test
+ public void postShouldFailOnUnknownExceptionOnGetUpdateUser() throws Exception {
+ when(usersRepository.getUserByName(username)).thenReturn(mock(User.class));
+ doThrow(new RuntimeException()).when(usersRepository).updateUser(any());
+
+ given()
+ .body("{\"password\":\"password\"}")
+ .when()
+ .put(USERNAME)
+ .then()
+ .statusCode(500);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/cca0f398/server/protocols/webadmin/webadmin-mailbox/pom.xml
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-mailbox/pom.xml b/server/protocols/webadmin/webadmin-mailbox/pom.xml
new file mode 100644
index 0000000..3b17b61
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-mailbox/pom.xml
@@ -0,0 +1,292 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<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>
+ <artifactId>james-server</artifactId>
+ <groupId>org.apache.james</groupId>
+ <version>3.0.0-beta6-SNAPSHOT</version>
+ <relativePath>../../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>james-server-webadmin-mailbox</artifactId>
+ <packaging>jar</packaging>
+
+ <name>Apache James :: Server :: Web Admin :: mailbox</name>
+
+ <profiles>
+ <profile>
+ <id>noTest</id>
+ <activation>
+ <os>
+ <family>windows</family>
+ </os>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skipTests>true</skipTests>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>disable-build-for-older-jdk</id>
+ <activation>
+ <jdk>(,1.8)</jdk>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>default-jar</id>
+ <phase>none</phase>
+ </execution>
+ <execution>
+ <id>jar</id>
+ <phase>none</phase>
+ </execution>
+ <execution>
+ <id>test-jar</id>
+ <phase>none</phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>default-compile</id>
+ <phase>none</phase>
+ </execution>
+ <execution>
+ <id>default-testCompile</id>
+ <phase>none</phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>default-test</id>
+ <phase>none</phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-source-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <phase>none</phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-install-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>default-install</id>
+ <phase>none</phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>default-resources</id>
+ <phase>none</phase>
+ </execution>
+ <execution>
+ <id>default-testResources</id>
+ <phase>none</phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-site-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-descriptor</id>
+ <phase>none</phase>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>build-for-jdk-8</id>
+ <activation>
+ <jdk>[1.8,)</jdk>
+ </activation>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.james</groupId>
+ <artifactId>apache-james-mailbox-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.james</groupId>
+ <artifactId>apache-james-mailbox-memory</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.james</groupId>
+ <artifactId>james-server-util-java8</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.james</groupId>
+ <artifactId>james-server-data-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.james</groupId>
+ <artifactId>james-server-data-memory</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.james</groupId>
+ <artifactId>james-server-webadmin-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.james</groupId>
+ <artifactId>metrics-logger</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.jayway.restassured</groupId>
+ <artifactId>rest-assured</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>de.bechte.junit</groupId>
+ <artifactId>junit-hierarchicalcontextrunner</artifactId>
+ <version>4.11.3</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.inject</groupId>
+ <artifactId>javax.inject</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ <version>${assertj-3.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>java-hamcrest</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifest>
+ <mainClass>fully.qualified.MainClass</mainClass>
+ </manifest>
+ </archive>
+ <descriptorRefs>
+ <descriptorRef>jar-with-dependencies</descriptorRef>
+ </descriptorRefs>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>animal-sniffer-java-8</id>
+ <activation>
+ <jdk>[1.8,)</jdk>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>animal-sniffer-maven-plugin</artifactId>
+ <configuration>
+ <signature>
+ <groupId>org.codehaus.mojo.signature</groupId>
+ <artifactId>java18</artifactId>
+ <version>1.0</version>
+ </signature>
+ </configuration>
+ <executions>
+ <execution>
+ <id>check_java_8</id>
+ <phase>test</phase>
+ <goals>
+ <goal>check</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project>
http://git-wip-us.apache.org/repos/asf/james-project/blob/cca0f398/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/dto/MailboxResponse.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/dto/MailboxResponse.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/dto/MailboxResponse.java
new file mode 100644
index 0000000..b552f45
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/dto/MailboxResponse.java
@@ -0,0 +1,33 @@
+/****************************************************************
+ * 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;
+
+public class MailboxResponse {
+
+ private final String mailboxName;
+
+ public MailboxResponse(String mailboxName) {
+ this.mailboxName = mailboxName;
+ }
+
+ public String getMailboxName() {
+ return mailboxName;
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/cca0f398/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/dto/QuotaDTO.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/dto/QuotaDTO.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/dto/QuotaDTO.java
new file mode 100644
index 0000000..b3403ae
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/dto/QuotaDTO.java
@@ -0,0 +1,73 @@
+/****************************************************************
+ * 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.apache.james.mailbox.model.Quota;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
+import com.google.common.base.Preconditions;
+
+@JsonDeserialize(builder = QuotaDTO.Builder.class)
+public class QuotaDTO {
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ @JsonPOJOBuilder(withPrefix="")
+ public static class Builder {
+ private long count;
+ private long size;
+
+ public Builder count(long count) {
+ this.count = count;
+ return this;
+ }
+
+ public Builder size(long size) {
+ this.size = size;
+ return this;
+ }
+
+ public QuotaDTO build() {
+ return new QuotaDTO(count, size);
+ }
+
+ }
+
+ private final long count;
+ private final long size;
+
+ private QuotaDTO(long count, long size) {
+ Preconditions.checkArgument(count >= Quota.UNLIMITED);
+ Preconditions.checkArgument(size >= Quota.UNLIMITED);
+ this.count = count;
+ this.size = size;
+ }
+
+ public long getCount() {
+ return count;
+ }
+
+ public long getSize() {
+ return size;
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/cca0f398/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/dto/QuotaRequest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/dto/QuotaRequest.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/dto/QuotaRequest.java
new file mode 100644
index 0000000..7ae9e85
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/dto/QuotaRequest.java
@@ -0,0 +1,39 @@
+/****************************************************************
+ * 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 com.google.common.base.Preconditions;
+
+public class QuotaRequest {
+ public static QuotaRequest parse(String serialized) {
+ return new QuotaRequest(Long.valueOf(serialized));
+ }
+
+ private final long value;
+
+ public QuotaRequest(long value) {
+ Preconditions.checkArgument(value >= 0);
+ this.value = value;
+ }
+
+ public long getValue() {
+ return value;
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/cca0f398/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/GlobalQuotaRoutes.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/GlobalQuotaRoutes.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/GlobalQuotaRoutes.java
new file mode 100644
index 0000000..eeca83a
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/GlobalQuotaRoutes.java
@@ -0,0 +1,130 @@
+/****************************************************************
+ * 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 javax.inject.Inject;
+
+import org.apache.james.mailbox.model.Quota;
+import org.apache.james.mailbox.quota.MaxQuotaManager;
+import org.apache.james.webadmin.Constants;
+import org.apache.james.webadmin.Routes;
+import org.apache.james.webadmin.dto.QuotaDTO;
+import org.apache.james.webadmin.dto.QuotaRequest;
+import org.apache.james.webadmin.utils.JsonExtractException;
+import org.apache.james.webadmin.utils.JsonExtractor;
+import org.apache.james.webadmin.utils.JsonTransformer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import spark.Service;
+
+public class GlobalQuotaRoutes implements Routes {
+
+ public static final String QUOTA_ENDPOINT = "/quota";
+ public static final String COUNT_ENDPOINT = QUOTA_ENDPOINT + "/count";
+ public static final String SIZE_ENDPOINT = QUOTA_ENDPOINT + "/size";
+ private static final Logger LOGGER = LoggerFactory.getLogger(Routes.class);
+
+ private final MaxQuotaManager maxQuotaManager;
+ private final JsonTransformer jsonTransformer;
+ private final JsonExtractor<QuotaDTO> jsonExtractor;
+
+ @Inject
+ public GlobalQuotaRoutes(MaxQuotaManager maxQuotaManager, JsonTransformer jsonTransformer) {
+ this.maxQuotaManager = maxQuotaManager;
+ this.jsonTransformer = jsonTransformer;
+ this.jsonExtractor = new JsonExtractor<>(QuotaDTO.class);
+ }
+
+ @Override
+ public void define(Service service) {
+ service.get(COUNT_ENDPOINT, (request, response) -> {
+ long value = maxQuotaManager.getDefaultMaxMessage();
+ response.status(200);
+ return value;
+ }, jsonTransformer);
+
+ service.delete(COUNT_ENDPOINT, (request, response) -> {
+ maxQuotaManager.setDefaultMaxMessage(Quota.UNLIMITED);
+ response.status(204);
+ return Constants.EMPTY_BODY;
+ });
+
+ service.put(COUNT_ENDPOINT, (request, response) -> {
+ try {
+ QuotaRequest quotaRequest = QuotaRequest.parse(request.body());
+ maxQuotaManager.setDefaultMaxMessage(quotaRequest.getValue());
+ response.status(204);
+ } catch (IllegalArgumentException e) {
+ LOGGER.info("Invalid quota. Need to be an integer value greater than 0");
+ response.status(400);
+ }
+ return Constants.EMPTY_BODY;
+ });
+
+ service.get(SIZE_ENDPOINT, (request, response) -> {
+ long value = maxQuotaManager.getDefaultMaxStorage();
+ response.status(200);
+ return value;
+ }, jsonTransformer);
+
+ service.delete(SIZE_ENDPOINT, (request, response) -> {
+ maxQuotaManager.setDefaultMaxStorage(Quota.UNLIMITED);
+ response.status(204);
+ return Constants.EMPTY_BODY;
+ });
+
+ service.put(SIZE_ENDPOINT, (request, response) -> {
+ try {
+ QuotaRequest quotaRequest = QuotaRequest.parse(request.body());
+ maxQuotaManager.setDefaultMaxStorage(quotaRequest.getValue());
+ response.status(204);
+ } catch (IllegalArgumentException e) {
+ LOGGER.info("Invalid quota. Need to be an integer value greater than 0");
+ response.status(400);
+ }
+ return Constants.EMPTY_BODY;
+ });
+
+ service.get(QUOTA_ENDPOINT, (request, response) -> {
+ QuotaDTO quotaDTO = QuotaDTO.builder()
+ .count(maxQuotaManager.getDefaultMaxMessage())
+ .size(maxQuotaManager.getDefaultMaxStorage()).build();
+ response.status(200);
+ return quotaDTO;
+ }, jsonTransformer);
+
+ service.put(QUOTA_ENDPOINT, ((request, response) -> {
+ try {
+ QuotaDTO quotaDTO = jsonExtractor.parse(request.body());
+ maxQuotaManager.setDefaultMaxMessage(quotaDTO.getCount());
+ maxQuotaManager.setDefaultMaxStorage(quotaDTO.getSize());
+ response.status(204);
+ } catch (JsonExtractException e) {
+ LOGGER.info("Malformed JSON", e);
+ response.status(400);
+ } catch (IllegalArgumentException e) {
+ LOGGER.info("Quota should be positive or unlimited (-1)", e);
+ response.status(400);
+ }
+ return Constants.EMPTY_BODY;
+ }));
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org