james-server-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From btell...@apache.org
Subject [01/20] james-project git commit: JAMES-2151 Administer Sieve quotas via webadmin
Date Tue, 26 Jun 2018 09:12:57 GMT
Repository: james-project
Updated Branches:
  refs/heads/master 5a4c0ded9 -> b10fa18aa


JAMES-2151 Administer Sieve quotas via webadmin

>From the awesome work of Sebastian Górecki on https://github.com/linagora/james-project/pull/1066


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/b9ac736b
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/b9ac736b
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/b9ac736b

Branch: refs/heads/master
Commit: b9ac736b4644c4471e931c12dffcd167e32aa3ba
Parents: 5a4c0de
Author: Sebastian Górecki <gorecki.sebastian@gmail.com>
Authored: Tue Oct 24 23:10:02 2017 +0200
Committer: benwa <btellier@linagora.com>
Committed: Tue Jun 26 16:05:27 2018 +0700

----------------------------------------------------------------------
 .../api/SieveQuotaRepository.java               |  46 ++++
 .../sieverepository/api/SieveRepository.java    |  19 +-
 .../james/webadmin/routes/SieveQuotaRoutes.java | 260 +++++++++++++++++++
 .../routes/InMemorySieveQuotaRepository.java    |  82 ++++++
 .../webadmin/routes/SieveQuotaRoutesTest.java   | 215 +++++++++++++++
 5 files changed, 604 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/b9ac736b/server/data/data-api/src/main/java/org/apache/james/sieverepository/api/SieveQuotaRepository.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/sieverepository/api/SieveQuotaRepository.java
