You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by rc...@apache.org on 2021/08/06 09:17:05 UTC

[james-project] 02/04: JAMES-3621 Mailbox webadmin - Clearing content of mailbox - Route

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

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

commit d5bab2ab6347eb42d5ed66436270f77a59f5442f
Author: Tung TRAN <vt...@linagora.com>
AuthorDate: Tue Aug 3 18:07:30 2021 +0700

    JAMES-3621 Mailbox webadmin - Clearing content of mailbox - Route
---
 .../WebadminMailboxTaskSerializationModule.java    |   8 +
 .../james/webadmin/routes/UserMailboxesRoutes.java |  43 +++++
 .../webadmin/service/UserMailboxesService.java     |  10 +-
 .../webadmin/routes/UserMailboxesRoutesTest.java   | 192 ++++++++++++++++++++-
 4 files changed, 251 insertions(+), 2 deletions(-)

diff --git a/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/WebadminMailboxTaskSerializationModule.java b/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/WebadminMailboxTaskSerializationModule.java
index 369949d..e9010a2 100644
--- a/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/WebadminMailboxTaskSerializationModule.java
+++ b/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/WebadminMailboxTaskSerializationModule.java
@@ -30,6 +30,7 @@ import org.apache.james.server.task.json.dto.TaskDTOModule;
 import org.apache.james.task.Task;
 import org.apache.james.task.TaskExecutionDetails;
 import org.apache.james.webadmin.dto.DTOModuleInjections;
+import org.apache.james.webadmin.service.ClearMailboxContentTaskAdditionalInformationDTO;
 import org.apache.james.webadmin.service.CreateMissingParentsTask;
 import org.apache.james.webadmin.service.CreateMissingParentsTaskAdditionalInformationDTO;
 import org.apache.james.webadmin.service.EventDeadLettersRedeliverAllTaskDTO;
@@ -140,4 +141,11 @@ public class WebadminMailboxTaskSerializationModule extends AbstractModule {
     public AdditionalInformationDTOModule<? extends TaskExecutionDetails.AdditionalInformation, ? extends  AdditionalInformationDTO> webAdminCreateMissingParentsAdditionalInformation() {
         return CreateMissingParentsTaskAdditionalInformationDTO.SERIALIZATION_MODULE;
     }
+
+    @Named(DTOModuleInjections.WEBADMIN_DTO)
+    @ProvidesIntoSet
+    public AdditionalInformationDTOModule<? extends TaskExecutionDetails.AdditionalInformation, ? extends  AdditionalInformationDTO> webAdminClearMailboxContentAdditionalInformation() {
+        return ClearMailboxContentTaskAdditionalInformationDTO.SERIALIZATION_MODULE;
+    }
+
 }
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserMailboxesRoutes.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserMailboxesRoutes.java
index 092c2c6..46746ed 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserMailboxesRoutes.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserMailboxesRoutes.java
@@ -35,13 +35,18 @@ import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 
 import org.apache.james.core.Username;
+import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.exception.MailboxNameException;
 import org.apache.james.mailbox.exception.MailboxNotFoundException;
 import org.apache.james.mailbox.indexer.ReIndexer;
+import org.apache.james.task.Task;
 import org.apache.james.task.TaskManager;
+import org.apache.james.user.api.UsersRepositoryException;
 import org.apache.james.webadmin.Constants;
 import org.apache.james.webadmin.Routes;
+import org.apache.james.webadmin.service.ClearMailboxContentTask;
 import org.apache.james.webadmin.service.UserMailboxesService;
+import org.apache.james.webadmin.tasks.TaskFromRequest;
 import org.apache.james.webadmin.tasks.TaskFromRequestRegistry;
 import org.apache.james.webadmin.tasks.TaskFromRequestRegistry.TaskRegistration;
 import org.apache.james.webadmin.tasks.TaskIdDto;
@@ -92,6 +97,7 @@ public class UserMailboxesRoutes implements Routes {
     public static final String SPECIFIC_MAILBOX = USER_MAILBOXES_BASE + Constants.SEPARATOR + MAILBOX_NAME;
     public static final String MESSAGE_COUNT_PATH = SPECIFIC_MAILBOX + "/messageCount";
     public static final String UNSEEN_MESSAGE_COUNT_PATH = SPECIFIC_MAILBOX + "/unseenMessageCount";
+    public static final String MESSAGES_PATH = SPECIFIC_MAILBOX + "/messages";
 
     private final UserMailboxesService userMailboxesService;
     private final JsonTransformer jsonTransformer;
@@ -135,6 +141,9 @@ public class UserMailboxesRoutes implements Routes {
             .ifPresent(route -> service.post(USER_MAILBOXES_BASE, route, jsonTransformer));
 
         unseenMessageCount();
+
+        TaskFromRequest clearMailboxContentTaskRequest = this::clearMailboxContent;
+        service.delete(MESSAGES_PATH, clearMailboxContentTaskRequest.asRoute(taskManager), jsonTransformer);
     }
 
     @GET
@@ -425,4 +434,38 @@ public class UserMailboxesRoutes implements Routes {
             }
         });
     }
