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 2019/03/12 03:19:51 UTC

[james-project] 13/15: JAMES-2663 Adding action parameter to restoring API path

This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 8ccfd9c1f0c8bb839785d2885d1586d8f5d4377f
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Tue Mar 5 15:15:03 2019 +0700

    JAMES-2663 Adding action parameter to restoring API path
---
 .../vault/routes/DeletedMessagesVaultRoutes.java   | 92 ++++++++++++++++++----
 .../routes/DeletedMessagesVaultRoutesTest.java     | 78 +++++++++++++++++-
 src/site/markdown/server/manage-webadmin.md        | 13 ++-
 3 files changed, 160 insertions(+), 23 deletions(-)

diff --git a/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/main/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutes.java b/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/main/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutes.java
index 3fc748a..edca31a 100644
--- a/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/main/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutes.java
+++ b/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/main/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutes.java
@@ -21,22 +21,31 @@ package org.apache.james.webadmin.vault.routes;
 
 import static org.apache.james.webadmin.Constants.SEPARATOR;
 
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Stream;
+
 import javax.inject.Inject;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 
+import org.apache.commons.lang3.NotImplementedException;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.james.core.User;
+import org.apache.james.task.Task;
 import org.apache.james.task.TaskId;
 import org.apache.james.task.TaskManager;
 import org.apache.james.webadmin.Constants;
 import org.apache.james.webadmin.Routes;
 import org.apache.james.webadmin.dto.TaskIdDto;
-import org.apache.james.webadmin.utils.ErrorResponder;
 import org.apache.james.webadmin.utils.JsonTransformer;
 import org.eclipse.jetty.http.HttpStatus;
 
+import com.github.steveash.guavate.Guavate;
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Joiner;
+import com.google.common.base.Preconditions;
 
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
@@ -53,9 +62,39 @@ import spark.Service;
 @Produces(Constants.JSON_CONTENT_TYPE)
 public class DeletedMessagesVaultRoutes implements Routes {
 
+    enum UserVaultAction {
+        RESTORE("restore");
+
+        static Optional<UserVaultAction> getAction(String value) {
+            Preconditions.checkNotNull(value, "action cannot be null");
+            Preconditions.checkArgument(StringUtils.isNotBlank(value), "action cannot be empty or blank");
+
+            return Stream.of(values())
+                .filter(action -> action.value.equals(value))
+                .findFirst();
+        }
+
+        private static List<String> plainValues() {
+            return Stream.of(values())
+                .map(UserVaultAction::getValue)
+                .collect(Guavate.toImmutableList());
+        }
+
+        private final String value;
+
+        UserVaultAction(String value) {
+            this.value = value;
+        }
+
+        public String getValue() {
+            return value;
+        }
+    }
+
     public static final String ROOT_PATH = "deletedMessages/user";
     private static final String USER_PATH_PARAM = "user";
     private static final String RESTORE_PATH = ROOT_PATH + SEPARATOR + ":" + USER_PATH_PARAM;
+    private static final String ACTION_QUERY_PARAM = "action";
 
     private final RestoreService vaultRestore;
     private final JsonTransformer jsonTransformer;
@@ -77,7 +116,7 @@ public class DeletedMessagesVaultRoutes implements Routes {
 
     @Override
     public void define(Service service) {
-        service.post(RESTORE_PATH, this::restore, jsonTransformer);
+        service.post(RESTORE_PATH, this::userActions, jsonTransformer);
     }
 
     @POST
@@ -91,28 +130,51 @@ public class DeletedMessagesVaultRoutes implements Routes {
             dataType = "String",
             defaultValue = "none",
             example = "user@james.org",
-            value = "Compulsory. Needs to be a valid username represent for an user had requested to restore deleted emails")
+            value = "Compulsory. Needs to be a valid username represent for an user had requested to restore deleted emails"),
+        @ApiImplicitParam(
+            required = true,
+            dataType = "String",
+            name = "action",
+            paramType = "query",
+            example = "?action=restore",
+            value = "Compulsory. Needs to be a valid action represent for an operation to perform on the Deleted Message Vault, " +
+                "valid action should be in the list (restore)")
     })
     @ApiResponses(value = {
         @ApiResponse(code = HttpStatus.CREATED_201, message = "Task is created", response = TaskIdDto.class),
         @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "Bad request - user param is invalid"),
         @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, message = "Internal server error - Something went bad on the server side.")
     })
