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


The following commit(s) were added to refs/heads/master by this push:
     new c3150d0990 JAMES-3918 Force deletion of user mailboxes (#1608)
c3150d0990 is described below

commit c3150d09903a2acaa6c152c84552992708842f07
Author: Benoit TELLIER <btell...@linagora.com>
AuthorDate: Tue Jun 27 07:08:52 2023 +0200

    JAMES-3918 Force deletion of user mailboxes (#1608)
---
 .../docs/modules/ROOT/pages/operate/webadmin.adoc  |  9 +++--
 .../james/webadmin/routes/UserMailboxesRoutes.java | 23 +++++++----
 .../webadmin/service/UserMailboxesService.java     | 37 ++++++++++--------
 .../webadmin/routes/UserMailboxesRoutesTest.java   | 44 ++++++++++++++++++++--
 src/site/markdown/server/manage-webadmin.md        | 11 +++---
 5 files changed, 87 insertions(+), 37 deletions(-)

diff --git 
a/server/apps/distributed-app/docs/modules/ROOT/pages/operate/webadmin.adoc 
b/server/apps/distributed-app/docs/modules/ROOT/pages/operate/webadmin.adoc
index 703169ee12..46c5d00439 100644
--- a/server/apps/distributed-app/docs/modules/ROOT/pages/operate/webadmin.adoc
+++ b/server/apps/distributed-app/docs/modules/ROOT/pages/operate/webadmin.adoc
@@ -1691,7 +1691,7 @@ Response codes:
 
 * 204: The mailbox now exists on the server
 * 400: Invalid mailbox name
-* 404: The user name does not exist
+* 404: The user name does not exist. Note that this check can be bypassed by 
specifying the `force` query parameter.
 
 To create nested mailboxes, for instance a work mailbox inside the INBOX
 mailbox, people should use the . separator. The sample query is:
@@ -1713,7 +1713,7 @@ Response codes:
 
 * 204: The mailbox now does not exist on the server
 * 400: Invalid mailbox name
-* 404: The user name does not exist
+* 404: The user name does not exist. Note that this check can be bypassed by 
specifying the `force` query parameter.
 
 === Testing existence of a mailbox
 
@@ -1747,7 +1747,8 @@ Resource name `usernameToBeUsed` should be an existing 
user
 Response codes:
 
 * 200: The mailboxes list was successfully retrieved
-* 404: The user name does not exist
+* 404: The user name does not exist, the mailbox does not exist. Note that 
this check can be bypassed by specifying the `force` query parameter.
+
 
 === Deleting user mailboxes
 
@@ -1760,7 +1761,7 @@ Resource name `usernameToBeUsed` should be an existing 
user
 Response codes:
 
 * 204: The user do not have mailboxes anymore
-* 404: The user name does not exist
+* 404: The user name does not exist. Note that this check can be bypassed by 
specifying the `force` query parameter.
 
 === Exporting user mailboxes
 
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 365c8e80d0..30c813fe1a 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
@@ -73,6 +73,13 @@ public class UserMailboxesRoutes implements Routes {
         return Username.of(request.params(USER_NAME));
     }
 
+    private static UserMailboxesService.Options getOptions(Request request) {
+        if (request.queryParams().contains("force")) {
+            return UserMailboxesService.Options.Force;
+        }
+        return UserMailboxesService.Options.Check;
+    }
+
     public static final String MAILBOX_NAME = ":mailboxName";
     public static final String MAILBOXES = "mailboxes";
     private static final String USER_NAME = ":userName";
@@ -134,7 +141,7 @@ public class UserMailboxesRoutes implements Routes {
         service.get(USER_MAILBOXES_BASE, (request, response) -> {
             response.status(HttpStatus.OK_200);
             try {
-                return 
userMailboxesService.listMailboxes(getUsernameParam(request));
+                return 
userMailboxesService.listMailboxes(getUsernameParam(request), 
getOptions(request));
             } catch (IllegalStateException e) {
                 LOGGER.info("Invalid get on user mailboxes", e);
                 throw ErrorResponder.builder()
@@ -157,7 +164,7 @@ public class UserMailboxesRoutes implements Routes {
     public void defineDeleteUserMailbox() {
         service.delete(SPECIFIC_MAILBOX, (request, response) -> {
             try {
-                userMailboxesService.deleteMailbox(getUsernameParam(request), 
new MailboxName(request.params(MAILBOX_NAME)));
+                userMailboxesService.deleteMailbox(getUsernameParam(request), 
new MailboxName(request.params(MAILBOX_NAME)), getOptions(request));
                 return Responses.returnNoContent(response);
             } catch (IllegalStateException e) {
                 LOGGER.info("Invalid delete on user mailbox", e);
@@ -190,7 +197,7 @@ public class UserMailboxesRoutes implements Routes {
     public void defineDeleteUserMailboxes() {
         service.delete(USER_MAILBOXES_BASE, (request, response) -> {
             try {
-                
userMailboxesService.deleteMailboxes(getUsernameParam(request));
+                
userMailboxesService.deleteMailboxes(getUsernameParam(request), 
getOptions(request));
                 return Responses.returnNoContent(response);
             } catch (IllegalStateException e) {
                 LOGGER.info("Invalid delete on user mailboxes", e);
@@ -207,7 +214,7 @@ public class UserMailboxesRoutes implements Routes {
     public void defineMailboxExists() {
         service.get(SPECIFIC_MAILBOX, (request, response) -> {
             try {
-                if 
(userMailboxesService.testMailboxExists(getUsernameParam(request), new 
MailboxName(request.params(MAILBOX_NAME)))) {
+                if 
(userMailboxesService.testMailboxExists(getUsernameParam(request), new 
MailboxName(request.params(MAILBOX_NAME)), getOptions(request))) {
                     return Responses.returnNoContent(response);
                 } else {
                     throw ErrorResponder.builder()
@@ -239,7 +246,7 @@ public class UserMailboxesRoutes implements Routes {
     public void defineCreateUserMailbox() {
         service.put(SPECIFIC_MAILBOX, (request, response) -> {
             try {
-                userMailboxesService.createMailbox(getUsernameParam(request), 
new MailboxName(request.params(MAILBOX_NAME)));
+                userMailboxesService.createMailbox(getUsernameParam(request), 
new MailboxName(request.params(MAILBOX_NAME)), getOptions(request));
                 return Responses.returnNoContent(response);
             } catch (IllegalStateException e) {
                 LOGGER.info("Invalid put on user mailbox", e);
@@ -264,7 +271,7 @@ public class UserMailboxesRoutes implements Routes {
     public void messageCount() {
         service.get(MESSAGE_COUNT_PATH, (request, response) -> {
             try {
-                return 
userMailboxesService.messageCount(getUsernameParam(request), new 
MailboxName(request.params(MAILBOX_NAME)));
+                return 
userMailboxesService.messageCount(getUsernameParam(request), new 
MailboxName(request.params(MAILBOX_NAME)), getOptions(request));
             } catch (IllegalStateException | MailboxNotFoundException e) {
                 LOGGER.info("Invalid get on user mailbox", e);
                 throw ErrorResponder.builder()
@@ -288,7 +295,7 @@ public class UserMailboxesRoutes implements Routes {
     public void unseenMessageCount() {
         service.get(UNSEEN_MESSAGE_COUNT_PATH, (request, response) -> {
             try {
-                return 
userMailboxesService.unseenMessageCount(getUsernameParam(request), new 
MailboxName(request.params(MAILBOX_NAME)));
+                return 
userMailboxesService.unseenMessageCount(getUsernameParam(request), new 
MailboxName(request.params(MAILBOX_NAME)), getOptions(request));
             } catch (IllegalStateException | MailboxNotFoundException e) {
                 LOGGER.info("Invalid get on user mailbox", e);
                 throw ErrorResponder.builder()
@@ -313,7 +320,7 @@ public class UserMailboxesRoutes implements Routes {
         Username username = getUsernameParam(request);
         MailboxName mailboxName = new 
MailboxName(request.params(MAILBOX_NAME));
         try {
-            userMailboxesService.usernamePreconditions(username);
+            userMailboxesService.usernamePreconditions(username, 
getOptions(request));
             userMailboxesService.mailboxExistPreconditions(username, 
mailboxName);
         } catch (IllegalStateException e) {
             LOGGER.info("Invalid put on user mailbox", e);
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 e57048f5ac..6a0a120fad 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
@@ -56,6 +56,11 @@ import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
 
 public class UserMailboxesService {
+    public enum Options {
+        Force,
+        Check
+    }
+
     private static final Logger LOGGER = 
LoggerFactory.getLogger(UserMailboxesService.class);
 
     private final MailboxManager mailboxManager;
@@ -67,8 +72,8 @@ public class UserMailboxesService {
         this.usersRepository = usersRepository;
     }
 
-    public void createMailbox(Username username, MailboxName mailboxName) 
throws MailboxException, UsersRepositoryException {
-        usernamePreconditions(username);
+    public void createMailbox(Username username, MailboxName mailboxName, 
Options options) throws MailboxException, UsersRepositoryException {
+        usernamePreconditions(username, options);
         MailboxSession mailboxSession = 
mailboxManager.createSystemSession(username);
         try {
             MailboxPath mailboxPath = MailboxPath.forUser(username, 
mailboxName.asString())
@@ -80,8 +85,8 @@ public class UserMailboxesService {
         }
     }
 
-    public void deleteMailboxes(Username username) throws 
UsersRepositoryException {
-        usernamePreconditions(username);
+    public void deleteMailboxes(Username username, Options options) throws 
UsersRepositoryException {
+        usernamePreconditions(username, options);
         MailboxSession mailboxSession = 
mailboxManager.createSystemSession(username);
         listUserMailboxes(mailboxSession)
             .map(MailboxMetaData::getPath)
@@ -89,8 +94,8 @@ public class UserMailboxesService {
         mailboxManager.endProcessingRequest(mailboxSession);
     }
 
-    public List<MailboxResponse> listMailboxes(Username username) throws 
UsersRepositoryException {
-        usernamePreconditions(username);
+    public List<MailboxResponse> listMailboxes(Username username, Options 
options) throws UsersRepositoryException {
+        usernamePreconditions(username, options);
         MailboxSession mailboxSession = 
mailboxManager.createSystemSession(username);
         try {
             return listUserMailboxes(mailboxSession)
@@ -101,8 +106,8 @@ public class UserMailboxesService {
         }
     }
 
-    public boolean testMailboxExists(Username username, MailboxName 
mailboxName) throws MailboxException, UsersRepositoryException {
-        usernamePreconditions(username);
+    public boolean testMailboxExists(Username username, MailboxName 
mailboxName, Options options) throws MailboxException, UsersRepositoryException 
{
+        usernamePreconditions(username, options);
         MailboxSession mailboxSession = 
mailboxManager.createSystemSession(username);
         MailboxPath mailboxPath = MailboxPath.forUser(username, 
mailboxName.asString())
             .assertAcceptable(mailboxSession.getPathDelimiter());
@@ -142,8 +147,8 @@ public class UserMailboxesService {
             });
     }
 
-    public void deleteMailbox(Username username, MailboxName mailboxName) 
throws MailboxException, UsersRepositoryException, MailboxHaveChildrenException 
{
-        usernamePreconditions(username);
+    public void deleteMailbox(Username username, MailboxName mailboxName, 
Options options) throws MailboxException, UsersRepositoryException, 
MailboxHaveChildrenException {
+        usernamePreconditions(username, options);
         MailboxSession mailboxSession = 
mailboxManager.createSystemSession(username);
         MailboxPath mailboxPath = MailboxPath.forUser(username, 
mailboxName.asString())
             .assertAcceptable(mailboxSession.getPathDelimiter());
@@ -152,8 +157,8 @@ public class UserMailboxesService {
         mailboxManager.endProcessingRequest(mailboxSession);
     }
 
-    public long messageCount(Username username, MailboxName mailboxName) 
throws UsersRepositoryException, MailboxException {
-        usernamePreconditions(username);
+    public long messageCount(Username username, MailboxName mailboxName, 
Options options) throws UsersRepositoryException, MailboxException {
+        usernamePreconditions(username, options);
         MailboxSession mailboxSession = 
mailboxManager.createSystemSession(username);
         try {
             return mailboxManager.getMailbox(MailboxPath.forUser(username, 
mailboxName.asString()), mailboxSession).getMessageCount(mailboxSession);
@@ -162,8 +167,8 @@ public class UserMailboxesService {
         }
     }
 
-    public long unseenMessageCount(Username username, MailboxName mailboxName) 
throws UsersRepositoryException, MailboxException {
-        usernamePreconditions(username);
+    public long unseenMessageCount(Username username, MailboxName mailboxName, 
Options options) throws UsersRepositoryException, MailboxException {
+        usernamePreconditions(username, options);
         MailboxSession mailboxSession = 
mailboxManager.createSystemSession(username);
         try {
             return mailboxManager.getMailbox(MailboxPath.forUser(username, 
mailboxName.asString()), mailboxSession)
@@ -188,8 +193,8 @@ public class UserMailboxesService {
         }
     }
 
-    public void usernamePreconditions(Username username) throws 
UsersRepositoryException {
-        Preconditions.checkState(usersRepository.contains(username), "User 
does not exist");
+    public void usernamePreconditions(Username username, Options options) 
throws UsersRepositoryException {
+        Preconditions.checkState(options == Options.Force || 
usersRepository.contains(username), "User does not exist");
     }
 
     public void mailboxExistPreconditions(Username username, MailboxName 
mailboxName) throws MailboxException {
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 3fa93a7d3e..bcfd26095d 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
@@ -270,7 +270,7 @@ class UserMailboxesRoutesTest {
         }
 
         @Test
-        void putShouldThrowWhenMailboxNameWithDots() throws Exception {
+        void putShouldThrowWhenMailboxNameWithDots() {
             Map<String, Object> errors = when()
                 .put(MAILBOX_NAME_WITH_DOTS)
             .then()
@@ -352,7 +352,7 @@ class UserMailboxesRoutesTest {
             when(usersRepository.contains(USERNAME)).thenReturn(false);
 
             Map<String, Object> errors = when()
-                .put(MAILBOX_NAME)
+                .delete(MAILBOX_NAME)
             .then()
                 .statusCode(NOT_FOUND_404)
                 .contentType(JSON)
@@ -364,12 +364,36 @@ class UserMailboxesRoutesTest {
             assertThat(errors)
                 .containsEntry("statusCode", NOT_FOUND_404)
                 .containsEntry("type", ERROR_TYPE_NOTFOUND)
-                .containsEntry("message", "Invalid get on user mailboxes")
+                .containsEntry("message", "Invalid delete on user mailboxes")
                 .containsEntry("details", "User does not exist");
         }
 
         @Test
-        void getShouldReturnUserErrorWithInvalidWildcardMailboxName() throws 
Exception {
+        void putShouldReturn204WhenForceNonExistingUser() throws Exception {
+            when(usersRepository.contains(USERNAME)).thenReturn(false);
+
+            given()
+                .queryParam("force")
+            .when()
+                .put(MAILBOX_NAME)
+            .then()
+                .statusCode(NO_CONTENT_204);
+        }
+
+        @Test
+        void deleteShouldReturn204WhenForceNonExistingUser() throws Exception {
+            when(usersRepository.contains(USERNAME)).thenReturn(false);
+
+            given()
+                .queryParam("force")
+            .when()
+                .delete(MAILBOX_NAME)
+            .then()
+                .statusCode(NO_CONTENT_204);
+        }
+
+        @Test
+        void getShouldReturnUserErrorWithInvalidWildcardMailboxName() {
             Map<String, Object> errors = when()
                 .get(MAILBOX_NAME + "*")
             .then()
@@ -605,6 +629,18 @@ class UserMailboxesRoutesTest {
                 .containsEntry("message", "Invalid delete on user mailboxes");
         }
 
+        @Test
+        void deleteMailboxesShouldReturn204UserErrorWithNonExistingUser() 
throws Exception {
+            when(usersRepository.contains(USERNAME)).thenReturn(false);
+
+            given()
+                .queryParam("force")
+            .when()
+                .delete()
+            .then()
+                .statusCode(NO_CONTENT_204);
+        }
+
         @Test
         void getMailboxesShouldReturnEmptyListByDefault() {
             List<Object> list =
diff --git a/src/site/markdown/server/manage-webadmin.md 
b/src/site/markdown/server/manage-webadmin.md
index 9c76eb5ce0..48c5614a7d 100644
--- a/src/site/markdown/server/manage-webadmin.md
+++ b/src/site/markdown/server/manage-webadmin.md
@@ -1356,7 +1356,8 @@ by an admin to ensure Cassandra message consistency.
  - [Recomputing User JMAP fast message view 
projection](#Recomputing_User_JMAP_fast_message_view_projection)
  - [Counting emails](#Counting_emails)
  - [Counting unseen emails](#Couting_unseen_emails)
- - [Clearing mailbox content][#Clearing_mailbox_content]   
+ - [Clearing mailbox content][#Clearing_mailbox_content]
+
 ### Creating a mailbox
 
 ```
@@ -1370,7 +1371,7 @@ Response codes:
 
  - 204: The mailbox now exists on the server
  - 400: Invalid mailbox name
- - 404: The user name does not exist
+ - 404: The user name does not exist. Note that this check can be bypassed by 
specifying the `force` query parameter.
 
  To create nested mailboxes, for instance a work mailbox inside the INBOX 
mailbox, people should use the . separator. The sample query is:
 
@@ -1391,7 +1392,7 @@ Response codes:
 
  - 204: The mailbox now does not exist on the server
  - 400: Invalid mailbox name
- - 404: The user name does not exist
+ - 404: The user name does not exist. Note that this check can be bypassed by 
specifying the `force` query parameter.
 
 ### Testing existence of a mailbox
 
@@ -1425,7 +1426,7 @@ Resource name `usernameToBeUsed` should be an existing 
user
 Response codes:
 
  - 200: The mailboxes list was successfully retrieved
- - 404: The user name does not exist
+ - 404: The user name does not exist. Note that this check can be bypassed by 
specifying the `force` query parameter.
 
 ### Deleting user mailboxes
 
@@ -1438,7 +1439,7 @@ Resource name `usernameToBeUsed` should be an existing 
user
 Response codes:
 
  - 204: The user do not have mailboxes anymore
- - 404: The user name does not exist
+ - 404: The user name does not exist. Note that this check can be bypassed by 
specifying the `force` query parameter.
 
 ### Exporting user mailboxes
 


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

Reply via email to