You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by bt...@apache.org on 2023/06/28 13:59:15 UTC
[james-project] branch 3.8.x updated: JAMES-3918 Force deletion of user mailboxes (#1608) (#1611)
This is an automated email from the ASF dual-hosted git repository.
btellier pushed a commit to branch 3.8.x
in repository https://gitbox.apache.org/repos/asf/james-project.git
The following commit(s) were added to refs/heads/3.8.x by this push:
new df07cd2ea6 JAMES-3918 Force deletion of user mailboxes (#1608) (#1611)
df07cd2ea6 is described below
commit df07cd2ea68e3b4f49917dad20f5e3abe8a2f26d
Author: Benoit TELLIER <bt...@linagora.com>
AuthorDate: Wed Jun 28 15:59:09 2023 +0200
JAMES-3918 Force deletion of user mailboxes (#1608) (#1611)
---
.../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 2449073d27..04c05b3db7 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
@@ -1610,7 +1610,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:
@@ -1632,7 +1632,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
@@ -1666,7 +1666,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
@@ -1679,7 +1680,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 f091d3c0a3..b630db5611 100644
--- a/src/site/markdown/server/manage-webadmin.md
+++ b/src/site/markdown/server/manage-webadmin.md
@@ -1272,7 +1272,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
```
@@ -1286,7 +1287,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:
@@ -1307,7 +1308,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
@@ -1341,7 +1342,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
@@ -1354,7 +1355,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-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org