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 <55171818+quantranhong1...@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-unsubscr...@james.apache.org For additional commands, e-mail: notifications-h...@james.apache.org