+
+    @DELETE
+    @Path("/{mailboxName}/messages")
+    @ApiOperation(value = "Clearing content of a given mailbox.", nickname = "ClearMailboxContent")
+    @ApiImplicitParams({
+        @ApiImplicitParam(required = true, dataType = "string", name = "username", paramType = "path"),
+        @ApiImplicitParam(required = true, dataType = "string", name = "mailboxName", paramType = "path")
+    })
+    @ApiResponses(
+        {
+            @ApiResponse(code = HttpStatus.CREATED_201, message = "The taskId of the given scheduled task", response = TaskIdDto.class),
+            @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "Invalid mailbox name"),
+            @ApiResponse(code = HttpStatus.UNAUTHORIZED_401, message = "Unauthorized. The user is not authenticated on the platform"),
+            @ApiResponse(code = HttpStatus.NOT_FOUND_404, message = "Invalid get on user mailboxes. The `username` or `mailboxName` does not exit"),
+        })
+
+    public Task clearMailboxContent(Request request) throws UsersRepositoryException, MailboxException {
+        Username username = getUsernameParam(request);
+        MailboxName mailboxName = new MailboxName(request.params(MAILBOX_NAME));
+        try {
+            userMailboxesService.usernamePreconditions(username);
+            userMailboxesService.mailboxExistPreconditions(username, mailboxName);
+        } catch (IllegalStateException e) {
+            LOGGER.info("Invalid put on user mailbox", e);
+            throw ErrorResponder.builder()
+                .statusCode(HttpStatus.NOT_FOUND_404)
+                .type(ErrorType.NOT_FOUND)
+                .message("Invalid get on user mailboxes")
+                .cause(e)
+                .haltError();
+        }
+
+        return new ClearMailboxContentTask(username, mailboxName, userMailboxesService);
+    }
 }
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/UserMailboxesService.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/UserMailboxesService.java
index dde29fe..f88c4c7 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/UserMailboxesService.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/UserMailboxesService.java
@@ -172,10 +172,18 @@ public class UserMailboxesService {
         }
     }
 
-    private void usernamePreconditions(Username username) throws UsersRepositoryException {
+    public void usernamePreconditions(Username username) throws UsersRepositoryException {
         Preconditions.checkState(usersRepository.contains(username), "User does not exist");
     }
 
+    public void mailboxExistPreconditions(Username username, MailboxName mailboxName) throws MailboxException {
+        MailboxSession mailboxSession = mailboxManager.createSystemSession(username);
+        MailboxPath mailboxPath = MailboxPath.forUser(username, mailboxName.asString())
+            .assertAcceptable(mailboxSession.getPathDelimiter());
+        Preconditions.checkState(Boolean.TRUE.equals(Mono.from(mailboxManager.mailboxExists(mailboxPath, mailboxSession)).block()),
+            "Mailbox does not exist. " + mailboxPath.asString());
+    }
+
     private Stream<MailboxMetaData> listUserMailboxes(MailboxSession mailboxSession) throws MailboxException {
         return mailboxManager.search(
             MailboxQuery.privateMailboxesBuilder(mailboxSession).build(),
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java
index 4fc7201..53fcf6e 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java
@@ -28,6 +28,7 @@ import static org.apache.james.webadmin.Constants.SEPARATOR;
 import static org.apache.james.webadmin.routes.UserMailboxesRoutes.USERS_BASE;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.eclipse.jetty.http.HttpStatus.BAD_REQUEST_400;
+import static org.eclipse.jetty.http.HttpStatus.CREATED_201;
 import static org.eclipse.jetty.http.HttpStatus.INTERNAL_SERVER_ERROR_500;
 import static org.eclipse.jetty.http.HttpStatus.NOT_FOUND_404;
 import static org.eclipse.jetty.http.HttpStatus.NO_CONTENT_204;
@@ -108,6 +109,8 @@ import org.apache.james.user.api.UsersRepositoryException;
 import org.apache.james.webadmin.WebAdminServer;
 import org.apache.james.webadmin.WebAdminUtils;
 import org.apache.james.webadmin.dto.WebAdminUserReindexingTaskAdditionalInformationDTO;
+import org.apache.james.webadmin.service.ClearMailboxContentTask;
+import org.apache.james.webadmin.service.ClearMailboxContentTaskAdditionalInformationDTO;
 import org.apache.james.webadmin.service.UserMailboxesService;
 import org.apache.james.webadmin.utils.JsonTransformer;
 import org.apache.mailbox.tools.indexer.ReIndexerImpl;
@@ -170,7 +173,8 @@ class UserMailboxesRoutesTest {
                     taskManager,
                     ImmutableSet.of(new UserMailboxesRoutes.UserReIndexingTaskRegistration(reIndexer))),
                 new TasksRoutes(taskManager, new JsonTransformer(),
-                    DTOConverter.of(WebAdminUserReindexingTaskAdditionalInformationDTO.serializationModule(mailboxIdFactory))))
+                    DTOConverter.of(WebAdminUserReindexingTaskAdditionalInformationDTO.serializationModule(mailboxIdFactory),
+                        ClearMailboxContentTaskAdditionalInformationDTO.SERIALIZATION_MODULE)))
             .start();
 
         RestAssured.requestSpecification = WebAdminUtils.buildRequestSpecification(webAdminServer)