-    private TaskIdDto restore(Request request, Response response) {
-        User userToRestore = extractUser(request);
-        TaskId taskId = taskManager.submit(new DeletedMessagesVaultRestoreTask(userToRestore, vaultRestore));
+    private TaskIdDto userActions(Request request, Response response) {
+        UserVaultAction requestedAction = extractUserVaultAction(request);
+
+        Task requestedTask = generateTask(requestedAction, request);
+        TaskId taskId = taskManager.submit(requestedTask);
         return TaskIdDto.respond(response, taskId);
     }
 
-    private User extractUser(Request request) {
-        try {
-            return User.fromUsername(request.params(USER_PATH_PARAM));
-        } catch (IllegalArgumentException e) {
-            throw ErrorResponder.builder()
-                .statusCode(HttpStatus.BAD_REQUEST_400)
-                .type(ErrorResponder.ErrorType.INVALID_ARGUMENT)
-                .message(e.getMessage())
-                .haltError();
+    private Task generateTask(UserVaultAction requestedAction, Request request) {
+        User userToRestore = User.fromUsername(request.params(USER_PATH_PARAM));
+
+        switch (requestedAction) {
+            case RESTORE:
+                return new DeletedMessagesVaultRestoreTask(userToRestore, vaultRestore);
+            default:
+                throw new NotImplementedException(requestedAction + " is not yet handled.");
         }
     }
+
+    private UserVaultAction extractUserVaultAction(Request request) {
+        String actionParam = request.queryParams(ACTION_QUERY_PARAM);
+        return Optional.ofNullable(actionParam)
+            .map(this::getUserVaultAction)
+            .orElseThrow(() -> new IllegalArgumentException("action parameter is missing"));
+    }
+
+    private UserVaultAction getUserVaultAction(String actionString) {
+        return UserVaultAction.getAction(actionString)
+            .orElseThrow(() -> new IllegalArgumentException(String.format("'%s' is not a valid action. Supported values are: (%s)",
+                actionString,
+                Joiner.on(",").join(UserVaultAction.plainValues()))));
+    }
 }
diff --git a/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutesTest.java
index 7349d5a..460e3c2 100644
--- a/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutesTest.java
@@ -116,19 +116,78 @@ class DeletedMessagesVaultRoutesTest {
     class ValidationTest {
 
         @Test
-        void restoreShouldReturnInvalidWhenUserIsInvalid() {
+        void restoreShouldReturnInvalidWhenActionIsMissing() {
             when()
+                .post(USER.asString())
+            .then()
+                .statusCode(HttpStatus.BAD_REQUEST_400)
+                .body("statusCode", is(400))
+                .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
+                .body("message", is(notNullValue()))
+                .body("details", is(notNullValue()));
+        }
+
+        @Test
+        void restoreShouldReturnInvalidWhenPassingEmptyAction() {
+            given()
+                .queryParam("action", "")
+            .when()
+                .post(USER.asString())
+            .then()
+                .statusCode(HttpStatus.BAD_REQUEST_400)
+                .body("statusCode", is(400))
+                .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
+                .body("message", is(notNullValue()))
+                .body("details", is(notNullValue()));
+        }
+
+        @Test
+        void restoreShouldReturnInvalidWhenActionIsInValid() {
+            given()
+                .queryParam("action", "invalid action")
+            .when()
+                .post(USER.asString())
+            .then()
+                .statusCode(HttpStatus.BAD_REQUEST_400)
+                .body("statusCode", is(400))
+                .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
+                .body("message", is(notNullValue()))
+                .body("details", is(notNullValue()));
+        }
+
+        @Test
+        void restoreShouldReturnInvalidWhenPassingCaseInsensitiveAction() {
+            given()
+                .queryParam("action", "RESTORE")
+            .when()
+                .post(USER.asString())
+            .then()
+                .statusCode(HttpStatus.BAD_REQUEST_400)
+                .body("statusCode", is(400))
+                .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
+                .body("message", is(notNullValue()))
+                .body("details", is(notNullValue()));
+        }
+
+        @Test
+        void restoreShouldReturnInvalidWhenUserIsInvalid() {
+            given()
+                .queryParam("action", "restore")
+            .when()
                 .post("not@valid@user.com")
             .then()
                 .statusCode(HttpStatus.BAD_REQUEST_400)
                 .body("statusCode", is(400))
                 .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
-                .body("message", is("The username should not contain multiple domain delimiter."));
+                .body("message", is(notNullValue()))
+                .body("details", is(notNullValue()));
         }
 
         @Test
         void postShouldReturnNotFoundWhenNoUserPathParameter() {
-            when()
+            given()
+                .queryParam("action", "restore")
+            .when()
                 .post()
             .then()
                 .statusCode(HttpStatus.NOT_FOUND_404)
@@ -151,11 +210,13 @@ class DeletedMessagesVaultRoutesTest {
                 .search(any(), any());
 
             String taskId = with()
+                .queryParam("action", "restore")
                 .post(USER.asString())
                 .jsonPath()
                 .get("taskId");
 
             given()
+                .queryParam("action", "restore")
                 .basePath(TasksRoutes.BASE)
             .when()
                 .get(taskId + "/await")
@@ -185,6 +246,7 @@ class DeletedMessagesVaultRoutesTest {
                 .appendMessage(any(), any());
 
             String taskId = with()
+                .queryParam("action", "restore")
                 .post(USER.asString())
                 .jsonPath()
                 .get("taskId");
@@ -214,6 +276,7 @@ class DeletedMessagesVaultRoutesTest {
                 .createMailbox(any(MailboxPath.class), any(MailboxSession.class));
 
             String taskId = with()
+                .queryParam("action", "restore")
                 .post(USER.asString())
                 .jsonPath()
                 .get("taskId");
@@ -236,7 +299,9 @@ class DeletedMessagesVaultRoutesTest {
 
     @Test
     void restoreShouldReturnATaskCreated() {
-        when()
+        given()
+            .queryParam("action", "restore")
+        .when()
             .post(USER.asString())
         .then()
             .statusCode(HttpStatus.CREATED_201)
@@ -249,6 +314,7 @@ class DeletedMessagesVaultRoutesTest {
         vault.append(USER, DELETED_MESSAGE_2, new ByteArrayInputStream(CONTENT)).block();
 
         String taskId = with()
+            .queryParam("action", "restore")
             .post(USER.asString())
             .jsonPath()
             .get("taskId");
@@ -275,6 +341,7 @@ class DeletedMessagesVaultRoutesTest {
         vault.append(USER, DELETED_MESSAGE_2, new ByteArrayInputStream(CONTENT)).block();
 
         String taskId = with()
+            .queryParam("action", "restore")
             .post(USER.asString())
             .jsonPath()
             .get("taskId");
@@ -304,6 +371,7 @@ class DeletedMessagesVaultRoutesTest {
         vault.append(USER, DELETED_MESSAGE_2, new ByteArrayInputStream(CONTENT)).block();
 
         String taskId = with()
+            .queryParam("action", "restore")
             .post(USER.asString())
             .jsonPath()
             .get("taskId");
@@ -325,6 +393,7 @@ class DeletedMessagesVaultRoutesTest {
         vault.append(USER, DELETED_MESSAGE_2, new ByteArrayInputStream(CONTENT)).block();
 
         String taskId = with()
+            .queryParam("action", "restore")
             .post(USER.asString())
             .jsonPath()
             .get("taskId");
@@ -348,6 +417,7 @@ class DeletedMessagesVaultRoutesTest {
         vault.append(USER, DELETED_MESSAGE_2, new ByteArrayInputStream(CONTENT)).block();
 
         String taskId = with()
+            .queryParam("action", "restore")
             .post(USER.asString())
             .jsonPath()
             .get("taskId");
diff --git a/src/site/markdown/server/manage-webadmin.md b/src/site/markdown/server/manage-webadmin.md
index b00a62f..a660766 100644
--- a/src/site/markdown/server/manage-webadmin.md
+++ b/src/site/markdown/server/manage-webadmin.md
@@ -2560,17 +2560,22 @@ Here are the following actions available on the 'Deleted Messages Vault'
 Deleted messages of a specific user can be restored by calling the following endpoint:
 
 ```
-curl -XPOST http://ip:port/deletedMessages/user/userToRestore@domain.ext
+curl -XPOST http://ip:port/deletedMessages/user/userToRestore@domain.ext?action=restore
 ```
 
 **All** messages in the Deleted Messages Vault of an specified user will be appended to his 'Restored-Messages' mailbox, which will be created if needed.
 
-**Note**: Restoring matched messages by queries is not supported yet 
-
+**Note**: 
+ - Restoring matched messages by queries is not supported yet 
+ - Query parameter `action` is required and should have value `restore` to represent for restoring feature. Otherwise, a bad request response will be returned
+ - Query parameter `action` is case sensitive
 Response code:
 
  - 201: Task for restoring deleted has been created
- - 400: Bad request, user parameter is invalid
+ - 400: Bad request: 
+   - action query param is not present
+   - action query param is not a valid action
+   - user parameter is invalid
 
 The scheduled task will have the following type `deletedMessages/restore` and the following `additionalInformation`:
 


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