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/05/25 05:45:00 UTC
[james-project] branch master updated: JAMES-3909 Mailboxes deletion step (#1571)
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 d7e717632e JAMES-3909 Mailboxes deletion step (#1571)
d7e717632e is described below
commit d7e717632ea2de8efa4e7ac05df54b7be7a58cec
Author: Trần Hồng Quân <55...@users.noreply.github.com>
AuthorDate: Thu May 25 12:44:54 2023 +0700
JAMES-3909 Mailboxes deletion step (#1571)
Delete mailboxes + messages + ACLs + subscriptions upon user data deletion.
---
.../modules/mailbox/CassandraMailboxModule.java | 5 +
.../james/modules/mailbox/JPAMailboxModule.java | 5 +
.../james/modules/mailbox/MemoryMailboxModule.java | 5 +
.../mailbox/MailboxUserDeletionTaskStep.java | 109 +++++++++++
.../mailbox/MailboxUserDeletionTaskStepTest.java | 212 +++++++++++++++++++++
.../memory/MemoryUserDeletionIntegrationTest.java | 111 +++++++++++
6 files changed, 447 insertions(+)
diff --git a/server/container/guice/cassandra/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java b/server/container/guice/cassandra/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java
index 174ed29b0b..81e6f3d411 100644
--- a/server/container/guice/cassandra/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java
+++ b/server/container/guice/cassandra/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java
@@ -23,6 +23,7 @@ import static org.apache.james.modules.Names.MAILBOXMANAGER_NAME;
import javax.inject.Singleton;
import org.apache.james.adapter.mailbox.ACLUsernameChangeTaskStep;
+import org.apache.james.adapter.mailbox.MailboxUserDeletionTaskStep;
import org.apache.james.adapter.mailbox.MailboxUsernameChangeTaskStep;
import org.apache.james.adapter.mailbox.QuotaUsernameChangeTaskStep;
import org.apache.james.adapter.mailbox.UserRepositoryAuthenticator;
@@ -117,6 +118,7 @@ import org.apache.james.mailbox.store.mail.ModSeqProvider;
import org.apache.james.mailbox.store.mail.ThreadIdGuessingAlgorithm;
import org.apache.james.mailbox.store.mail.UidProvider;
import org.apache.james.mailbox.store.user.SubscriptionMapperFactory;
+import org.apache.james.user.api.DeleteUserDataTaskStep;
import org.apache.james.user.api.UsernameChangeTaskStep;
import org.apache.james.utils.MailboxManagerDefinition;
import org.apache.mailbox.tools.indexer.MessageIdReIndexerImpl;
@@ -250,6 +252,9 @@ public class CassandraMailboxModule extends AbstractModule {
usernameChangeTaskStepMultibinder.addBinding().to(MailboxUsernameChangeTaskStep.class);
usernameChangeTaskStepMultibinder.addBinding().to(ACLUsernameChangeTaskStep.class);
usernameChangeTaskStepMultibinder.addBinding().to(QuotaUsernameChangeTaskStep.class);
+
+ Multibinder<DeleteUserDataTaskStep> deleteUserDataTaskStepMultibinder = Multibinder.newSetBinder(binder(), DeleteUserDataTaskStep.class);
+ deleteUserDataTaskStepMultibinder.addBinding().to(MailboxUserDeletionTaskStep.class);
}
@Provides
diff --git a/server/container/guice/mailbox-jpa/src/main/java/org/apache/james/modules/mailbox/JPAMailboxModule.java b/server/container/guice/mailbox-jpa/src/main/java/org/apache/james/modules/mailbox/JPAMailboxModule.java
index 5bf648d6d8..f56415cb62 100644
--- a/server/container/guice/mailbox-jpa/src/main/java/org/apache/james/modules/mailbox/JPAMailboxModule.java
+++ b/server/container/guice/mailbox-jpa/src/main/java/org/apache/james/modules/mailbox/JPAMailboxModule.java
@@ -23,6 +23,7 @@ import static org.apache.james.modules.Names.MAILBOXMANAGER_NAME;
import javax.inject.Singleton;
import org.apache.james.adapter.mailbox.ACLUsernameChangeTaskStep;
+import org.apache.james.adapter.mailbox.MailboxUserDeletionTaskStep;
import org.apache.james.adapter.mailbox.MailboxUsernameChangeTaskStep;
import org.apache.james.adapter.mailbox.QuotaUsernameChangeTaskStep;
import org.apache.james.adapter.mailbox.UserRepositoryAuthenticator;
@@ -62,6 +63,7 @@ import org.apache.james.mailbox.store.mail.UidProvider;
import org.apache.james.mailbox.store.mail.model.DefaultMessageId;
import org.apache.james.mailbox.store.user.SubscriptionMapperFactory;
import org.apache.james.modules.data.JPAEntityManagerModule;
+import org.apache.james.user.api.DeleteUserDataTaskStep;
import org.apache.james.user.api.UsernameChangeTaskStep;
import org.apache.james.utils.MailboxManagerDefinition;
import org.apache.mailbox.tools.indexer.ReIndexerImpl;
@@ -130,6 +132,9 @@ public class JPAMailboxModule extends AbstractModule {
usernameChangeTaskStepMultibinder.addBinding().to(MailboxUsernameChangeTaskStep.class);
usernameChangeTaskStepMultibinder.addBinding().to(ACLUsernameChangeTaskStep.class);
usernameChangeTaskStepMultibinder.addBinding().to(QuotaUsernameChangeTaskStep.class);
+
+ Multibinder<DeleteUserDataTaskStep> deleteUserDataTaskStepMultibinder = Multibinder.newSetBinder(binder(), DeleteUserDataTaskStep.class);
+ deleteUserDataTaskStepMultibinder.addBinding().to(MailboxUserDeletionTaskStep.class);
}
@Singleton
diff --git a/server/container/guice/memory/src/main/java/org/apache/james/modules/mailbox/MemoryMailboxModule.java b/server/container/guice/memory/src/main/java/org/apache/james/modules/mailbox/MemoryMailboxModule.java
index 61083eb515..0eddc3cc35 100644
--- a/server/container/guice/memory/src/main/java/org/apache/james/modules/mailbox/MemoryMailboxModule.java
+++ b/server/container/guice/memory/src/main/java/org/apache/james/modules/mailbox/MemoryMailboxModule.java
@@ -25,6 +25,7 @@ import javax.inject.Singleton;
import org.apache.james.adapter.mailbox.ACLUsernameChangeTaskStep;
import org.apache.james.adapter.mailbox.DelegationStoreAuthorizator;
+import org.apache.james.adapter.mailbox.MailboxUserDeletionTaskStep;
import org.apache.james.adapter.mailbox.MailboxUsernameChangeTaskStep;
import org.apache.james.adapter.mailbox.QuotaUsernameChangeTaskStep;
import org.apache.james.adapter.mailbox.UserRepositoryAuthenticator;
@@ -75,6 +76,7 @@ import org.apache.james.mailbox.store.mail.UidProvider;
import org.apache.james.mailbox.store.search.MessageSearchIndex;
import org.apache.james.mailbox.store.search.SimpleMessageSearchIndex;
import org.apache.james.mailbox.store.user.SubscriptionMapperFactory;
+import org.apache.james.user.api.DeleteUserDataTaskStep;
import org.apache.james.user.api.UsernameChangeTaskStep;
import org.apache.james.utils.MailboxManagerDefinition;
import org.apache.james.vault.memory.metadata.MemoryDeletedMessageMetadataVault;
@@ -162,6 +164,9 @@ public class MemoryMailboxModule extends AbstractModule {
usernameChangeTaskStepMultibinder.addBinding().to(MailboxUsernameChangeTaskStep.class);
usernameChangeTaskStepMultibinder.addBinding().to(ACLUsernameChangeTaskStep.class);
usernameChangeTaskStepMultibinder.addBinding().to(QuotaUsernameChangeTaskStep.class);
+
+ Multibinder<DeleteUserDataTaskStep> deleteUserDataTaskStepMultibinder = Multibinder.newSetBinder(binder(), DeleteUserDataTaskStep.class);
+ deleteUserDataTaskStepMultibinder.addBinding().to(MailboxUserDeletionTaskStep.class);
}
@Singleton
diff --git a/server/container/mailbox-adapter/src/main/java/org/apache/james/adapter/mailbox/MailboxUserDeletionTaskStep.java b/server/container/mailbox-adapter/src/main/java/org/apache/james/adapter/mailbox/MailboxUserDeletionTaskStep.java
new file mode 100644
index 0000000000..035686decf
--- /dev/null
+++ b/server/container/mailbox-adapter/src/main/java/org/apache/james/adapter/mailbox/MailboxUserDeletionTaskStep.java
@@ -0,0 +1,109 @@
+/****************************************************************
+ * 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.adapter.mailbox;
+
+import java.util.Optional;
+
+import javax.inject.Inject;
+
+import org.apache.james.core.Username;
+import org.apache.james.mailbox.MailboxManager;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.SubscriptionManager;
+import org.apache.james.mailbox.model.Mailbox;
+import org.apache.james.mailbox.model.MailboxACL;
+import org.apache.james.mailbox.model.MailboxMetaData;
+import org.apache.james.mailbox.model.search.MailboxQuery;
+import org.apache.james.mailbox.store.StoreMailboxManager;
+import org.apache.james.user.api.DeleteUserDataTaskStep;
+import org.apache.james.util.ReactorUtils;
+import org.reactivestreams.Publisher;
+
+import com.github.fge.lambdas.Throwing;
+
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+public class MailboxUserDeletionTaskStep implements DeleteUserDataTaskStep {
+ private final StoreMailboxManager mailboxManager;
+ private final SubscriptionManager subscriptionManager;
+
+ @Inject
+ public MailboxUserDeletionTaskStep(StoreMailboxManager mailboxManager, SubscriptionManager subscriptionManager) {
+ this.mailboxManager = mailboxManager;
+ this.subscriptionManager = subscriptionManager;
+ }
+
+ @Override
+ public StepName name() {
+ return new StepName("MailboxUserDeletionTaskStep");
+ }
+
+ @Override
+ public int priority() {
+ return 5;
+ }
+
+ @Override
+ public Publisher<Void> deleteUserData(Username username) {
+ MailboxSession mailboxSession = mailboxManager.createSystemSession(username);
+
+ return getAllMailboxesOfUser(mailboxSession)
+ .concatMap(mailbox -> deleteMailbox(mailboxSession, mailbox)
+ .then(deleteSubscription(mailboxSession, mailbox)))
+ .then(getSharedMailboxesOfUser(mailboxSession)
+ .flatMap(sharedMailbox -> revokeACLs(username, sharedMailbox)
+ .then(deleteSubscription(mailboxSession, sharedMailbox)))
+ .then());
+ }
+
+ private Flux<MailboxMetaData> getAllMailboxesOfUser(MailboxSession mailboxSession) {
+ MailboxQuery queryMailboxesOfUser = MailboxQuery.builder()
+ .privateNamespace()
+ .user(mailboxSession.getUser())
+ .build();
+
+ return mailboxManager.search(queryMailboxesOfUser, MailboxManager.MailboxSearchFetchType.Minimal, mailboxSession);
+ }
+
+ private Flux<MailboxMetaData> getSharedMailboxesOfUser(MailboxSession mailboxSession) {
+ return mailboxManager.search(MailboxQuery.builder().matchesAllMailboxNames().build(), mailboxSession)
+ .filter(mailbox -> !mailbox.getPath().getUser().equals(mailboxSession.getUser()));
+ }
+
+ private Mono<Mailbox> deleteMailbox(MailboxSession mailboxSession, MailboxMetaData mailbox) {
+ return mailboxManager.deleteMailboxReactive(mailbox.getId(), mailboxSession);
+ }
+
+ private Mono<Void> deleteSubscription(MailboxSession mailboxSession, MailboxMetaData mailbox) {
+ return Mono.from(subscriptionManager.unsubscribeReactive(mailbox.getPath(), mailboxSession));
+ }
+
+ private Mono<Void> revokeACLs(Username username, MailboxMetaData mailbox) {
+ MailboxSession ownerSession = mailboxManager.createSystemSession(mailbox.getPath().getUser());
+ MailboxACL.Rfc4314Rights rights = Optional.ofNullable(mailbox.getMailbox().getACL().getEntries().get(MailboxACL.EntryKey.createUserEntryKey(username)))
+ .orElse(MailboxACL.NO_RIGHTS);
+
+ return Mono.fromRunnable(Throwing.runnable(() -> mailboxManager.applyRightsCommand(mailbox.getId(), MailboxACL.command().rights(rights).forUser(username).asRemoval(), ownerSession)))
+ .subscribeOn(ReactorUtils.BLOCKING_CALL_WRAPPER)
+ .then();
+ }
+
+}
diff --git a/server/container/mailbox-adapter/src/test/java/org/apache/james/adapter/mailbox/MailboxUserDeletionTaskStepTest.java b/server/container/mailbox-adapter/src/test/java/org/apache/james/adapter/mailbox/MailboxUserDeletionTaskStepTest.java
new file mode 100644
index 0000000000..4040a4050b
--- /dev/null
+++ b/server/container/mailbox-adapter/src/test/java/org/apache/james/adapter/mailbox/MailboxUserDeletionTaskStepTest.java
@@ -0,0 +1,212 @@
+/****************************************************************
+ * 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.adapter.mailbox;
+
+import static org.apache.james.mailbox.MailboxManager.MailboxSearchFetchType.Minimal;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
+
+import org.apache.james.core.Username;
+import org.apache.james.mailbox.MailboxManager;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.MessageManager;
+import org.apache.james.mailbox.inmemory.InMemoryMailboxManager;
+import org.apache.james.mailbox.inmemory.manager.InMemoryIntegrationResources;
+import org.apache.james.mailbox.model.MailboxACL;
+import org.apache.james.mailbox.model.MailboxMetaData;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.MultimailboxesSearchQuery;
+import org.apache.james.mailbox.model.SearchQuery;
+import org.apache.james.mailbox.model.search.MailboxQuery;
+import org.apache.james.mailbox.store.StoreSubscriptionManager;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import reactor.core.publisher.Mono;
+
+class MailboxUserDeletionTaskStepTest {
+ private static final Username ALICE = Username.of("alice");
+ private static final Username BOB = Username.of("bob");
+
+ private InMemoryMailboxManager mailboxManager;
+ private StoreSubscriptionManager subscriptionManager;
+ private MailboxUserDeletionTaskStep testee;
+
+ @BeforeEach
+ void setUp() {
+ InMemoryIntegrationResources resources = InMemoryIntegrationResources.defaultResources();
+ mailboxManager = resources.getMailboxManager();
+ subscriptionManager = new StoreSubscriptionManager(resources.getMailboxManager().getMapperFactory(), resources.getMailboxManager().getMapperFactory(),
+ resources.getEventBus());
+ testee = new MailboxUserDeletionTaskStep(mailboxManager, subscriptionManager);
+ }
+
+ @Test
+ void shouldRemoveSubscriptionsOnMailboxes() throws Exception {
+ MailboxSession session = mailboxManager.createSystemSession(ALICE);
+ mailboxManager.createMailbox(MailboxPath.forUser(ALICE, "subscribed1"), MailboxManager.CreateOption.CREATE_SUBSCRIPTION, session);
+ mailboxManager.createMailbox(MailboxPath.forUser(ALICE, "subscribed2"), MailboxManager.CreateOption.CREATE_SUBSCRIPTION, session);
+
+ Mono.from(testee.deleteUserData(ALICE)).block();
+
+ assertThat(subscriptionManager.subscriptions(session)).isEmpty();
+ }
+
+ @Test
+ void shouldRemoveSubscriptionsOnSubMailboxes() throws Exception {
+ MailboxSession session = mailboxManager.createSystemSession(ALICE);
+ mailboxManager.createMailbox(MailboxPath.forUser(ALICE, "parent"), MailboxManager.CreateOption.CREATE_SUBSCRIPTION, session);
+ mailboxManager.createMailbox(MailboxPath.forUser(ALICE, "parent.child1"), MailboxManager.CreateOption.CREATE_SUBSCRIPTION, session);
+ mailboxManager.createMailbox(MailboxPath.forUser(ALICE, "parent.child2"), MailboxManager.CreateOption.CREATE_SUBSCRIPTION, session);
+
+ Mono.from(testee.deleteUserData(ALICE)).block();
+
+ assertThat(subscriptionManager.subscriptions(session)).isEmpty();
+ }
+
+ @Test
+ void shouldRemoveSubscriptionsOnSharedMailboxes() throws Exception {
+ // BOB shares his Inbox access to ALICE
+ MailboxSession bobSession = mailboxManager.createSystemSession(BOB);
+ mailboxManager.createMailbox(MailboxPath.inbox(BOB), MailboxManager.CreateOption.NONE, bobSession);
+ mailboxManager.applyRightsCommand(MailboxPath.inbox(BOB),
+ MailboxACL.command().forUser(ALICE).rights(MailboxACL.FULL_RIGHTS).asAddition(),
+ bobSession);
+
+ // ALICE subscribes to BOB Inbox
+ subscriptionManager.subscribe(mailboxManager.createSystemSession(ALICE), MailboxPath.inbox(BOB));
+
+ Mono.from(testee.deleteUserData(ALICE)).block();
+
+ // ALICE subscription on the shared mailbox should be deleted
+ assertThat(subscriptionManager.subscriptions(mailboxManager.createSystemSession(ALICE)))
+ .isEmpty();
+ }
+
+ @Test
+ void shouldRemoveMailboxes() throws Exception {
+ MailboxSession session = mailboxManager.createSystemSession(ALICE);
+ mailboxManager.createMailbox(MailboxPath.inbox(ALICE), MailboxManager.CreateOption.NONE, session);
+ mailboxManager.createMailbox(MailboxPath.forUser(ALICE, "test"), MailboxManager.CreateOption.NONE, session);
+
+ Mono.from(testee.deleteUserData(ALICE)).block();
+
+ assertThat(mailboxManager.list(session))
+ .isEmpty();
+ }
+
+ @Test
+ void shouldRemoveMessagesInMailboxes() throws Exception {
+ MailboxSession session = mailboxManager.createSystemSession(ALICE);
+ mailboxManager.createMailbox(MailboxPath.inbox(ALICE), MailboxManager.CreateOption.NONE, session);
+ mailboxManager.getMailbox(MailboxPath.inbox(ALICE), session)
+ .appendMessage(MessageManager.AppendCommand.builder()
+ .build("message content"), session);
+
+ Mono.from(testee.deleteUserData(ALICE)).block();
+
+ assertThat(mailboxManager.search(MultimailboxesSearchQuery.from(SearchQuery.matchAll()).build(), session, 100L)
+ .collectList().block())
+ .isEmpty();
+ }
+
+ @Test
+ void shouldRemoveSubMailboxes() throws Exception {
+ MailboxSession session = mailboxManager.createSystemSession(ALICE);
+ mailboxManager.createMailbox(MailboxPath.forUser(ALICE, "parent"), MailboxManager.CreateOption.NONE, session);
+ mailboxManager.createMailbox(MailboxPath.forUser(ALICE, "parent.child1"), MailboxManager.CreateOption.NONE, session);
+ mailboxManager.createMailbox(MailboxPath.forUser(ALICE, "parent.child2"), MailboxManager.CreateOption.NONE, session);
+
+ Mono.from(testee.deleteUserData(ALICE)).block();
+
+ assertThat(mailboxManager.list(session))
+ .isEmpty();
+ }
+
+ @Test
+ void shouldRemoveMessagesInSubMailboxes() throws Exception {
+ MailboxSession session = mailboxManager.createSystemSession(ALICE);
+ mailboxManager.createMailbox(MailboxPath.forUser(ALICE, "parent.child1"), MailboxManager.CreateOption.NONE, session);
+ mailboxManager.getMailbox(MailboxPath.forUser(ALICE, "parent.child1"), session)
+ .appendMessage(MessageManager.AppendCommand.builder()
+ .build("message content"), session);
+
+ Mono.from(testee.deleteUserData(ALICE)).block();
+
+ assertThat(mailboxManager.search(MultimailboxesSearchQuery.from(SearchQuery.matchAll()).build(), session, 100L)
+ .collectList().block())
+ .isEmpty();
+ }
+
+ @Test
+ void shouldNotRemoveMailboxesOfOtherUsers() throws Exception {
+ MailboxSession bobSession = mailboxManager.createSystemSession(BOB);
+ mailboxManager.createMailbox(MailboxPath.inbox(BOB), MailboxManager.CreateOption.NONE, bobSession);
+
+ Mono.from(testee.deleteUserData(ALICE)).block();
+
+ assertThat(mailboxManager.list(bobSession))
+ .containsOnly(MailboxPath.inbox(BOB));
+ }
+
+ @Test
+ void shouldNotRemoveSubscriptionsOnMailboxesOfOtherUsers() throws Exception {
+ MailboxSession bobSession = mailboxManager.createSystemSession(BOB);
+ mailboxManager.createMailbox(MailboxPath.forUser(BOB, "subscribed"), MailboxManager.CreateOption.CREATE_SUBSCRIPTION, bobSession);
+
+ Mono.from(testee.deleteUserData(ALICE)).block();
+
+ assertThat(subscriptionManager.subscriptions(bobSession))
+ .containsOnly(MailboxPath.forUser(BOB, "subscribed"));
+ }
+
+ @Test
+ void shouldRevokeRightsOnSharedMailboxes() throws Exception {
+ // BOB creates Inbox
+ MailboxSession bobSession = mailboxManager.createSystemSession(BOB);
+ mailboxManager.createMailbox(MailboxPath.inbox(BOB), MailboxManager.CreateOption.NONE, bobSession);
+
+ // BOB shares his Inbox access to ALICE
+ mailboxManager.applyRightsCommand(MailboxPath.inbox(BOB),
+ MailboxACL.command().forUser(ALICE).rights(MailboxACL.FULL_RIGHTS).asAddition(),
+ bobSession);
+
+ Mono.from(testee.deleteUserData(ALICE)).block();
+
+ // Alice ACL on the shared mailbox should be no longer existed
+ MailboxSession aliceSession = mailboxManager.createSystemSession(ALICE);
+
+ assertThat(mailboxManager.search(MailboxQuery.builder().matchesAllMailboxNames().build(), Minimal, aliceSession)
+ .map(MailboxMetaData::getPath)
+ .collectList()
+ .block())
+ .isEmpty();
+ assertThat(mailboxManager.hasRight(MailboxPath.inbox(BOB), MailboxACL.Right.Read, aliceSession))
+ .isFalse();
+ }
+
+ @Test
+ void shouldBeIdempotent() {
+ Mono.from(testee.deleteUserData(ALICE)).block();
+
+ assertThatCode(() -> Mono.from(testee.deleteUserData(ALICE)).block())
+ .doesNotThrowAnyException();
+ }
+}
diff --git a/server/protocols/webadmin-integration-test/memory-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/memory/MemoryUserDeletionIntegrationTest.java b/server/protocols/webadmin-integration-test/memory-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/memory/MemoryUserDeletionIntegrationTest.java
new file mode 100644
index 0000000000..40659bbac7
--- /dev/null
+++ b/server/protocols/webadmin-integration-test/memory-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/memory/MemoryUserDeletionIntegrationTest.java
@@ -0,0 +1,111 @@
+/****************************************************************
+ * 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.integration.memory;
+
+import static org.apache.james.data.UsersRepositoryModuleChooser.Implementation.DEFAULT;
+import static org.apache.james.jmap.JMAPTestingConstants.ALICE;
+import static org.apache.james.jmap.JMAPTestingConstants.ALICE_PASSWORD;
+import static org.apache.james.jmap.JMAPTestingConstants.BOB;
+import static org.apache.james.jmap.JMAPTestingConstants.BOB_PASSWORD;
+import static org.apache.james.jmap.JMAPTestingConstants.DOMAIN;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.Matchers.hasSize;
+
+import org.apache.james.GuiceJamesServer;
+import org.apache.james.JamesServerBuilder;
+import org.apache.james.JamesServerExtension;
+import org.apache.james.MemoryJamesConfiguration;
+import org.apache.james.MemoryJamesServerMain;
+import org.apache.james.mailbox.model.MailboxACL;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.modules.ACLProbeImpl;
+import org.apache.james.modules.MailboxProbeImpl;
+import org.apache.james.modules.TestJMAPServerModule;
+import org.apache.james.probe.DataProbe;
+import org.apache.james.utils.DataProbeImpl;
+import org.apache.james.utils.WebAdminGuiceProbe;
+import org.apache.james.webadmin.WebAdminUtils;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import io.restassured.specification.RequestSpecification;
+
+class MemoryUserDeletionIntegrationTest {
+ @RegisterExtension
+ static JamesServerExtension jamesServerExtension = new JamesServerBuilder<MemoryJamesConfiguration>(tmpDir ->
+ MemoryJamesConfiguration.builder()
+ .workingDirectory(tmpDir)
+ .configurationFromClasspath()
+ .usersRepository(DEFAULT)
+ .build())
+ .server(configuration -> MemoryJamesServerMain.createServer(configuration)
+ .overrideWith(new TestJMAPServerModule()))
+ .build();
+
+ private RequestSpecification webAdminApi;
+
+ @BeforeEach
+ void setUp(GuiceJamesServer jmapServer) throws Exception {
+ DataProbe dataProbe = jmapServer.getProbe(DataProbeImpl.class);
+ dataProbe.addDomain(DOMAIN);
+ dataProbe.addUser(ALICE.asString(), ALICE_PASSWORD);
+ dataProbe.addUser(BOB.asString(), BOB_PASSWORD);
+
+ webAdminApi = WebAdminUtils.spec(jmapServer.getProbe(WebAdminGuiceProbe.class).getWebAdminPort());
+ }
+
+ @Test
+ void shouldDeleteMailboxes() {
+ webAdminApi.put("/users/" + ALICE.asString() + "/mailboxes/test");
+
+ String taskId = webAdminApi
+ .queryParam("action", "deleteData")
+ .post("/users/" + ALICE.asString())
+ .jsonPath()
+ .get("taskId");
+
+ webAdminApi.get("/tasks/" + taskId + "/await");
+
+ webAdminApi.get("/users/" + ALICE.asString() + "/mailboxes")
+ .then()
+ .body(".", hasSize(0));
+ }
+
+ @Test
+ void shouldDeleteACLs(GuiceJamesServer server) throws Exception {
+ server.getProbe(MailboxProbeImpl.class).createMailbox(MailboxPath.inbox(BOB));
+ server.getProbe(ACLProbeImpl.class).addRights(MailboxPath.inbox(BOB), ALICE.asString(), MailboxACL.FULL_RIGHTS);
+
+ String taskId = webAdminApi
+ .queryParam("action", "deleteData")
+ .post("/users/" + ALICE.asString())
+ .jsonPath()
+ .get("taskId");
+
+ webAdminApi.get("/tasks/" + taskId + "/await");
+
+ // Bob Inbox should no longer accept Alice access
+ MailboxACL acls = server.getProbe(ACLProbeImpl.class).retrieveRights(MailboxPath.inbox(BOB));
+ assertThat(acls.getEntries())
+ .hasSize(1)
+ .containsEntry(MailboxACL.EntryKey.deserialize("owner"), MailboxACL.FULL_RIGHTS);
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org