@@ -1114,6 +1118,63 @@ class UserMailboxesRoutesTest {
                 .containsEntry("message", "Invalid get on user mailboxes")
                 .containsEntry("details", String.format("#private:%s:%s can not be found", USERNAME.asString(), MAILBOX_NAME));
         }
+
+        @Test
+        void deleteMailboxContentShouldReturnErrorWhenUserIsNotFound() throws UsersRepositoryException {
+            when(usersRepository.contains(USERNAME)).thenReturn(false);
+
+            Map<String, Object> errors = when()
+                .delete(MAILBOX_NAME + "/messages")
+            .then()
+                .statusCode(NOT_FOUND_404)
+                .contentType(JSON)
+                .extract()
+                .body()
+                .jsonPath()
+                .getMap(".");
+
+            assertThat(errors)
+                .containsEntry("statusCode", NOT_FOUND_404)
+                .containsEntry("type", ERROR_TYPE_NOTFOUND)
+                .containsEntry("message", "Invalid get on user mailboxes")
+                .containsEntry("details", "User does not exist");
+        }
+
+        @Test
+        void deleteMailboxContentShouldReturnErrorWhenMailboxDoesNotExist() {
+            Map<String, Object> errors = when()
+                .delete(MAILBOX_NAME + "/messages")
+            .then()
+                .statusCode(NOT_FOUND_404)
+                .contentType(JSON)
+                .extract()
+                .body()
+                .jsonPath()
+                .getMap(".");
+
+            assertThat(errors)
+                .containsEntry("statusCode", NOT_FOUND_404)
+                .containsEntry("type", ERROR_TYPE_NOTFOUND)
+                .containsEntry("message", "Invalid get on user mailboxes")
+                .containsEntry("details", String.format("Mailbox does not exist. #private:%s:%s", USERNAME.asString(), MAILBOX_NAME));
+        }
+
+        @Test
+        void deleteMailboxContentShouldReturnTaskId() {
+            with()
+                .put(MAILBOX_NAME);
+
+            String taskId = when()
+                .delete(MAILBOX_NAME + "/messages")
+            .then()
+                .statusCode(CREATED_201)
+                .extract()
+                .jsonPath()
+                .get("taskId");
+
+            assertThat(taskId)
+                .isNotEmpty();
+        }
     }
 
     @Nested
@@ -1804,6 +1865,135 @@ class UserMailboxesRoutesTest {
                 assertThat(searchIndex.retrieveIndexedFlags(mailbox, uid).blockOptional())
                     .isEmpty();
             }