b/server/data/data-api/src/main/java/org/apache/james/sieverepository/api/SieveQuotaRepository.java
new file mode 100644
index 0000000..ec11c1e
--- /dev/null
+++ b/server/data/data-api/src/main/java/org/apache/james/sieverepository/api/SieveQuotaRepository.java
@@ -0,0 +1,46 @@
+/*
+ *   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.sieverepository.api;
+
+import org.apache.james.sieverepository.api.exception.QuotaNotFoundException;
+import org.apache.james.sieverepository.api.exception.StorageException;
+
+/**
+ * SieveQuotaRepository
+ */
+public interface SieveQuotaRepository {
+
+    boolean hasQuota() throws StorageException;
+
+    long getQuota() throws QuotaNotFoundException, StorageException;
+
+    void setQuota(long quota) throws StorageException;
+
+    void removeQuota() throws QuotaNotFoundException, StorageException;
+
+    boolean hasQuota(String user) throws StorageException;
+
+    long getQuota(String user) throws QuotaNotFoundException, StorageException;
+
+    void setQuota(String user, long quota) throws StorageException;
+
+    void removeQuota(String user) throws QuotaNotFoundException, StorageException;
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/b9ac736b/server/data/data-api/src/main/java/org/apache/james/sieverepository/api/SieveRepository.java
----------------------------------------------------------------------
diff --git a/server/data/data-api/src/main/java/org/apache/james/sieverepository/api/SieveRepository.java
b/server/data/data-api/src/main/java/org/apache/james/sieverepository/api/SieveRepository.java
index 9bdb55e..f93d080 100644
--- a/server/data/data-api/src/main/java/org/apache/james/sieverepository/api/SieveRepository.java
+++ b/server/data/data-api/src/main/java/org/apache/james/sieverepository/api/SieveRepository.java
@@ -26,7 +26,6 @@ import java.util.List;
 import org.apache.james.sieverepository.api.exception.DuplicateException;
 import org.apache.james.sieverepository.api.exception.IsActiveException;
 import org.apache.james.sieverepository.api.exception.QuotaExceededException;
-import org.apache.james.sieverepository.api.exception.QuotaNotFoundException;
 import org.apache.james.sieverepository.api.exception.ScriptNotFoundException;
 import org.apache.james.sieverepository.api.exception.StorageException;
 import org.joda.time.DateTime;
@@ -35,7 +34,7 @@ import org.joda.time.DateTime;
 /**
  * <code>SieveRepository</code>
  */
-public interface SieveRepository {
+public interface SieveRepository extends SieveQuotaRepository {
 
     String NO_SCRIPT_NAME = "";
 
@@ -68,20 +67,4 @@ public interface SieveRepository {
     
     void renameScript(String user, String oldName, String newName) throws ScriptNotFoundException,
DuplicateException, StorageException;
 
-    boolean hasQuota() throws StorageException;
-    
-    long getQuota() throws QuotaNotFoundException, StorageException;
-    
-    void setQuota(long quota) throws StorageException;
-    
-    void removeQuota() throws QuotaNotFoundException, StorageException;
-    
-    boolean hasQuota(String user) throws StorageException;
-    
-    long getQuota(String user) throws QuotaNotFoundException, StorageException;
-    
-    void setQuota(String user, long quota) throws StorageException;
-    
-    void removeQuota(String user) throws QuotaNotFoundException, StorageException;
-
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/b9ac736b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/SieveQuotaRoutes.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/SieveQuotaRoutes.java
b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/SieveQuotaRoutes.java
new file mode 100644
index 0000000..1c779db
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/SieveQuotaRoutes.java
@@ -0,0 +1,260 @@
+/****************************************************************
+ * 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 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.sieverepository.api.SieveQuotaRepository;
+import org.apache.james.sieverepository.api.exception.QuotaNotFoundException;
+import org.apache.james.webadmin.Constants;
+import org.apache.james.webadmin.Routes;
+import org.apache.james.webadmin.utils.ErrorResponder;
+import org.apache.james.webadmin.utils.JsonExtractException;
+import org.apache.james.webadmin.utils.JsonExtractor;
+import org.apache.james.webadmin.utils.JsonTransformer;
+import org.eclipse.jetty.http.HttpStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+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.Request;
+import spark.Service;
+
+@Api(tags = "SieveQuota")
+@Path(SieveQuotaRoutes.ROOT_PATH)
+@Produces("application/json")
+public class SieveQuotaRoutes implements Routes {
+
+    static final String ROOT_PATH = "/sieve/quota";
+    private static final String USER_ID = "userId";
+    private static final String USER_SIEVE_QUOTA_PATH = ROOT_PATH + SEPARATOR + ":" + USER_ID;
+    private static final String REQUESTED_SIZE = "requestedSize";
+    private static final Logger LOGGER = LoggerFactory.getLogger(SieveQuotaRoutes.class);
+
+    private final SieveQuotaRepository sieveQuotaRepository;
+    private final JsonTransformer jsonTransformer;
+    private final JsonExtractor<Long> jsonExtractor;
+
+    @Inject
+    public SieveQuotaRoutes(SieveQuotaRepository sieveQuotaRepository, JsonTransformer jsonTransformer)
{
+        this.sieveQuotaRepository = sieveQuotaRepository;
+        this.jsonTransformer = jsonTransformer;
+        this.jsonExtractor = new JsonExtractor<>(Long.class);
+    }
+
+    @Override
+    public void define(Service service) {
+        defineGetGlobalSieveQuota(service);
+        defineUpdateGlobalSieveQuota(service);
+        defineRemoveGlobalSieveQuota(service);
+
+        defineGetPerUserSieveQuota(service);
+        defineUpdatePerUserSieveQuota(service);
+        defineRemovePerUserSieveQuota(service);
+    }
+
+    @GET
+    @ApiOperation(value = "Reading global sieve quota size")
+    @ApiResponses(value = {
+            @ApiResponse(code = 200, message = "OK", response = Long.class),
+            @ApiResponse(code = 404, message = "Global sieve quota not set."),
+            @ApiResponse(code = 500, message = "Internal server error - Something went bad
on the server side.")
+    })
+    public void defineGetGlobalSieveQuota(Service service) {
+        service.get(ROOT_PATH, (request, response) -> {
+            try {
+                long sieveQuota = sieveQuotaRepository.getQuota();
+                response.status(HttpStatus.OK_200);
+                return sieveQuota;
+            } catch (QuotaNotFoundException e) {
+                LOGGER.info("Global sieve quota not set", e);
+                throw ErrorResponder.builder()
+                    .type(ErrorResponder.ErrorType.NOT_FOUND)
+                    .statusCode(HttpStatus.NOT_FOUND_404)
+                    .message("Global sieve quota not set")
+                    .haltError();
+            }
+        }, jsonTransformer);
+    }
+
+    @PUT
+    @ApiOperation(value = "Update global sieve quota size")
+    @ApiImplicitParams({
+            @ApiImplicitParam(required = true, dataType = "long", name = REQUESTED_SIZE,
paramType = "body")
+    })
+    @ApiResponses(value = {
+            @ApiResponse(code = 200, message = "OK", response = Long.class),
+            @ApiResponse(code = 400, message = "The body is not a positive integer."),
+            @ApiResponse(code = 500, message = "Internal server error - Something went bad
on the server side.")
+    })
+    public void defineUpdateGlobalSieveQuota(Service service) {
+        service.put(ROOT_PATH, (request, response) -> {
+            try {
+                Long requestedSize = extractRequestedQuotaSizeFromRequest(request);
+                sieveQuotaRepository.setQuota(requestedSize);
+                response.status(HttpStatus.NO_CONTENT_204);
+                return Constants.EMPTY_BODY;
+            } catch (JsonExtractException e) {
+                LOGGER.info("Malformed JSON", e);
+                throw ErrorResponder.builder()
+                    .type(ErrorResponder.ErrorType.INVALID_ARGUMENT)
+                    .statusCode(HttpStatus.BAD_REQUEST_400)
+                    .message("Malformed JSON")
+                    .cause(e)
+                    .haltError();
+            }
+        }, jsonTransformer);
+    }
+
+    @DELETE
+    @ApiOperation(value = "Removes global sieve quota")
+    @ApiResponses(value = {
+            @ApiResponse(code = 204, message = "Global sieve quota removed."),
+            @ApiResponse(code = 404, message = "Global sieve quota not set."),
+            @ApiResponse(code = 500, message = "Internal server error - Something went bad
on the server side.")
+    })
+    public void defineRemoveGlobalSieveQuota(Service service) {
+        service.delete(ROOT_PATH, (request, response) -> {
+            try {
+                sieveQuotaRepository.removeQuota();
+                response.status(HttpStatus.NO_CONTENT_204);
+            } catch (QuotaNotFoundException e) {
+                LOGGER.info("Global sieve quota not set", e);
+                throw ErrorResponder.builder()
+                    .type(ErrorResponder.ErrorType.NOT_FOUND)
+                    .statusCode(HttpStatus.NOT_FOUND_404)
+                    .message("Global sieve quota not set")
+                    .haltError();
+            }
+            return Constants.EMPTY_BODY;
+        });
+    }
+
+    @GET
+    @Path(value = ROOT_PATH + "/{" + USER_ID + "}")
+    @ApiImplicitParams({
+            @ApiImplicitParam(required = true, dataType = "string", name = USER_ID, paramType
= "path")
+    })
+    @ApiResponses(value = {
+            @ApiResponse(code = 200, message = "OK", response = Long.class),
+            @ApiResponse(code = 404, message = "User sieve quota not set."),
+            @ApiResponse(code = 500, message = "Internal server error - Something went bad
on the server side.")
+    })
+    public void defineGetPerUserSieveQuota(Service service) {
+        service.get(USER_SIEVE_QUOTA_PATH, (request, response) -> {
+            String userId = request.params(USER_ID);
+            try {
+                long userQuota = sieveQuotaRepository.getQuota(userId);
+                response.status(HttpStatus.OK_200);
+                return userQuota;
+            } catch (QuotaNotFoundException e) {
+                LOGGER.info("User sieve quota not set", e);
+                throw ErrorResponder.builder()
+                    .type(ErrorResponder.ErrorType.NOT_FOUND)
+                    .statusCode(HttpStatus.NOT_FOUND_404)
+                    .message("User sieve quota not set")
+                    .haltError();
+            }
+        }, jsonTransformer);
+    }
+
+    @PUT
+    @Path(value = ROOT_PATH + "/{" + USER_ID + "}")
+    @ApiImplicitParams({
+            @ApiImplicitParam(required = true, dataType = "string", name = USER_ID, paramType
= "path"),
+            @ApiImplicitParam(required = true, dataType = "long", name = REQUESTED_SIZE,
paramType = "body")
+    })
+    @ApiResponses(value = {
+            @ApiResponse(code = 200, message = "OK", response = Long.class),
+            @ApiResponse(code = 400, message = "The body is not a positive integer."),
+            @ApiResponse(code = 500, message = "Internal server error - Something went bad
on the server side.")
+    })
+    public void defineUpdatePerUserSieveQuota(Service service) {
+        service.put(USER_SIEVE_QUOTA_PATH, (request, response) -> {
+            String userId = request.params(USER_ID);
+            try {
+                Long requestedSize = extractRequestedQuotaSizeFromRequest(request);
+                sieveQuotaRepository.setQuota(userId, requestedSize);
+                response.status(HttpStatus.NO_CONTENT_204);
+            } catch (JsonExtractException e) {
+                LOGGER.info("Malformed JSON", e);
+                throw ErrorResponder.builder()
+                    .type(ErrorResponder.ErrorType.INVALID_ARGUMENT)
+                    .statusCode(HttpStatus.BAD_REQUEST_400)
+                    .message("Malformed JSON")
+                    .cause(e)
+                    .haltError();
+            }
+            return Constants.EMPTY_BODY;
+        }, jsonTransformer);
+    }
+
+    @DELETE
+    @Path(value = ROOT_PATH + "/{" + USER_ID + "}")
+    @ApiImplicitParams({
+            @ApiImplicitParam(required = true, dataType = "string", name = USER_ID, paramType
= "path")
+    })
+    @ApiResponses(value = {
+            @ApiResponse(code = 204, message = "User sieve quota removed."),
+            @ApiResponse(code = 404, message = "User sieve quota not set."),
+            @ApiResponse(code = 500, message = "Internal server error - Something went bad
on the server side.")
+    })
+    public void defineRemovePerUserSieveQuota(Service service) {
+        service.delete(USER_SIEVE_QUOTA_PATH, (request, response) -> {
+            String userId = request.params(USER_ID);
+            try {
+                sieveQuotaRepository.removeQuota(userId);
+                response.status(HttpStatus.NO_CONTENT_204);
+            } catch (QuotaNotFoundException e) {
+                LOGGER.info("User sieve quota not set", e);
+                throw ErrorResponder.builder()
+                    .type(ErrorResponder.ErrorType.NOT_FOUND)
+                    .statusCode(HttpStatus.NOT_FOUND_404)
+                    .message("User sieve quota not set")
+                    .haltError();
+            }
+            return Constants.EMPTY_BODY;
+        });
+    }
+
+    private Long extractRequestedQuotaSizeFromRequest(Request request) throws JsonExtractException
{
+        Long requestedSize = jsonExtractor.parse(request.body());
+        if (requestedSize < 0) {
+            throw ErrorResponder.builder()
+                .type(ErrorResponder.ErrorType.INVALID_ARGUMENT)
+                .statusCode(HttpStatus.BAD_REQUEST_400)
+                .message("Requested quota size have to be a positive integer")
+                .haltError();
+        }
+        return requestedSize;
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/b9ac736b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/InMemorySieveQuotaRepository.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/InMemorySieveQuotaRepository.java
b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/InMemorySieveQuotaRepository.java
new file mode 100644
index 0000000..d3aedd0
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/InMemorySieveQuotaRepository.java
@@ -0,0 +1,82 @@
+/****************************************************************
+ * 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 java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.james.sieverepository.api.SieveQuotaRepository;
+import org.apache.james.sieverepository.api.exception.QuotaNotFoundException;
+
+public class InMemorySieveQuotaRepository implements SieveQuotaRepository {
+
+    private Optional<Long> globalQuota = Optional.empty();
+
+    private Map<String, Long> userQuota = new ConcurrentHashMap<>();
+
+    @Override
+    public boolean hasQuota() {
+        return globalQuota.isPresent();
+    }
+
+    @Override
+    public long getQuota() throws QuotaNotFoundException {
+        return globalQuota.orElseThrow(QuotaNotFoundException::new);
+    }
+
+    @Override
+    public void setQuota(long quota) {
+        this.globalQuota = Optional.of(quota);
+    }
+
+    @Override
+    public void removeQuota() throws QuotaNotFoundException {
+        if (!globalQuota.isPresent()) {
+            throw new QuotaNotFoundException();
+        }
+        globalQuota = Optional.empty();
+    }
+
+    @Override
+    public boolean hasQuota(String user) {
+        return userQuota.containsKey(user);
+    }
+
+    @Override
+    public long getQuota(String user) throws QuotaNotFoundException {
+        return Optional.ofNullable(userQuota.get(user))
+            .orElseThrow(QuotaNotFoundException::new);
+    }
+
+    @Override
+    public void setQuota(String user, long quota) {
+        userQuota.put(user, quota);
+    }
+
+    @Override
+    public void removeQuota(String user) throws QuotaNotFoundException {
+        Optional<Long> quotaValue = Optional.ofNullable(userQuota.get(user));
+        if (!quotaValue.isPresent()) {
+            throw new QuotaNotFoundException();
+        }
+        userQuota.remove(user);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/b9ac736b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/SieveQuotaRoutesTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/SieveQuotaRoutesTest.java
b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/SieveQuotaRoutesTest.java
new file mode 100644
index 0000000..e127901
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/SieveQuotaRoutesTest.java
@@ -0,0 +1,215 @@
+/****************************************************************
+ * 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 org.apache.james.webadmin.Constants.SEPARATOR;
+import static org.apache.james.webadmin.WebAdminServer.NO_CONFIGURATION;
+import static org.apache.james.webadmin.routes.SieveQuotaRoutes.ROOT_PATH;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.apache.james.metrics.logger.DefaultMetricFactory;
+import org.apache.james.sieverepository.api.SieveQuotaRepository;
+import org.apache.james.webadmin.WebAdminServer;
+import org.apache.james.webadmin.WebAdminUtils;
+import org.apache.james.webadmin.utils.JsonTransformer;
+import org.eclipse.jetty.http.HttpStatus;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import com.jayway.restassured.RestAssured;
+import com.jayway.restassured.http.ContentType;
+
+public class SieveQuotaRoutesTest {
+
+    private static final String USER_A = "userA";
+
+    private WebAdminServer webAdminServer;
+    private SieveQuotaRepository sieveRepository;
+
+    @BeforeEach
+    public void setUp() throws Exception {
+        sieveRepository = new InMemorySieveQuotaRepository();
+        webAdminServer = WebAdminUtils.createWebAdminServer(
+                new DefaultMetricFactory(),
+                new SieveQuotaRoutes(sieveRepository, new JsonTransformer()));
+        webAdminServer.configure(NO_CONFIGURATION);
+        webAdminServer.await();
+
+        RestAssured.requestSpecification = WebAdminUtils.buildRequestSpecification(webAdminServer)
+            .build();
+    }
+
+    @AfterEach
+    public void tearDown() {
+        webAdminServer.destroy();
+    }
+
+    @Test
+    public void getGlobalSieveQuotaShouldReturn404WhenNoQuotaSet() {
+        given()
+            .get(SieveQuotaRoutes.ROOT_PATH)
+        .then()
+            .statusCode(404);
+    }
+
+    @Test
+    public void getGlobalSieveQuotaShouldReturnStoredValue() throws Exception {
+        long value = 1000L;
+        sieveRepository.setQuota(value);
+
+        long actual =
+            given()
+                .get(SieveQuotaRoutes.ROOT_PATH)
+            .then()
+                .statusCode(HttpStatus.OK_200)
+                .contentType(ContentType.JSON)
+                .extract()
+                .as(Long.class);
+
+        assertThat(actual).isEqualTo(value);
+    }
+
+    @Test
+    public void updateGlobalSieveQuotaShouldUpdateStoredValue() throws Exception {
+        sieveRepository.setQuota(500L);
+        long requiredSize = 1024L;
+
+        given()
+            .body(requiredSize)
+            .put(SieveQuotaRoutes.ROOT_PATH)
+        .then()
+            .statusCode(HttpStatus.NO_CONTENT_204);
+
+        assertThat(sieveRepository.getQuota()).isEqualTo(requiredSize);
+    }
+
+    @Test
+    public void updateGlobalSieveQuotaShouldReturn400WhenMalformedJSON() {
+        given()
+            .body("invalid")
+            .put(SieveQuotaRoutes.ROOT_PATH)
+        .then()
+            .statusCode(HttpStatus.BAD_REQUEST_400);
+    }
+
+    @Test
+    public void updateGlobalSieveQuotaShouldReturn400WhenRequestedSizeNotPositiveInteger()
{
+        given()
+            .body(-100L)
+            .put(SieveQuotaRoutes.ROOT_PATH)
+        .then()
+            .statusCode(HttpStatus.BAD_REQUEST_400);
+    }
+
+    @Test
+    public void removeGlobalSieveQuotaShouldReturn404WhenNoQuotaSet() {
+        given()
+            .delete(SieveQuotaRoutes.ROOT_PATH)
+        .then()
+            .statusCode(HttpStatus.NOT_FOUND_404);
+    }
+
+    @Test
+    public void removeGlobalSieveQuotaShouldRemoveGlobalSieveQuota() throws Exception {
+        sieveRepository.setQuota(1024L);
+
+        given()
+            .delete(SieveQuotaRoutes.ROOT_PATH)
+        .then()
+            .statusCode(HttpStatus.NO_CONTENT_204);
+    }
+
+    @Test
+    public void getPerUserQuotaShouldReturn404WhenNoQuotaSetForUser() {
+        given()
+            .get(ROOT_PATH + SEPARATOR + USER_A)
+        .then()
+            .statusCode(HttpStatus.NOT_FOUND_404);
+    }
+
+    @Test
+    public void getPerUserSieveQuotaShouldReturnedStoredValue() throws Exception {
+        long value = 1024L;
+        sieveRepository.setQuota(USER_A, value);
+
+        long actual =
+            given()
+                .get(ROOT_PATH + SEPARATOR + USER_A)
+            .then()
+                .statusCode(HttpStatus.OK_200)
+                .contentType(ContentType.JSON)
+                .extract()
+                .as(Long.class);
+
+        assertThat(actual).isEqualTo(value);
+    }
+
+    @Test
+    public void updatePerUserSieveQuotaShouldUpdateStoredValue() throws Exception {
+        sieveRepository.setQuota(USER_A, 500L);
+        long requiredSize = 1024L;
+
+        given()
+            .body(requiredSize)
+            .put(ROOT_PATH + SEPARATOR + USER_A)
+        .then()
+            .statusCode(HttpStatus.NO_CONTENT_204);
+
+        assertThat(sieveRepository.getQuota(USER_A)).isEqualTo(requiredSize);
+    }
+
+    @Test
+    public void updatePerUserSieveQuotaShouldReturn400WhenMalformedJSON() {
+        given()
+            .body("invalid")
+            .put(ROOT_PATH + SEPARATOR + USER_A)
+        .then()
+            .statusCode(HttpStatus.BAD_REQUEST_400);
+    }
+
+    @Test
+    public void updatePerUserSieveQuotaShouldReturn400WhenRequestedSizeNotPositiveInteger()
{
+        given()
+            .body(-100L)
+            .put(ROOT_PATH + SEPARATOR + USER_A)
+        .then()
+            .statusCode(HttpStatus.BAD_REQUEST_400);
+    }
+
+    @Test
+    public void removePerUserSieveQuotaShouldReturn404WhenNoQuotaSetForUser() {
+        given()
+            .delete(ROOT_PATH + SEPARATOR + USER_A)
+        .then()
+            .statusCode(HttpStatus.NOT_FOUND_404);
+    }
+
+    @Test
+    public void removePerUserSieveQuotaShouldRemoveQuotaForUser() throws Exception {
+        sieveRepository.setQuota(USER_A, 1024L);
+
+        given()
+            .delete(ROOT_PATH + SEPARATOR + USER_A)
+        .then()
+            .statusCode(HttpStatus.NO_CONTENT_204);
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


Mime
View raw message