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
commit bffdedf5e3c27a0e1861e377644f064b0c122493 Author: duc91 <duc91....@gmail.com> AuthorDate: Tue Jun 16 16:57:26 2020 +0700 JAMES-3212: handle subcrible/unsubcrible child's folder when update mailbox --- .../org/apache/james/mailbox/MailboxManager.java | 58 +++++- .../apache/james/mailbox/MailboxManagerTest.java | 197 +++++++++++++++++++++ .../cassandra/CassandraMailboxManagerTest.java | 7 + .../james/mailbox/jpa/JPAMailboxManagerTest.java | 7 + .../DomainUserMaildirMailboxManagerTest.java | 21 ++- .../maildir/FullUserMaildirMailboxManagerTest.java | 18 ++ .../mailbox/inmemory/MemoryMailboxManagerTest.java | 7 + .../james/mailbox/store/MailboxReactorUtils.java | 7 +- .../james/mailbox/store/StoreMailboxManager.java | 149 ++++++++++------ .../integration/SetMailboxesMethodTest.java | 145 ++++++++++++++- .../draft/methods/SetMailboxesUpdateProcessor.java | 14 +- .../methods/SetMessagesCreationProcessor.java | 2 +- .../methods/SetMailboxesUpdateProcessorTest.java | 5 +- 13 files changed, 553 insertions(+), 84 deletions(-) diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/MailboxManager.java b/mailbox/api/src/main/java/org/apache/james/mailbox/MailboxManager.java index ee859af..1b235bd 100644 --- a/mailbox/api/src/main/java/org/apache/james/mailbox/MailboxManager.java +++ b/mailbox/api/src/main/java/org/apache/james/mailbox/MailboxManager.java @@ -21,6 +21,7 @@ package org.apache.james.mailbox; import java.util.EnumSet; import java.util.List; +import java.util.Objects; import java.util.Optional; import org.apache.james.mailbox.exception.MailboxException; @@ -163,6 +164,51 @@ public interface MailboxManager extends RequestAware, RightManager, MailboxAnnot */ Mailbox deleteMailbox(MailboxId mailboxId, MailboxSession session) throws MailboxException; + class MailboxRenamedResult { + private final MailboxId mailboxId; + private final MailboxPath originPath; + private final MailboxPath destinationPath; + + public MailboxRenamedResult(MailboxId mailboxId, MailboxPath originPath, MailboxPath destinationPath) { + this.mailboxId = mailboxId; + this.originPath = originPath; + this.destinationPath = destinationPath; + } + + public MailboxId getMailboxId() { + return mailboxId; + } + + public MailboxPath getOriginPath() { + return originPath; + } + + public MailboxPath getDestinationPath() { + return destinationPath; + } + + @Override + public final boolean equals(Object o) { + if (o instanceof MailboxRenamedResult) { + MailboxRenamedResult that = (MailboxRenamedResult) o; + + return Objects.equals(this.mailboxId, that.mailboxId) + && Objects.equals(this.originPath, that.originPath) + && Objects.equals(this.destinationPath, that.destinationPath); + } + return false; + } + + @Override + public final int hashCode() { + return Objects.hash(mailboxId, originPath, destinationPath); + } + } + + enum RenameOption { + NONE, RENAME_SUBSCRIPTIONS + } + /** * Renames a mailbox. * @@ -179,7 +225,11 @@ public interface MailboxManager extends RequestAware, RightManager, MailboxAnnot * @throws MailboxNotFoundException * when the <code>from</code> mailbox does not exist */ - void renameMailbox(MailboxPath from, MailboxPath to, MailboxSession session) throws MailboxException; + List<MailboxRenamedResult> renameMailbox(MailboxPath from, MailboxPath to, RenameOption option, MailboxSession session) throws MailboxException; + + default List<MailboxRenamedResult> renameMailbox(MailboxPath from, MailboxPath to, MailboxSession session) throws MailboxException { + return renameMailbox(from, to, RenameOption.NONE, session); + } /** * Renames a mailbox. @@ -197,7 +247,11 @@ public interface MailboxManager extends RequestAware, RightManager, MailboxAnnot * @throws MailboxNotFoundException * when the <code>mailboxId</code> original mailbox does not exist */ - void renameMailbox(MailboxId mailboxId, MailboxPath newMailboxPath, MailboxSession session) throws MailboxException; + List<MailboxRenamedResult> renameMailbox(MailboxId mailboxId, MailboxPath newMailboxPath, RenameOption option, MailboxSession session) throws MailboxException; + + default List<MailboxRenamedResult> renameMailbox(MailboxId mailboxId, MailboxPath newMailboxPath, MailboxSession session) throws MailboxException { + return renameMailbox(mailboxId, newMailboxPath, RenameOption.NONE, session); + } /** * Copy the given {@link MessageRange} from one Mailbox to the other. diff --git a/mailbox/api/src/test/java/org/apache/james/mailbox/MailboxManagerTest.java b/mailbox/api/src/test/java/org/apache/james/mailbox/MailboxManagerTest.java index 3d92d48..09069fe 100644 --- a/mailbox/api/src/test/java/org/apache/james/mailbox/MailboxManagerTest.java +++ b/mailbox/api/src/test/java/org/apache/james/mailbox/MailboxManagerTest.java @@ -18,6 +18,7 @@ ****************************************************************/ package org.apache.james.mailbox; +import static org.apache.james.mailbox.MailboxManager.RenameOption.RENAME_SUBSCRIPTIONS; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -45,6 +46,7 @@ import org.apache.james.core.quota.QuotaCountUsage; import org.apache.james.core.quota.QuotaSizeLimit; import org.apache.james.core.quota.QuotaSizeUsage; import org.apache.james.mailbox.MailboxManager.MailboxCapabilities; +import org.apache.james.mailbox.MailboxManager.MailboxRenamedResult; import org.apache.james.mailbox.MessageManager.AppendCommand; import org.apache.james.mailbox.events.EventBus; import org.apache.james.mailbox.events.MailboxIdRegistrationKey; @@ -112,6 +114,7 @@ public abstract class MailboxManagerTest<T extends MailboxManager> { private static final int DEFAULT_MAXIMUM_LIMIT = 256; protected T mailboxManager; + private SubscriptionManager subscriptionManager; private MailboxSession session; protected Message.Builder message; @@ -120,6 +123,8 @@ public abstract class MailboxManagerTest<T extends MailboxManager> { protected abstract T provideMailboxManager(); + protected abstract SubscriptionManager provideSubscriptionManager(); + protected abstract EventBus retrieveEventBus(T mailboxManager); protected Set<PreDeletionHook> preDeletionHooks() { @@ -130,6 +135,7 @@ public abstract class MailboxManagerTest<T extends MailboxManager> { void setUp() throws Exception { setupMockForPreDeletionHooks(); this.mailboxManager = provideMailboxManager(); + this.subscriptionManager = provideSubscriptionManager(); this.message = Message.Builder.of() .setSubject("test") @@ -1533,6 +1539,197 @@ public abstract class MailboxManagerTest<T extends MailboxManager> { @Nested public class BasicFeaturesTests { + + @Test + void renameMailboxShouldReturnAllRenamedResultsIncludeChildren() throws MailboxException { + MailboxSession session = mailboxManager.createSystemSession(USER_1); + + MailboxPath mailboxPath1 = MailboxPath.forUser(USER_1, "mbx1"); + MailboxPath mailboxPath2 = MailboxPath.forUser(USER_1, "mbx1.mbx2"); + MailboxPath mailboxPath3 = MailboxPath.forUser(USER_1, "mbx1.mbx2.mbx3"); + MailboxPath mailboxPath4 = MailboxPath.forUser(USER_1, "mbx1.mbx2.mbx3.mbx4"); + MailboxPath newMailboxPath = MailboxPath.forUser(USER_1, "mbx1.mbx9"); + + mailboxManager.createMailbox(mailboxPath1, session); + Optional<MailboxId> mailboxId2 = mailboxManager.createMailbox(mailboxPath2, session); + Optional<MailboxId> mailboxId3 = mailboxManager.createMailbox(mailboxPath3, session); + Optional<MailboxId> mailboxId4 = mailboxManager.createMailbox(mailboxPath4, session); + + List<MailboxRenamedResult> mailboxRenamedResults = mailboxManager.renameMailbox(mailboxPath2, newMailboxPath, session); + + SoftAssertions.assertSoftly(softly -> { + softly.assertThat(mailboxRenamedResults).hasSize(3); + softly.assertThat(mailboxRenamedResults).contains( + new MailboxRenamedResult(mailboxId2.get(), mailboxPath2, MailboxPath.forUser(USER_1, "mbx1.mbx9")), + new MailboxRenamedResult(mailboxId3.get(), mailboxPath3, MailboxPath.forUser(USER_1, "mbx1.mbx9.mbx3")), + new MailboxRenamedResult(mailboxId4.get(), mailboxPath4, MailboxPath.forUser(USER_1, "mbx1.mbx9.mbx3.mbx4")) + ); + }); + } + + @Test + void renameMailboxShouldReturnRenamedMailboxOnlyWhenNoChildren() throws MailboxException { + MailboxSession session = mailboxManager.createSystemSession(USER_1); + + MailboxPath mailboxPath1 = MailboxPath.forUser(USER_1, "mbx1"); + MailboxPath mailboxPath2 = MailboxPath.forUser(USER_1, "mbx1.mbx2"); + MailboxPath originalPath = MailboxPath.forUser(USER_1, "mbx1.mbx2.mbx3"); + MailboxPath newMailboxPath = MailboxPath.forUser(USER_1, "mbx1.mbx2.mbx9"); + + mailboxManager.createMailbox(mailboxPath1, session); + mailboxManager.createMailbox(mailboxPath2, session); + Optional<MailboxId> mailboxId3 = mailboxManager.createMailbox(originalPath, session); + + List<MailboxRenamedResult> mailboxRenamedResults = mailboxManager.renameMailbox(originalPath, newMailboxPath, session); + + SoftAssertions.assertSoftly(softly -> { + softly.assertThat(mailboxRenamedResults).hasSize(1); + softly.assertThat(mailboxRenamedResults).contains( + new MailboxRenamedResult(mailboxId3.get(), originalPath, newMailboxPath) + ); + }); + } + + @Test + void renameMailboxShouldRenamedChildMailboxesWithRenameOption() throws MailboxException { + MailboxSession session = mailboxManager.createSystemSession(USER_1); + + MailboxPath originalPath = MailboxPath.forUser(USER_1, "mbx1"); + MailboxPath mailboxPath2 = MailboxPath.forUser(USER_1, "mbx1.mbx2"); + MailboxPath mailboxPath3 = MailboxPath.forUser(USER_1, "mbx1.mbx2.mbx3"); + MailboxPath newMailboxPath = MailboxPath.forUser(USER_1, "mbx9"); + + mailboxManager.createMailbox(originalPath, session); + mailboxManager.createMailbox(mailboxPath2, session); + subscriptionManager.subscribe(session, originalPath.getName()); + subscriptionManager.subscribe(session, mailboxPath2.getName()); + + mailboxManager.createMailbox(mailboxPath3, session); + subscriptionManager.subscribe(session, mailboxPath3.getName()); + + mailboxManager.renameMailbox(originalPath, newMailboxPath, RENAME_SUBSCRIPTIONS, session); + + assertThat(subscriptionManager.subscriptions(session)).containsExactly( + newMailboxPath.getName(), + "mbx9.mbx2", + "mbx9.mbx2.mbx3" + ); + } + + @Test + void renameMailboxShouldRenameSubscriptionWhenCalledWithRenameSubscriptionOption() throws MailboxException { + MailboxSession session = mailboxManager.createSystemSession(USER_1); + + MailboxPath originalPath = MailboxPath.forUser(USER_1, "mbx1"); + MailboxPath newMailboxPath = MailboxPath.forUser(USER_1, "mbx2"); + + mailboxManager.createMailbox(originalPath, session); + subscriptionManager.subscribe(session, originalPath.getName()); + + mailboxManager.renameMailbox(originalPath, newMailboxPath, RENAME_SUBSCRIPTIONS, session); + + assertThat(subscriptionManager.subscriptions(session)).containsExactly(newMailboxPath.getName()); + } + + @Test + void renameMailboxShouldNotSubscribeUnsubscribedMailboxes() throws MailboxException { + MailboxSession session = mailboxManager.createSystemSession(USER_1); + + MailboxPath originalPath = MailboxPath.forUser(USER_1, "mbx1"); + MailboxPath newMailboxPath = MailboxPath.forUser(USER_1, "mbx2"); + + mailboxManager.createMailbox(originalPath, session); + + mailboxManager.renameMailbox(originalPath, newMailboxPath, RENAME_SUBSCRIPTIONS, session); + + assertThat(subscriptionManager.subscriptions(session)).isEmpty(); + } + + @Test + void renameMailboxShouldNotRenameSubscriptionWhenCalledWithoutRenameSubscriptionOption() throws MailboxException { + MailboxSession session = mailboxManager.createSystemSession(USER_1); + + MailboxPath originalPath = MailboxPath.forUser(USER_1, "mbx1"); + MailboxPath newMailboxPath = MailboxPath.forUser(USER_1, "mbx2"); + + mailboxManager.createMailbox(originalPath, session); + subscriptionManager.subscribe(session, originalPath.getName()); + + mailboxManager.renameMailbox(originalPath, newMailboxPath, MailboxManager.RenameOption.NONE, session); + + assertThat(subscriptionManager.subscriptions(session)).containsExactly(originalPath.getName()); + } + + @Test + void renameMailboxByIdShouldRenamedMailboxesWithRenameOption() throws MailboxException { + MailboxSession session = mailboxManager.createSystemSession(USER_1); + + MailboxPath originalPath = MailboxPath.forUser(USER_1, "mbx1"); + MailboxPath mailboxPath2 = MailboxPath.forUser(USER_1, "mbx1.mbx2"); + MailboxPath mailboxPath3 = MailboxPath.forUser(USER_1, "mbx1.mbx2.mbx3"); + MailboxPath newMailboxPath = MailboxPath.forUser(USER_1, "mbx9"); + + Optional<MailboxId> id = mailboxManager.createMailbox(originalPath, session); + mailboxManager.createMailbox(mailboxPath2, session); + subscriptionManager.subscribe(session, originalPath.getName()); + subscriptionManager.subscribe(session, mailboxPath2.getName()); + + mailboxManager.createMailbox(mailboxPath3, session); + subscriptionManager.subscribe(session, mailboxPath3.getName()); + + mailboxManager.renameMailbox(id.get(), newMailboxPath, RENAME_SUBSCRIPTIONS, session); + + assertThat(subscriptionManager.subscriptions(session)).containsExactly( + newMailboxPath.getName(), + "mbx9.mbx2", + "mbx9.mbx2.mbx3" + ); + } + + @Test + void renameMailboxByIdShouldRenameSubscriptionWhenCalledWithRenameSubscriptionOption() throws MailboxException { + MailboxSession session = mailboxManager.createSystemSession(USER_1); + + MailboxPath originalPath = MailboxPath.forUser(USER_1, "mbx1"); + MailboxPath newMailboxPath = MailboxPath.forUser(USER_1, "mbx2"); + + Optional<MailboxId> id = mailboxManager.createMailbox(originalPath, session); + subscriptionManager.subscribe(session, originalPath.getName()); + + mailboxManager.renameMailbox(id.get(), newMailboxPath, RENAME_SUBSCRIPTIONS, session); + + assertThat(subscriptionManager.subscriptions(session)).containsExactly(newMailboxPath.getName()); + } + + @Test + void renameMailboxByIdShouldNotSubscribeUnsubscribedMailboxes() throws MailboxException { + MailboxSession session = mailboxManager.createSystemSession(USER_1); + + MailboxPath originalPath = MailboxPath.forUser(USER_1, "mbx1"); + MailboxPath newMailboxPath = MailboxPath.forUser(USER_1, "mbx2"); + + Optional<MailboxId> id = mailboxManager.createMailbox(originalPath, session); + + mailboxManager.renameMailbox(id.get(), newMailboxPath, RENAME_SUBSCRIPTIONS, session); + + assertThat(subscriptionManager.subscriptions(session)).isEmpty(); + } + + @Test + void renameMailboxByIdShouldNotRenameSubscriptionWhenCalledWithoutRenameSubscriptionOption() throws MailboxException { + MailboxSession session = mailboxManager.createSystemSession(USER_1); + + MailboxPath originalPath = MailboxPath.forUser(USER_1, "mbx1"); + MailboxPath newMailboxPath = MailboxPath.forUser(USER_1, "mbx2"); + + Optional<MailboxId> id = mailboxManager.createMailbox(originalPath, session); + subscriptionManager.subscribe(session, originalPath.getName()); + + mailboxManager.renameMailbox(id.get(), newMailboxPath, MailboxManager.RenameOption.NONE, session); + + assertThat(subscriptionManager.subscriptions(session)).containsExactly(originalPath.getName()); + } + @Test void user1ShouldNotHaveAnInbox() throws Exception { session = mailboxManager.createSystemSession(USER_1); diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java index f57f28e..328fcc6 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java @@ -39,6 +39,7 @@ import org.apache.james.mailbox.MailboxManagerTest; import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.MessageManager; import org.apache.james.mailbox.MessageManager.AppendResult; +import org.apache.james.mailbox.SubscriptionManager; import org.apache.james.mailbox.cassandra.ids.CassandraId; import org.apache.james.mailbox.cassandra.ids.CassandraMessageId; import org.apache.james.mailbox.cassandra.mail.CassandraACLMapper; @@ -65,6 +66,7 @@ import org.apache.james.mailbox.model.MessageAttachmentMetadata; import org.apache.james.mailbox.model.MessageRange; import org.apache.james.mailbox.model.MessageResult; import org.apache.james.mailbox.store.PreDeletionHooks; +import org.apache.james.mailbox.store.StoreSubscriptionManager; import org.apache.james.mailbox.store.mail.MessageMapper; import org.apache.james.metrics.tests.RecordingMetricFactory; import org.apache.james.util.ClassLoaderUtils; @@ -92,6 +94,11 @@ public class CassandraMailboxManagerTest extends MailboxManagerTest<CassandraMai } @Override + protected SubscriptionManager provideSubscriptionManager() { + return new StoreSubscriptionManager(provideMailboxManager().getMapperFactory()); + } + + @Override protected EventBus retrieveEventBus(CassandraMailboxManager mailboxManager) { return mailboxManager.getEventBus(); } diff --git a/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/JPAMailboxManagerTest.java b/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/JPAMailboxManagerTest.java index 4b917d9..530a596 100644 --- a/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/JPAMailboxManagerTest.java +++ b/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/JPAMailboxManagerTest.java @@ -22,8 +22,10 @@ import java.util.Optional; import org.apache.james.backends.jpa.JpaTestCluster; import org.apache.james.mailbox.MailboxManagerTest; +import org.apache.james.mailbox.SubscriptionManager; import org.apache.james.mailbox.events.EventBus; import org.apache.james.mailbox.jpa.openjpa.OpenJPAMailboxManager; +import org.apache.james.mailbox.store.StoreSubscriptionManager; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Nested; @@ -48,6 +50,11 @@ class JPAMailboxManagerTest extends MailboxManagerTest<OpenJPAMailboxManager> { return openJPAMailboxManager.get(); } + @Override + protected SubscriptionManager provideSubscriptionManager() { + return new StoreSubscriptionManager(provideMailboxManager().getMapperFactory()); + } + @AfterEach void tearDownJpa() { JPA_TEST_CLUSTER.clear(JPAMailboxFixture.MAILBOX_TABLE_NAMES); diff --git a/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/DomainUserMaildirMailboxManagerTest.java b/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/DomainUserMaildirMailboxManagerTest.java index c54dd2c..601b019 100644 --- a/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/DomainUserMaildirMailboxManagerTest.java +++ b/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/DomainUserMaildirMailboxManagerTest.java @@ -18,10 +18,14 @@ ****************************************************************/ package org.apache.james.mailbox.maildir; +import java.util.Optional; + import org.apache.james.junit.TemporaryFolderExtension; import org.apache.james.mailbox.MailboxManagerTest; +import org.apache.james.mailbox.SubscriptionManager; import org.apache.james.mailbox.events.EventBus; import org.apache.james.mailbox.store.StoreMailboxManager; +import org.apache.james.mailbox.store.StoreSubscriptionManager; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -88,11 +92,24 @@ class DomainUserMaildirMailboxManagerTest extends MailboxManagerTest<StoreMailbo @RegisterExtension TemporaryFolderExtension temporaryFolder = new TemporaryFolderExtension(); - + Optional<StoreMailboxManager> mailboxManager = Optional.empty(); + @Override protected StoreMailboxManager provideMailboxManager() { + if (!mailboxManager.isPresent()) { + mailboxManager = Optional.of(createMailboxManager()); + } + return mailboxManager.get(); + } + + @Override + protected SubscriptionManager provideSubscriptionManager() { + return new StoreSubscriptionManager(provideMailboxManager().getMapperFactory()); + } + + private StoreMailboxManager createMailboxManager() { try { - return MaildirMailboxManagerProvider.createMailboxManager("/%domain/%user", temporaryFolder.getTemporaryFolder().getTempDir()); + return MaildirMailboxManagerProvider.createMailboxManager("/%fulluser", temporaryFolder.getTemporaryFolder().getTempDir()); } catch (Exception e) { throw new RuntimeException(e); } diff --git a/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/FullUserMaildirMailboxManagerTest.java b/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/FullUserMaildirMailboxManagerTest.java index cb5d08f..e580662 100644 --- a/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/FullUserMaildirMailboxManagerTest.java +++ b/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/FullUserMaildirMailboxManagerTest.java @@ -18,10 +18,15 @@ ****************************************************************/ package org.apache.james.mailbox.maildir; +import java.util.Optional; + import org.apache.james.junit.TemporaryFolderExtension; import org.apache.james.mailbox.MailboxManagerTest; +import org.apache.james.mailbox.SubscriptionManager; import org.apache.james.mailbox.events.EventBus; import org.apache.james.mailbox.store.StoreMailboxManager; +import org.apache.james.mailbox.store.StoreSubscriptionManager; +import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.extension.RegisterExtension; @@ -36,9 +41,22 @@ class FullUserMaildirMailboxManagerTest extends MailboxManagerTest<StoreMailboxM @RegisterExtension TemporaryFolderExtension temporaryFolder = new TemporaryFolderExtension(); + Optional<StoreMailboxManager> mailboxManager = Optional.empty(); @Override protected StoreMailboxManager provideMailboxManager() { + if (!mailboxManager.isPresent()) { + mailboxManager = Optional.of(createMailboxManager()); + } + return mailboxManager.get(); + } + + @Override + protected SubscriptionManager provideSubscriptionManager() { + return new StoreSubscriptionManager(provideMailboxManager().getMapperFactory()); + } + + private StoreMailboxManager createMailboxManager() { try { return MaildirMailboxManagerProvider.createMailboxManager("/%fulluser", temporaryFolder.getTemporaryFolder().getTempDir()); } catch (Exception e) { diff --git a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/MemoryMailboxManagerTest.java b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/MemoryMailboxManagerTest.java index 7eb0846..c02c55f 100644 --- a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/MemoryMailboxManagerTest.java +++ b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/MemoryMailboxManagerTest.java @@ -20,7 +20,9 @@ package org.apache.james.mailbox.inmemory; import org.apache.james.mailbox.MailboxManagerTest; +import org.apache.james.mailbox.SubscriptionManager; import org.apache.james.mailbox.events.EventBus; +import org.apache.james.mailbox.store.StoreSubscriptionManager; class MemoryMailboxManagerTest extends MailboxManagerTest<InMemoryMailboxManager> { @@ -30,6 +32,11 @@ class MemoryMailboxManagerTest extends MailboxManagerTest<InMemoryMailboxManager } @Override + protected SubscriptionManager provideSubscriptionManager() { + return new StoreSubscriptionManager(provideMailboxManager().getMapperFactory()); + } + + @Override protected EventBus retrieveEventBus(InMemoryMailboxManager mailboxManager) { return mailboxManager.getEventBus(); } diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/MailboxReactorUtils.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/MailboxReactorUtils.java index c8e3cd3..0bfa8f8 100644 --- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/MailboxReactorUtils.java +++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/MailboxReactorUtils.java @@ -22,6 +22,7 @@ package org.apache.james.mailbox.store; import java.util.Optional; import org.apache.james.mailbox.exception.MailboxException; +import org.reactivestreams.Publisher; import reactor.core.publisher.Mono; @@ -37,7 +38,11 @@ public abstract class MailboxReactorUtils { throw e; } } - + + public static <T> T block(Publisher<T> publisher) throws MailboxException { + return block(Mono.from(publisher)); + } + public static <T> Optional<T> blockOptional(Mono<T> publisher) throws MailboxException { try { return publisher.blockOptional(); diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java index cab65d7..091e40b 100644 --- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java +++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java @@ -50,6 +50,7 @@ import org.apache.james.mailbox.exception.InsufficientRightsException; import org.apache.james.mailbox.exception.MailboxException; import org.apache.james.mailbox.exception.MailboxExistsException; import org.apache.james.mailbox.exception.MailboxNotFoundException; +import org.apache.james.mailbox.exception.SubscriptionException; import org.apache.james.mailbox.exception.UnsupportedRightException; import org.apache.james.mailbox.extension.PreDeletionHook; import org.apache.james.mailbox.model.Mailbox; @@ -82,6 +83,8 @@ import org.apache.james.mailbox.store.mail.model.impl.MessageParser; import org.apache.james.mailbox.store.quota.QuotaComponents; import org.apache.james.mailbox.store.search.MessageSearchIndex; import org.apache.james.mailbox.store.transaction.Mapper; +import org.apache.james.mailbox.store.user.SubscriptionMapper; +import org.apache.james.mailbox.store.user.model.Subscription; import org.apache.james.util.FunctionalUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -89,6 +92,7 @@ import org.slf4j.LoggerFactory; import com.github.fge.lambdas.Throwing; import com.github.steveash.guavate.Guavate; import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; @@ -101,7 +105,6 @@ import reactor.core.publisher.Mono; * to extend just this class or use it directly. * <p/> * If you need a more low-level api just implement {@link MailboxManager} directly - * */ public class StoreMailboxManager implements MailboxManager { private static final Logger LOGGER = LoggerFactory.getLogger(StoreMailboxManager.class); @@ -170,7 +173,7 @@ public class StoreMailboxManager implements MailboxManager { public EnumSet<MessageCapabilities> getSupportedMessageCapabilities() { return DEFAULT_NO_MESSAGE_CAPABILITIES; } - + @Override public EnumSet<SearchCapabilities> getSupportedSearchCapabilities() { return index.getSupportedCapabilities(getSupportedMessageCapabilities()); @@ -248,14 +251,13 @@ public class StoreMailboxManager implements MailboxManager { */ protected StoreMessageManager createMessageManager(Mailbox mailbox, MailboxSession session) throws MailboxException { return new StoreMessageManager(DEFAULT_NO_MESSAGE_CAPABILITIES, getMapperFactory(), getMessageSearchIndex(), getEventBus(), - getLocker(), mailbox, quotaManager, + getLocker(), mailbox, quotaManager, getQuotaComponents().getQuotaRootResolver(), configuration.getBatchSizes(), getStoreRightManager(), preDeletionHooks, new MessageStorer.WithoutAttachment(mailboxSessionMapperFactory, messageIdFactory, new MessageFactory.StoreMessageFactory())); } @Override - public MessageManager getMailbox(MailboxPath mailboxPath, MailboxSession session) - throws MailboxException { + public MessageManager getMailbox(MailboxPath mailboxPath, MailboxSession session) throws MailboxException { final MailboxMapper mapper = mailboxSessionMapperFactory.getMailboxMapper(session); Mailbox mailboxRow = mapper.findMailboxByPath(mailboxPath) .blockOptional() @@ -275,8 +277,7 @@ public class StoreMailboxManager implements MailboxManager { } @Override - public MessageManager getMailbox(MailboxId mailboxId, MailboxSession session) - throws MailboxException { + public MessageManager getMailbox(MailboxId mailboxId, MailboxSession session) throws MailboxException { MailboxMapper mapper = mailboxSessionMapperFactory.getMailboxMapper(session); Mailbox mailboxRow = block(mapper.findMailboxById(mailboxId)); @@ -303,8 +304,7 @@ public class StoreMailboxManager implements MailboxManager { } @Override - public Optional<MailboxId> createMailbox(MailboxPath mailboxPath, MailboxSession mailboxSession) - throws MailboxException { + public Optional<MailboxId> createMailbox(MailboxPath mailboxPath, MailboxSession mailboxSession) throws MailboxException { LOGGER.debug("createMailbox {}", mailboxPath); assertMailboxPathBelongToUser(mailboxSession, mailboxPath); @@ -343,7 +343,7 @@ public class StoreMailboxManager implements MailboxManager { private Stream<MailboxId> manageMailboxCreation(MailboxSession mailboxSession, boolean isRootPath, MailboxPath mailboxPath) throws MailboxException { if (mailboxPath.isInbox()) { - if (block(Mono.from(hasInbox(mailboxSession)))) { + if (block(hasInbox(mailboxSession))) { return duplicatedINBOXCreation(isRootPath, mailboxPath); } @@ -376,11 +376,11 @@ public class StoreMailboxManager implements MailboxManager { .flatMap(mailbox -> // notify listeners eventBus.dispatch(EventFactory.mailboxAdded() - .randomEventId() - .mailboxSession(mailboxSession) - .mailbox(mailbox) - .build(), - new MailboxIdRegistrationKey(mailbox.getMailboxId())))))); + .randomEventId() + .mailboxSession(mailboxSession) + .mailbox(mailbox) + .build(), + new MailboxIdRegistrationKey(mailbox.getMailboxId())))))); } catch (Exception e) { if (e instanceof MailboxExistsException) { LOGGER.info("{} mailbox was created concurrently", mailboxPath.asString()); @@ -421,12 +421,12 @@ public class StoreMailboxManager implements MailboxManager { MailboxMapper mailboxMapper = mailboxSessionMapperFactory.getMailboxMapper(session); return mailboxMapper.execute(() -> block(mailboxMapper.findMailboxById(mailboxId) - .map(Throwing.<Mailbox, Mailbox>function(mailbox -> { - assertIsOwner(session, mailbox.generateAssociatedPath()); - return mailbox; - }).sneakyThrow()) - .flatMap(Throwing.<Mailbox, Mono<Mailbox>>function(mailbox -> - doDeleteMailbox(mailboxMapper, mailbox, session)).sneakyThrow()))); + .map(Throwing.<Mailbox, Mailbox>function(mailbox -> { + assertIsOwner(session, mailbox.generateAssociatedPath()); + return mailbox; + }).sneakyThrow()) + .flatMap(Throwing.<Mailbox, Mono<Mailbox>>function(mailbox -> + doDeleteMailbox(mailboxMapper, mailbox, session)).sneakyThrow()))); } private Mono<Mailbox> doDeleteMailbox(MailboxMapper mailboxMapper, Mailbox mailbox, MailboxSession session) throws MailboxException { @@ -447,14 +447,14 @@ public class StoreMailboxManager implements MailboxManager { return preDeletionHooks.runHooks(PreDeletionHook.DeleteOperation.from(metadata)) .then(mailboxMapper.delete(mailbox)) .then(eventBus.dispatch(EventFactory.mailboxDeleted() - .randomEventId() - .mailboxSession(session) - .mailbox(mailbox) - .quotaRoot(quotaRoot) - .quotaCount(QuotaCountUsage.count(messageCount)) - .quotaSize(QuotaSizeUsage.size(totalSize)) - .build(), - new MailboxIdRegistrationKey(mailbox.getMailboxId()))); + .randomEventId() + .mailboxSession(session) + .mailbox(mailbox) + .quotaRoot(quotaRoot) + .quotaCount(QuotaCountUsage.count(messageCount)) + .quotaSize(QuotaSizeUsage.size(totalSize)) + .build(), + new MailboxIdRegistrationKey(mailbox.getMailboxId()))); }) // We need to create a copy of the mailbox as maybe we can not refer to the real // mailbox once we remove it @@ -462,7 +462,8 @@ public class StoreMailboxManager implements MailboxManager { } @Override - public void renameMailbox(MailboxPath from, MailboxPath to, MailboxSession session) throws MailboxException { + public List<MailboxRenamedResult> renameMailbox(MailboxPath from, MailboxPath to, RenameOption option, + MailboxSession session) throws MailboxException { LOGGER.debug("renameMailbox {} to {}", from, to); MailboxPath sanitizedMailboxPath = to.sanitize(session.getPathDelimiter()); validateDestinationPath(sanitizedMailboxPath, session); @@ -470,26 +471,46 @@ public class StoreMailboxManager implements MailboxManager { assertIsOwner(session, from); MailboxMapper mapper = mailboxSessionMapperFactory.getMailboxMapper(session); - mapper.execute(Mapper.toTransaction(() -> { + return mapper.execute(() -> { Mailbox mailbox = blockOptional(mapper.findMailboxByPath(from)) .orElseThrow(() -> new MailboxNotFoundException(from)); - doRenameMailbox(mailbox, sanitizedMailboxPath, session, mapper); - })); + return renameSubscriptionsIfNeeded( + doRenameMailbox(mailbox, sanitizedMailboxPath, session, mapper), option, session); + }); + } + + private List<MailboxRenamedResult> renameSubscriptionsIfNeeded(List<MailboxRenamedResult> renamedResults, + RenameOption option, MailboxSession session) throws SubscriptionException { + if (option == RenameOption.RENAME_SUBSCRIPTIONS) { + SubscriptionMapper subscriptionMapper = mailboxSessionMapperFactory.getSubscriptionMapper(session); + List<Subscription> subscriptionsForUser = subscriptionMapper.findSubscriptionsForUser(session.getUser()); + renamedResults.forEach(Throwing.<MailboxRenamedResult>consumer(renamedResult -> { + Subscription subscription = new Subscription(session.getUser(), renamedResult.getOriginPath().getName()); + if (subscriptionsForUser.contains(subscription)) { + subscriptionMapper.delete(subscription); + subscriptionMapper.save(new Subscription(session.getUser(), renamedResult.getDestinationPath().getName())); + } + }).sneakyThrow()); + } + return renamedResults; } @Override - public void renameMailbox(MailboxId mailboxId, MailboxPath newMailboxPath, MailboxSession session) throws MailboxException { + public List<MailboxRenamedResult> renameMailbox(MailboxId mailboxId, MailboxPath newMailboxPath, RenameOption option, + MailboxSession session) throws MailboxException { LOGGER.debug("renameMailbox {} to {}", mailboxId, newMailboxPath); MailboxPath sanitizedMailboxPath = newMailboxPath.sanitize(session.getPathDelimiter()); validateDestinationPath(sanitizedMailboxPath, session); MailboxMapper mapper = mailboxSessionMapperFactory.getMailboxMapper(session); - mapper.execute(Mapper.toTransaction(() -> { - Mailbox mailbox = block(mapper.findMailboxById(mailboxId)); + return mapper.execute(() -> { + Mailbox mailbox = mapper.findMailboxById(mailboxId).blockOptional() + .orElseThrow(() -> new MailboxNotFoundException(mailboxId)); assertIsOwner(session, mailbox.generateAssociatedPath()); - doRenameMailbox(mailbox, sanitizedMailboxPath, session, mapper); - })); + return renameSubscriptionsIfNeeded( + doRenameMailbox(mailbox, sanitizedMailboxPath, session, mapper), option, session); + }); } private void validateDestinationPath(MailboxPath newMailboxPath, MailboxSession session) throws MailboxException { @@ -507,21 +528,27 @@ public class StoreMailboxManager implements MailboxManager { } } - private void doRenameMailbox(Mailbox mailbox, MailboxPath newMailboxPath, MailboxSession session, MailboxMapper mapper) throws MailboxException { + private List<MailboxRenamedResult> doRenameMailbox(Mailbox mailbox, MailboxPath newMailboxPath, MailboxSession session, MailboxMapper mapper) throws MailboxException { // TODO put this into a serilizable transaction + ImmutableList.Builder<MailboxRenamedResult> resultBuilder = ImmutableList.builder(); + MailboxPath from = mailbox.generateAssociatedPath(); mailbox.setNamespace(newMailboxPath.getNamespace()); mailbox.setUser(newMailboxPath.getUser()); mailbox.setName(newMailboxPath.getName()); + block(mapper.rename(mailbox) - .then(eventBus.dispatch(EventFactory.mailboxRenamed() - .randomEventId() - .mailboxSession(session) - .mailboxId(mailbox.getMailboxId()) - .oldPath(from) - .newPath(newMailboxPath) - .build(), + .map(mailboxId -> { + resultBuilder.add(new MailboxRenamedResult(mailboxId, from, newMailboxPath)); + return mailboxId; + }).then(eventBus.dispatch(EventFactory.mailboxRenamed() + .randomEventId() + .mailboxSession(session) + .mailboxId(mailbox.getMailboxId()) + .oldPath(from) + .newPath(newMailboxPath) + .build(), new MailboxIdRegistrationKey(mailbox.getMailboxId())))); // rename submailboxes @@ -538,13 +565,16 @@ public class StoreMailboxManager implements MailboxManager { MailboxPath fromPath = new MailboxPath(from, subOriginalName); sub.setName(subNewName); return mapper.rename(sub) - .then(eventBus.dispatch(EventFactory.mailboxRenamed() - .randomEventId() - .mailboxSession(session) - .mailboxId(sub.getMailboxId()) - .oldPath(fromPath) - .newPath(sub.generateAssociatedPath()) - .build(), + .map(mailboxId -> { + resultBuilder.add(new MailboxRenamedResult(sub.getMailboxId(), fromPath, sub.generateAssociatedPath())); + return mailboxId; + }).then(eventBus.dispatch(EventFactory.mailboxRenamed() + .randomEventId() + .mailboxSession(session) + .mailboxId(sub.getMailboxId()) + .oldPath(fromPath) + .newPath(sub.generateAssociatedPath()) + .build(), new MailboxIdRegistrationKey(sub.getMailboxId()))) .then(Mono.fromRunnable(() -> LOGGER.debug("Rename mailbox sub-mailbox {} to {}", subOriginalName, subNewName))); }) @@ -553,6 +583,7 @@ public class StoreMailboxManager implements MailboxManager { return null; }, MailboxPathLocker.LockType.Write); + return resultBuilder.build(); } @Override @@ -571,7 +602,7 @@ public class StoreMailboxManager implements MailboxManager { return copyMessages(set, session, toMailbox, fromMailbox); } - + private List<MessageRange> copyMessages(MessageRange set, MailboxSession session, StoreMessageManager toMailbox, StoreMessageManager fromMailbox) throws MailboxException { return configuration.getCopyBatcher().batchMessages(set, messageRange -> fromMailbox.copyTo(messageRange, toMailbox, session)); @@ -673,7 +704,7 @@ public class StoreMailboxManager implements MailboxManager { private Flux<MailboxId> getInMailboxes(ImmutableSet<MailboxId> inMailboxes, MailboxSession session) throws MailboxException { - if (inMailboxes.isEmpty()) { + if (inMailboxes.isEmpty()) { return getAllReadableMailbox(session); } else { return filterReadable(inMailboxes, session); @@ -782,13 +813,13 @@ public class StoreMailboxManager implements MailboxManager { @Override public List<MailboxAnnotation> getAnnotationsByKeys(MailboxPath mailboxPath, MailboxSession session, Set<MailboxAnnotationKey> keys) - throws MailboxException { + throws MailboxException { return annotationManager.getAnnotationsByKeys(mailboxPath, session, keys); } @Override public void updateAnnotations(MailboxPath mailboxPath, MailboxSession session, List<MailboxAnnotation> mailboxAnnotations) - throws MailboxException { + throws MailboxException { annotationManager.updateAnnotations(mailboxPath, session, mailboxAnnotations); } @@ -800,13 +831,13 @@ public class StoreMailboxManager implements MailboxManager { @Override public List<MailboxAnnotation> getAnnotationsByKeysWithOneDepth(MailboxPath mailboxPath, MailboxSession session, - Set<MailboxAnnotationKey> keys) throws MailboxException { + Set<MailboxAnnotationKey> keys) throws MailboxException { return annotationManager.getAnnotationsByKeysWithOneDepth(mailboxPath, session, keys); } @Override public List<MailboxAnnotation> getAnnotationsByKeysWithAllDepth(MailboxPath mailboxPath, MailboxSession session, - Set<MailboxAnnotationKey> keys) throws MailboxException { + Set<MailboxAnnotationKey> keys) throws MailboxException { return annotationManager.getAnnotationsByKeysWithAllDepth(mailboxPath, session, keys); } diff --git a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/SetMailboxesMethodTest.java b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/SetMailboxesMethodTest.java index 2d9e3d0..86a9586 100644 --- a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/SetMailboxesMethodTest.java +++ b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/SetMailboxesMethodTest.java @@ -21,6 +21,7 @@ package org.apache.james.jmap.draft.methods.integration; import static io.restassured.RestAssured.given; import static io.restassured.RestAssured.with; +import static io.restassured.http.ContentType.JSON; import static org.apache.james.jmap.HttpJmapAuthentication.authenticateJamesUser; import static org.apache.james.jmap.JMAPTestingConstants.ARGUMENTS; import static org.apache.james.jmap.JMAPTestingConstants.DOMAIN; @@ -74,6 +75,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import io.restassured.RestAssured; +import io.restassured.response.Response; public abstract class SetMailboxesMethodTest { @@ -81,7 +83,7 @@ public abstract class SetMailboxesMethodTest { private static final String WRITE = String.valueOf(Right.Write.asCharacter()); private static final String DELETE_MESSAGES = String.valueOf(Right.DeleteMessages.asCharacter()); - private static int MAILBOX_NAME_LENGTH_64K = 65536; + private static final int MAILBOX_NAME_LENGTH_64K = 65536; protected abstract GuiceJamesServer createJmapServer() throws IOException; @@ -338,17 +340,15 @@ public abstract class SetMailboxesMethodTest { @Test public void subscriptionUserShouldBeChangedWhenUpdateMailbox() throws Exception { - mailboxProbe.createMailbox(MailboxConstants.USER_NAMESPACE, username.asString(), "root"); - - String initialMailboxName = "root.myBox"; - MailboxId mailboxId = mailboxProbe.createMailbox(MailboxConstants.USER_NAMESPACE, username.asString(), initialMailboxName); + String initialMailboxName = "myBox"; + String mailboxId = createMailBoxThroughJMAP(initialMailboxName); String requestBody = "[" + " [ \"setMailboxes\"," + " {" + " \"update\": {" + - " \"" + mailboxId.serialize() + "\" : {" + + " \"" + mailboxId + "\" : {" + " \"name\" : \"mySecondBox\"" + " }" + " }" + @@ -367,6 +367,139 @@ public abstract class SetMailboxesMethodTest { } @Test + public void subscriptionUserShouldBeChangedWhenUpdateParentMailbox() throws Exception { + MailboxId parentId = mailboxProbe.createMailbox(MailboxConstants.USER_NAMESPACE, username.asString(), "root"); + + String secondMailboxName = "second"; + String secondMailboxId = createSubMailBox(parentId.serialize(), secondMailboxName); + + String thirdMailBoxName = "third"; + String thirdMailboxId = createSubMailBox(secondMailboxId, thirdMailBoxName); + + String fourthMailboxName = "fourth"; + createSubMailBox(thirdMailboxId, fourthMailboxName); + + String requestBody = + "[" + + " [ \"setMailboxes\"," + + " {" + + " \"update\": {" + + " \"" + thirdMailboxId + "\" : {" + + " \"name\" : \"thirdtest\" ," + + " \"parentId\" : \"" + secondMailboxId + "\"" + + " }" + + " }" + + " }," + + " \"#0\"" + + " ]" + + "]"; + with() + .header("Authorization", accessToken.asString()) + .body(requestBody) + .post("/jmap"); + + assertThat(mailboxProbe.listSubscriptions(username.asString())) + .contains("root.second.thirdtest.fourth") + .doesNotContain("root.second.third.fourth"); + } + + @Test + public void subscriptionUserShouldBeChangedForAllChildrenWhenUpdateParentMailbox() throws Exception { + MailboxId parentId = mailboxProbe.createMailbox(MailboxConstants.USER_NAMESPACE, username.asString(), "root"); + + String secondMailboxName = "second"; + String secondMailboxId = createSubMailBox(parentId.serialize(), secondMailboxName); + + String thirdMailBoxName = "third"; + String thirdMailboxId = createSubMailBox(secondMailboxId, thirdMailBoxName); + + String fourthMailboxName = "fourth"; + createSubMailBox(thirdMailboxId, fourthMailboxName); + + String requestBody = + "[" + + " [ \"setMailboxes\"," + + " {" + + " \"update\": {" + + " \"" + secondMailboxId + "\" : {" + + " \"name\" : \"secondtest\" ," + + " \"parentId\" : \"" + parentId.serialize() + "\"" + + " }" + + " }" + + " }," + + " \"#0\"" + + " ]" + + "]"; + with() + .header("Authorization", accessToken.asString()) + .body(requestBody) + .post("/jmap"); + + assertThat(mailboxProbe.listSubscriptions(username.asString())) + .contains("root.secondtest.third.fourth") + .doesNotContain("root.second.third.fourth"); + } + + private String createSubMailBox(String parentMailboxId, String childMailboxName) { + String clientIdentifier = "whatever"; + String createChildMailbox = + "[" + + " [ \"setMailboxes\"," + + " {" + + " \"create\": {" + + " \"" + clientIdentifier + "\" : {" + + " \"name\" : \"" + childMailboxName + "\"," + + " \"parentId\" : \"" + parentMailboxId + "\"" + + " }" + + " }" + + " }," + + " \"#0\"" + + " ]" + + "]"; + + Response response = given() + .header("Authorization", accessToken.asString()) + .body(createChildMailbox) + .when() + .post("/jmap") + .then() + .contentType(JSON) + .extract() + .response(); + + return response.jsonPath().get("[0][1].created." + clientIdentifier + ".id"); + } + + private String createMailBoxThroughJMAP(String mailboxName) { + String clientIdentifier = "whatever"; + String createMailbox = + "[" + + " [ \"setMailboxes\"," + + " {" + + " \"create\": {" + + " \"" + clientIdentifier + "\" : {" + + " \"name\" : \"" + mailboxName + "\"" + + " }" + + " }" + + " }," + + " \"#0\"" + + " ]" + + "]"; + + Response response = given() + .header("Authorization", accessToken.asString()) + .body(createMailbox) + .when() + .post("/jmap") + .then() + .contentType(JSON) + .extract() + .response(); + + return response.jsonPath().get("[0][1].created." + clientIdentifier + ".id"); + } + + @Test public void subscriptionUserShouldBeChangedWhenCreateThenUpdateMailboxNameWithJMAP() throws Exception { String requestBody = "[" + diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMailboxesUpdateProcessor.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMailboxesUpdateProcessor.java index b64d8d8..1d79ceb 100644 --- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMailboxesUpdateProcessor.java +++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMailboxesUpdateProcessor.java @@ -41,7 +41,6 @@ import org.apache.james.mailbox.MailboxManager; import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.MessageManager; import org.apache.james.mailbox.Role; -import org.apache.james.mailbox.SubscriptionManager; import org.apache.james.mailbox.exception.DifferentDomainException; import org.apache.james.mailbox.exception.MailboxException; import org.apache.james.mailbox.exception.MailboxExistsException; @@ -70,14 +69,12 @@ public class SetMailboxesUpdateProcessor implements SetMailboxesProcessor { private final MailboxManager mailboxManager; private final MailboxFactory mailboxFactory; private final MetricFactory metricFactory; - private final SubscriptionManager subscriptionManager; @Inject @VisibleForTesting - SetMailboxesUpdateProcessor(MailboxUtils mailboxUtils, MailboxManager mailboxManager, SubscriptionManager subscriptionManager, MailboxFactory mailboxFactory, MetricFactory metricFactory) { + SetMailboxesUpdateProcessor(MailboxUtils mailboxUtils, MailboxManager mailboxManager, MailboxFactory mailboxFactory, MetricFactory metricFactory) { this.mailboxUtils = mailboxUtils; this.mailboxManager = mailboxManager; - this.subscriptionManager = subscriptionManager; this.mailboxFactory = mailboxFactory; this.metricFactory = metricFactory; } @@ -156,7 +153,7 @@ public class SetMailboxesUpdateProcessor implements SetMailboxesProcessor { .description("An error occurred when updating the mailbox") .build()); } - } + } private void assertNotSharedOutboxOrDraftMailbox(Mailbox mailbox, MailboxUpdateRequest updateRequest) { Preconditions.checkArgument(!updateRequest.getSharedWith().isPresent() || !mailbox.hasRole(Role.OUTBOX), "Sharing 'Outbox' is forbidden"); @@ -258,6 +255,7 @@ public class SetMailboxesUpdateProcessor implements SetMailboxesProcessor { private void updateMailbox(Mailbox mailbox, MailboxUpdateRequest updateRequest, MailboxSession mailboxSession) throws MailboxException { MailboxPath originMailboxPath = mailboxManager.getMailbox(mailbox.getId(), mailboxSession).getMailboxPath(); MailboxPath destinationMailboxPath = computeNewMailboxPath(mailbox, originMailboxPath, updateRequest, mailboxSession); + if (updateRequest.getSharedWith().isPresent()) { mailboxManager.setRights(mailbox.getId(), updateRequest.getSharedWith() @@ -266,11 +264,9 @@ public class SetMailboxesUpdateProcessor implements SetMailboxesProcessor { .toMailboxAcl(), mailboxSession); } - if (!originMailboxPath.equals(destinationMailboxPath)) { - mailboxManager.renameMailbox(mailbox.getId(), destinationMailboxPath, mailboxSession); - subscriptionManager.unsubscribe(mailboxSession, originMailboxPath.getName()); - subscriptionManager.subscribe(mailboxSession, destinationMailboxPath.getName()); + if (!originMailboxPath.equals(destinationMailboxPath)) { + mailboxManager.renameMailbox(mailbox.getId(), destinationMailboxPath, MailboxManager.RenameOption.RENAME_SUBSCRIPTIONS, mailboxSession); } } diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMessagesCreationProcessor.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMessagesCreationProcessor.java index a384bd8..9936468 100644 --- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMessagesCreationProcessor.java +++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMessagesCreationProcessor.java @@ -221,7 +221,7 @@ public class SetMessagesCreationProcessor implements SetMessagesProcessor { } private void performCreate(CreationMessageEntry entry, Builder responseBuilder, MailboxSession session) - throws MailboxException, InvalidMailboxForCreationException, MessagingException, AttachmentsNotFoundException, IOException { + throws MailboxException, MessagingException, AttachmentsNotFoundException, IOException { if (isAppendToMailboxWithRole(Role.OUTBOX, entry.getValue(), session)) { sendMailViaOutbox(entry, responseBuilder, session); diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetMailboxesUpdateProcessorTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetMailboxesUpdateProcessorTest.java index 34cc705..79859c4 100644 --- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetMailboxesUpdateProcessorTest.java +++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetMailboxesUpdateProcessorTest.java @@ -37,7 +37,6 @@ import org.apache.james.jmap.draft.utils.MailboxUtils; import org.apache.james.mailbox.MailboxManager; import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.MessageManager; -import org.apache.james.mailbox.SubscriptionManager; import org.apache.james.mailbox.exception.MailboxException; import org.apache.james.mailbox.inmemory.InMemoryId; import org.apache.james.metrics.api.MetricFactory; @@ -49,7 +48,6 @@ import org.mockito.Mockito; public class SetMailboxesUpdateProcessorTest { private MailboxManager mockedMailboxManager; - private SubscriptionManager mockSubscriptionManager; private MailboxUtils mockedMailboxUtils; private MailboxFactory mockedMailboxFactory; private MailboxSession mockedMailboxSession; @@ -58,12 +56,11 @@ public class SetMailboxesUpdateProcessorTest { @Before public void setup() { mockedMailboxManager = mock(MailboxManager.class); - mockSubscriptionManager = mock(SubscriptionManager.class); mockedMailboxUtils = mock(MailboxUtils.class); mockedMailboxFactory = mock(MailboxFactory.class); mockedMailboxSession = mock(MailboxSession.class); MetricFactory metricFactory = new RecordingMetricFactory(); - sut = new SetMailboxesUpdateProcessor(mockedMailboxUtils, mockedMailboxManager, mockSubscriptionManager, mockedMailboxFactory, metricFactory); + sut = new SetMailboxesUpdateProcessor(mockedMailboxUtils, mockedMailboxManager, mockedMailboxFactory, metricFactory); } @Test --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org