+
+            @Test
+            void userReprocessingShouldReturnTaskDetailWhenDeleteMailboxContentWithNoEmail() {
+                with()
+                    .put(MAILBOX_NAME);
+
+                String taskId = when()
+                    .delete(MAILBOX_NAME + "/messages")
+                    .jsonPath()
+                    .get("taskId");
+
+                given()
+                    .basePath(TasksRoutes.BASE)
+                .when()
+                    .get(taskId + "/await")
+                .then()
+                    .body("status", Matchers.is("completed"))
+                    .body("taskId", Matchers.is(notNullValue()))
+                    .body("type", Matchers.is(ClearMailboxContentTask.TASK_TYPE.asString()))
+                    .body("startedDate", Matchers.is(notNullValue()))
+                    .body("submitDate", Matchers.is(notNullValue()))
+                    .body("completedDate", Matchers.is(notNullValue()))
+                    .body("additionalInformation.username", Matchers.is(USERNAME.asString()))
+                    .body("additionalInformation.mailboxName", Matchers.is(MAILBOX_NAME))
+                    .body("additionalInformation.messagesSuccessCount", Matchers.is(0))
+                    .body("additionalInformation.messagesFailCount", Matchers.is(0));
+            }
+
+            @Test
+            void userReprocessingShouldReturnTaskDetailWhenDeleteMailboxContentWithHasEmails() {
+                with()
+                    .put(MAILBOX_NAME);
+
+                MailboxPath mailboxPath = MailboxPath.forUser(USERNAME, MAILBOX_NAME);
+                MailboxSession systemSession = mailboxManager.createSystemSession(USERNAME);
+
+                IntStream.range(0, 10)
+                    .forEach(index -> {
+                        try {
+                            mailboxManager.getMailbox(mailboxPath, systemSession)
+                                .appendMessage(
+                                    MessageManager.AppendCommand.builder()
+                                        .build("header: value\r\n\r\nbody"),
+                                    systemSession);
+                        } catch (MailboxException e) {
+                            LOGGER.warn("Error when append message " + e);
+                        }
+                    });
+
+                String taskId = when()
+                    .delete(MAILBOX_NAME + "/messages")
+                    .jsonPath()
+                    .get("taskId");
+
+                given()
+                    .basePath(TasksRoutes.BASE)
+                .when()
+                    .get(taskId + "/await")
+                    .then()
+                    .body("status", Matchers.is("completed"))
+                    .body("taskId", Matchers.is(notNullValue()))
+                    .body("type", Matchers.is(ClearMailboxContentTask.TASK_TYPE.asString()))
+                    .body("startedDate", Matchers.is(notNullValue()))
+                    .body("submitDate", Matchers.is(notNullValue()))
+                    .body("completedDate", Matchers.is(notNullValue()))
+                    .body("additionalInformation.username", Matchers.is(USERNAME.asString()))
+                    .body("additionalInformation.mailboxName", Matchers.is(MAILBOX_NAME))
+                    .body("additionalInformation.messagesSuccessCount", Matchers.is(10))
+                    .body("additionalInformation.messagesFailCount", Matchers.is(0));
+            }
+
+            @Test
+            void userReprocessingShouldEmptyMailboxWhenDeleteMailboxContent() throws MailboxException {
+                with()
+                    .put(MAILBOX_NAME);
+
+                MailboxPath mailboxPath = MailboxPath.forUser(USERNAME, MAILBOX_NAME);
+                MailboxSession systemSession = mailboxManager.createSystemSession(USERNAME);
+
+                mailboxManager.getMailbox(mailboxPath, systemSession)
+                    .appendMessage(
+                        MessageManager.AppendCommand.builder()
+                            .build("header: value\r\n\r\nbody"),
+                        systemSession);
+
+                String taskId = when()
+                    .delete(MAILBOX_NAME + "/messages")
+                    .jsonPath()
+                    .get("taskId");
+
+                given()
+                    .basePath(TasksRoutes.BASE)
+                .when()
+                    .get(taskId + "/await");
+
+                assertThat(mailboxManager.getMailbox(mailboxPath, systemSession).getMailboxCounters(systemSession).getCount())
+                    .isEqualTo(0);
+            }
+
+            @Test
+            void userReprocessingShouldNotClearUnRelatedMailboxWhenDeleteMailboxContent() throws MailboxException {
+                with()
+                    .put(MAILBOX_NAME);
+
+                String unRelatedMailbox = "unRelatedMailbox";
+                with()
+                    .put(unRelatedMailbox);
+                MailboxPath mailboxPath = MailboxPath.forUser(USERNAME, unRelatedMailbox);
+                MailboxSession systemSession = mailboxManager.createSystemSession(USERNAME);
+
+                mailboxManager.getMailbox(mailboxPath, systemSession)
+                    .appendMessage(
+                        MessageManager.AppendCommand.builder()
+                            .build("header: value\r\n\r\nbody"),
+                        systemSession);
+
+                String taskId = when()
+                    .delete(MAILBOX_NAME + "/messages")
+                    .jsonPath()
+                    .get("taskId");
+
+                given()
+                    .basePath(TasksRoutes.BASE)
+                .when()
+                    .get(taskId + "/await");
+
+                assertThat(mailboxManager.getMailbox(mailboxPath, systemSession).getMailboxCounters(systemSession).getCount())
+                    .isEqualTo(1);
+            }
         }
 
         @Nested

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