You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by rc...@apache.org on 2021/01/05 04:55:39 UTC
[james-project] branch master updated (e9a3cbf -> 5e80fe6)
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git.
from e9a3cbf JAMES-3462 Binding for CassandraMailboxChangeModule
new 39ee787 JAMES-3486 Add missing binding
new 4ac8c99 JAMES-3486 Fix indent
new 49b3668 JAMES-3486 Test MailboxId should be generated
new 6efd140 JAMES-3486 Distributed MailboxChangeMethod test
new 47ee646 JAMES-3486 MemoryMailboxChangeRepository getSinceState should not include delegated changes
new da29db1 JAMES-3486 RightManager listRights should depend on mailboxId
new b6fee54 JAMES-3486 Adapt MailboxChangesMethodContract for stability against distributed environment
new d619483 JAMES-3461 Register MailboxChangeListener by default
new 91fd382 JAMES-3431 RecipientRewriteTableProcessor needs to modify DSN parameters
new be946ff JAMES-3407 Disable read repairs on outdated schema verison
new 9fe885b JAMES-3485 Group attachment right checking together
new 1ef4ffb JAMES-3485 Avoid reading messageV3 table upon attachment right setting
new 893ccaa JAMES-3485 Remove unused method
new 0ad37ca JAMES-3485 Searching all mailboxes reads too much ACLs
new 7a7afdd JAMES-3485 MessageAppender should group attachment reads too
new b2c9553 JAMES-3202 ReIndexerPerformer in corrective mode should add missing messages in the index
new 8630f34 JAMES-3202 ReIndexerPerformer in corrective mode: add missing error handling
new c8033f4 JAMES-3202 Leverage the fact that index does an upsert, removing pre-existing documents
new 4b3785d [REFACTORING] Steps of the staged builder should be inside the Builder of MailboxChange
new 5fc498a [REFACTORING] MailboxManager is not used in MailboxChangeListener anymore
new a8e7a33 JAMES-3471 Should be able to serialize UpdatedFlags with and without a message id
new 3ba4665 JAMES-3471 Adapt the different implementations of MessageMapper and MessageIdMapper to add the message id
new ebad11e JAMES-3471 Computing uids and message ids from updated flags is easy
new 5e80fe6 JAMES-3471 Disable tests on JpaMessageMapperTest using messageId, as it is not supported
The 24 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../org/apache/james/mailbox/RightManager.java | 2 +
.../james/mailbox/events/MailboxListener.java | 23 +-
.../mailbox/model/MultimailboxesSearchQuery.java | 12 +
.../apache/james/mailbox/model/UpdatedFlags.java | 37 +-
.../cassandra/mail/CassandraMessageIdMapper.java | 1 +
.../cassandra/mail/CassandraMessageMapper.java | 2 +
.../cassandra/mail/CassandraMailboxMapperTest.java | 599 ++++----
.../ElasticSearchListeningMessageSearchIndex.java | 5 +-
...asticSearchListeningMessageSearchIndexTest.java | 6 +-
.../scala/org/apache/james/event/json/DTOs.scala | 5 +-
.../event/json/FlagsUpdatedSerializationTest.java | 72 +
.../james/mailbox/jpa/mail/MessageUtils.java | 1 +
.../mailbox/jpa/mail/JpaMessageMapperTest.java | 33 +
.../mailbox/maildir/mail/MaildirMessageMapper.java | 1 +
.../inmemory/mail/InMemoryMessageIdMapper.java | 1 +
.../mailbox/store/StoreAttachmentManager.java | 48 +-
.../james/mailbox/store/StoreMailboxManager.java | 42 +-
.../james/mailbox/store/StoreMessageIdManager.java | 24 +-
.../james/mailbox/store/StoreRightManager.java | 7 +
.../mailbox/store/mail/AbstractMessageMapper.java | 1 +
.../james/mailbox/store/mail/MailboxMapper.java | 12 +
.../AbstractMessageIdManagerSideEffectTest.java | 1 +
.../store/mail/model/MessageIdMapperTest.java | 7 +
.../store/mail/model/MessageMapperTest.java | 15 +-
.../mailbox/tools/indexer/ReIndexerPerformer.java | 20 +-
.../mailbox/tools/indexer/ReIndexerImplTest.java | 30 +
.../main/java/org/apache/mailet/DsnParameters.java | 4 +
.../modules/mailbox/CassandraMailboxModule.java | 6 +
.../org/apache/james/jmap/draft/JMAPModule.java | 2 +
.../apache/james/jmap/draft/JmapGuiceProbe.java | 6 +-
.../james/jmap/api/change/MailboxChange.java | 51 +-
.../change/MemoryMailboxChangeRepository.java | 1 +
.../change/MailboxChangeRepositoryContract.java | 48 +
.../java/org/apache/james/smtp/DSNRelayTest.java | 47 +-
.../mailets/RecipientRewriteTableProcessor.java | 76 +-
.../james/jmap/draft/methods/MessageAppender.java | 28 +-
...ava => DistributedMailboxChangeMethodTest.java} | 22 +-
.../DistributedMailboxGetMethodTest.java | 6 +-
.../contract/MailboxChangesMethodContract.scala | 1613 +++++++++++---------
.../memory/MemoryMailboxChangesMethodTest.java | 8 +
.../src/test/resources/listeners.xml | 3 -
.../james/jmap/change/MailboxChangeListener.scala | 2 -
.../jmap/change/MailboxChangeListenerTest.scala | 2 +-
.../james/webadmin/routes/MailboxesRoutesTest.java | 8 +-
.../webadmin/routes/UserMailboxesRoutesTest.java | 4 +-
45 files changed, 1770 insertions(+), 1174 deletions(-)
copy server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/{DistributedMailboxSetMethodTest.java => DistributedMailboxChangeMethodTest.java} (83%)
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 24/24: JAMES-3471 Disable tests on
JpaMessageMapperTest using messageId, as it is not supported
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 5e80fe6d73c06d4f1b40c17885a13b01d6f1fbbb
Author: Rene Cordier <rc...@linagora.com>
AuthorDate: Mon Jan 4 15:10:57 2021 +0700
JAMES-3471 Disable tests on JpaMessageMapperTest using messageId, as it is not supported
---
.../mailbox/jpa/mail/JpaMessageMapperTest.java | 33 ++++++++++++++++++++++
.../store/mail/model/MessageMapperTest.java | 10 +++----
2 files changed, 38 insertions(+), 5 deletions(-)
diff --git a/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/JpaMessageMapperTest.java b/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/JpaMessageMapperTest.java
index 87cb269..5fea0fd 100644
--- a/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/JpaMessageMapperTest.java
+++ b/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/JpaMessageMapperTest.java
@@ -20,10 +20,13 @@
package org.apache.james.mailbox.jpa.mail;
import org.apache.james.backends.jpa.JpaTestCluster;
+import org.apache.james.mailbox.exception.MailboxException;
import org.apache.james.mailbox.jpa.JPAMailboxFixture;
import org.apache.james.mailbox.store.mail.model.MapperProvider;
import org.apache.james.mailbox.store.mail.model.MessageMapperTest;
import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
class JpaMessageMapperTest extends MessageMapperTest {
@@ -38,4 +41,34 @@ class JpaMessageMapperTest extends MessageMapperTest {
void cleanUp() {
JPA_TEST_CLUSTER.clear(JPAMailboxFixture.MAILBOX_TABLE_NAMES);
}
+
+ @Disabled("JAMES-3471 messageId is not supported by JPA ")
+ @Test
+ public void flagsAdditionShouldReturnAnUpdatedFlagHighlightingTheAddition() throws MailboxException {
+
+ }
+
+ @Disabled("")
+ @Test
+ public void flagsReplacementShouldReturnAnUpdatedFlagHighlightingTheReplacement() throws MailboxException {
+
+ }
+
+ @Disabled("")
+ @Test
+ public void flagsRemovalShouldReturnAnUpdatedFlagHighlightingTheRemoval() throws MailboxException {
+
+ }
+
+ @Disabled("")
+ @Test
+ public void userFlagsUpdateShouldReturnCorrectUpdatedFlags() throws MailboxException {
+
+ }
+
+ @Disabled("")
+ @Test
+ public void userFlagsUpdateShouldReturnCorrectUpdatedFlagsWhenNoop() throws MailboxException {
+
+ }
}
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java
index cc949d5..6f4d93d 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java
@@ -701,7 +701,7 @@ public abstract class MessageMapperTest {
}
@Test
- void flagsReplacementShouldReturnAnUpdatedFlagHighlightingTheReplacement() throws MailboxException {
+ protected void flagsReplacementShouldReturnAnUpdatedFlagHighlightingTheReplacement() throws MailboxException {
saveMessages();
ModSeq modSeq = messageMapper.getHighestModSeq(benwaInboxMailbox);
Optional<UpdatedFlags> updatedFlags = messageMapper.updateFlags(benwaInboxMailbox, message1.getUid(),
@@ -717,7 +717,7 @@ public abstract class MessageMapperTest {
}
@Test
- void flagsAdditionShouldReturnAnUpdatedFlagHighlightingTheAddition() throws MailboxException {
+ protected void flagsAdditionShouldReturnAnUpdatedFlagHighlightingTheAddition() throws MailboxException {
saveMessages();
messageMapper.updateFlags(benwaInboxMailbox, message1.getUid(), new FlagsUpdateCalculator(new Flags(Flags.Flag.FLAGGED), FlagsUpdateMode.REPLACE));
ModSeq modSeq = messageMapper.getHighestModSeq(benwaInboxMailbox);
@@ -750,7 +750,7 @@ public abstract class MessageMapperTest {
}
@Test
- void flagsRemovalShouldReturnAnUpdatedFlagHighlightingTheRemoval() throws MailboxException {
+ protected void flagsRemovalShouldReturnAnUpdatedFlagHighlightingTheRemoval() throws MailboxException {
saveMessages();
messageMapper.updateFlags(benwaInboxMailbox, message1.getUid(), new FlagsUpdateCalculator(new FlagsBuilder().add(Flags.Flag.FLAGGED, Flags.Flag.SEEN).build(), FlagsUpdateMode.REPLACE));
ModSeq modSeq = messageMapper.getHighestModSeq(benwaInboxMailbox);
@@ -877,7 +877,7 @@ public abstract class MessageMapperTest {
}
@Test
- void userFlagsUpdateShouldReturnCorrectUpdatedFlags() throws Exception {
+ protected void userFlagsUpdateShouldReturnCorrectUpdatedFlags() throws Exception {
saveMessages();
ModSeq modSeq = messageMapper.getHighestModSeq(benwaInboxMailbox);
assertThat(messageMapper.updateFlags(benwaInboxMailbox, message1.getUid(), new FlagsUpdateCalculator(new Flags(USER_FLAG), FlagsUpdateMode.ADD)))
@@ -892,7 +892,7 @@ public abstract class MessageMapperTest {
}
@Test
- void userFlagsUpdateShouldReturnCorrectUpdatedFlagsWhenNoop() throws Exception {
+ protected void userFlagsUpdateShouldReturnCorrectUpdatedFlagsWhenNoop() throws Exception {
saveMessages();
assertThat(
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 14/24: JAMES-3485 Searching all mailboxes reads too
much ACLs
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 0ad37ca0a5cb230f7fed2c8d76d0c49cfd5f2547
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Fri Dec 25 19:51:23 2020 +0700
JAMES-3485 Searching all mailboxes reads too much ACLs
Reference updater is called after sending a message. In order
to retrieve the message being replied/ forwarded and update its flags, a full mailbox search is being performed.
This unrestricted search was leading to unecessary ACL reads (1 ACL reads per mailbox accessible by the owner)
Upon Message search, we can skip safely
---
.../mailbox/model/MultimailboxesSearchQuery.java | 12 ++++++++
.../james/mailbox/store/StoreMailboxManager.java | 33 ++++++++++++++++------
.../james/mailbox/store/mail/MailboxMapper.java | 12 ++++++++
3 files changed, 49 insertions(+), 8 deletions(-)
diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/model/MultimailboxesSearchQuery.java b/mailbox/api/src/main/java/org/apache/james/mailbox/model/MultimailboxesSearchQuery.java
index 540f05f..4785111 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/model/MultimailboxesSearchQuery.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/MultimailboxesSearchQuery.java
@@ -40,6 +40,8 @@ public class MultimailboxesSearchQuery {
public interface Namespace {
boolean keepAccessible(Mailbox mailbox);
+ boolean accessDelegatedMailboxes();
+
MailboxQuery associatedMailboxSearchQuery();
}
@@ -61,6 +63,11 @@ public class MultimailboxesSearchQuery {
.matchesAllMailboxNames()
.build();
}
+
+ @Override
+ public boolean accessDelegatedMailboxes() {
+ return false;
+ }
}
public static class AccessibleNamespace implements Namespace {
@@ -83,6 +90,11 @@ public class MultimailboxesSearchQuery {
public boolean equals(Object obj) {
return obj instanceof AccessibleNamespace;
}
+
+ @Override
+ public boolean accessDelegatedMailboxes() {
+ return true;
+ }
}
public static class Builder {
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 23b3e25..3ec0836 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
@@ -688,6 +688,15 @@ public class StoreMailboxManager implements MailboxManager {
.filter(Throwing.predicate(mailbox -> storeRightManager.hasRight(mailbox, right, session)));
}
+ private Flux<MailboxId> accessibleMailboxIds(MultimailboxesSearchQuery.Namespace namespace, Right right, MailboxSession session) {
+ MailboxMapper mailboxMapper = mailboxSessionMapperFactory.getMailboxMapper(session);
+ Flux<MailboxId> baseMailboxes = mailboxMapper
+ .userMailboxes(session.getUser());
+ Flux<MailboxId> delegatedMailboxes = getDelegatedMailboxes(mailboxMapper, namespace, right, session);
+ return Flux.concat(baseMailboxes, delegatedMailboxes)
+ .distinct();
+ }
+
static MailboxQuery.UserBound toSingleUserQuery(MailboxQuery mailboxQuery, MailboxSession mailboxSession) {
return MailboxQuery.builder()
.namespace(mailboxQuery.getNamespace().orElse(MailboxConstants.USER_NAMESPACE))
@@ -706,6 +715,15 @@ public class StoreMailboxManager implements MailboxManager {
return mailboxMapper.findNonPersonalMailboxes(session.getUser(), right);
}
+ private Flux<MailboxId> getDelegatedMailboxes(MailboxMapper mailboxMapper, MultimailboxesSearchQuery.Namespace namespace,
+ Right right, MailboxSession session) {
+ if (!namespace.accessDelegatedMailboxes()) {
+ return Flux.empty();
+ }
+ return mailboxMapper.findNonPersonalMailboxes(session.getUser(), right)
+ .map(Mailbox::getMailboxId);
+ }
+
private MailboxMetaData toMailboxMetadata(MailboxSession session, List<Mailbox> mailboxes, Mailbox mailbox, MailboxCounters counters) throws UnsupportedRightException {
return new MailboxMetaData(
mailbox.generateAssociatedPath(),
@@ -732,20 +750,19 @@ public class StoreMailboxManager implements MailboxManager {
@Override
public Flux<MessageId> search(MultimailboxesSearchQuery expression, MailboxSession session, long limit) throws MailboxException {
- return getInMailboxes(expression, session)
- .filter(id -> !expression.getNotInMailboxes().contains(id.getMailboxId()))
- .filter(mailbox -> expression.getNamespace().keepAccessible(mailbox))
- .map(Mailbox::getMailboxId)
+ return getInMailboxIds(expression, session)
+ .filter(id -> !expression.getNotInMailboxes().contains(id))
.collect(Guavate.toImmutableSet())
.flatMapMany(Throwing.function(ids -> index.search(session, ids, expression.getSearchQuery(), limit)));
}
-
- private Flux<Mailbox> getInMailboxes(MultimailboxesSearchQuery expression, MailboxSession session) throws MailboxException {
+ private Flux<MailboxId> getInMailboxIds(MultimailboxesSearchQuery expression, MailboxSession session) throws MailboxException {
if (expression.getInMailboxes().isEmpty()) {
- return searchMailboxes(expression.getNamespace().associatedMailboxSearchQuery(), session, Right.Read);
+ return accessibleMailboxIds(expression.getNamespace(), Right.Read, session);
} else {
- return filterReadable(expression.getInMailboxes(), session);
+ return filterReadable(expression.getInMailboxes(), session)
+ .filter(mailbox -> expression.getNamespace().keepAccessible(mailbox))
+ .map(Mailbox::getMailboxId);
}
}
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/MailboxMapper.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/MailboxMapper.java
index 8743be6..a88d6a1 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/MailboxMapper.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/MailboxMapper.java
@@ -29,6 +29,7 @@ import org.apache.james.mailbox.model.MailboxId;
import org.apache.james.mailbox.model.MailboxPath;
import org.apache.james.mailbox.model.UidValidity;
import org.apache.james.mailbox.model.search.MailboxQuery;
+import org.apache.james.mailbox.model.search.Wildcard;
import org.apache.james.mailbox.store.transaction.Mapper;
import reactor.core.publisher.Flux;
@@ -81,6 +82,17 @@ public interface MailboxMapper extends Mapper {
*/
Flux<Mailbox> findMailboxWithPathLike(MailboxQuery.UserBound query);
+ default Flux<MailboxId> userMailboxes(Username username) {
+ return findMailboxWithPathLike(
+ MailboxQuery.builder()
+ .privateNamespace()
+ .username(username)
+ .expression(Wildcard.INSTANCE)
+ .build()
+ .asUserBound())
+ .map(Mailbox::getMailboxId);
+ }
+
/**
* Return if the given {@link Mailbox} has children
*
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 20/24: [REFACTORING] MailboxManager is not used in
MailboxChangeListener anymore
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 5fc498af76fb0026de3d165968431b26eec4ac3d
Author: Rene Cordier <rc...@linagora.com>
AuthorDate: Thu Dec 31 11:44:53 2020 +0700
[REFACTORING] MailboxManager is not used in MailboxChangeListener anymore
---
.../main/scala/org/apache/james/jmap/change/MailboxChangeListener.scala | 2 --
.../scala/org/apache/james/jmap/change/MailboxChangeListenerTest.scala | 2 +-
2 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/change/MailboxChangeListener.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/change/MailboxChangeListener.scala
index aba030f..f84e64a 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/change/MailboxChangeListener.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/change/MailboxChangeListener.scala
@@ -21,7 +21,6 @@ package org.apache.james.jmap.change
import javax.inject.Inject
import org.apache.james.jmap.api.change.{MailboxChange, MailboxChangeRepository}
-import org.apache.james.mailbox.MailboxManager
import org.apache.james.mailbox.events.MailboxListener.{MailboxEvent, ReactiveGroupMailboxListener}
import org.apache.james.mailbox.events.{Event, Group}
import org.apache.james.util.ReactorUtils.DEFAULT_CONCURRENCY
@@ -33,7 +32,6 @@ import scala.jdk.CollectionConverters._
case class MailboxChangeListenerGroup() extends Group {}
case class MailboxChangeListener @Inject() (mailboxChangeRepository: MailboxChangeRepository,
- mailboxManager: MailboxManager,
mailboxChangeFactory: MailboxChange.Factory) extends ReactiveGroupMailboxListener {
override def reactiveEvent(event: Event): Publisher[Void] =
diff --git a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/change/MailboxChangeListenerTest.scala b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/change/MailboxChangeListenerTest.scala
index edced0c..ba6ec97 100644
--- a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/change/MailboxChangeListenerTest.scala
+++ b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/change/MailboxChangeListenerTest.scala
@@ -67,7 +67,7 @@ class MailboxChangeListenerTest {
stateFactory = new State.DefaultFactory
mailboxChangeFactory = new MailboxChange.Factory(clock, mailboxManager, stateFactory)
repository = new MemoryMailboxChangeRepository()
- listener = MailboxChangeListener(repository, mailboxManager, mailboxChangeFactory)
+ listener = MailboxChangeListener(repository, mailboxChangeFactory)
resources.getEventBus.register(listener)
}
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 18/24: JAMES-3202 Leverage the fact that index does
an upsert, removing pre-existing documents
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit c8033f4bfe68810bc3e8a131aaf93926d8980349
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Wed Dec 30 17:02:51 2020 +0700
JAMES-3202 Leverage the fact that index does an upsert, removing pre-existing documents
We do not need to delete the existing document before indexing it
---
.../org/apache/mailbox/tools/indexer/ReIndexerPerformer.java | 9 +++++----
.../java/org/apache/mailbox/tools/indexer/ReIndexerImplTest.java | 1 -
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/mailbox/tools/indexer/src/main/java/org/apache/mailbox/tools/indexer/ReIndexerPerformer.java b/mailbox/tools/indexer/src/main/java/org/apache/mailbox/tools/indexer/ReIndexerPerformer.java
index 2dd9cde..8343f32 100644
--- a/mailbox/tools/indexer/src/main/java/org/apache/mailbox/tools/indexer/ReIndexerPerformer.java
+++ b/mailbox/tools/indexer/src/main/java/org/apache/mailbox/tools/indexer/ReIndexerPerformer.java
@@ -329,7 +329,7 @@ public class ReIndexerPerformer {
if (upToDate) {
return Mono.just(Either.<Failure, Result>right(Result.COMPLETED));
}
- return correct(entry, message);
+ return correct(entry);
}))
.onErrorResume(e -> {
LOGGER.warn("ReIndexing failed for {} {}", entry.getMailbox().generateAssociatedPath(), entry.getUid(), e);
@@ -337,9 +337,10 @@ public class ReIndexerPerformer {
});
}
- private Mono<Either<Failure, Result>> correct(ReIndexingEntry entry, MailboxMessage message) {
- return messageSearchIndex.delete(entry.getMailboxSession(), entry.getMailbox().getMailboxId(), ImmutableList.of(message.getUid()))
- .then(index(entry));
+ private Mono<Either<Failure, Result>> correct(ReIndexingEntry entry) {
+ // Leverage the fact that index does an upsert, removing pre-existing documents
+ // We do not need to delete the existing document before indexing it
+ return index(entry);
}
private Mono<Boolean> isIndexUpToDate(Mailbox mailbox, MailboxMessage message) {
diff --git a/mailbox/tools/indexer/src/test/java/org/apache/mailbox/tools/indexer/ReIndexerImplTest.java b/mailbox/tools/indexer/src/test/java/org/apache/mailbox/tools/indexer/ReIndexerImplTest.java
index a47f208..dc9088a 100644
--- a/mailbox/tools/indexer/src/test/java/org/apache/mailbox/tools/indexer/ReIndexerImplTest.java
+++ b/mailbox/tools/indexer/src/test/java/org/apache/mailbox/tools/indexer/ReIndexerImplTest.java
@@ -261,7 +261,6 @@ public class ReIndexerImplTest {
ArgumentCaptor<Mailbox> mailboxCaptor = ArgumentCaptor.forClass(Mailbox.class);
verify(messageSearchIndex).retrieveIndexedFlags(any(), any());
- verify(messageSearchIndex).delete(any(), any(), any());
verify(messageSearchIndex).add(any(MailboxSession.class), mailboxCaptor.capture(), messageCaptor.capture());
verifyNoMoreInteractions(messageSearchIndex);
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 06/24: JAMES-3486 RightManager listRights should
depend on mailboxId
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit da29db1d8798efa25afd8c98db4b1d5590b11e35
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Mon Dec 28 11:02:19 2020 +0700
JAMES-3486 RightManager listRights should depend on mailboxId
---
.../main/java/org/apache/james/mailbox/RightManager.java | 2 ++
.../apache/james/mailbox/store/StoreMailboxManager.java | 5 +++++
.../org/apache/james/mailbox/store/StoreRightManager.java | 7 +++++++
.../org/apache/james/jmap/api/change/MailboxChange.java | 15 +++++++--------
4 files changed, 21 insertions(+), 8 deletions(-)
diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/RightManager.java b/mailbox/api/src/main/java/org/apache/james/mailbox/RightManager.java
index deade96..7ec2421 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/RightManager.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/RightManager.java
@@ -85,6 +85,8 @@ public interface RightManager {
MailboxACL listRights(MailboxPath mailboxPath, MailboxSession session) throws MailboxException;
+ MailboxACL listRights(MailboxId mailboxId, MailboxSession session) throws MailboxException;
+
/**
* Returns the rights applicable to the user who has sent the current
* request on the mailbox designated by this mailboxPath.
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 f51b780..d9fdb2c 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
@@ -828,6 +828,11 @@ public class StoreMailboxManager implements MailboxManager {
}
@Override
+ public MailboxACL listRights(MailboxId mailboxId, MailboxSession session) throws MailboxException {
+ return storeRightManager.listRights(mailboxId, session);
+ }
+
+ @Override
public void applyRightsCommand(MailboxPath mailboxPath, MailboxACL.ACLCommand mailboxACLCommand, MailboxSession session) throws MailboxException {
storeRightManager.applyRightsCommand(mailboxPath, mailboxACLCommand, session);
}
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreRightManager.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreRightManager.java
index 3c15ace..89a2213 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreRightManager.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreRightManager.java
@@ -151,6 +151,13 @@ public class StoreRightManager implements RightManager {
return mailbox.getACL();
}
+ public MailboxACL listRights(MailboxId mailboxId, MailboxSession session) throws MailboxException {
+ MailboxMapper mapper = mailboxSessionMapperFactory.getMailboxMapper(session);
+ Mailbox mailbox = blockOptional(mapper.findMailboxById(mailboxId))
+ .orElseThrow(() -> new MailboxNotFoundException(mailboxId));
+ return mailbox.getACL();
+ }
+
@Override
public void applyRightsCommand(MailboxPath mailboxPath, ACLCommand mailboxACLCommand, MailboxSession session) throws MailboxException {
assertSharesBelongsToUserDomain(mailboxPath.getUser(), mailboxACLCommand);
diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/change/MailboxChange.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/change/MailboxChange.java
index 2b04691..d4ea806 100644
--- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/change/MailboxChange.java
+++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/change/MailboxChange.java
@@ -44,7 +44,6 @@ import org.apache.james.mailbox.events.MailboxListener.MailboxRenamed;
import org.apache.james.mailbox.exception.MailboxException;
import org.apache.james.mailbox.model.MailboxACL;
import org.apache.james.mailbox.model.MailboxId;
-import org.apache.james.mailbox.model.MailboxPath;
import com.github.steveash.guavate.Guavate;
import com.google.common.base.MoreObjects;
@@ -165,7 +164,7 @@ public class MailboxChange {
.updated(ImmutableList.of(mailboxRenamed.getMailboxId()))
.build();
- Stream<MailboxChange> shareeChanges = getSharees(mailboxRenamed.getNewPath(), mailboxRenamed.getUsername(), mailboxManager)
+ Stream<MailboxChange> shareeChanges = getSharees(mailboxRenamed.getMailboxId(), mailboxRenamed.getUsername(), mailboxManager)
.map(name -> MailboxChange.builder()
.accountId(AccountId.fromString(name))
.state(stateFactory.generate())
@@ -189,7 +188,7 @@ public class MailboxChange {
.updated(ImmutableList.of(mailboxACLUpdated.getMailboxId()))
.build();
- Stream<MailboxChange> shareeChanges = getSharees(mailboxACLUpdated.getMailboxPath(), mailboxACLUpdated.getUsername(), mailboxManager)
+ Stream<MailboxChange> shareeChanges = getSharees(mailboxACLUpdated.getMailboxId(), mailboxACLUpdated.getUsername(), mailboxManager)
.map(name -> MailboxChange.builder()
.accountId(AccountId.fromString(name))
.state(stateFactory.generate())
@@ -242,7 +241,7 @@ public class MailboxChange {
.updated(ImmutableList.of(messageAdded.getMailboxId()))
.build();
- Stream<MailboxChange> shareeChanges = getSharees(messageAdded.getMailboxPath(), messageAdded.getUsername(), mailboxManager)
+ Stream<MailboxChange> shareeChanges = getSharees(messageAdded.getMailboxId(), messageAdded.getUsername(), mailboxManager)
.map(name -> MailboxChange.builder()
.accountId(AccountId.fromString(name))
.state(stateFactory.generate())
@@ -269,7 +268,7 @@ public class MailboxChange {
.updated(ImmutableList.of(messageFlagUpdated.getMailboxId()))
.build();
- Stream<MailboxChange> shareeChanges = getSharees(messageFlagUpdated.getMailboxPath(), messageFlagUpdated.getUsername(), mailboxManager)
+ Stream<MailboxChange> shareeChanges = getSharees(messageFlagUpdated.getMailboxId(), messageFlagUpdated.getUsername(), mailboxManager)
.map(name -> MailboxChange.builder()
.accountId(AccountId.fromString(name))
.state(stateFactory.generate())
@@ -293,7 +292,7 @@ public class MailboxChange {
.updated(ImmutableList.of(expunged.getMailboxId()))
.build();
- Stream<MailboxChange> shareeChanges = getSharees(expunged.getMailboxPath(), expunged.getUsername(), mailboxManager)
+ Stream<MailboxChange> shareeChanges = getSharees(expunged.getMailboxId(), expunged.getUsername(), mailboxManager)
.map(name -> MailboxChange.builder()
.accountId(AccountId.fromString(name))
.state(stateFactory.generate())
@@ -311,10 +310,10 @@ public class MailboxChange {
}
}
- private static Stream<String> getSharees(MailboxPath path, Username username, MailboxManager mailboxManager) {
+ private static Stream<String> getSharees(MailboxId mailboxId, Username username, MailboxManager mailboxManager) {
MailboxSession mailboxSession = mailboxManager.createSystemSession(username);
try {
- MailboxACL mailboxACL = mailboxManager.listRights(path, mailboxSession);
+ MailboxACL mailboxACL = mailboxManager.listRights(mailboxId, mailboxSession);
return mailboxACL.getEntries().keySet()
.stream()
.filter(rfc4314Rights -> !rfc4314Rights.isNegative())
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 10/24: JAMES-3407 Disable read repairs on outdated
schema verison
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit be946ffc69823fa98d8fcd4d6f7c678c0d15bcf4
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Tue Dec 29 18:01:25 2020 +0700
JAMES-3407 Disable read repairs on outdated schema verison
Here is a flacky test output:
```
[ERROR] CassandraMailboxMapperTest$ConsistencyTest.createAfterPreviousDeleteOnFailedCreateShouldCreateAMailbox:617 Multiple Failures (1 failure)
Expected size:<1> but was:<2> in:
<[Mailbox{id=88fcc460-49bf-11eb-84d0-b78591c28a40, namespace=#private, user=Username{localPart=user, domainPart=Optional.empty}, name=name},
Mailbox{id=9a2095a0-49bf-11eb-84d0-b78591c28a40, namespace=#private, user=Username{localPart=user, domainPart=Optional.empty}, name=INBOX}]>
at CassandraMailboxMapperTest$ConsistencyTest.lambda$createAfterPreviousDeleteOnFailedCreateShouldCreateAMailbox$34(CassandraMailboxMapperTest$ConsistencyTest.java:628)
```
What is stricking is that createAfterPreviousDeleteOnFailedCreateShouldCreateAMailbox
do not rely on "name" mailbox, which do not appear in the test.
Likely an asynchronous read repair being triggered, that violates
test encapsulation...
---
.../cassandra/mail/CassandraMailboxMapperTest.java | 599 +++++++++++----------
1 file changed, 312 insertions(+), 287 deletions(-)
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java
index 7e9fb00..d2f060b 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxMapperTest.java
@@ -69,6 +69,7 @@ import com.github.fge.lambdas.Throwing;
import com.github.fge.lambdas.runnable.ThrowingRunnable;
import reactor.core.publisher.Mono;
+import reactor.core.scheduler.Schedulers;
class CassandraMailboxMapperTest {
private static final UidValidity UID_VALIDITY = UidValidity.of(52);
@@ -112,9 +113,14 @@ class CassandraMailboxMapperTest {
versionDAO.truncateVersion()
.then(versionDAO.updateVersion(new SchemaVersion(7)))
.block();
+ setUpTestee(CassandraConfiguration.DEFAULT_CONFIGURATION);
+ }
+
+ private void setUpTestee(CassandraConfiguration cassandraConfiguration) {
+ CassandraCluster cassandra = cassandraCluster.getCassandraCluster();
CassandraSchemaVersionManager versionManager = new CassandraSchemaVersionManager(versionDAO);
- CassandraACLDAOV1 aclDAOV1 = new CassandraACLDAOV1(cassandra.getConf(), CassandraConfiguration.DEFAULT_CONFIGURATION, CassandraConsistenciesConfiguration.DEFAULT);
+ CassandraACLDAOV1 aclDAOV1 = new CassandraACLDAOV1(cassandra.getConf(), cassandraConfiguration, CassandraConsistenciesConfiguration.DEFAULT);
CassandraACLDAOV2 aclDAOv2 = new CassandraACLDAOV2(cassandra.getConf());
JsonEventSerializer jsonEventSerializer = JsonEventSerializer
.forModules(ACLModule.ACL_UPDATE)
@@ -133,7 +139,7 @@ class CassandraMailboxMapperTest {
usersRightDAO,
aclMapper,
versionManager,
- CassandraConfiguration.DEFAULT_CONFIGURATION);
+ cassandraConfiguration);
}
@Nested
@@ -273,6 +279,14 @@ class CassandraMailboxMapperTest {
@Nested
class ReadRepairs {
+ @BeforeEach
+ void setVersion() {
+ // Read repairs should not be performed with an outdated data representation
+ versionDAO.truncateVersion()
+ .then(versionDAO.updateVersion(new SchemaVersion(8)))
+ .block();
+ }
+
@Test
void findMailboxByIdShouldEventuallyFixInconsistencyWhenMailboxIsNotInPath() {
mailboxDAO.save(MAILBOX)
@@ -770,335 +784,346 @@ class CassandraMailboxMapperTest {
return new MailboxPath(fromMailboxPath, StringUtils.repeat("b", 65537));
}
- @Test
- void deleteShouldDeleteMailboxAndMailboxPathFromV1Table() {
- mailboxDAO.save(MAILBOX)
- .block();
- mailboxPathDAO.save(MAILBOX_PATH, MAILBOX_ID)
- .block();
-
- testee.delete(MAILBOX).block();
-
- assertThat(testee.findMailboxByPath(MAILBOX_PATH).blockOptional())
- .isEmpty();
- }
-
- @Test
- void deleteShouldDeleteMailboxAndMailboxPathFromV2Table() {
- mailboxDAO.save(MAILBOX)
- .block();
- mailboxPathV2DAO.save(MAILBOX_PATH, MAILBOX_ID)
- .block();
-
- testee.delete(MAILBOX).block();
-
- assertThat(testee.findMailboxByPath(MAILBOX_PATH).blockOptional())
- .isEmpty();
- }
-
- @Test
- void deleteShouldDeleteMailboxAndMailboxPathFromV3Table() {
- mailboxDAO.save(MAILBOX)
- .block();
- mailboxPathV3DAO.save(MAILBOX)
- .block();
-
- testee.delete(MAILBOX).block();
-
- assertThat(testee.findMailboxByPath(MAILBOX_PATH).blockOptional())
- .isEmpty();
- }
-
- @Test
- void deleteShouldDeleteMailboxAndMailboxPathFromAllTables() {
- mailboxDAO.save(MAILBOX)
- .block();
- mailboxPathDAO.save(MAILBOX_PATH, MAILBOX_ID)
- .block();
- mailboxPathV2DAO.save(MAILBOX_PATH, MAILBOX_ID)
- .block();
- mailboxPathV3DAO.save(MAILBOX)
- .block();
-
- testee.delete(MAILBOX).block();
-
- assertThat(testee.findMailboxByPath(MAILBOX_PATH).blockOptional())
- .isEmpty();
- }
-
- @Test
- void findMailboxByPathShouldReturnMailboxWhenExistsInV1Table() {
- mailboxDAO.save(MAILBOX)
- .block();
- mailboxPathDAO.save(MAILBOX_PATH, MAILBOX_ID)
- .block();
-
- Mailbox mailbox = testee.findMailboxByPath(MAILBOX_PATH).block();
+ @Nested
+ class ReadFallbackToPreviousTables {
+ @BeforeEach
+ void setUp() {
+ // Read repairs are not supported accross schema versions...
+ setUpTestee(CassandraConfiguration.builder()
+ .mailboxReadRepair(0f)
+ .build());
+ }
- assertThat(mailbox.generateAssociatedPath()).isEqualTo(MAILBOX_PATH);
- }
+ @Test
+ void deleteShouldDeleteMailboxAndMailboxPathFromV1Table() {
+ mailboxDAO.save(MAILBOX)
+ .block();
+ mailboxPathDAO.save(MAILBOX_PATH, MAILBOX_ID)
+ .block();
- @Test
- void findMailboxByPathShouldReturnMailboxWhenExistsInV2Table() {
- mailboxDAO.save(MAILBOX)
- .block();
- mailboxPathV2DAO.save(MAILBOX_PATH, MAILBOX_ID)
- .block();
+ testee.delete(MAILBOX).block();
- Mailbox mailbox = testee.findMailboxByPath(MAILBOX_PATH).block();
+ assertThat(testee.findMailboxByPath(MAILBOX_PATH).blockOptional())
+ .isEmpty();
+ }
- assertThat(mailbox.generateAssociatedPath()).isEqualTo(MAILBOX_PATH);
- }
+ @Test
+ void deleteShouldDeleteMailboxAndMailboxPathFromV2Table() {
+ mailboxDAO.save(MAILBOX)
+ .block();
+ mailboxPathV2DAO.save(MAILBOX_PATH, MAILBOX_ID)
+ .block();
- @Test
- void findMailboxByPathShouldReturnMailboxWhenExistsInV3Table() {
- mailboxDAO.save(MAILBOX)
- .block();
- mailboxPathV3DAO.save(MAILBOX)
- .block();
+ testee.delete(MAILBOX).block();
- Mailbox mailbox = testee.findMailboxByPath(MAILBOX_PATH).block();
+ assertThat(testee.findMailboxByPath(MAILBOX_PATH).blockOptional())
+ .isEmpty();
+ }
- assertThat(mailbox.generateAssociatedPath()).isEqualTo(MAILBOX_PATH);
- }
+ @Test
+ void deleteShouldDeleteMailboxAndMailboxPathFromV3Table() {
+ mailboxDAO.save(MAILBOX)
+ .block();
+ mailboxPathV3DAO.save(MAILBOX)
+ .block();
- @Test
- void findMailboxByPathShouldReturnMailboxWhenExistsInAllTables() {
- mailboxDAO.save(MAILBOX)
- .block();
- mailboxPathDAO.save(MAILBOX_PATH, MAILBOX_ID)
- .block();
- mailboxPathV2DAO.save(MAILBOX_PATH, MAILBOX_ID)
- .block();
- mailboxPathV3DAO.save(MAILBOX)
- .block();
+ testee.delete(MAILBOX).block();
- Mailbox mailbox = testee.findMailboxByPath(MAILBOX_PATH).block();
+ assertThat(testee.findMailboxByPath(MAILBOX_PATH).blockOptional())
+ .isEmpty();
+ }
- assertThat(mailbox.generateAssociatedPath()).isEqualTo(MAILBOX_PATH);
- }
+ @Test
+ void deleteShouldDeleteMailboxAndMailboxPathFromAllTables() {
+ mailboxDAO.save(MAILBOX)
+ .block();
+ mailboxPathDAO.save(MAILBOX_PATH, MAILBOX_ID)
+ .block();
+ mailboxPathV2DAO.save(MAILBOX_PATH, MAILBOX_ID)
+ .block();
+ mailboxPathV3DAO.save(MAILBOX)
+ .block();
+
+ testee.delete(MAILBOX).block();
+
+ assertThat(testee.findMailboxByPath(MAILBOX_PATH).blockOptional())
+ .isEmpty();
+ }
- @Test
- void deleteShouldRemoveMailboxWhenInAllTables() {
- mailboxDAO.save(MAILBOX)
- .block();
- mailboxPathDAO.save(MAILBOX_PATH, MAILBOX_ID)
- .block();
- mailboxPathV2DAO.save(MAILBOX_PATH, MAILBOX_ID)
- .block();
- mailboxPathV3DAO.save(MAILBOX)
- .block();
+ @Test
+ void findMailboxByPathShouldReturnMailboxWhenExistsInV1Table() {
+ mailboxDAO.save(MAILBOX)
+ .block();
+ mailboxPathDAO.save(MAILBOX_PATH, MAILBOX_ID)
+ .block();
- testee.delete(MAILBOX).block();
+ Mailbox mailbox = testee.findMailboxByPath(MAILBOX_PATH).block();
- assertThat(testee.findMailboxByPath(MAILBOX_PATH).blockOptional())
- .isEmpty();
- }
+ assertThat(mailbox.generateAssociatedPath()).isEqualTo(MAILBOX_PATH);
+ }
- @Test
- void deleteShouldRemoveMailboxWhenInV1Tables() {
- mailboxDAO.save(MAILBOX)
- .block();
- mailboxPathDAO.save(MAILBOX_PATH, MAILBOX_ID)
- .block();
+ @Test
+ void findMailboxByPathShouldReturnMailboxWhenExistsInV2Table() {
+ mailboxDAO.save(MAILBOX)
+ .block();
+ mailboxPathV2DAO.save(MAILBOX_PATH, MAILBOX_ID)
+ .block();
- testee.delete(MAILBOX).block();
+ Mailbox mailbox = testee.findMailboxByPath(MAILBOX_PATH).block();
- assertThat(testee.findMailboxByPath(MAILBOX_PATH).blockOptional())
- .isEmpty();
- }
+ assertThat(mailbox.generateAssociatedPath()).isEqualTo(MAILBOX_PATH);
+ }
- @Test
- void deleteShouldRemoveMailboxWhenInV2Table() {
- mailboxDAO.save(MAILBOX)
- .block();
- mailboxPathV2DAO.save(MAILBOX_PATH, MAILBOX_ID)
- .block();
+ @Test
+ void findMailboxByPathShouldReturnMailboxWhenExistsInV3Table() {
+ mailboxDAO.save(MAILBOX)
+ .block();
+ mailboxPathV3DAO.save(MAILBOX)
+ .block();
- testee.delete(MAILBOX).block();
+ Mailbox mailbox = testee.findMailboxByPath(MAILBOX_PATH).block();
- assertThat(testee.findMailboxByPath(MAILBOX_PATH).blockOptional())
- .isEmpty();
- }
+ assertThat(mailbox.generateAssociatedPath()).isEqualTo(MAILBOX_PATH);
+ }
- @Test
- void findMailboxByPathShouldThrowWhenDoesntExistInBothTables() {
- mailboxDAO.save(MAILBOX)
- .block();
+ @Test
+ void findMailboxByPathShouldReturnMailboxWhenExistsInAllTables() {
+ mailboxDAO.save(MAILBOX)
+ .block();
+ mailboxPathDAO.save(MAILBOX_PATH, MAILBOX_ID)
+ .block();
+ mailboxPathV2DAO.save(MAILBOX_PATH, MAILBOX_ID)
+ .block();
+ mailboxPathV3DAO.save(MAILBOX)
+ .block();
+
+ Mailbox mailbox = testee.findMailboxByPath(MAILBOX_PATH).block();
+
+ assertThat(mailbox.generateAssociatedPath()).isEqualTo(MAILBOX_PATH);
+ }
- assertThat(testee.findMailboxByPath(MAILBOX_PATH).blockOptional())
- .isEmpty();
- }
+ @Test
+ void deleteShouldRemoveMailboxWhenInAllTables() {
+ mailboxDAO.save(MAILBOX)
+ .block();
+ mailboxPathDAO.save(MAILBOX_PATH, MAILBOX_ID)
+ .block();
+ mailboxPathV2DAO.save(MAILBOX_PATH, MAILBOX_ID)
+ .block();
+ mailboxPathV3DAO.save(MAILBOX)
+ .block();
+
+ testee.delete(MAILBOX).block();
+
+ assertThat(testee.findMailboxByPath(MAILBOX_PATH).blockOptional())
+ .isEmpty();
+ }
- @Test
- void findMailboxWithPathLikeShouldReturnMailboxesWhenExistsInV1Table() {
- mailboxDAO.save(MAILBOX)
- .block();
- mailboxPathDAO.save(MAILBOX_PATH, MAILBOX_ID)
- .block();
+ @Test
+ void deleteShouldRemoveMailboxWhenInV1Tables() {
+ mailboxDAO.save(MAILBOX)
+ .block();
+ mailboxPathDAO.save(MAILBOX_PATH, MAILBOX_ID)
+ .block();
- List<Mailbox> mailboxes = testee.findMailboxWithPathLike(MailboxQuery.builder()
- .privateNamespace()
- .username(USER)
- .expression(Wildcard.INSTANCE)
- .build()
- .asUserBound())
- .collectList().block();
+ testee.delete(MAILBOX).block();
- assertThat(mailboxes).containsOnly(MAILBOX);
- }
+ assertThat(testee.findMailboxByPath(MAILBOX_PATH).blockOptional())
+ .isEmpty();
+ }
- @Test
- void findMailboxWithPathLikeShouldReturnMailboxesWhenExistsInBothTables() {
- mailboxDAO.save(MAILBOX)
- .block();
- mailboxPathDAO.save(MAILBOX_PATH, MAILBOX_ID)
- .block();
- mailboxPathV2DAO.save(MAILBOX_PATH, MAILBOX_ID)
- .block();
+ @Test
+ void deleteShouldRemoveMailboxWhenInV2Table() {
+ mailboxDAO.save(MAILBOX)
+ .block();
+ mailboxPathV2DAO.save(MAILBOX_PATH, MAILBOX_ID)
+ .block();
- List<Mailbox> mailboxes = testee.findMailboxWithPathLike(MailboxQuery.builder()
- .privateNamespace()
- .username(USER)
- .expression(Wildcard.INSTANCE)
- .build()
- .asUserBound())
- .collectList().block();
+ testee.delete(MAILBOX).block();
- assertThat(mailboxes).containsOnly(MAILBOX);
- }
+ assertThat(testee.findMailboxByPath(MAILBOX_PATH).blockOptional())
+ .isEmpty();
+ }
- @Test
- void findMailboxWithPathLikeShouldReturnMailboxesWhenExistsInV2Table() {
- mailboxDAO.save(MAILBOX)
- .block();
- mailboxPathV2DAO.save(MAILBOX_PATH, MAILBOX_ID)
- .block();
+ @Test
+ void findMailboxByPathShouldThrowWhenDoesntExistInBothTables() {
+ mailboxDAO.save(MAILBOX)
+ .block();
- List<Mailbox> mailboxes = testee.findMailboxWithPathLike(MailboxQuery.builder()
- .privateNamespace()
- .username(USER)
- .expression(Wildcard.INSTANCE)
- .build()
- .asUserBound())
- .collectList().block();
+ assertThat(testee.findMailboxByPath(MAILBOX_PATH).blockOptional())
+ .isEmpty();
+ }
- assertThat(mailboxes).containsOnly(MAILBOX);
- }
+ @Test
+ void findMailboxWithPathLikeShouldReturnMailboxesWhenExistsInV1Table() {
+ mailboxDAO.save(MAILBOX)
+ .block();
+ mailboxPathDAO.save(MAILBOX_PATH, MAILBOX_ID)
+ .block();
- @Test
- void findMailboxWithPathLikeShouldReturnMailboxesWhenExistsInV3Table() {
- mailboxDAO.save(MAILBOX)
- .block();
- mailboxPathV3DAO.save(MAILBOX)
- .block();
+ List<Mailbox> mailboxes = testee.findMailboxWithPathLike(MailboxQuery.builder()
+ .privateNamespace()
+ .username(USER)
+ .expression(Wildcard.INSTANCE)
+ .build()
+ .asUserBound())
+ .collectList().block();
- List<Mailbox> mailboxes = testee.findMailboxWithPathLike(MailboxQuery.builder()
- .privateNamespace()
- .username(USER)
- .expression(Wildcard.INSTANCE)
- .build()
- .asUserBound())
- .collectList()
- .block();
+ assertThat(mailboxes).containsOnly(MAILBOX);
+ }
- assertThat(mailboxes).containsOnly(MAILBOX);
- }
+ @Test
+ void findMailboxWithPathLikeShouldReturnMailboxesWhenExistsInBothTables() {
+ mailboxDAO.save(MAILBOX)
+ .block();
+ mailboxPathDAO.save(MAILBOX_PATH, MAILBOX_ID)
+ .block();
+ mailboxPathV2DAO.save(MAILBOX_PATH, MAILBOX_ID)
+ .block();
+
+ List<Mailbox> mailboxes = testee.findMailboxWithPathLike(MailboxQuery.builder()
+ .privateNamespace()
+ .username(USER)
+ .expression(Wildcard.INSTANCE)
+ .build()
+ .asUserBound())
+ .collectList().block();
- @Test
- void hasChildrenShouldReturnChildWhenExistsInV1Table() {
- mailboxDAO.save(MAILBOX)
- .block();
- mailboxPathDAO.save(MAILBOX_PATH, MAILBOX_ID)
- .block();
- CassandraId childMailboxId = CassandraId.timeBased();
- MailboxPath childMailboxPath = MailboxPath.forUser(USER, "name.child");
- Mailbox childMailbox = new Mailbox(childMailboxPath, UID_VALIDITY, childMailboxId);
- mailboxDAO.save(childMailbox)
- .block();
- mailboxPathDAO.save(childMailboxPath, childMailboxId)
- .block();
-
- boolean hasChildren = testee.hasChildren(MAILBOX, '.').block();
+ assertThat(mailboxes).containsOnly(MAILBOX);
+ }
- assertThat(hasChildren).isTrue();
- }
+ @Test
+ void findMailboxWithPathLikeShouldReturnMailboxesWhenExistsInV2Table() {
+ mailboxDAO.save(MAILBOX)
+ .block();
+ mailboxPathV2DAO.save(MAILBOX_PATH, MAILBOX_ID)
+ .block();
- @Test
- void hasChildrenShouldReturnChildWhenExistsInBothTables() {
- mailboxDAO.save(MAILBOX)
- .block();
- mailboxPathDAO.save(MAILBOX_PATH, MAILBOX_ID)
- .block();
- mailboxPathV2DAO.save(MAILBOX_PATH, MAILBOX_ID)
- .block();
- CassandraId childMailboxId = CassandraId.timeBased();
- MailboxPath childMailboxPath = MailboxPath.forUser(USER, "name.child");
- Mailbox childMailbox = new Mailbox(childMailboxPath, UID_VALIDITY, childMailboxId);
- mailboxDAO.save(childMailbox)
- .block();
- mailboxPathDAO.save(childMailboxPath, childMailboxId)
- .block();
+ List<Mailbox> mailboxes = testee.findMailboxWithPathLike(MailboxQuery.builder()
+ .privateNamespace()
+ .username(USER)
+ .expression(Wildcard.INSTANCE)
+ .build()
+ .asUserBound())
+ .collectList().block();
- boolean hasChildren = testee.hasChildren(MAILBOX, '.').block();
+ assertThat(mailboxes).containsOnly(MAILBOX);
+ }
- assertThat(hasChildren).isTrue();
- }
+ @Test
+ void findMailboxWithPathLikeShouldReturnMailboxesWhenExistsInV3Table() {
+ mailboxDAO.save(MAILBOX)
+ .block();
+ mailboxPathV3DAO.save(MAILBOX)
+ .block();
- @Test
- void hasChildrenShouldReturnChildWhenExistsInV2Table() {
- mailboxDAO.save(MAILBOX)
- .block();
- mailboxPathV2DAO.save(MAILBOX_PATH, MAILBOX_ID)
- .block();
- CassandraId childMailboxId = CassandraId.timeBased();
- MailboxPath childMailboxPath = MailboxPath.forUser(USER, "name.child");
- Mailbox childMailbox = new Mailbox(childMailboxPath, UID_VALIDITY, childMailboxId);
- mailboxDAO.save(childMailbox)
- .block();
- mailboxPathV2DAO.save(childMailboxPath, childMailboxId)
- .block();
-
- boolean hasChildren = testee.hasChildren(MAILBOX, '.').block();
-
- assertThat(hasChildren).isTrue();
- }
+ List<Mailbox> mailboxes = testee.findMailboxWithPathLike(MailboxQuery.builder()
+ .privateNamespace()
+ .username(USER)
+ .expression(Wildcard.INSTANCE)
+ .build()
+ .asUserBound())
+ .collectList()
+ .block();
- @Test
- void hasChildrenShouldReturnChildWhenExistsInV3Table() {
- mailboxDAO.save(MAILBOX)
- .block();
- mailboxPathV3DAO.save(MAILBOX)
- .block();
- CassandraId childMailboxId = CassandraId.timeBased();
- MailboxPath childMailboxPath = MailboxPath.forUser(USER, "name.child");
- Mailbox childMailbox = new Mailbox(childMailboxPath, UID_VALIDITY, childMailboxId);
- mailboxDAO.save(childMailbox)
- .block();
- mailboxPathV3DAO.save(childMailbox)
- .block();
+ assertThat(mailboxes).containsOnly(MAILBOX);
+ }
- boolean hasChildren = testee.hasChildren(MAILBOX, '.').block();
+ @Test
+ void hasChildrenShouldReturnChildWhenExistsInV1Table() {
+ mailboxDAO.save(MAILBOX)
+ .block();
+ mailboxPathDAO.save(MAILBOX_PATH, MAILBOX_ID)
+ .block();
+ CassandraId childMailboxId = CassandraId.timeBased();
+ MailboxPath childMailboxPath = MailboxPath.forUser(USER, "name.child");
+ Mailbox childMailbox = new Mailbox(childMailboxPath, UID_VALIDITY, childMailboxId);
+ mailboxDAO.save(childMailbox)
+ .block();
+ mailboxPathDAO.save(childMailboxPath, childMailboxId)
+ .block();
+
+ boolean hasChildren = testee.hasChildren(MAILBOX, '.').block();
+
+ assertThat(hasChildren).isTrue();
+ }
- assertThat(hasChildren).isTrue();
- }
+ @Test
+ void hasChildrenShouldReturnChildWhenExistsInBothTables() {
+ mailboxDAO.save(MAILBOX)
+ .block();
+ mailboxPathDAO.save(MAILBOX_PATH, MAILBOX_ID)
+ .block();
+ mailboxPathV2DAO.save(MAILBOX_PATH, MAILBOX_ID)
+ .block();
+ CassandraId childMailboxId = CassandraId.timeBased();
+ MailboxPath childMailboxPath = MailboxPath.forUser(USER, "name.child");
+ Mailbox childMailbox = new Mailbox(childMailboxPath, UID_VALIDITY, childMailboxId);
+ mailboxDAO.save(childMailbox)
+ .block();
+ mailboxPathDAO.save(childMailboxPath, childMailboxId)
+ .block();
+
+ boolean hasChildren = testee.hasChildren(MAILBOX, '.').block();
+
+ assertThat(hasChildren).isTrue();
+ }
- @Test
- void findMailboxWithPathLikeShouldRemoveDuplicatesAndKeepV3() {
- mailboxDAO.save(MAILBOX).block();
- mailboxPathV3DAO.save(MAILBOX).block();
+ @Test
+ void hasChildrenShouldReturnChildWhenExistsInV2Table() {
+ mailboxDAO.save(MAILBOX)
+ .block();
+ mailboxPathV2DAO.save(MAILBOX_PATH, MAILBOX_ID)
+ .block();
+ CassandraId childMailboxId = CassandraId.timeBased();
+ MailboxPath childMailboxPath = MailboxPath.forUser(USER, "name.child");
+ Mailbox childMailbox = new Mailbox(childMailboxPath, UID_VALIDITY, childMailboxId);
+ mailboxDAO.save(childMailbox)
+ .block();
+ mailboxPathV2DAO.save(childMailboxPath, childMailboxId)
+ .block();
+
+ boolean hasChildren = testee.hasChildren(MAILBOX, '.').block();
+
+ assertThat(hasChildren).isTrue();
+ }
- mailboxDAO.save(MAILBOX_BIS).block();
- mailboxPathDAO.save(MAILBOX_PATH, MAILBOX_ID_2).block();
+ @Test
+ void hasChildrenShouldReturnChildWhenExistsInV3Table() {
+ mailboxDAO.save(MAILBOX)
+ .block();
+ mailboxPathV3DAO.save(MAILBOX)
+ .block();
+ CassandraId childMailboxId = CassandraId.timeBased();
+ MailboxPath childMailboxPath = MailboxPath.forUser(USER, "name.child");
+ Mailbox childMailbox = new Mailbox(childMailboxPath, UID_VALIDITY, childMailboxId);
+ mailboxDAO.save(childMailbox)
+ .block();
+ mailboxPathV3DAO.save(childMailbox)
+ .block();
+
+ boolean hasChildren = testee.hasChildren(MAILBOX, '.').block();
+
+ assertThat(hasChildren).isTrue();
+ }
- assertThat(testee.findMailboxWithPathLike(
- MailboxQuery.builder()
- .privateNamespace()
- .username(USER)
- .expression(Wildcard.INSTANCE)
- .build()
- .asUserBound())
- .collectList().block())
- .containsOnly(MAILBOX);
+ @Test
+ void findMailboxWithPathLikeShouldRemoveDuplicatesAndKeepV3() {
+ mailboxDAO.save(MAILBOX).block();
+ mailboxPathV3DAO.save(MAILBOX).block();
+
+ mailboxDAO.save(MAILBOX_BIS).block();
+ mailboxPathDAO.save(MAILBOX_PATH, MAILBOX_ID_2).block();
+
+ assertThat(testee.findMailboxWithPathLike(
+ MailboxQuery.builder()
+ .privateNamespace()
+ .username(USER)
+ .expression(Wildcard.INSTANCE)
+ .build()
+ .asUserBound())
+ .collectList().block())
+ .containsOnly(MAILBOX);
+ }
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 03/24: JAMES-3486 Test MailboxId should be generated
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 49b3668bf6ebd66726a364788f24c3694a67891e
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Mon Dec 28 10:44:40 2020 +0700
JAMES-3486 Test MailboxId should be generated
---
.../james/jmap/rfc8621/memory/MemoryMailboxChangesMethodTest.java | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryMailboxChangesMethodTest.java b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryMailboxChangesMethodTest.java
index 58e6359..df68a52 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryMailboxChangesMethodTest.java
+++ b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryMailboxChangesMethodTest.java
@@ -26,10 +26,13 @@ import org.apache.james.JamesServerBuilder;
import org.apache.james.JamesServerExtension;
import org.apache.james.jmap.api.change.State;
import org.apache.james.jmap.rfc8621.contract.MailboxChangesMethodContract;
+import org.apache.james.mailbox.inmemory.InMemoryId;
+import org.apache.james.mailbox.model.MailboxId;
import org.apache.james.modules.TestJMAPServerModule;
import org.junit.jupiter.api.extension.RegisterExtension;
public class MemoryMailboxChangesMethodTest implements MailboxChangesMethodContract {
+
@RegisterExtension
static JamesServerExtension testExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
.server(configuration -> GuiceJamesServer.forConfiguration(configuration)
@@ -41,4 +44,9 @@ public class MemoryMailboxChangesMethodTest implements MailboxChangesMethodContr
public State.Factory stateFactory() {
return new State.DefaultFactory();
}
+
+ @Override
+ public MailboxId generateMailboxId() {
+ return InMemoryId.of(0);
+ }
}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 13/24: JAMES-3485 Remove unused method
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 893ccaa5232729c55530b3f84bfc02f32478a045
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Fri Dec 25 19:32:12 2020 +0700
JAMES-3485 Remove unused method
---
.../main/java/org/apache/james/mailbox/store/StoreMailboxManager.java | 4 ----
1 file changed, 4 deletions(-)
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 d9fdb2c..23b3e25 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
@@ -749,10 +749,6 @@ public class StoreMailboxManager implements MailboxManager {
}
}
- private Flux<Mailbox> getAllReadableMailbox(MailboxQuery mailboxQuery, MailboxSession session) throws MailboxException {
- return searchMailboxes(mailboxQuery, session, Right.Read);
- }
-
private Flux<Mailbox> filterReadable(ImmutableSet<MailboxId> inMailboxes, MailboxSession session) throws MailboxException {
MailboxMapper mailboxMapper = mailboxSessionMapperFactory.getMailboxMapper(session);
return Flux.fromIterable(inMailboxes)
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 11/24: JAMES-3485 Group attachment right checking
together
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 9fe885b27a0791a8e2f700adb210faf3dd4b045e
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Fri Dec 25 19:14:30 2020 +0700
JAMES-3485 Group attachment right checking together
A common JMAP pattern is to save a message being a copy of
another one (draft update).
Updating a draft with several attachment will lead to right
checking to happen for each attachment independently despite them
to be related to the same message.
So here are the reads being performed:
- From attachmentId retrieve the owner -> miss
- From attachmentId retrieve the messageId
- From the messageId retrieve the message (and its mailbox
context) - imapUidTable + messageV3 table
- Then read the mailbox to validate the ACLs (mailbox + aclV2)
---
.../mailbox/store/StoreAttachmentManager.java | 48 ++++++++++++++++++++--
1 file changed, 45 insertions(+), 3 deletions(-)
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreAttachmentManager.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreAttachmentManager.java
index 7a4efe2..4044b4c 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreAttachmentManager.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreAttachmentManager.java
@@ -23,9 +23,13 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Stream;
import javax.inject.Inject;
+import org.apache.commons.lang3.tuple.Pair;
import org.apache.james.core.Username;
import org.apache.james.mailbox.AttachmentManager;
import org.apache.james.mailbox.MailboxSession;
@@ -41,7 +45,10 @@ import org.reactivestreams.Publisher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.github.fge.lambdas.Throwing;
import com.github.steveash.guavate.Guavate;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
public class StoreAttachmentManager implements AttachmentManager {
private static final Logger LOGGER = LoggerFactory.getLogger(StoreAttachmentManager.class);
@@ -70,9 +77,7 @@ public class StoreAttachmentManager implements AttachmentManager {
@Override
public List<AttachmentMetadata> getAttachments(List<AttachmentId> attachmentIds, MailboxSession mailboxSession) throws MailboxException {
- List<AttachmentId> accessibleAttachmentIds = attachmentIds.stream()
- .filter(attachmentId -> userHasAccessToAttachment(attachmentId, mailboxSession))
- .collect(Guavate.toImmutableList());
+ Collection<AttachmentId> accessibleAttachmentIds = keepAccessible(attachmentIds, mailboxSession);
return attachmentMapperFactory.getAttachmentMapper(mailboxSession).getAttachments(accessibleAttachmentIds);
}
@@ -93,6 +98,24 @@ public class StoreAttachmentManager implements AttachmentManager {
}
}
+ private Collection<AttachmentId> keepAccessible(Collection<AttachmentId> attachmentIds, MailboxSession mailboxSession) {
+ try {
+ Set<AttachmentId> referencedByMessages = referencedInUserMessages(attachmentIds, mailboxSession);
+ ImmutableSet<AttachmentId> owned = Sets.difference(ImmutableSet.copyOf(attachmentIds), referencedByMessages)
+ .stream()
+ .filter(Throwing.<AttachmentId>predicate(id -> isExplicitlyAOwner(id, mailboxSession)).sneakyThrow())
+ .collect(Guavate.toImmutableSet());
+
+ return ImmutableSet.<AttachmentId>builder()
+ .addAll(referencedByMessages)
+ .addAll(owned)
+ .build();
+ } catch (MailboxException e) {
+ LOGGER.warn("Error while checking attachment related accessible message ids", e);
+ throw new RuntimeException(e);
+ }
+ }
+
private boolean isReferencedInUserMessages(AttachmentId attachmentId, MailboxSession mailboxSession) throws MailboxException {
Collection<MessageId> relatedMessageIds = getRelatedMessageIds(attachmentId, mailboxSession);
return !messageIdManager
@@ -100,6 +123,25 @@ public class StoreAttachmentManager implements AttachmentManager {
.isEmpty();
}
+ private Set<AttachmentId> referencedInUserMessages(Collection<AttachmentId> attachmentIds, MailboxSession mailboxSession) throws MailboxException {
+ Map<MessageId, Collection<AttachmentId>> entries = attachmentIds.stream()
+ .flatMap(Throwing.<AttachmentId, Stream<Pair<MessageId, AttachmentId>>>function(
+ attachmentId -> getRelatedMessageIds(attachmentId, mailboxSession).stream()
+ .map(messageId -> Pair.of(messageId, attachmentId)))
+ .sneakyThrow())
+ .collect(Guavate.toImmutableListMultimap(
+ Pair::getKey,
+ Pair::getValue))
+ .asMap();
+
+ Set<MessageId> accessibleMessages = messageIdManager.accessibleMessages(entries.keySet(), mailboxSession);
+
+ return entries.entrySet().stream()
+ .filter(entry -> accessibleMessages.contains(entry.getKey()))
+ .flatMap(entry -> entry.getValue().stream())
+ .collect(Guavate.toImmutableSet());
+ }
+
private boolean isExplicitlyAOwner(AttachmentId attachmentId, MailboxSession mailboxSession) throws MailboxException {
Collection<Username> explicitOwners = attachmentMapperFactory.getAttachmentMapper(mailboxSession)
.getOwners(attachmentId);
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 08/24: JAMES-3461 Register MailboxChangeListener by
default
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit d619483c7c554b809300a4a4cceb0db2dc51f3c0
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Thu Dec 31 18:15:38 2020 +0700
JAMES-3461 Register MailboxChangeListener by default
tI usage is needed for JMAP RFC-8621 correctness, running it is not an option
---
.../java/org/apache/james/modules/mailbox/CassandraMailboxModule.java | 1 +
.../jmap/src/main/java/org/apache/james/jmap/draft/JMAPModule.java | 2 ++
.../src/test/resources/listeners.xml | 3 ---
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java
index 86ac2e8..722a653 100644
--- a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java
+++ b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java
@@ -184,6 +184,7 @@ public class CassandraMailboxModule extends AbstractModule {
bind(MailboxManager.class).to(CassandraMailboxManager.class);
bind(StoreMailboxManager.class).to(CassandraMailboxManager.class);
bind(MailboxChangeRepository.class).to(CassandraMailboxChangeRepository.class);
+ bind(State.Factory.class).to(CassandraStateFactory.class);
bind(MailboxId.Factory.class).to(CassandraId.Factory.class);
bind(State.Factory.class).to(CassandraStateFactory.class);
bind(MessageId.Factory.class).to(CassandraMessageId.Factory.class);
diff --git a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JMAPModule.java b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JMAPModule.java
index 49613ca..95f6f5b 100644
--- a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JMAPModule.java
+++ b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JMAPModule.java
@@ -34,6 +34,7 @@ import org.apache.james.filesystem.api.FileSystem;
import org.apache.james.jmap.JMAPConfiguration;
import org.apache.james.jmap.JMAPServer;
import org.apache.james.jmap.Version;
+import org.apache.james.jmap.change.MailboxChangeListener;
import org.apache.james.jmap.draft.methods.RequestHandler;
import org.apache.james.jmap.draft.send.PostDequeueDecoratorFactory;
import org.apache.james.jmap.draft.utils.JsoupHtmlTextExtractor;
@@ -125,6 +126,7 @@ public class JMAPModule extends AbstractModule {
bind(MailQueueItemDecoratorFactory.class).to(PostDequeueDecoratorFactory.class).in(Scopes.SINGLETON);
Multibinder.newSetBinder(binder(), MailboxListener.GroupMailboxListener.class).addBinding().to(PropagateLookupRightListener.class);
+ Multibinder.newSetBinder(binder(), MailboxListener.GroupMailboxListener.class).addBinding().to(MailboxChangeListener.class);
Multibinder<Version> supportedVersions = Multibinder.newSetBinder(binder(), Version.class);
supportedVersions.addBinding().toInstance(Version.DRAFT);
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/resources/listeners.xml b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/resources/listeners.xml
index af44f35..a1a139d 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/resources/listeners.xml
+++ b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/resources/listeners.xml
@@ -47,7 +47,4 @@
<class>org.apache.james.jmap.event.PopulateEmailQueryViewListener</class>
<async>true</async>
</listener>
- <listener>
- <class>org.apache.james.jmap.change.MailboxChangeListener</class>
- </listener>
</listeners>
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 12/24: JAMES-3485 Avoid reading messageV3 table
upon attachment right setting
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 1ef4ffbf7f9ca5dc7fed1580cbb8059a415b0c0a
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Fri Dec 25 19:21:46 2020 +0700
JAMES-3485 Avoid reading messageV3 table upon attachment right setting
Relying on message metadata reads allow to bypass this step...
---
.../james/mailbox/store/StoreMessageIdManager.java | 24 ++++++++++++++--------
1 file changed, 15 insertions(+), 9 deletions(-)
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageIdManager.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageIdManager.java
index 43578c4..eecc808 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageIdManager.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageIdManager.java
@@ -29,6 +29,7 @@ import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
+import java.util.stream.Stream;
import javax.inject.Inject;
import javax.mail.Flags;
@@ -141,13 +142,17 @@ public class StoreMessageIdManager implements MessageIdManager {
@Override
public Set<MessageId> accessibleMessages(Collection<MessageId> messageIds, MailboxSession mailboxSession) throws MailboxException {
MessageIdMapper messageIdMapper = mailboxSessionMapperFactory.getMessageIdMapper(mailboxSession);
- List<MailboxMessage> messageList = messageIdMapper.find(messageIds, MessageMapper.FetchType.Metadata);
+ ImmutableList<ComposedMessageIdWithMetaData> idList = Flux.fromIterable(messageIds)
+ .flatMap(messageIdMapper::findMetadata, DEFAULT_CONCURRENCY)
+ .collect(Guavate.toImmutableList())
+ .block();
- ImmutableSet<MailboxId> allowedMailboxIds = getAllowedMailboxIds(mailboxSession, messageList, Right.Read);
+ ImmutableSet<MailboxId> allowedMailboxIds = getAllowedMailboxIds(mailboxSession, idList.stream()
+ .map(id -> id.getComposedMessageId().getMailboxId()), Right.Read);
- return messageList.stream()
- .filter(message -> allowedMailboxIds.contains(message.getMailboxId()))
- .map(MailboxMessage::getMessageId)
+ return idList.stream()
+ .filter(id -> allowedMailboxIds.contains(id.getComposedMessageId().getMailboxId()))
+ .map(id -> id.getComposedMessageId().getMessageId())
.collect(Guavate.toImmutableSet());
}
@@ -181,9 +186,8 @@ public class StoreMessageIdManager implements MessageIdManager {
.flatMap(Function.identity(), DEFAULT_CONCURRENCY);
}
- private ImmutableSet<MailboxId> getAllowedMailboxIds(MailboxSession mailboxSession, List<MailboxMessage> messageList, Right... rights) throws MailboxException {
- return MailboxReactorUtils.block(Flux.fromIterable(messageList)
- .map(MailboxMessage::getMailboxId)
+ private ImmutableSet<MailboxId> getAllowedMailboxIds(MailboxSession mailboxSession, Stream<MailboxId> idList, Right... rights) throws MailboxException {
+ return MailboxReactorUtils.block(Flux.fromStream(idList)
.distinct()
.filterWhen(hasRightsOnMailboxReactive(mailboxSession, rights), DEFAULT_CONCURRENCY)
.collect(Guavate.toImmutableSet()));
@@ -213,7 +217,9 @@ public class StoreMessageIdManager implements MessageIdManager {
MessageIdMapper messageIdMapper = mailboxSessionMapperFactory.getMessageIdMapper(mailboxSession);
List<MailboxMessage> messageList = messageIdMapper.find(messageIds, MessageMapper.FetchType.Metadata);
- ImmutableSet<MailboxId> allowedMailboxIds = getAllowedMailboxIds(mailboxSession, messageList, Right.DeleteMessages);
+ ImmutableSet<MailboxId> allowedMailboxIds = getAllowedMailboxIds(mailboxSession, messageList
+ .stream()
+ .map(MailboxMessage::getMailboxId), Right.DeleteMessages);
ImmutableSet<MessageId> accessibleMessages = messageList.stream()
.filter(message -> allowedMailboxIds.contains(message.getMailboxId()))
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 22/24: JAMES-3471 Adapt the different
implementations of MessageMapper and MessageIdMapper to add the message id
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 3ba4665a13ebbd2218555c7bc8e7969f68c08b8c
Author: Rene Cordier <rc...@linagora.com>
AuthorDate: Thu Dec 31 17:50:07 2020 +0700
JAMES-3471 Adapt the different implementations of MessageMapper and MessageIdMapper to add the message id
---
.../james/mailbox/cassandra/mail/CassandraMessageIdMapper.java | 1 +
.../james/mailbox/cassandra/mail/CassandraMessageMapper.java | 2 ++
.../main/java/org/apache/james/mailbox/jpa/mail/MessageUtils.java | 1 +
.../apache/james/mailbox/maildir/mail/MaildirMessageMapper.java | 1 +
.../james/mailbox/inmemory/mail/InMemoryMessageIdMapper.java | 1 +
.../org/apache/james/mailbox/store/mail/AbstractMessageMapper.java | 1 +
.../mailbox/store/AbstractMessageIdManagerSideEffectTest.java | 1 +
.../apache/james/mailbox/store/mail/model/MessageIdMapperTest.java | 7 +++++++
.../apache/james/mailbox/store/mail/model/MessageMapperTest.java | 5 +++++
9 files changed, 20 insertions(+)
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapper.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapper.java
index 19fe49b..3fae704 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapper.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageIdMapper.java
@@ -268,6 +268,7 @@ public class CassandraMessageIdMapper implements MessageIdMapper {
return Pair.of(composedMessageIdWithMetaData.getComposedMessageId().getMailboxId(),
UpdatedFlags.builder()
.uid(composedMessageIdWithMetaData.getComposedMessageId().getUid())
+ .messageId(composedMessageIdWithMetaData.getComposedMessageId().getMessageId())
.modSeq(composedMessageIdWithMetaData.getModSeq())
.oldFlags(oldFlags)
.newFlags(composedMessageIdWithMetaData.getFlags())
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
index 88c23e6..419b8f8 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageMapper.java
@@ -541,6 +541,7 @@ public class CassandraMessageMapper implements MessageMapper {
if (identicalFlags(oldFlags, newFlags)) {
return Mono.just(FlagsUpdateStageResult.success(UpdatedFlags.builder()
.uid(oldMetaData.getComposedMessageId().getUid())
+ .messageId(oldMetaData.getComposedMessageId().getMessageId())
.modSeq(oldMetaData.getModSeq())
.oldFlags(oldFlags)
.newFlags(newFlags)
@@ -552,6 +553,7 @@ public class CassandraMessageMapper implements MessageMapper {
if (success) {
return FlagsUpdateStageResult.success(UpdatedFlags.builder()
.uid(oldMetaData.getComposedMessageId().getUid())
+ .messageId(oldMetaData.getComposedMessageId().getMessageId())
.modSeq(newModSeq)
.oldFlags(oldFlags)
.newFlags(newFlags)
diff --git a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/MessageUtils.java b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/MessageUtils.java
index bd5d513..1c097e7 100644
--- a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/MessageUtils.java
+++ b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/MessageUtils.java
@@ -74,6 +74,7 @@ class MessageUtils {
updatedFlags.add(UpdatedFlags.builder()
.uid(member.getUid())
+ .messageId(member.getMessageId())
.modSeq(member.getModSeq())
.newFlags(newFlags)
.oldFlags(originalFlags)
diff --git a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/MaildirMessageMapper.java b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/MaildirMessageMapper.java
index e670055..f8f7894 100644
--- a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/MaildirMessageMapper.java
+++ b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/MaildirMessageMapper.java
@@ -194,6 +194,7 @@ public class MaildirMessageMapper extends AbstractMessageMapper {
updatedFlags.add(UpdatedFlags.builder()
.uid(member.getUid())
+ .messageId(member.getMessageId())
.modSeq(member.getModSeq())
.newFlags(newFlags)
.oldFlags(originalFlags)
diff --git a/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryMessageIdMapper.java b/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryMessageIdMapper.java
index 521cb96..626640a 100644
--- a/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryMessageIdMapper.java
+++ b/mailbox/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryMessageIdMapper.java
@@ -151,6 +151,7 @@ public class InMemoryMessageIdMapper implements MessageIdMapper {
UpdatedFlags updatedFlags = UpdatedFlags.builder()
.modSeq(message.getModSeq())
.uid(message.getUid())
+ .messageId(message.getMessageId())
.oldFlags(message.createFlags())
.newFlags(newState)
.build();
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/AbstractMessageMapper.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/AbstractMessageMapper.java
index 9fd5cf3..a80eead 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/AbstractMessageMapper.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/AbstractMessageMapper.java
@@ -102,6 +102,7 @@ public abstract class AbstractMessageMapper extends TransactionalMapper implemen
updatedFlags.add(UpdatedFlags.builder()
.uid(member.getUid())
+ .messageId(member.getMessageId())
.modSeq(member.getModSeq())
.newFlags(newFlags)
.oldFlags(originalFlags)
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerSideEffectTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerSideEffectTest.java
index 751704b..63e87f1 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerSideEffectTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerSideEffectTest.java
@@ -467,6 +467,7 @@ public abstract class AbstractMessageIdManagerSideEffectTest {
ModSeq modSeq = messageResult.getModSeq();
UpdatedFlags updatedFlags = UpdatedFlags.builder()
.uid(messageUid)
+ .messageId(messageId)
.modSeq(modSeq)
.oldFlags(FLAGS)
.newFlags(newFlags)
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageIdMapperTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageIdMapperTest.java
index 6f97388..5093ea9 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageIdMapperTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageIdMapperTest.java
@@ -355,6 +355,7 @@ public abstract class MessageIdMapperTest {
ModSeq modSeq = mapperProvider.highestModSeq(benwaInboxMailbox);
UpdatedFlags expectedUpdatedFlags = UpdatedFlags.builder()
.uid(message1.getUid())
+ .messageId(messageId)
.modSeq(modSeq)
.oldFlags(new Flags())
.newFlags(newFlags)
@@ -382,6 +383,7 @@ public abstract class MessageIdMapperTest {
ModSeq modSeq = mapperProvider.highestModSeq(benwaInboxMailbox);
UpdatedFlags expectedUpdatedFlags = UpdatedFlags.builder()
.uid(message1.getUid())
+ .messageId(messageId)
.modSeq(modSeq)
.oldFlags(messageFlags)
.newFlags(newFlags)
@@ -411,6 +413,7 @@ public abstract class MessageIdMapperTest {
ModSeq modSeq = mapperProvider.highestModSeq(benwaInboxMailbox);
UpdatedFlags expectedUpdatedFlags = UpdatedFlags.builder()
.uid(message1.getUid())
+ .messageId(messageId)
.modSeq(modSeq)
.oldFlags(messageFlags)
.newFlags(new Flags(Flags.Flag.RECENT))
@@ -483,6 +486,7 @@ public abstract class MessageIdMapperTest {
ModSeq modSeq = mapperProvider.highestModSeq(benwaInboxMailbox);
UpdatedFlags expectedUpdatedFlags = UpdatedFlags.builder()
.uid(message1.getUid())
+ .messageId(messageId)
.modSeq(modSeq)
.oldFlags(initialFlags)
.newFlags(newFlags)
@@ -510,12 +514,14 @@ public abstract class MessageIdMapperTest {
ModSeq modSeqBenwaWorkMailbox = mapperProvider.highestModSeq(benwaWorkMailbox);
UpdatedFlags expectedUpdatedFlags = UpdatedFlags.builder()
.uid(message1.getUid())
+ .messageId(messageId)
.modSeq(modSeqBenwaInboxMailbox)
.oldFlags(new Flags())
.newFlags(newFlags)
.build();
UpdatedFlags expectedUpdatedFlags2 = UpdatedFlags.builder()
.uid(message1InOtherMailbox.getUid())
+ .messageId(messageId)
.modSeq(modSeqBenwaWorkMailbox)
.oldFlags(new Flags())
.newFlags(newFlags)
@@ -854,6 +860,7 @@ public abstract class MessageIdMapperTest {
ImmutableList.of(UpdatedFlags.builder()
.modSeq(modSeq)
.uid(message1.getUid())
+ .messageId(message1.getMessageId())
.newFlags(flags)
.oldFlags(flags)
.build())));
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java
index 0a59a33..cc949d5 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java
@@ -709,6 +709,7 @@ public abstract class MessageMapperTest {
assertThat(updatedFlags)
.contains(UpdatedFlags.builder()
.uid(message1.getUid())
+ .messageId(message1.getMessageId())
.modSeq(modSeq.next())
.oldFlags(new Flags())
.newFlags(new Flags(Flags.Flag.FLAGGED))
@@ -723,6 +724,7 @@ public abstract class MessageMapperTest {
assertThat(messageMapper.updateFlags(benwaInboxMailbox, message1.getUid(), new FlagsUpdateCalculator(new Flags(Flags.Flag.SEEN), FlagsUpdateMode.ADD)))
.contains(UpdatedFlags.builder()
.uid(message1.getUid())
+ .messageId(message1.getMessageId())
.modSeq(modSeq.next())
.oldFlags(new Flags(Flags.Flag.FLAGGED))
.newFlags(new FlagsBuilder().add(Flags.Flag.SEEN, Flags.Flag.FLAGGED).build())
@@ -756,6 +758,7 @@ public abstract class MessageMapperTest {
.contains(
UpdatedFlags.builder()
.uid(message1.getUid())
+ .messageId(message1.getMessageId())
.modSeq(modSeq.next())
.oldFlags(new FlagsBuilder().add(Flags.Flag.SEEN, Flags.Flag.FLAGGED).build())
.newFlags(new Flags(Flags.Flag.FLAGGED))
@@ -881,6 +884,7 @@ public abstract class MessageMapperTest {
.contains(
UpdatedFlags.builder()
.uid(message1.getUid())
+ .messageId(message1.getMessageId())
.modSeq(modSeq.next())
.oldFlags(new Flags())
.newFlags(new Flags(USER_FLAG))
@@ -897,6 +901,7 @@ public abstract class MessageMapperTest {
.contains(
UpdatedFlags.builder()
.uid(message1.getUid())
+ .messageId(message1.getMessageId())
.modSeq(message1.getModSeq())
.oldFlags(new Flags())
.newFlags(new Flags())
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 05/24: JAMES-3486 MemoryMailboxChangeRepository
getSinceState should not include delegated changes
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 47ee6467ebb525d9b80d5bb3dea83ac642e7e80a
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Mon Dec 28 11:00:11 2020 +0700
JAMES-3486 MemoryMailboxChangeRepository getSinceState should not include delegated changes
---
.../change/MemoryMailboxChangeRepository.java | 1 +
.../change/MailboxChangeRepositoryContract.java | 48 ++++++++++++++++++++++
.../memory/MemoryMailboxChangesMethodTest.java | 7 ----
3 files changed, 49 insertions(+), 7 deletions(-)
diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/change/MemoryMailboxChangeRepository.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/change/MemoryMailboxChangeRepository.java
index 6dc9105..efcc22a 100644
--- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/change/MemoryMailboxChangeRepository.java
+++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/change/MemoryMailboxChangeRepository.java
@@ -61,6 +61,7 @@ public class MemoryMailboxChangeRepository implements MailboxChangeRepository {
if (state.equals(State.INITIAL)) {
return Flux.fromIterable(mailboxChangeMap.get(accountId))
+ .filter(Predicate.not(MailboxChange::isDelegated))
.sort(Comparator.comparing(MailboxChange::getDate))
.collect(new MailboxChangeCollector(state, maxChanges.orElse(DEFAULT_NUMBER_OF_CHANGES)));
}
diff --git a/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/change/MailboxChangeRepositoryContract.java b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/change/MailboxChangeRepositoryContract.java
index 4034849..fc895a8 100644
--- a/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/change/MailboxChangeRepositoryContract.java
+++ b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/change/MailboxChangeRepositoryContract.java
@@ -281,6 +281,54 @@ public interface MailboxChangeRepositoryContract {
}
@Test
+ default void getSinceStateFromInitialShouldNotIncludeDeletegatedChanges() {
+ MailboxChangeRepository repository = mailboxChangeRepository();
+ State.Factory stateFactory = stateFactory();
+ State referenceState = stateFactory.generate();
+
+ MailboxId id1 = generateNewMailboxId();
+ MailboxId id2 = generateNewMailboxId();
+ MailboxId id3 = generateNewMailboxId();
+ MailboxId id4 = generateNewMailboxId();
+
+ MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(3)).isCountChange(false).created(ImmutableList.of(id1)).build();
+ MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(2)).isCountChange(false).created(ImmutableList.of(id2)).build();
+ MailboxChange change3 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).isCountChange(false).delegated(true).created(ImmutableList.of(id3)).build();
+ MailboxChange change4 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).isCountChange(false).delegated(true).created(ImmutableList.of(id4)).build();
+ repository.save(change1).block();
+ repository.save(change2).block();
+ repository.save(change3).block();
+ repository.save(change4).block();
+
+ assertThat(repository.getSinceState(ACCOUNT_ID, State.INITIAL, Optional.empty()).block().getCreated())
+ .containsExactlyInAnyOrder(id1, id2);
+ }
+
+ @Test
+ default void getSinceStateWithDelegationFromInitialShouldIncludeDeletegatedChanges() {
+ MailboxChangeRepository repository = mailboxChangeRepository();
+ State.Factory stateFactory = stateFactory();
+ State referenceState = stateFactory.generate();
+
+ MailboxId id1 = generateNewMailboxId();
+ MailboxId id2 = generateNewMailboxId();
+ MailboxId id3 = generateNewMailboxId();
+ MailboxId id4 = generateNewMailboxId();
+
+ MailboxChange change1 = MailboxChange.builder().accountId(ACCOUNT_ID).state(referenceState).date(DATE.minusHours(3)).isCountChange(false).created(ImmutableList.of(id1)).build();
+ MailboxChange change2 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(2)).isCountChange(false).created(ImmutableList.of(id2)).build();
+ MailboxChange change3 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE.minusHours(1)).isCountChange(false).delegated(true).created(ImmutableList.of(id3)).build();
+ MailboxChange change4 = MailboxChange.builder().accountId(ACCOUNT_ID).state(stateFactory.generate()).date(DATE).isCountChange(false).delegated(true).created(ImmutableList.of(id4)).build();
+ repository.save(change1).block();
+ repository.save(change2).block();
+ repository.save(change3).block();
+ repository.save(change4).block();
+
+ assertThat(repository.getSinceStateWithDelegation(ACCOUNT_ID, State.INITIAL, Optional.empty()).block().getCreated())
+ .containsExactlyInAnyOrder(id1, id2, id3, id4);
+ }
+
+ @Test
default void getChangesShouldLimitChangesWhenMaxChangesOmitted() {
MailboxChangeRepository repository = mailboxChangeRepository();
State.Factory stateFactory = stateFactory();
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryMailboxChangesMethodTest.java b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryMailboxChangesMethodTest.java
index df68a52..b01641a 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryMailboxChangesMethodTest.java
+++ b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryMailboxChangesMethodTest.java
@@ -26,8 +26,6 @@ import org.apache.james.JamesServerBuilder;
import org.apache.james.JamesServerExtension;
import org.apache.james.jmap.api.change.State;
import org.apache.james.jmap.rfc8621.contract.MailboxChangesMethodContract;
-import org.apache.james.mailbox.inmemory.InMemoryId;
-import org.apache.james.mailbox.model.MailboxId;
import org.apache.james.modules.TestJMAPServerModule;
import org.junit.jupiter.api.extension.RegisterExtension;
@@ -44,9 +42,4 @@ public class MemoryMailboxChangesMethodTest implements MailboxChangesMethodContr
public State.Factory stateFactory() {
return new State.DefaultFactory();
}
-
- @Override
- public MailboxId generateMailboxId() {
- return InMemoryId.of(0);
- }
}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 19/24: [REFACTORING] Steps of the staged builder
should be inside the Builder of MailboxChange
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 4b3785dea7283c988206de6303d19bb0c6da7dbc
Author: Rene Cordier <rc...@linagora.com>
AuthorDate: Thu Dec 31 10:54:26 2020 +0700
[REFACTORING] Steps of the staged builder should be inside the Builder of MailboxChange
That's the pattern we use generally in the code... And my IDE was screaming at it for some reasons
---
.../james/jmap/api/change/MailboxChange.java | 36 +++++++++++-----------
1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/change/MailboxChange.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/change/MailboxChange.java
index d4ea806..3d8533d 100644
--- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/change/MailboxChange.java
+++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/change/MailboxChange.java
@@ -51,27 +51,27 @@ import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
public class MailboxChange {
- @FunctionalInterface
- public interface RequiredAccountId {
- RequiredState accountId(AccountId accountId);
- }
+ public static class Builder {
+ @FunctionalInterface
+ public interface RequiredAccountId {
+ RequiredState accountId(AccountId accountId);
+ }
- @FunctionalInterface
- public interface RequiredState {
- RequiredDate state(State state);
- }
+ @FunctionalInterface
+ public interface RequiredState {
+ RequiredDate state(State state);
+ }
- @FunctionalInterface
- public interface RequiredDate {
- RequiredIsCountChange date(ZonedDateTime date);
- }
+ @FunctionalInterface
+ public interface RequiredDate {
+ RequiredIsCountChange date(ZonedDateTime date);
+ }
- @FunctionalInterface
- public interface RequiredIsCountChange {
- Builder isCountChange(boolean isCountChange);
- }
+ @FunctionalInterface
+ public interface RequiredIsCountChange {
+ Builder isCountChange(boolean isCountChange);
+ }
- public static class Builder {
private final AccountId accountId;
private final State state;
private final ZonedDateTime date;
@@ -124,7 +124,7 @@ public class MailboxChange {
}
}
- public static RequiredAccountId builder() {
+ public static Builder.RequiredAccountId builder() {
return accountId -> state -> date -> isCountChange -> new Builder(accountId, state, date, isCountChange);
}
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 02/24: JAMES-3486 Fix indent
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 4ac8c99d000d6ab8a60f3ba32767480b474f6214
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Mon Dec 28 10:42:43 2020 +0700
JAMES-3486 Fix indent
---
.../jmap/rfc8621/distributed/DistributedMailboxGetMethodTest.java | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedMailboxGetMethodTest.java b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedMailboxGetMethodTest.java
index 5de500d..0235d09 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedMailboxGetMethodTest.java
+++ b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedMailboxGetMethodTest.java
@@ -43,9 +43,9 @@ public class DistributedMailboxGetMethodTest implements MailboxGetMethodContract
.workingDirectory(tmpDir)
.configurationFromClasspath()
.blobStore(BlobStoreConfiguration.builder()
- .s3()
- .disableCache()
- .deduplication())
+ .s3()
+ .disableCache()
+ .deduplication())
.build())
.extension(new DockerElasticSearchExtension())
.extension(new CassandraExtension())
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 09/24: JAMES-3431 RecipientRewriteTableProcessor
needs to modify DSN parameters
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 91fd382e1949db9d888262a1ceeb53093be76177
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Wed Dec 30 10:47:54 2020 +0700
JAMES-3431 RecipientRewriteTableProcessor needs to modify DSN parameters
ORCPT is preserved (should not be rewritten):
```
The purpose of ORCPT is to preserve the original recipient of an email message, for example, if it is forwarded to another address.
```
(source: https://www.lifewire.com/what-is-dsn-delivery-status-notification-for-smtp-email-3860942, for what it is worth)
---
.../main/java/org/apache/mailet/DsnParameters.java | 4 ++
.../java/org/apache/james/smtp/DSNRelayTest.java | 47 ++++++++++++-
.../mailets/RecipientRewriteTableProcessor.java | 76 +++++++++++++++++++---
3 files changed, 118 insertions(+), 9 deletions(-)
diff --git a/mailet/api/src/main/java/org/apache/mailet/DsnParameters.java b/mailet/api/src/main/java/org/apache/mailet/DsnParameters.java
index 612fbc0..6dc46ee 100644
--- a/mailet/api/src/main/java/org/apache/mailet/DsnParameters.java
+++ b/mailet/api/src/main/java/org/apache/mailet/DsnParameters.java
@@ -424,6 +424,10 @@ public class DsnParameters {
this.rcptParameters = rcptParameters;
}
+ public DsnParameters withRcptParameters(Map<MailAddress, RecipientDsnParameters> rcptParameters) {
+ return new DsnParameters(envIdParameter, retParameter, ImmutableMap.copyOf(rcptParameters));
+ }
+
public Optional<EnvId> getEnvIdParameter() {
return envIdParameter;
}
diff --git a/server/mailet/integration-testing/src/test/java/org/apache/james/smtp/DSNRelayTest.java b/server/mailet/integration-testing/src/test/java/org/apache/james/smtp/DSNRelayTest.java
index 4f79750..3a1b00d 100644
--- a/server/mailet/integration-testing/src/test/java/org/apache/james/smtp/DSNRelayTest.java
+++ b/server/mailet/integration-testing/src/test/java/org/apache/james/smtp/DSNRelayTest.java
@@ -29,6 +29,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Duration.TEN_SECONDS;
import org.apache.commons.net.smtp.AuthenticatingSMTPClient;
+import org.apache.james.core.Domain;
import org.apache.james.core.MailAddress;
import org.apache.james.dnsservice.api.DNSService;
import org.apache.james.dnsservice.api.InMemoryDNSService;
@@ -47,6 +48,7 @@ import org.apache.james.smtpserver.dsn.DSNEhloHook;
import org.apache.james.smtpserver.dsn.DSNMailParameterHook;
import org.apache.james.smtpserver.dsn.DSNMessageHook;
import org.apache.james.smtpserver.dsn.DSNRcptParameterHook;
+import org.apache.james.transport.mailets.RecipientRewriteTable;
import org.apache.james.transport.mailets.RemoteDelivery;
import org.apache.james.transport.matchers.All;
import org.apache.james.util.Host;
@@ -327,6 +329,47 @@ public class DSNRelayTest {
}
@Test
+ public void dsnShouldBeCarriedAfterRRT() throws Exception {
+ DataProbeImpl dataProbe = jamesServer.getProbe(DataProbeImpl.class);
+ dataProbe.addDomain(ANOTHER_DOMAIN);
+ dataProbe.addAddressMapping("touser", ANOTHER_DOMAIN, "touser-alias@other.com");
+
+ AuthenticatingSMTPClient smtpClient = new AuthenticatingSMTPClient("TLS", "UTF-8");
+
+ try {
+ smtpClient.connect("localhost", jamesServer.getProbe(SmtpGuiceProbe.class).getSmtpPort().getValue());
+ smtpClient.ehlo(DEFAULT_DOMAIN);
+ smtpClient.mail("<" + FROM + "> RET=HDRS ENVID=gabouzomeuh");
+ smtpClient.rcpt("<" + RECIPIENT + "> NOTIFY=FAILURE,DELAY");
+ smtpClient.sendShortMessageData("A short message...");
+ } finally {
+ smtpClient.disconnect();
+ }
+
+ calmlyAwait.atMost(TEN_SECONDS).untilAsserted(() -> assertThat(mockSMTPConfiguration.listMails())
+ .hasSize(1)
+ .extracting(Mail::getEnvelope)
+ .containsExactly(Mail.Envelope.builder()
+ .from(new MailAddress(FROM))
+ .addMailParameter(Mail.Parameter.builder()
+ .name("RET")
+ .value("HDRS")
+ .build())
+ .addMailParameter(Mail.Parameter.builder()
+ .name("ENVID")
+ .value("gabouzomeuh")
+ .build())
+ .addRecipient(Mail.Recipient.builder()
+ .address(new MailAddress("touser-alias@other.com"))
+ .addParameter(Mail.Parameter.builder()
+ .name("NOTIFY")
+ .value("FAILURE,DELAY")
+ .build())
+ .build())
+ .build()));
+ }
+
+ @Test
public void remoteDeliveryShouldCarryOverDSNMailParameters() throws Exception {
AuthenticatingSMTPClient smtpClient = new AuthenticatingSMTPClient("TLS", "UTF-8");
@@ -363,7 +406,9 @@ public class DSNRelayTest {
private ProcessorConfiguration.Builder directResolutionTransport() {
return ProcessorConfiguration.transport()
.addMailet(MailetConfiguration.BCC_STRIPPER)
- .addMailet(MailetConfiguration.LOCAL_DELIVERY)
+ .addMailet(MailetConfiguration.builder()
+ .matcher(All.class)
+ .mailet(RecipientRewriteTable.class))
.addMailet(MailetConfiguration.builder()
.mailet(RemoteDelivery.class)
.matcher(All.class)
diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RecipientRewriteTableProcessor.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RecipientRewriteTableProcessor.java
index 8eef3e9..77660c2 100644
--- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RecipientRewriteTableProcessor.java
+++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RecipientRewriteTableProcessor.java
@@ -31,6 +31,8 @@ import java.util.stream.Stream;
import javax.mail.MessagingException;
+import org.apache.commons.lang3.NotImplementedException;
+import org.apache.commons.lang3.tuple.Pair;
import org.apache.james.core.Domain;
import org.apache.james.core.MailAddress;
import org.apache.james.domainlist.api.DomainList;
@@ -42,6 +44,8 @@ import org.apache.james.rrt.lib.Mapping;
import org.apache.james.rrt.lib.Mappings;
import org.apache.james.server.core.MailImpl;
import org.apache.james.util.MemoizedSupplier;
+import org.apache.mailet.DsnParameters;
+import org.apache.mailet.DsnParameters.RecipientDsnParameters;
import org.apache.mailet.Mail;
import org.apache.mailet.MailetContext;
import org.slf4j.Logger;
@@ -58,6 +62,44 @@ import com.google.common.collect.ImmutableSet;
public class RecipientRewriteTableProcessor {
private static final Logger LOGGER = LoggerFactory.getLogger(RecipientRewriteTableProcessor.class);
+ private static class Decision {
+ private final MailAddress originalAddress;
+ private final RrtExecutionResult executionResult;
+
+ private Decision(MailAddress originalAddress, RrtExecutionResult executionResult) {
+ this.originalAddress = originalAddress;
+ this.executionResult = executionResult;
+ }
+
+ MailAddress originalAddress() {
+ return originalAddress;
+ }
+
+ RrtExecutionResult executionResult() {
+ return executionResult;
+ }
+
+ DsnParameters applyOnDsnParameters(DsnParameters dsnParameters) {
+ ImmutableMap<MailAddress, RecipientDsnParameters> rcptParameters = dsnParameters.getRcptParameters();
+
+ Optional<RecipientDsnParameters> originalRcptParameter = Optional.ofNullable(rcptParameters.get(originalAddress));
+
+ return originalRcptParameter.map(parameters -> {
+ Map<MailAddress, RecipientDsnParameters> newRcptParameters = executionResult.getNewRecipients().stream()
+ .map(newRcpt -> Pair.of(newRcpt, parameters))
+ .collect(Guavate.toImmutableMap(Pair::getKey, Pair::getValue));
+ Map<MailAddress, RecipientDsnParameters> rcptParametersWithoutOriginal = rcptParameters.entrySet().stream()
+ .filter(rcpt -> !rcpt.getKey().equals(originalAddress))
+ .collect(Guavate.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue));
+
+ return dsnParameters.withRcptParameters(ImmutableMap.<MailAddress, RecipientDsnParameters>builder()
+ .putAll(rcptParametersWithoutOriginal)
+ .putAll(newRcptParameters)
+ .build());
+ }).orElse(dsnParameters);
+ }
+ }
+
private static class RrtExecutionResult {
private static RrtExecutionResult empty() {
return new RrtExecutionResult(ImmutableSet.of(), ImmutableSet.of());
@@ -131,7 +173,25 @@ public class RecipientRewriteTableProcessor {
}
public void processMail(Mail mail) throws MessagingException {
- RrtExecutionResult executionResults = executeRrtFor(mail);
+ List<Decision> decisions = executeRrtFor(mail);
+
+ applyDecisionsOnMailRecipients(mail, decisions);
+ applyDecisionOnDSNParameters(mail, decisions);
+ }
+
+ private void applyDecisionOnDSNParameters(Mail mail, List<Decision> decisions) {
+ mail.dsnParameters()
+ .map(dsnParameters -> decisions.stream()
+ .reduce(dsnParameters, (parameters, decision) -> decision.applyOnDsnParameters(parameters), (a, b) -> {
+ throw new NotImplementedException("No combiner needed as we are not in a multi-threaded environment");
+ }))
+ .ifPresent(mail::setDsnParameters);
+ }
+
+ private void applyDecisionsOnMailRecipients(Mail mail, List<Decision> decisions) throws MessagingException {
+ RrtExecutionResult executionResults = decisions.stream()
+ .map(Decision::executionResult)
+ .reduce(RrtExecutionResult.empty(), RrtExecutionResult::merge);
if (!executionResults.recipientWithError.isEmpty()) {
MailImpl newMail = MailImpl.builder()
@@ -151,8 +211,8 @@ public class RecipientRewriteTableProcessor {
mail.setRecipients(executionResults.newRecipients);
}
- private RrtExecutionResult executeRrtFor(Mail mail) {
- Function<MailAddress, RrtExecutionResult> convertToMappingData = recipient -> {
+ private List<Decision> executeRrtFor(Mail mail) {
+ Function<MailAddress, Decision> convertToMappingData = recipient -> {
Preconditions.checkNotNull(recipient);
return executeRrtForRecipient(mail, recipient);
@@ -161,21 +221,21 @@ public class RecipientRewriteTableProcessor {
return mail.getRecipients()
.stream()
.map(convertToMappingData)
- .reduce(RrtExecutionResult.empty(), RrtExecutionResult::merge);
+ .collect(Guavate.toImmutableList());
}
- private RrtExecutionResult executeRrtForRecipient(Mail mail, MailAddress recipient) {
+ private Decision executeRrtForRecipient(Mail mail, MailAddress recipient) {
try {
Mappings mappings = virtualTableStore.getResolvedMappings(recipient.getLocalPart(), recipient.getDomain());
if (mappings != null && !mappings.isEmpty()) {
List<MailAddress> newMailAddresses = handleMappings(mappings, mail, recipient);
- return RrtExecutionResult.success(newMailAddresses);
+ return new Decision(recipient, RrtExecutionResult.success(newMailAddresses));
}
- return RrtExecutionResult.success(recipient);
+ return new Decision(recipient, RrtExecutionResult.success(recipient));
} catch (ErrorMappingException | RecipientRewriteTableException e) {
LOGGER.warn("Could not rewrite recipient {}", recipient, e);
- return RrtExecutionResult.error(recipient);
+ return new Decision(recipient, RrtExecutionResult.error(recipient));
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 01/24: JAMES-3486 Add missing binding
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 39ee787387031b4ef981e52ac3e198a2793b2cc7
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Fri Dec 25 16:36:00 2020 +0700
JAMES-3486 Add missing binding
---
.../org/apache/james/modules/mailbox/CassandraMailboxModule.java | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java
index 0e393d9..86ac2e8 100644
--- a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java
+++ b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/modules/mailbox/CassandraMailboxModule.java
@@ -29,7 +29,10 @@ import org.apache.james.eventsourcing.Event;
import org.apache.james.eventsourcing.eventstore.cassandra.dto.EventDTO;
import org.apache.james.eventsourcing.eventstore.cassandra.dto.EventDTOModule;
import org.apache.james.jmap.api.change.MailboxChangeRepository;
+import org.apache.james.jmap.api.change.State;
import org.apache.james.jmap.cassandra.change.CassandraMailboxChangeRepository;
+import org.apache.james.jmap.cassandra.change.CassandraStateFactory;
+import org.apache.james.jmap.change.MailboxChangeListener;
import org.apache.james.mailbox.AttachmentContentLoader;
import org.apache.james.mailbox.AttachmentManager;
import org.apache.james.mailbox.Authenticator;
@@ -182,6 +185,7 @@ public class CassandraMailboxModule extends AbstractModule {
bind(StoreMailboxManager.class).to(CassandraMailboxManager.class);
bind(MailboxChangeRepository.class).to(CassandraMailboxChangeRepository.class);
bind(MailboxId.Factory.class).to(CassandraId.Factory.class);
+ bind(State.Factory.class).to(CassandraStateFactory.class);
bind(MessageId.Factory.class).to(CassandraMessageId.Factory.class);
bind(MessageIdManager.class).to(StoreMessageIdManager.class);
bind(AttachmentManager.class).to(StoreAttachmentManager.class);
@@ -212,6 +216,7 @@ public class CassandraMailboxModule extends AbstractModule {
Multibinder<MailboxListener.GroupMailboxListener> mailboxListeners = Multibinder.newSetBinder(binder(), MailboxListener.GroupMailboxListener.class);
mailboxListeners.addBinding().to(MailboxAnnotationListener.class);
mailboxListeners.addBinding().to(DeleteMessageListener.class);
+ mailboxListeners.addBinding().to(MailboxChangeListener.class);
bind(MailboxManager.class).annotatedWith(Names.named(MAILBOXMANAGER_NAME)).to(MailboxManager.class);
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 21/24: JAMES-3471 Should be able to serialize
UpdatedFlags with and without a message id
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit a8e7a33d134e9a32bef64f65304b822a2662d945
Author: Rene Cordier <rc...@linagora.com>
AuthorDate: Thu Dec 31 16:54:19 2020 +0700
JAMES-3471 Should be able to serialize UpdatedFlags with and without a message id
---
.../james/mailbox/events/MailboxListener.java | 18 +++++-
.../apache/james/mailbox/model/UpdatedFlags.java | 37 ++++++++---
.../scala/org/apache/james/event/json/DTOs.scala | 5 +-
.../event/json/FlagsUpdatedSerializationTest.java | 72 ++++++++++++++++++++++
4 files changed, 121 insertions(+), 11 deletions(-)
diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/events/MailboxListener.java b/mailbox/api/src/main/java/org/apache/james/mailbox/events/MailboxListener.java
index d305d82..3517801 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/events/MailboxListener.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/events/MailboxListener.java
@@ -24,6 +24,7 @@ import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Optional;
import java.util.SortedMap;
import org.apache.james.core.Username;
@@ -587,15 +588,21 @@ public interface MailboxListener {
*/
class FlagsUpdated extends MessageEvent {
private final List<MessageUid> uids;
+ private final List<MessageId> messageIds;
private final List<UpdatedFlags> updatedFlags;
- public FlagsUpdated(MailboxSession.SessionId sessionId, Username username, MailboxPath path, MailboxId mailboxId, List<UpdatedFlags> updatedFlags,
- EventId eventId) {
+ public FlagsUpdated(MailboxSession.SessionId sessionId, Username username, MailboxPath path,
+ MailboxId mailboxId, List<UpdatedFlags> updatedFlags, EventId eventId) {
super(sessionId, username, path, mailboxId, eventId);
this.updatedFlags = ImmutableList.copyOf(updatedFlags);
this.uids = updatedFlags.stream()
.map(UpdatedFlags::getUid)
.collect(Guavate.toImmutableList());
+ this.messageIds = updatedFlags.stream()
+ .map(UpdatedFlags::getMessageId)
+ .filter(Optional::isPresent)
+ .map(Optional::get)
+ .collect(Guavate.toImmutableList());
}
@Override
@@ -603,6 +610,10 @@ public interface MailboxListener {
return uids;
}
+ public Collection<MessageId> getMessageIds() {
+ return messageIds;
+ }
+
public List<UpdatedFlags> getUpdatedFlags() {
return updatedFlags;
}
@@ -623,6 +634,7 @@ public interface MailboxListener {
&& Objects.equals(this.path, that.path)
&& Objects.equals(this.mailboxId, that.mailboxId)
&& Objects.equals(this.uids, that.uids)
+ && Objects.equals(this.messageIds, that.messageIds)
&& Objects.equals(this.updatedFlags, that.updatedFlags);
}
return false;
@@ -630,7 +642,7 @@ public interface MailboxListener {
@Override
public final int hashCode() {
- return Objects.hash(eventId, sessionId, username, path, mailboxId, uids, updatedFlags);
+ return Objects.hash(eventId, sessionId, username, path, mailboxId, uids, messageIds, updatedFlags);
}
}
diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/model/UpdatedFlags.java b/mailbox/api/src/main/java/org/apache/james/mailbox/model/UpdatedFlags.java
index 1611a63..0649c58 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/model/UpdatedFlags.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/UpdatedFlags.java
@@ -43,6 +43,7 @@ public class UpdatedFlags {
public static class Builder {
private MessageUid uid;
+ private Optional<MessageId> messageId = Optional.empty();
private Flags oldFlags;
private Flags newFlags;
private Optional<ModSeq> modSeq = Optional.empty();
@@ -55,6 +56,16 @@ public class UpdatedFlags {
return this;
}
+ public Builder messageId(MessageId messageId) {
+ this.messageId = Optional.of(messageId);
+ return this;
+ }
+
+ public Builder messageId(Optional<MessageId> messageId) {
+ this.messageId = messageId;
+ return this;
+ }
+
public Builder oldFlags(Flags oldFlags) {
this.oldFlags = oldFlags;
return this;
@@ -71,22 +82,27 @@ public class UpdatedFlags {
}
public UpdatedFlags build() {
- Preconditions.checkState(uid != null);
- Preconditions.checkState(newFlags != null);
- Preconditions.checkState(oldFlags != null);
+ Preconditions.checkNotNull(uid);
+ Preconditions.checkNotNull(newFlags);
+ Preconditions.checkNotNull(oldFlags);
Preconditions.checkState(modSeq.isPresent());
- return new UpdatedFlags(uid, modSeq.get(), oldFlags, newFlags);
+ return new UpdatedFlags(uid, messageId, modSeq.get(), oldFlags, newFlags);
}
}
private final MessageUid uid;
+ /**
+ * The usage of Optional here is for backward compatibility (to be able to still dequeue older events)
+ */
+ private final Optional<MessageId> messageId;
private final Flags oldFlags;
private final Flags newFlags;
private final Flags modifiedFlags;
private final ModSeq modSeq;
- private UpdatedFlags(MessageUid uid, ModSeq modSeq, Flags oldFlags, Flags newFlags) {
+ private UpdatedFlags(MessageUid uid, Optional<MessageId> messageId, ModSeq modSeq, Flags oldFlags, Flags newFlags) {
this.uid = uid;
+ this.messageId = messageId;
this.modSeq = modSeq;
this.oldFlags = oldFlags;
this.newFlags = newFlags;
@@ -177,7 +193,13 @@ public class UpdatedFlags {
public MessageUid getUid() {
return uid;
}
-
+
+ /**
+ * Return the uid for the message whichs {@link Flags} was updated
+ */
+ public Optional<MessageId> getMessageId() {
+ return messageId;
+ }
/**
* Gets an iterator for the system flags changed.
@@ -238,6 +260,7 @@ public class UpdatedFlags {
UpdatedFlags that = (UpdatedFlags) other;
return Objects.equals(uid, that.uid) &&
+ Objects.equals(messageId, that.messageId) &&
Objects.equals(oldFlags, that.oldFlags) &&
Objects.equals(newFlags, that.newFlags) &&
Objects.equals(modSeq, that.modSeq);
@@ -245,7 +268,7 @@ public class UpdatedFlags {
@Override
public final int hashCode() {
- return Objects.hash(uid, oldFlags, newFlags, modSeq);
+ return Objects.hash(uid, messageId, oldFlags, newFlags, modSeq);
}
@Override
diff --git a/mailbox/event/json/src/main/scala/org/apache/james/event/json/DTOs.scala b/mailbox/event/json/src/main/scala/org/apache/james/event/json/DTOs.scala
index 08ab9e3..f51f100 100644
--- a/mailbox/event/json/src/main/scala/org/apache/james/event/json/DTOs.scala
+++ b/mailbox/event/json/src/main/scala/org/apache/james/event/json/DTOs.scala
@@ -32,6 +32,7 @@ import org.apache.james.mailbox.model.{MessageId, MailboxACL => JavaMailboxACL,
import org.apache.james.mailbox.{FlagsBuilder, MessageUid, ModSeq}
import scala.jdk.CollectionConverters._
+import scala.jdk.OptionConverters._
object DTOs {
@@ -142,14 +143,16 @@ object DTOs {
object UpdatedFlags {
def toUpdatedFlags(javaUpdatedFlags: JavaUpdatedFlags): UpdatedFlags = UpdatedFlags(
javaUpdatedFlags.getUid,
+ javaUpdatedFlags.getMessageId.toScala,
javaUpdatedFlags.getModSeq,
Flags.fromJavaFlags(javaUpdatedFlags.getOldFlags),
Flags.fromJavaFlags(javaUpdatedFlags.getNewFlags))
}
- case class UpdatedFlags(uid: MessageUid, modSeq: ModSeq, oldFlags: Flags, newFlags: Flags) {
+ case class UpdatedFlags(uid: MessageUid, messageId: Option[MessageId], modSeq: ModSeq, oldFlags: Flags, newFlags: Flags) {
def toJava: JavaUpdatedFlags = JavaUpdatedFlags.builder()
.uid(uid)
+ .messageId(messageId.toJava)
.modSeq(modSeq)
.oldFlags(Flags.toJavaFlags(oldFlags))
.newFlags(Flags.toJavaFlags(newFlags))
diff --git a/mailbox/event/json/src/test/java/org/apache/james/event/json/FlagsUpdatedSerializationTest.java b/mailbox/event/json/src/test/java/org/apache/james/event/json/FlagsUpdatedSerializationTest.java
index 8a2347e..6cb82f3 100644
--- a/mailbox/event/json/src/test/java/org/apache/james/event/json/FlagsUpdatedSerializationTest.java
+++ b/mailbox/event/json/src/test/java/org/apache/james/event/json/FlagsUpdatedSerializationTest.java
@@ -39,7 +39,9 @@ import org.apache.james.mailbox.events.MailboxListener;
import org.apache.james.mailbox.model.MailboxConstants;
import org.apache.james.mailbox.model.MailboxId;
import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.MessageId;
import org.apache.james.mailbox.model.TestId;
+import org.apache.james.mailbox.model.TestMessageId;
import org.apache.james.mailbox.model.UpdatedFlags;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
@@ -173,6 +175,76 @@ class FlagsUpdatedSerializationTest {
}
@Nested
+ class WithMessageId {
+ private final MessageId messageId1 = TestMessageId.of(23456);
+ private final MessageId messageId2 = TestMessageId.of(78901);
+
+ private final UpdatedFlags updatedFlagsWithMessageId1 = UpdatedFlags.builder()
+ .uid(MESSAGE_UID_1)
+ .messageId(messageId1)
+ .modSeq(MOD_SEQ_1)
+ .oldFlags(OLD_FLAGS_1)
+ .newFlags(NEW_FLAGS_1)
+ .build();
+ private final UpdatedFlags updatedFlagsWithMessageId2 = UpdatedFlags.builder()
+ .uid(MESSAGE_UID_2)
+ .messageId(messageId2)
+ .modSeq(MOD_SEQ_2)
+ .oldFlags(OLD_FLAGS_2)
+ .newFlags(NEW_FLAGS_2)
+ .build();
+
+ private final List<UpdatedFlags> updatedFlagsListWithMessageIds = ImmutableList.of(updatedFlagsWithMessageId1, updatedFlagsWithMessageId2);
+
+ private final MailboxListener.FlagsUpdated eventWithMessageIds = new MailboxListener.FlagsUpdated(SESSION_ID, USERNAME,
+ MAILBOX_PATH, MAILBOX_ID, updatedFlagsListWithMessageIds, EVENT_ID);
+
+ private static final String EVENT_WITH_MESSAGE_IDS_JSON =
+ "{" +
+ " \"FlagsUpdated\": {" +
+ " \"eventId\":\"6e0dd59d-660e-4d9b-b22f-0354479f47b4\"," +
+ " \"path\": {" +
+ " \"namespace\": \"#private\"," +
+ " \"user\": \"user\"," +
+ " \"name\": \"mailboxName\"" +
+ " }," +
+ " \"mailboxId\": \"18\"," +
+ " \"sessionId\": 42," +
+ " \"updatedFlags\": [" +
+ " {" +
+ " \"uid\": 123456," +
+ " \"messageId\": \"23456\"," +
+ " \"modSeq\": 35," +
+ " \"oldFlags\": {\"systemFlags\":[\"Deleted\",\"Seen\"],\"userFlags\":[\"Old Flag 1\"]}," +
+ " \"newFlags\": {\"systemFlags\":[\"Answered\",\"Draft\"],\"userFlags\":[\"New Flag 1\"]}" +
+ " }," +
+ " {" +
+ " \"uid\": 654321," +
+ " \"messageId\": \"78901\"," +
+ " \"modSeq\": 36," +
+ " \"oldFlags\": {\"systemFlags\":[\"Flagged\",\"Recent\"],\"userFlags\":[\"Old Flag 2\"]}," +
+ " \"newFlags\": {\"systemFlags\":[\"Answered\",\"Seen\"],\"userFlags\":[\"New Flag 2\"]}" +
+ " }" +
+ " ]," +
+ " \"user\": \"user\"" +
+ " }" +
+ "}";
+
+ @Test
+ void flagsUpdatedShouldBeWellSerialized() {
+ assertThatJson(EVENT_SERIALIZER.toJson(eventWithMessageIds))
+ .when(Option.IGNORING_ARRAY_ORDER)
+ .isEqualTo(EVENT_WITH_MESSAGE_IDS_JSON);
+ }
+
+ @Test
+ void flagsUpdatedShouldBeWellDeSerialized() {
+ assertThat(EVENT_SERIALIZER.fromJson(EVENT_WITH_MESSAGE_IDS_JSON).get())
+ .isEqualTo(eventWithMessageIds);
+ }
+ }
+
+ @Nested
class DeserializationError {
@Test
void flagsUpdatedShouldThrowWhenMissingSessionId() {
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 07/24: JAMES-3486 Adapt
MailboxChangesMethodContract for stability against distributed environment
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit b6fee54188409eb5a115468d52511f78cac08ca6
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Mon Dec 28 11:03:48 2020 +0700
JAMES-3486 Adapt MailboxChangesMethodContract for stability against distributed environment
Because changes in distributed environment do not happen instantaneously, we need to adapt the contract so that the tests behave in a more reliable way.
Before, we were storing a state manually as a reference point, then the change(s) that we interested in would be conducted after that. This will not work
in distributed environment, since the reference state might be stored even before the provisioning process complete and leads to unpredictable result.
The fix:
- We will wait for a new state to be recorded successfully each time there is a change happen
- Fetch them sequentially until all the preparation steps are completed
- Mark the latest stage
- Conduct the change that we are interested in
- fetch the result with the latest state as reference point.
---
.../apache/james/jmap/draft/JmapGuiceProbe.java | 6 +-
.../contract/MailboxChangesMethodContract.scala | 1613 +++++++++++---------
.../memory/MemoryMailboxChangesMethodTest.java | 7 +
3 files changed, 869 insertions(+), 757 deletions(-)
diff --git a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JmapGuiceProbe.java b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JmapGuiceProbe.java
index 9c9affe..ca1616a 100644
--- a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JmapGuiceProbe.java
+++ b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JmapGuiceProbe.java
@@ -96,7 +96,11 @@ public class JmapGuiceProbe implements GuiceProbe {
mailboxChangeRepository.save(change).block();
}
- public State latestState(AccountId accountId) {
+ public State getLastestState(AccountId accountId) {
return mailboxChangeRepository.getLatestState(accountId).block();
}
+
+ public State getLastestStateWithDelegation(AccountId accountId) {
+ return mailboxChangeRepository.getLatestStateWithDelegation(accountId).block();
+ }
}
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxChangesMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxChangesMethodContract.scala
index 85f88e6..7ecf86f 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxChangesMethodContract.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxChangesMethodContract.scala
@@ -20,8 +20,7 @@
package org.apache.james.jmap.rfc8621.contract
import java.nio.charset.StandardCharsets
-import java.time.ZonedDateTime
-import java.util.UUID
+import java.util.concurrent.TimeUnit
import io.netty.handler.codec.http.HttpHeaderNames.ACCEPT
import io.restassured.RestAssured.{`given`, requestSpecification}
@@ -33,8 +32,6 @@ import net.javacrumbs.jsonunit.core.Option.IGNORING_ARRAY_ORDER
import net.javacrumbs.jsonunit.core.internal.Options
import org.apache.http.HttpStatus.SC_OK
import org.apache.james.GuiceJamesServer
-import org.apache.james.core.Username
-import org.apache.james.jmap.api.change.MailboxChange
import org.apache.james.jmap.api.change.State
import org.apache.james.jmap.api.model.AccountId
import org.apache.james.jmap.core.ResponseObject.SESSION_STATE
@@ -48,22 +45,22 @@ import org.apache.james.mime4j.dom.Message
import org.apache.james.modules.{ACLProbeImpl, MailboxProbeImpl}
import org.apache.james.utils.DataProbeImpl
import org.assertj.core.api.Assertions.assertThat
+import org.awaitility.Awaitility
+import org.awaitility.Duration.ONE_HUNDRED_MILLISECONDS
import org.junit.jupiter.api.{BeforeEach, Nested, Test}
-import play.api.libs.json.{JsString, Json}
-
-import scala.jdk.CollectionConverters._
-
-object TestId {
- def of(value: Long): MailboxId = TestId(value)
-}
-
-case class TestId(value: Long) extends MailboxId {
- override def serialize(): String = String.valueOf(value)
-}
+import play.api.libs.json.{JsArray, JsString, Json}
trait MailboxChangesMethodContract {
+ private lazy val slowPacedPollInterval = ONE_HUNDRED_MILLISECONDS
+ private lazy val calmlyAwait = Awaitility.`with`
+ .pollInterval(slowPacedPollInterval)
+ .and.`with`.pollDelay(slowPacedPollInterval)
+ .await
+ private lazy val awaitAtMostTenSeconds = calmlyAwait.atMost(10, TimeUnit.SECONDS)
+
def stateFactory: State.Factory
+ def generateMailboxId: MailboxId
@BeforeEach
def setUp(server: GuiceJamesServer): Unit = {
@@ -82,9 +79,7 @@ trait MailboxChangesMethodContract {
@Test
def mailboxChangesShouldReturnCreatedChanges(server: GuiceJamesServer): Unit = {
val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
- provisionSystemMailboxes(server)
-
- val oldState: State = storeReferenceState(server, BOB)
+ val provisioningState: State = provisionSystemMailboxes(server)
val mailboxId1: String = mailboxProbe
.createMailbox(MailboxPath.forUser(BOB, "mailbox1"))
@@ -105,11 +100,12 @@ trait MailboxChangesMethodContract {
| "Mailbox/changes",
| {
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "sinceState": "${oldState.getValue}"
+ | "sinceState": "${provisioningState.getValue}"
| },
| "c1"]]
|}""".stripMargin
+ awaitAtMostTenSeconds.untilAsserted { () =>
val response = `given`
.header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
.body(request)
@@ -127,32 +123,35 @@ trait MailboxChangesMethodContract {
.withOptions(new Options(IGNORING_ARRAY_ORDER))
.isEqualTo(
s"""{
- | "sessionState": "${SESSION_STATE.value}",
- | "methodResponses": [
- | [ "Mailbox/changes", {
- | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "oldState": "${oldState.getValue}",
- | "hasMoreChanges": false,
- | "updatedProperties":null,
- | "created": ["$mailboxId1", "$mailboxId2", "$mailboxId3"],
- | "updated": [],
- | "destroyed": []
- | }, "c1"]
- | ]
- |}""".stripMargin)
+ | "sessionState": "${SESSION_STATE.value}",
+ | "methodResponses": [
+ | [ "Mailbox/changes", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "oldState": "${provisioningState.getValue}",
+ | "hasMoreChanges": false,
+ | "updatedProperties": null,
+ | "created": ["$mailboxId1", "$mailboxId2", "$mailboxId3"],
+ | "updated": [],
+ | "destroyed": []
+ | }, "c1"]
+ | ]
+ |}""".stripMargin)
+ }
}
@Test
def mailboxChangesShouldReturnUpdatedChangesWhenRenameMailbox(server: GuiceJamesServer): Unit = {
val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
+ val accountId: AccountId = AccountId.fromUsername(BOB)
+
+ val provisioningState: State = provisionSystemMailboxes(server)
- provisionSystemMailboxes(server)
val path = MailboxPath.forUser(BOB, "mailbox1")
val mailboxId: String = mailboxProbe
.createMailbox(path)
.serialize
- val oldState: State = storeReferenceState(server, BOB)
+ val oldState: State = waitForNextState(server, accountId, provisioningState)
JmapRequests.renameMailbox(mailboxId, "mailbox11")
@@ -168,50 +167,52 @@ trait MailboxChangesMethodContract {
| "c1"]]
|}""".stripMargin
- val response = `given`
- .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
- .body(request)
- .when
- .post
- .`then`
- .statusCode(SC_OK)
- .contentType(JSON)
- .extract
- .body
- .asString
+ awaitAtMostTenSeconds.untilAsserted { () =>
+ val response = `given`
+ .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .body(request)
+ .when
+ .post
+ .`then`
+ .statusCode(SC_OK)
+ .contentType(JSON)
+ .extract
+ .body
+ .asString
- assertThatJson(response)
- .whenIgnoringPaths("methodResponses[0][1].newState")
- .withOptions(new Options(IGNORING_ARRAY_ORDER))
- .isEqualTo(
- s"""{
- | "sessionState": "${SESSION_STATE.value}",
- | "methodResponses": [
- | [ "Mailbox/changes", {
- | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "oldState": "${oldState.getValue}",
- | "hasMoreChanges": false,
- | "updatedProperties":null,
- | "created": [],
- | "updated": ["$mailboxId"],
- | "destroyed": []
- | }, "c1"]
- | ]
- |}""".stripMargin)
+ assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].newState")
+ .withOptions(new Options(IGNORING_ARRAY_ORDER))
+ .isEqualTo(
+ s"""{
+ | "sessionState": "${SESSION_STATE.value}",
+ | "methodResponses": [
+ | [ "Mailbox/changes", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "oldState": "${oldState.getValue}",
+ | "hasMoreChanges": false,
+ | "updatedProperties": null,
+ | "created": [],
+ | "updated": ["$mailboxId"],
+ | "destroyed": []
+ | }, "c1"]
+ | ]
+ |}""".stripMargin)
+ }
}
@Test
def mailboxChangesShouldReturnUpdatedChangesWhenAppendMessageToMailbox(server: GuiceJamesServer): Unit = {
val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
- provisionSystemMailboxes(server)
+ val provisioningState: State = provisionSystemMailboxes(server)
val path = MailboxPath.forUser(BOB, "mailbox1")
val mailboxId: String = mailboxProbe
.createMailbox(path)
.serialize
- val oldState: State = storeReferenceState(server, BOB)
+ val oldState: State = waitForNextState(server, AccountId.fromUsername(BOB), provisioningState)
val message: Message = Message.Builder
.of
@@ -232,49 +233,54 @@ trait MailboxChangesMethodContract {
| "c1"]]
|}""".stripMargin
- val response = `given`
- .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
- .body(request)
- .when
- .post
- .`then`
- .statusCode(SC_OK)
- .contentType(JSON)
- .extract
- .body
- .asString
+ awaitAtMostTenSeconds.untilAsserted { () =>
+ val response = `given`
+ .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .body(request)
+ .when
+ .post
+ .`then`
+ .statusCode(SC_OK)
+ .contentType(JSON)
+ .extract
+ .body
+ .asString
- assertThatJson(response)
- .whenIgnoringPaths("methodResponses[0][1].newState")
- .withOptions(new Options(IGNORING_ARRAY_ORDER))
- .isEqualTo(
- s"""{
- | "sessionState": "${SESSION_STATE.value}",
- | "methodResponses": [
- | [ "Mailbox/changes", {
- | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "oldState": "${oldState.getValue}",
- | "hasMoreChanges": false,
- | "updatedProperties": ["totalEmails", "unreadEmails", "totalThreads", "unreadThreads"],
- | "created": [],
- | "updated": ["$mailboxId"],
- | "destroyed": []
- | }, "c1"]
- | ]
- |}""".stripMargin)
+ assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].newState")
+ .withOptions(new Options(IGNORING_ARRAY_ORDER))
+ .isEqualTo(
+ s"""{
+ | "sessionState": "${SESSION_STATE.value}",
+ | "methodResponses": [
+ | [ "Mailbox/changes", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "oldState": "${oldState.getValue}",
+ | "hasMoreChanges": false,
+ | "updatedProperties": ["totalEmails", "unreadEmails", "totalThreads", "unreadThreads"],
+ | "created": [],
+ | "updated": ["$mailboxId"],
+ | "destroyed": []
+ | }, "c1"]
+ | ]
+ |}""".stripMargin)
+ }
}
@Test
def mailboxChangesShouldReturnUpdatedChangesWhenAddSeenFlag(server: GuiceJamesServer): Unit = {
val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
+ val accountId: AccountId = AccountId.fromUsername(BOB)
- provisionSystemMailboxes(server)
+ val provisioningState: State = provisionSystemMailboxes(server)
val path = MailboxPath.forUser(BOB, "mailbox1")
val mailboxId: String = mailboxProbe
.createMailbox(path)
.serialize
+ val state1: State = waitForNextState(server, accountId, provisioningState)
+
val message: Message = Message.Builder
.of
.setSubject("test")
@@ -282,7 +288,7 @@ trait MailboxChangesMethodContract {
.build
val messageId: MessageId = mailboxProbe.appendMessage(BOB.asString(), path, AppendCommand.from(message)).getMessageId
- val oldState: State = storeReferenceState(server, BOB)
+ val oldState: State = waitForNextState(server, accountId, state1)
JmapRequests.markEmailAsSeen(messageId)
@@ -298,59 +304,66 @@ trait MailboxChangesMethodContract {
| "c1"]]
|}""".stripMargin
- val response = `given`
- .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
- .body(request)
- .when
- .post
- .`then`
- .statusCode(SC_OK)
- .contentType(JSON)
- .extract
- .body
- .asString
+ awaitAtMostTenSeconds.untilAsserted { () =>
+ val response = `given`
+ .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .body(request)
+ .when
+ .post
+ .`then`
+ .statusCode(SC_OK)
+ .contentType(JSON)
+ .extract
+ .body
+ .asString
- assertThatJson(response)
- .whenIgnoringPaths("methodResponses[0][1].newState")
- .withOptions(new Options(IGNORING_ARRAY_ORDER))
- .isEqualTo(
- s"""{
- | "sessionState": "${SESSION_STATE.value}",
- | "methodResponses": [
- | [ "Mailbox/changes", {
- | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "oldState": "${oldState.getValue}",
- | "hasMoreChanges": false,
- | "updatedProperties": ["totalEmails", "unreadEmails", "totalThreads", "unreadThreads"],
- | "created": [],
- | "updated": ["$mailboxId"],
- | "destroyed": []
- | }, "c1"]
- | ]
- |}""".stripMargin)
+ assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].newState")
+ .withOptions(new Options(IGNORING_ARRAY_ORDER))
+ .isEqualTo(
+ s"""{
+ | "sessionState": "${SESSION_STATE.value}",
+ | "methodResponses": [
+ | [ "Mailbox/changes", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "oldState": "${oldState.getValue}",
+ | "hasMoreChanges": false,
+ | "updatedProperties": ["totalEmails", "unreadEmails", "totalThreads", "unreadThreads"],
+ | "created": [],
+ | "updated": ["$mailboxId"],
+ | "destroyed": []
+ | }, "c1"]
+ | ]
+ |}""".stripMargin)
+ }
}
@Test
def mailboxChangesShouldReturnUpdatedChangesWhenRemoveSeenFlag(server: GuiceJamesServer): Unit = {
val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
+ val accountId: AccountId = AccountId.fromUsername(BOB)
- provisionSystemMailboxes(server)
+ val provisioningState: State = provisionSystemMailboxes(server)
val path = MailboxPath.forUser(BOB, "mailbox1")
val mailboxId: String = mailboxProbe
.createMailbox(path)
.serialize
+ val state1: State = waitForNextState(server, accountId, provisioningState)
+
server.getProbe(classOf[ACLProbeImpl])
.replaceRights(path, ANDRE.asString, new MailboxACL.Rfc4314Rights(Right.Lookup, Right.Read))
+ val state2: State = waitForNextState(server, accountId, state1)
+
val messageId: MessageId = mailboxProbe.appendMessage(BOB.asString(), path,
AppendCommand.builder()
.withFlags(new Flags(Flags.Flag.SEEN))
.build("header: value\r\n\r\nbody"))
.getMessageId
- val oldState: State = storeReferenceState(server, BOB)
+ val oldState: State = waitForNextState(server, accountId, state2)
JmapRequests.markEmailAsNotSeen(messageId)
@@ -366,7 +379,8 @@ trait MailboxChangesMethodContract {
| "c1"]]
|}""".stripMargin
- val response = `given`
+ awaitAtMostTenSeconds.untilAsserted { () =>
+ val response = `given`
.header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
.body(request)
.when
@@ -378,37 +392,41 @@ trait MailboxChangesMethodContract {
.body
.asString
- assertThatJson(response)
- .whenIgnoringPaths("methodResponses[0][1].newState")
- .withOptions(new Options(IGNORING_ARRAY_ORDER))
- .isEqualTo(
- s"""{
- | "sessionState": "${SESSION_STATE.value}",
- | "methodResponses": [
- | ["Mailbox/changes", {
- | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "oldState": "${oldState.getValue}",
- | "hasMoreChanges": false,
- | "updatedProperties": ["totalEmails", "unreadEmails", "totalThreads", "unreadThreads"],
- | "created": [],
- | "updated": ["$mailboxId"],
- | "destroyed": []
- | }, "c1"]
- | ]
- |}""".stripMargin)
+ assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].newState")
+ .withOptions(new Options(IGNORING_ARRAY_ORDER))
+ .isEqualTo(
+ s"""{
+ | "sessionState": "${SESSION_STATE.value}",
+ | "methodResponses": [
+ | ["Mailbox/changes", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "oldState": "${oldState.getValue}",
+ | "hasMoreChanges": false,
+ | "updatedProperties": ["totalEmails", "unreadEmails", "totalThreads", "unreadThreads"],
+ | "created": [],
+ | "updated": ["$mailboxId"],
+ | "destroyed": []
+ | }, "c1"]
+ | ]
+ |}""".stripMargin)
+ }
}
@Test
def mailboxChangesShouldReturnUpdatedChangesWhenDestroyEmail(server: GuiceJamesServer): Unit = {
val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
+ val accountId: AccountId = AccountId.fromUsername(BOB)
- provisionSystemMailboxes(server)
+ val provisioningState: State = provisionSystemMailboxes(server)
val path = MailboxPath.forUser(BOB, "mailbox1")
val mailboxId: String = mailboxProbe
.createMailbox(path)
.serialize
+ val state1: State = waitForNextState(server, accountId, provisioningState)
+
val message: Message = Message.Builder
.of
.setSubject("test")
@@ -416,7 +434,7 @@ trait MailboxChangesMethodContract {
.build
val messageId: MessageId = mailboxProbe.appendMessage(BOB.asString(), path, AppendCommand.from(message)).getMessageId
- val oldState: State = storeReferenceState(server, BOB)
+ val oldState: State = waitForNextState(server, accountId, state1)
JmapRequests.destroyEmail(messageId)
@@ -432,7 +450,8 @@ trait MailboxChangesMethodContract {
| "c1"]]
|}""".stripMargin
- val response = `given`
+ awaitAtMostTenSeconds.untilAsserted { () =>
+ val response = `given`
.header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
.body(request)
.when
@@ -444,24 +463,25 @@ trait MailboxChangesMethodContract {
.body
.asString
- assertThatJson(response)
- .whenIgnoringPaths("methodResponses[0][1].newState")
- .withOptions(new Options(IGNORING_ARRAY_ORDER))
- .isEqualTo(
- s"""{
- | "sessionState": "${SESSION_STATE.value}",
- | "methodResponses": [
- | ["Mailbox/changes", {
- | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "oldState": "${oldState.getValue}",
- | "hasMoreChanges": false,
- | "updatedProperties": ["totalEmails", "unreadEmails", "totalThreads", "unreadThreads"],
- | "created": [],
- | "updated": ["$mailboxId"],
- | "destroyed": []
- | }, "c1"]
- | ]
- |}""".stripMargin)
+ assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].newState")
+ .withOptions(new Options(IGNORING_ARRAY_ORDER))
+ .isEqualTo(
+ s"""{
+ | "sessionState": "${SESSION_STATE.value}",
+ | "methodResponses": [
+ | ["Mailbox/changes", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "oldState": "${oldState.getValue}",
+ | "hasMoreChanges": false,
+ | "updatedProperties": ["totalEmails", "unreadEmails", "totalThreads", "unreadThreads"],
+ | "created": [],
+ | "updated": ["$mailboxId"],
+ | "destroyed": []
+ | }, "c1"]
+ | ]
+ |}""".stripMargin)
+ }
}
@Nested
@@ -480,7 +500,7 @@ trait MailboxChangesMethodContract {
server.getProbe(classOf[ACLProbeImpl])
.replaceRights(path, ANDRE.asString, new MailboxACL.Rfc4314Rights(Right.Lookup, Right.Read))
- val oldState: State = storeReferenceState(server, ANDRE)
+ val oldState: State = waitForNextStateWithDelegation(server, AccountId.fromUsername(ANDRE), State.INITIAL)
val message: Message = Message.Builder
.of
@@ -501,39 +521,41 @@ trait MailboxChangesMethodContract {
| "c1"]]
|}""".stripMargin
- val response = `given`(
- baseRequestSpecBuilder(server)
- .setAuth(authScheme(UserCredential(ANDRE, ANDRE_PASSWORD)))
- .addHeader(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
- .setBody(request)
- .build, new ResponseSpecBuilder().build)
- .post
- .`then`
- .statusCode(SC_OK)
- .contentType(JSON)
- .extract
- .body
- .asString
-
- assertThatJson(response)
- .whenIgnoringPaths("methodResponses[0][1].newState")
- .withOptions(new Options(IGNORING_ARRAY_ORDER))
- .isEqualTo(
- s"""{
- | "sessionState": "${SESSION_STATE.value}",
- | "methodResponses": [
- | [ "Mailbox/changes", {
- | "accountId": "$ANDRE_ACCOUNT_ID",
- | "oldState": "${oldState.getValue}",
- | "hasMoreChanges": false,
- | "updatedProperties": ["totalEmails", "unreadEmails", "totalThreads", "unreadThreads"],
- | "created": [],
- | "updated": ["$mailboxId"],
- | "destroyed": []
- | }, "c1"]
- | ]
- |}""".stripMargin)
- }
+ awaitAtMostTenSeconds.untilAsserted { () =>
+ val response = `given`(
+ baseRequestSpecBuilder(server)
+ .setAuth(authScheme(UserCredential(ANDRE, ANDRE_PASSWORD)))
+ .addHeader(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .setBody(request)
+ .build, new ResponseSpecBuilder().build)
+ .post
+ .`then`
+ .statusCode(SC_OK)
+ .contentType(JSON)
+ .extract
+ .body
+ .asString
+
+ assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].newState")
+ .withOptions(new Options(IGNORING_ARRAY_ORDER))
+ .isEqualTo(
+ s"""{
+ | "sessionState": "${SESSION_STATE.value}",
+ | "methodResponses": [
+ | [ "Mailbox/changes", {
+ | "accountId": "$ANDRE_ACCOUNT_ID",
+ | "oldState": "${oldState.getValue}",
+ | "hasMoreChanges": false,
+ | "updatedProperties": ["totalEmails", "unreadEmails", "totalThreads", "unreadThreads"],
+ | "created": [],
+ | "updated": ["$mailboxId"],
+ | "destroyed": []
+ | }, "c1"]
+ | ]
+ |}""".stripMargin)
+ }
+ }
@Test
def mailboxChangesShouldReturnUpdatedChangesWhenRenameMailbox(server: GuiceJamesServer): Unit = {
@@ -549,7 +571,7 @@ trait MailboxChangesMethodContract {
server.getProbe(classOf[ACLProbeImpl])
.replaceRights(path, ANDRE.asString, new MailboxACL.Rfc4314Rights(Right.Lookup, Right.Read))
- val oldState: State = storeReferenceState(server, ANDRE)
+ val oldState: State = waitForNextStateWithDelegation(server, AccountId.fromUsername(ANDRE), State.INITIAL)
JmapRequests.renameMailbox(mailboxId, "mailbox11")
@@ -565,38 +587,40 @@ trait MailboxChangesMethodContract {
| "c1"]]
|}""".stripMargin
- val response = `given`(
- baseRequestSpecBuilder(server)
- .setAuth(authScheme(UserCredential(ANDRE, ANDRE_PASSWORD)))
- .addHeader(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
- .setBody(request)
- .build, new ResponseSpecBuilder().build)
- .post
- .`then`
- .statusCode(SC_OK)
- .contentType(JSON)
- .extract
- .body
- .asString
-
- assertThatJson(response)
- .whenIgnoringPaths("methodResponses[0][1].newState")
- .withOptions(new Options(IGNORING_ARRAY_ORDER))
- .isEqualTo(
- s"""{
- | "sessionState": "${SESSION_STATE.value}",
- | "methodResponses": [
- | [ "Mailbox/changes", {
- | "accountId": "$ANDRE_ACCOUNT_ID",
- | "oldState": "${oldState.getValue}",
- | "hasMoreChanges": false,
- | "updatedProperties":null,
- | "created": [],
- | "updated": ["$mailboxId"],
- | "destroyed": []
- | }, "c1"]
- | ]
- |}""".stripMargin)
+ awaitAtMostTenSeconds.untilAsserted { () =>
+ val response = `given`(
+ baseRequestSpecBuilder(server)
+ .setAuth(authScheme(UserCredential(ANDRE, ANDRE_PASSWORD)))
+ .addHeader(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .setBody(request)
+ .build, new ResponseSpecBuilder().build)
+ .post
+ .`then`
+ .statusCode(SC_OK)
+ .contentType(JSON)
+ .extract
+ .body
+ .asString
+
+ assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].newState")
+ .withOptions(new Options(IGNORING_ARRAY_ORDER))
+ .isEqualTo(
+ s"""{
+ | "sessionState": "${SESSION_STATE.value}",
+ | "methodResponses": [
+ | [ "Mailbox/changes", {
+ | "accountId": "$ANDRE_ACCOUNT_ID",
+ | "oldState": "${oldState.getValue}",
+ | "hasMoreChanges": false,
+ | "updatedProperties":null,
+ | "created": [],
+ | "updated": ["$mailboxId"],
+ | "destroyed": []
+ | }, "c1"]
+ | ]
+ |}""".stripMargin)
+ }
}
@Test
@@ -613,6 +637,8 @@ trait MailboxChangesMethodContract {
server.getProbe(classOf[ACLProbeImpl])
.replaceRights(path, ANDRE.asString, new MailboxACL.Rfc4314Rights(Right.Lookup, Right.Read))
+ val state1: State = waitForNextStateWithDelegation(server, AccountId.fromUsername(ANDRE), State.INITIAL)
+
val message: Message = Message.Builder
.of
.setSubject("test")
@@ -620,7 +646,7 @@ trait MailboxChangesMethodContract {
.build
val messageId: MessageId = mailboxProbe.appendMessage(BOB.asString(), path, AppendCommand.from(message)).getMessageId
- val oldState: State = storeReferenceState(server, ANDRE)
+ val oldState: State = waitForNextStateWithDelegation(server, AccountId.fromUsername(ANDRE), state1)
JmapRequests.markEmailAsSeen(messageId)
@@ -636,38 +662,40 @@ trait MailboxChangesMethodContract {
| "c1"]]
|}""".stripMargin
- val response = `given`(
- baseRequestSpecBuilder(server)
- .setAuth(authScheme(UserCredential(ANDRE, ANDRE_PASSWORD)))
- .addHeader(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
- .setBody(request)
- .build, new ResponseSpecBuilder().build)
- .post
- .`then`
- .statusCode(SC_OK)
- .contentType(JSON)
- .extract
- .body
- .asString
-
- assertThatJson(response)
- .whenIgnoringPaths("methodResponses[0][1].newState")
- .withOptions(new Options(IGNORING_ARRAY_ORDER))
- .isEqualTo(
- s"""{
- | "sessionState": "${SESSION_STATE.value}",
- | "methodResponses": [
- | [ "Mailbox/changes", {
- | "accountId": "$ANDRE_ACCOUNT_ID",
- | "oldState": "${oldState.getValue}",
- | "hasMoreChanges": false,
- | "updatedProperties": ["totalEmails", "unreadEmails", "totalThreads", "unreadThreads"],
- | "created": [],
- | "updated": ["$mailboxId"],
- | "destroyed": []
- | }, "c1"]
- | ]
- |}""".stripMargin)
+ awaitAtMostTenSeconds.untilAsserted { () =>
+ val response = `given`(
+ baseRequestSpecBuilder(server)
+ .setAuth(authScheme(UserCredential(ANDRE, ANDRE_PASSWORD)))
+ .addHeader(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .setBody(request)
+ .build, new ResponseSpecBuilder().build)
+ .post
+ .`then`
+ .statusCode(SC_OK)
+ .contentType(JSON)
+ .extract
+ .body
+ .asString
+
+ assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].newState")
+ .withOptions(new Options(IGNORING_ARRAY_ORDER))
+ .isEqualTo(
+ s"""{
+ | "sessionState": "${SESSION_STATE.value}",
+ | "methodResponses": [
+ | [ "Mailbox/changes", {
+ | "accountId": "$ANDRE_ACCOUNT_ID",
+ | "oldState": "${oldState.getValue}",
+ | "hasMoreChanges": false,
+ | "updatedProperties": ["totalEmails", "unreadEmails", "totalThreads", "unreadThreads"],
+ | "created": [],
+ | "updated": ["$mailboxId"],
+ | "destroyed": []
+ | }, "c1"]
+ | ]
+ |}""".stripMargin)
+ }
}
@Test
@@ -684,13 +712,15 @@ trait MailboxChangesMethodContract {
server.getProbe(classOf[ACLProbeImpl])
.replaceRights(path, ANDRE.asString, new MailboxACL.Rfc4314Rights(Right.Lookup, Right.Read))
+ val state1: State = waitForNextStateWithDelegation(server, AccountId.fromUsername(ANDRE), State.INITIAL)
+
val messageId: MessageId = mailboxProbe.appendMessage(BOB.asString(), path,
AppendCommand.builder()
.withFlags(new Flags(Flags.Flag.SEEN))
.build("header: value\r\n\r\nbody"))
.getMessageId
- val oldState: State = storeReferenceState(server, ANDRE)
+ val oldState: State = waitForNextStateWithDelegation(server, AccountId.fromUsername(ANDRE), state1)
JmapRequests.markEmailAsNotSeen(messageId)
@@ -706,38 +736,40 @@ trait MailboxChangesMethodContract {
| "c1"]]
|}""".stripMargin
- val response = `given`(
- baseRequestSpecBuilder(server)
- .setAuth(authScheme(UserCredential(ANDRE, ANDRE_PASSWORD)))
- .addHeader(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
- .setBody(request)
- .build, new ResponseSpecBuilder().build)
- .post
- .`then`
- .statusCode(SC_OK)
- .contentType(JSON)
- .extract
- .body
- .asString
-
- assertThatJson(response)
- .whenIgnoringPaths("methodResponses[0][1].newState")
- .withOptions(new Options(IGNORING_ARRAY_ORDER))
- .isEqualTo(
- s"""{
- | "sessionState": "${SESSION_STATE.value}",
- | "methodResponses": [
- | [ "Mailbox/changes", {
- | "accountId": "$ANDRE_ACCOUNT_ID",
- | "oldState": "${oldState.getValue}",
- | "hasMoreChanges": false,
- | "updatedProperties": ["totalEmails", "unreadEmails", "totalThreads", "unreadThreads"],
- | "created": [],
- | "updated": ["$mailboxId"],
- | "destroyed": []
- | }, "c1"]
- | ]
- |}""".stripMargin)
+ awaitAtMostTenSeconds.untilAsserted { () =>
+ val response = `given`(
+ baseRequestSpecBuilder(server)
+ .setAuth(authScheme(UserCredential(ANDRE, ANDRE_PASSWORD)))
+ .addHeader(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .setBody(request)
+ .build, new ResponseSpecBuilder().build)
+ .post
+ .`then`
+ .statusCode(SC_OK)
+ .contentType(JSON)
+ .extract
+ .body
+ .asString
+
+ assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].newState")
+ .withOptions(new Options(IGNORING_ARRAY_ORDER))
+ .isEqualTo(
+ s"""{
+ | "sessionState": "${SESSION_STATE.value}",
+ | "methodResponses": [
+ | [ "Mailbox/changes", {
+ | "accountId": "$ANDRE_ACCOUNT_ID",
+ | "oldState": "${oldState.getValue}",
+ | "hasMoreChanges": false,
+ | "updatedProperties": ["totalEmails", "unreadEmails", "totalThreads", "unreadThreads"],
+ | "created": [],
+ | "updated": ["$mailboxId"],
+ | "destroyed": []
+ | }, "c1"]
+ | ]
+ |}""".stripMargin)
+ }
}
@Test
@@ -754,6 +786,8 @@ trait MailboxChangesMethodContract {
server.getProbe(classOf[ACLProbeImpl])
.replaceRights(path, ANDRE.asString, new MailboxACL.Rfc4314Rights(Right.Lookup, Right.Read))
+ val state1: State = waitForNextStateWithDelegation(server, AccountId.fromUsername(ANDRE), State.INITIAL)
+
val message: Message = Message.Builder
.of
.setSubject("test")
@@ -761,7 +795,7 @@ trait MailboxChangesMethodContract {
.build
val messageId: MessageId = mailboxProbe.appendMessage(BOB.asString(), path, AppendCommand.from(message)).getMessageId
- val oldState: State = storeReferenceState(server, ANDRE)
+ val oldState: State = waitForNextStateWithDelegation(server, AccountId.fromUsername(ANDRE), state1)
JmapRequests.destroyEmail(messageId)
@@ -777,38 +811,40 @@ trait MailboxChangesMethodContract {
| "c1"]]
|}""".stripMargin
- val response = `given`(
- baseRequestSpecBuilder(server)
- .setAuth(authScheme(UserCredential(ANDRE, ANDRE_PASSWORD)))
- .addHeader(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
- .setBody(request)
- .build, new ResponseSpecBuilder().build)
- .post
- .`then`
- .statusCode(SC_OK)
- .contentType(JSON)
- .extract
- .body
- .asString
-
- assertThatJson(response)
- .whenIgnoringPaths("methodResponses[0][1].newState")
- .withOptions(new Options(IGNORING_ARRAY_ORDER))
- .isEqualTo(
- s"""{
- | "sessionState": "${SESSION_STATE.value}",
- | "methodResponses": [
- | [ "Mailbox/changes", {
- | "accountId": "$ANDRE_ACCOUNT_ID",
- | "oldState": "${oldState.getValue}",
- | "hasMoreChanges": false,
- | "updatedProperties": ["totalEmails", "unreadEmails", "totalThreads", "unreadThreads"],
- | "created": [],
- | "updated": ["$mailboxId"],
- | "destroyed": []
- | }, "c1"]
- | ]
- |}""".stripMargin)
+ awaitAtMostTenSeconds.untilAsserted { () =>
+ val response = `given`(
+ baseRequestSpecBuilder(server)
+ .setAuth(authScheme(UserCredential(ANDRE, ANDRE_PASSWORD)))
+ .addHeader(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .setBody(request)
+ .build, new ResponseSpecBuilder().build)
+ .post
+ .`then`
+ .statusCode(SC_OK)
+ .contentType(JSON)
+ .extract
+ .body
+ .asString
+
+ assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].newState")
+ .withOptions(new Options(IGNORING_ARRAY_ORDER))
+ .isEqualTo(
+ s"""{
+ | "sessionState": "${SESSION_STATE.value}",
+ | "methodResponses": [
+ | [ "Mailbox/changes", {
+ | "accountId": "$ANDRE_ACCOUNT_ID",
+ | "oldState": "${oldState.getValue}",
+ | "hasMoreChanges": false,
+ | "updatedProperties": ["totalEmails", "unreadEmails", "totalThreads", "unreadThreads"],
+ | "created": [],
+ | "updated": ["$mailboxId"],
+ | "destroyed": []
+ | }, "c1"]
+ | ]
+ |}""".stripMargin)
+ }
}
@Test
@@ -818,9 +854,7 @@ trait MailboxChangesMethodContract {
provisionSystemMailboxes(server)
val path = MailboxPath.forUser(BOB, "mailbox1")
- val mailboxId: String = mailboxProbe
- .createMailbox(path)
- .serialize
+ mailboxProbe.createMailbox(path)
server.getProbe(classOf[ACLProbeImpl])
.replaceRights(path, ANDRE.asString, new MailboxACL.Rfc4314Rights(Right.Lookup, Right.Read))
@@ -832,7 +866,7 @@ trait MailboxChangesMethodContract {
.build
val messageId: MessageId = mailboxProbe.appendMessage(BOB.asString(), path, AppendCommand.from(message)).getMessageId
- val oldState: State = storeReferenceState(server, ANDRE)
+ waitForNextStateWithDelegation(server, AccountId.fromUsername(ANDRE), State.INITIAL)
JmapRequests.destroyEmail(messageId)
@@ -843,47 +877,49 @@ trait MailboxChangesMethodContract {
| "Mailbox/changes",
| {
| "accountId": "$ANDRE_ACCOUNT_ID",
- | "sinceState": "${oldState.getValue}"
+ | "sinceState": "${State.INITIAL.getValue}"
| },
| "c1"]]
|}""".stripMargin
- val response = `given`(
- baseRequestSpecBuilder(server)
- .setAuth(authScheme(UserCredential(ANDRE, ANDRE_PASSWORD)))
- .addHeader(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
- .setBody(request)
- .build, new ResponseSpecBuilder().build)
- .post
- .`then`
- .statusCode(SC_OK)
- .contentType(JSON)
- .extract
- .body
- .asString
-
- assertThatJson(response)
- .whenIgnoringPaths("methodResponses[0][1].newState")
- .withOptions(new Options(IGNORING_ARRAY_ORDER))
- .isEqualTo(
- s"""{
- | "sessionState": "${SESSION_STATE.value}",
- | "methodResponses": [
- | [ "Mailbox/changes", {
- | "accountId": "$ANDRE_ACCOUNT_ID",
- | "oldState": "${oldState.getValue}",
- | "hasMoreChanges": false,
- | "updatedProperties":null,
- | "created": [],
- | "updated": [],
- | "destroyed": []
- | }, "c1"]
- | ]
- |}""".stripMargin)
+ awaitAtMostTenSeconds.untilAsserted { () =>
+ val response = `given`(
+ baseRequestSpecBuilder(server)
+ .setAuth(authScheme(UserCredential(ANDRE, ANDRE_PASSWORD)))
+ .addHeader(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .setBody(request)
+ .build, new ResponseSpecBuilder().build)
+ .post
+ .`then`
+ .statusCode(SC_OK)
+ .contentType(JSON)
+ .extract
+ .body
+ .asString
+
+ assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].newState")
+ .withOptions(new Options(IGNORING_ARRAY_ORDER))
+ .isEqualTo(
+ s"""{
+ | "sessionState": "${SESSION_STATE.value}",
+ | "methodResponses": [
+ | [ "Mailbox/changes", {
+ | "accountId": "$ANDRE_ACCOUNT_ID",
+ | "oldState": "${State.INITIAL.getValue}",
+ | "hasMoreChanges": false,
+ | "updatedProperties": null,
+ | "created": [],
+ | "updated": [],
+ | "destroyed": []
+ | }, "c1"]
+ | ]
+ |}""".stripMargin)
+ }
}
@Test
- def mailboxChangesShouldReturnUpdatedChangesWhenDestroyDelegatedMailbox(server: GuiceJamesServer): Unit = {
+ def mailboxChangesShouldReturnDestroyedChangesWhenDestroyDelegatedMailbox(server: GuiceJamesServer): Unit = {
val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
provisionSystemMailboxes(server)
@@ -896,7 +932,7 @@ trait MailboxChangesMethodContract {
server.getProbe(classOf[ACLProbeImpl])
.replaceRights(path, ANDRE.asString, new MailboxACL.Rfc4314Rights(Right.Lookup, Right.Read))
- val oldState: State = storeReferenceState(server, ANDRE)
+ val oldState: State = waitForNextStateWithDelegation(server, AccountId.fromUsername(ANDRE), State.INITIAL)
JmapRequests.destroyMailbox(mailboxId)
@@ -912,56 +948,58 @@ trait MailboxChangesMethodContract {
| "c1"]]
|}""".stripMargin
- val response = `given`(
- baseRequestSpecBuilder(server)
- .setAuth(authScheme(UserCredential(ANDRE, ANDRE_PASSWORD)))
- .addHeader(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
- .setBody(request)
- .build, new ResponseSpecBuilder().build)
- .post
- .`then`
- .statusCode(SC_OK)
- .contentType(JSON)
- .extract
- .body
- .asString
-
- assertThatJson(response)
- .whenIgnoringPaths("methodResponses[0][1].newState")
- .withOptions(new Options(IGNORING_ARRAY_ORDER))
- .isEqualTo(
- s"""{
- | "sessionState": "${SESSION_STATE.value}",
- | "methodResponses": [
- | [ "Mailbox/changes", {
- | "accountId": "$ANDRE_ACCOUNT_ID",
- | "oldState": "${oldState.getValue}",
- | "hasMoreChanges": false,
- | "updatedProperties": null,
- | "created": [],
- | "updated": [],
- | "destroyed": ["$mailboxId"]
- | }, "c1"]
- | ]
- |}""".stripMargin)
+ awaitAtMostTenSeconds.untilAsserted { () =>
+ val response = `given`(
+ baseRequestSpecBuilder(server)
+ .setAuth(authScheme(UserCredential(ANDRE, ANDRE_PASSWORD)))
+ .addHeader(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .setBody(request)
+ .build, new ResponseSpecBuilder().build)
+ .post
+ .`then`
+ .statusCode(SC_OK)
+ .contentType(JSON)
+ .extract
+ .body
+ .asString
+
+ assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].newState")
+ .withOptions(new Options(IGNORING_ARRAY_ORDER))
+ .isEqualTo(
+ s"""{
+ | "sessionState": "${SESSION_STATE.value}",
+ | "methodResponses": [
+ | [ "Mailbox/changes", {
+ | "accountId": "$ANDRE_ACCOUNT_ID",
+ | "oldState": "${oldState.getValue}",
+ | "hasMoreChanges": false,
+ | "updatedProperties": null,
+ | "created": [],
+ | "updated": [],
+ | "destroyed": ["$mailboxId"]
+ | }, "c1"]
+ | ]
+ |}""".stripMargin)
+ }
}
}
@Test
def mailboxChangesShouldReturnDestroyedChanges(server: GuiceJamesServer): Unit = {
val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
+ val accountId: AccountId = AccountId.fromUsername(BOB)
- provisionSystemMailboxes(server)
+ val provisioningState: State = provisionSystemMailboxes(server)
val path = MailboxPath.forUser(BOB, "mailbox1")
val mailboxId: String = mailboxProbe
.createMailbox(path)
.serialize
- val oldState: State = storeReferenceState(server, BOB)
+ val oldState: State = waitForNextState(server, accountId, provisioningState)
- mailboxProbe
- .deleteMailbox(path.getNamespace, BOB.asString(), path.getName)
+ mailboxProbe.deleteMailbox(path.getNamespace, BOB.asString(), path.getName)
val request =
s"""{
@@ -975,58 +1013,51 @@ trait MailboxChangesMethodContract {
| "c1"]]
|}""".stripMargin
- val response = `given`
- .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
- .body(request)
- .when
- .post
- .`then`
- .statusCode(SC_OK)
- .contentType(JSON)
- .extract
- .body
- .asString
+ awaitAtMostTenSeconds.untilAsserted { () =>
+ val response = `given`
+ .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .body(request)
+ .when
+ .post
+ .`then`
+ .statusCode(SC_OK)
+ .contentType(JSON)
+ .extract
+ .body
+ .asString
- assertThatJson(response)
- .whenIgnoringPaths("methodResponses[0][1].newState")
- .withOptions(new Options(IGNORING_ARRAY_ORDER))
- .isEqualTo(
- s"""{
- | "sessionState": "${SESSION_STATE.value}",
- | "methodResponses": [
- | [ "Mailbox/changes", {
- | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "oldState": "${oldState.getValue}",
- | "hasMoreChanges": false,
- | "updatedProperties":null,
- | "created": [],
- | "updated": [],
- | "destroyed": ["$mailboxId"]
- | }, "c1"]
- | ]
- |}""".stripMargin)
+ assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].newState")
+ .withOptions(new Options(IGNORING_ARRAY_ORDER))
+ .isEqualTo(
+ s"""{
+ | "sessionState": "${SESSION_STATE.value}",
+ | "methodResponses": [
+ | [ "Mailbox/changes", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "oldState": "${oldState.getValue}",
+ | "hasMoreChanges": false,
+ | "updatedProperties":null,
+ | "created": [],
+ | "updated": [],
+ | "destroyed": ["$mailboxId"]
+ | }, "c1"]
+ | ]
+ |}""".stripMargin)
+ }
}
@Test
- def mailboxChangesShouldReturnAllTypeOfChanges(server: GuiceJamesServer): Unit = {
+ def returnedIdsShouldNotReturnDuplicatesAccrossCreatedUpdatedOrDestroyed(server: GuiceJamesServer): Unit = {
val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
- provisionSystemMailboxes(server)
+ val provisioningState: State = provisionSystemMailboxes(server)
val path1 = MailboxPath.forUser(BOB, "mailbox1")
val mailboxId1: String = mailboxProbe
.createMailbox(path1)
.serialize
- val path2 = MailboxPath.forUser(BOB, "mailbox2")
- val mailboxId2: String = mailboxProbe
- .createMailbox(path2)
- .serialize
- val path3 = MailboxPath.forUser(BOB, "mailbox3")
- val oldState: State = server.getProbe(classOf[JmapGuiceProbe]).latestState(AccountId.fromUsername(BOB))
- val mailboxId3: String = mailboxProbe
- .createMailbox(path3)
- .serialize
val message: Message = Message.Builder
.of
.setSubject("test")
@@ -1034,8 +1065,13 @@ trait MailboxChangesMethodContract {
.build
mailboxProbe.appendMessage(BOB.asString(), path1, AppendCommand.from(message))
- server.getProbe(classOf[MailboxProbeImpl])
- .deleteMailbox(path1.getNamespace, BOB.asString(), path2.getName)
+ val path2 = MailboxPath.forUser(BOB, "mailbox2")
+ val mailboxId2: String = mailboxProbe
+ .createMailbox(path2)
+ .serialize
+ JmapRequests.renameMailbox(mailboxId2, "mailbox22")
+
+ mailboxProbe.deleteMailbox(path1.getNamespace, BOB.asString(), path1.getName)
val request =
s"""{
@@ -1044,56 +1080,71 @@ trait MailboxChangesMethodContract {
| "Mailbox/changes",
| {
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "sinceState": "${oldState.getValue}"
+ | "sinceState": "${provisioningState.getValue}"
| },
| "c1"]]
|}""".stripMargin
- val response = `given`
- .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
- .body(request)
- .when
- .post
- .`then`
- .statusCode(SC_OK)
- .contentType(JSON)
- .extract
- .body
- .asString
+ awaitAtMostTenSeconds.untilAsserted { () =>
+ val response = `given`
+ .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .body(request)
+ .when
+ .post
+ .`then`
+ .statusCode(SC_OK)
+ .contentType(JSON)
+ .extract
+ .body
+ .asString
- assertThatJson(response)
- .whenIgnoringPaths("methodResponses[0][1].newState")
- .withOptions(new Options(IGNORING_ARRAY_ORDER))
- .isEqualTo(
- s"""{
- | "sessionState": "${SESSION_STATE.value}",
- | "methodResponses": [
- | [ "Mailbox/changes", {
- | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "oldState": "${oldState.getValue}",
- | "hasMoreChanges": false,
- | "updatedProperties": null,
- | "created": ["$mailboxId3"],
- | "updated": ["$mailboxId1"],
- | "destroyed": ["$mailboxId2"]
- | }, "c1"]
- | ]
- |}""".stripMargin)
+ assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].newState")
+ .withOptions(new Options(IGNORING_ARRAY_ORDER))
+ .isEqualTo(
+ s"""{
+ | "sessionState": "${SESSION_STATE.value}",
+ | "methodResponses": [
+ | [ "Mailbox/changes", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "oldState": "${provisioningState.getValue}",
+ | "hasMoreChanges": false,
+ | "updatedProperties":null,
+ | "created": ["$mailboxId2"],
+ | "updated": [],
+ | "destroyed": []
+ | }, "c1"]
+ | ]
+ |}""".stripMargin)
+ }
}
@Test
- def returnedIdsShouldNotReturnDuplicatesAccrossCreatedUpdatedOrDestroyed(server: GuiceJamesServer): Unit = {
+ def mailboxChangesShouldReturnAllTypeOfChanges(server: GuiceJamesServer): Unit = {
val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
+ val accountId: AccountId = AccountId.fromUsername(BOB)
- provisionSystemMailboxes(server)
-
- val oldState: State = storeReferenceState(server, BOB)
+ val provisioningState: State = provisionSystemMailboxes(server)
val path1 = MailboxPath.forUser(BOB, "mailbox1")
val mailboxId1: String = mailboxProbe
.createMailbox(path1)
.serialize
+ val state1: State = waitForNextState(server, accountId, provisioningState)
+
+ val path2 = MailboxPath.forUser(BOB, "mailbox2")
+ val mailboxId2: String = mailboxProbe
+ .createMailbox(path2)
+ .serialize
+
+ val oldState: State = waitForNextState(server, accountId, state1)
+
+ val path3 = MailboxPath.forUser(BOB, "mailbox3")
+ val mailboxId3: String = mailboxProbe
+ .createMailbox(path3)
+ .serialize
+
val message: Message = Message.Builder
.of
.setSubject("test")
@@ -1101,14 +1152,7 @@ trait MailboxChangesMethodContract {
.build
mailboxProbe.appendMessage(BOB.asString(), path1, AppendCommand.from(message))
- val path2 = MailboxPath.forUser(BOB, "mailbox2")
- val mailboxId2: String = mailboxProbe
- .createMailbox(path2)
- .serialize
- JmapRequests.renameMailbox(mailboxId2, "mailbox22")
-
- server.getProbe(classOf[MailboxProbeImpl])
- .deleteMailbox(path1.getNamespace, BOB.asString(), path1.getName)
+ mailboxProbe.deleteMailbox(path2.getNamespace, BOB.asString(), path2.getName)
val request =
s"""{
@@ -1122,44 +1166,45 @@ trait MailboxChangesMethodContract {
| "c1"]]
|}""".stripMargin
- val response = `given`
- .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
- .body(request)
- .when
- .post
- .`then`
- .statusCode(SC_OK)
- .contentType(JSON)
- .extract
- .body
- .asString
+ awaitAtMostTenSeconds.untilAsserted { () =>
+ val response = `given`
+ .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .body(request)
+ .when
+ .post
+ .`then`
+ .statusCode(SC_OK)
+ .contentType(JSON)
+ .extract
+ .body
+ .asString
- assertThatJson(response)
- .whenIgnoringPaths("methodResponses[0][1].newState")
- .withOptions(new Options(IGNORING_ARRAY_ORDER))
- .isEqualTo(
- s"""{
- | "sessionState": "${SESSION_STATE.value}",
- | "methodResponses": [
- | [ "Mailbox/changes", {
- | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "oldState": "${oldState.getValue}",
- | "hasMoreChanges": false,
- | "updatedProperties":null,
- | "created": ["$mailboxId2"],
- | "updated": [],
- | "destroyed": []
- | }, "c1"]
- | ]
- |}""".stripMargin)
+ assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].newState")
+ .withOptions(new Options(IGNORING_ARRAY_ORDER))
+ .isEqualTo(
+ s"""{
+ | "sessionState": "${SESSION_STATE.value}",
+ | "methodResponses": [
+ | [ "Mailbox/changes", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "oldState": "${oldState.getValue}",
+ | "hasMoreChanges": false,
+ | "updatedProperties": null,
+ | "created": ["$mailboxId3"],
+ | "updated": ["$mailboxId1"],
+ | "destroyed": ["$mailboxId2"]
+ | }, "c1"]
+ | ]
+ |}""".stripMargin)
+ }
}
@Test
def mailboxChangesShouldReturnHasMoreChangesWhenTrue(server: GuiceJamesServer): Unit = {
val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
- provisionSystemMailboxes(server)
- val oldState: State = storeReferenceState(server, BOB)
+ val provisioningState: State = provisionSystemMailboxes(server)
val mailboxId1: String = mailboxProbe
.createMailbox(MailboxPath.forUser(BOB, "mailbox1"))
@@ -1192,46 +1237,49 @@ trait MailboxChangesMethodContract {
| "Mailbox/changes",
| {
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "sinceState": "${oldState.getValue}"
+ | "sinceState": "${provisioningState.getValue}"
| },
| "c1"]]
|}""".stripMargin
- val response = `given`
- .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
- .body(request)
- .when
- .post
- .`then`
- .statusCode(SC_OK)
- .contentType(JSON)
- .extract
- .body
- .asString
+ awaitAtMostTenSeconds.untilAsserted { () =>
+ val response = `given`
+ .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .body(request)
+ .when
+ .post
+ .`then`
+ .statusCode(SC_OK)
+ .contentType(JSON)
+ .extract
+ .body
+ .asString
- assertThatJson(response)
- .whenIgnoringPaths("methodResponses[0][1].newState")
- .withOptions(new Options(IGNORING_ARRAY_ORDER))
- .isEqualTo(
- s"""{
- | "sessionState": "${SESSION_STATE.value}",
- | "methodResponses": [
- | [ "Mailbox/changes", {
- | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "oldState": "${oldState.getValue}",
- | "hasMoreChanges": true,
- | "updatedProperties":null,
- | "created": ["$mailboxId1", "$mailboxId2", "$mailboxId3", "$mailboxId4", "$mailboxId5"],
- | "updated": [],
- | "destroyed": []
- | }, "c1"]
- | ]
- |}""".stripMargin)
+ assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].newState")
+ .withOptions(new Options(IGNORING_ARRAY_ORDER))
+ .isEqualTo(
+ s"""{
+ | "sessionState": "${SESSION_STATE.value}",
+ | "methodResponses": [
+ | [ "Mailbox/changes", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "oldState": "${provisioningState.getValue}",
+ | "hasMoreChanges": true,
+ | "updatedProperties": null,
+ | "created": ["$mailboxId1", "$mailboxId2", "$mailboxId3", "$mailboxId4", "$mailboxId5"],
+ | "updated": [],
+ | "destroyed": []
+ | }, "c1"]
+ | ]
+ |}""".stripMargin)
+ }
}
@Test
def mailboxChangesShouldFailWhenAccountIdNotFound(server: GuiceJamesServer): Unit = {
- val oldState: State = storeReferenceState(server, BOB)
+ val jmapGuiceProbe:JmapGuiceProbe = server.getProbe(classOf[JmapGuiceProbe])
+ val oldState: State = jmapGuiceProbe.getLastestState(AccountId.fromUsername(BOB))
val request =
s"""{
@@ -1273,7 +1321,7 @@ trait MailboxChangesMethodContract {
def mailboxChangesShouldFailWhenStateNotFound(server: GuiceJamesServer): Unit = {
provisionSystemMailboxes(server)
- val state: String = UUID.randomUUID().toString
+ val state: String = stateFactory.generate().getValue.toString
val request =
s"""{
@@ -1316,9 +1364,7 @@ trait MailboxChangesMethodContract {
@Test
def mailboxChangesShouldReturnNoChangesWhenNoNewerState(server: GuiceJamesServer): Unit = {
- provisionSystemMailboxes(server)
-
- val oldState: State = storeReferenceState(server, BOB)
+ val provisioningState: State = provisionSystemMailboxes(server)
val request =
s"""{
@@ -1327,49 +1373,51 @@ trait MailboxChangesMethodContract {
| "Mailbox/changes",
| {
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "sinceState": "${oldState.getValue}"
+ | "sinceState": "${provisioningState.getValue}"
| },
| "c1"]]
|}""".stripMargin
- val response = `given`
- .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
- .body(request)
- .when
- .post
- .`then`
- .statusCode(SC_OK)
- .contentType(JSON)
- .extract
- .body
- .asString
-
- assertThatJson(response)
- .withOptions(new Options(IGNORING_ARRAY_ORDER))
- .isEqualTo(
- s"""{
- | "sessionState": "${SESSION_STATE.value}",
- | "methodResponses": [
- | [ "Mailbox/changes", {
- | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "oldState": "${oldState.getValue}",
- | "newState": "${oldState.getValue}",
- | "hasMoreChanges": false,
- | "updatedProperties":null,
- | "created": [],
- | "updated": [],
- | "destroyed": []
- | }, "c1"]
- | ]
- |}""".stripMargin)
+ awaitAtMostTenSeconds.untilAsserted { () =>
+ val response = `given`
+ .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .body(request)
+ .when
+ .post
+ .`then`
+ .statusCode(SC_OK)
+ .contentType(JSON)
+ .extract
+ .body
+ .asString
+
+ assertThatJson(response)
+ .withOptions(new Options(IGNORING_ARRAY_ORDER))
+ .isEqualTo(
+ s"""{
+ | "sessionState": "${SESSION_STATE.value}",
+ | "methodResponses": [
+ | [ "Mailbox/changes", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "oldState": "${provisioningState.getValue}",
+ | "newState": "${provisioningState.getValue}",
+ | "hasMoreChanges": false,
+ | "updatedProperties": null,
+ | "created": [],
+ | "updated": [],
+ | "destroyed": []
+ | }, "c1"]
+ | ]
+ |}""".stripMargin)
+ }
}
@Test
def mailboxChangesShouldReturnDifferentStateThanOldState(server: GuiceJamesServer): Unit = {
val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
- provisionSystemMailboxes(server)
- val oldState: State = storeReferenceState(server, BOB)
+ val provisioningState: State = provisionSystemMailboxes(server)
+
mailboxProbe.createMailbox(MailboxPath.forUser(BOB, "mailbox1"))
mailboxProbe.createMailbox(MailboxPath.forUser(BOB, "mailbox2"))
@@ -1380,40 +1428,41 @@ trait MailboxChangesMethodContract {
| "Mailbox/changes",
| {
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "sinceState": "${oldState.getValue}"
+ | "sinceState": "${provisioningState.getValue}"
| },
| "c1"]]
|}""".stripMargin
- val response = `given`
- .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
- .body(request)
- .when
- .post
- .`then`
- .statusCode(SC_OK)
- .contentType(JSON)
- .extract
- .body
- .asString
+ awaitAtMostTenSeconds.untilAsserted { () =>
+ val response = `given`
+ .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .body(request)
+ .when
+ .post
+ .`then`
+ .statusCode(SC_OK)
+ .contentType(JSON)
+ .extract
+ .body
+ .asString
- val newState = Json.parse(response)
- .\("methodResponses")
- .\(0).\(1)
- .\("newState")
- .get.asInstanceOf[JsString].value
+ val newState = Json.parse(response)
+ .\("methodResponses")
+ .\(0).\(1)
+ .\("newState")
+ .get.asInstanceOf[JsString].value
- assertThat(oldState.getValue.toString).isNotEqualTo(newState)
+ assertThat(provisioningState.getValue.toString).isNotEqualTo(newState)
+ }
}
@Test
def mailboxChangesShouldEventuallyReturnNoChanges(server: GuiceJamesServer): Unit = {
val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
- provisionSystemMailboxes(server)
- val oldState: State = storeReferenceState(server, BOB)
+ val provisioningState: State = provisionSystemMailboxes(server)
+
mailboxProbe.createMailbox(MailboxPath.forUser(BOB, "mailbox1"))
- mailboxProbe.createMailbox(MailboxPath.forUser(BOB, "mailbox2"))
val request1 =
s"""{
@@ -1422,7 +1471,7 @@ trait MailboxChangesMethodContract {
| "Mailbox/changes",
| {
| "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "sinceState": "${oldState.getValue}"
+ | "sinceState": "${provisioningState.getValue}"
| },
| "c1"]]
|}""".stripMargin
@@ -1492,15 +1541,16 @@ trait MailboxChangesMethodContract {
@Test
def mailboxChangesShouldReturnUpdatedPropertiesWhenOnlyCountChanges(server: GuiceJamesServer): Unit = {
val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
+ val accountId: AccountId = AccountId.fromUsername(BOB)
- provisionSystemMailboxes(server)
+ val provisioningState: State = provisionSystemMailboxes(server)
val path = MailboxPath.forUser(BOB, "mailbox1")
val mailboxId: String = mailboxProbe
.createMailbox(path)
.serialize
- val oldState: State = storeReferenceState(server, BOB)
+ val oldState: State = waitForNextState(server, accountId, provisioningState)
val message: Message = Message.Builder
.of
@@ -1561,15 +1611,16 @@ trait MailboxChangesMethodContract {
@Test
def mailboxChangesShouldNotReturnUpdatedPropertiesWhenMixedChanges(server: GuiceJamesServer): Unit = {
val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
+ val accountId: AccountId = AccountId.fromUsername(BOB)
- provisionSystemMailboxes(server)
+ val provisioningState: State = provisionSystemMailboxes(server)
val path = MailboxPath.forUser(BOB, "mailbox1")
val mailboxId1: String = mailboxProbe
.createMailbox(path)
.serialize
- val oldState: State = storeReferenceState(server, BOB)
+ val oldState: State = waitForNextState(server, accountId, provisioningState)
val path2 = MailboxPath.forUser(BOB, "mailbox2")
val mailboxId2: String = mailboxProbe
@@ -1595,50 +1646,53 @@ trait MailboxChangesMethodContract {
| "c1"]]
|}""".stripMargin
- val response = `given`
- .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
- .body(request)
- .when
- .post
- .`then`
- .statusCode(SC_OK)
- .contentType(JSON)
- .extract
- .body
- .asString
+ awaitAtMostTenSeconds.untilAsserted { () =>
+ val response = `given`
+ .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .body(request)
+ .when
+ .post
+ .`then`
+ .statusCode(SC_OK)
+ .contentType(JSON)
+ .extract
+ .body
+ .asString
- assertThatJson(response)
- .whenIgnoringPaths("methodResponses[0][1].newState")
- .withOptions(new Options(IGNORING_ARRAY_ORDER))
- .isEqualTo(
- s"""{
- | "sessionState": "${SESSION_STATE.value}",
- | "methodResponses": [
- | [ "Mailbox/changes", {
- | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "oldState": "${oldState.getValue}",
- | "hasMoreChanges": false,
- | "updatedProperties":null,
- | "created": ["$mailboxId2"],
- | "updated": ["$mailboxId1"],
- | "destroyed": []
- | }, "c1"]
- | ]
- |}""".stripMargin)
+ assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].newState")
+ .withOptions(new Options(IGNORING_ARRAY_ORDER))
+ .isEqualTo(
+ s"""{
+ | "sessionState": "${SESSION_STATE.value}",
+ | "methodResponses": [
+ | [ "Mailbox/changes", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "oldState": "${oldState.getValue}",
+ | "hasMoreChanges": false,
+ | "updatedProperties":null,
+ | "created": ["$mailboxId2"],
+ | "updated": ["$mailboxId1"],
+ | "destroyed": []
+ | }, "c1"]
+ | ]
+ |}""".stripMargin)
+ }
}
@Test
def mailboxChangesShouldSupportBackReferenceWithUpdatedProperties(server: GuiceJamesServer): Unit = {
val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
+ val accountId: AccountId = AccountId.fromUsername(BOB)
- provisionSystemMailboxes(server)
+ val provisioningState: State = provisionSystemMailboxes(server)
val path = MailboxPath.forUser(BOB, "mailbox1")
val mailboxId: String = mailboxProbe
.createMailbox(path)
.serialize
- val oldState: State = storeReferenceState(server, BOB)
+ val oldState: State = waitForNextState(server, accountId, provisioningState)
val message: Message = Message.Builder
.of
@@ -1646,9 +1700,6 @@ trait MailboxChangesMethodContract {
.setBody("testmail", StandardCharsets.UTF_8)
.build
mailboxProbe.appendMessage(BOB.asString(), path, AppendCommand.from(message)).getMessageId
- val messageId2: MessageId = mailboxProbe.appendMessage(BOB.asString(), path, AppendCommand.from(message)).getMessageId
-
- JmapRequests.destroyEmail(messageId2)
val request =
s"""{
@@ -1674,63 +1725,66 @@ trait MailboxChangesMethodContract {
| ]
|}""".stripMargin
- val response = `given`
- .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
- .body(request)
- .when
- .post
- .`then`
- .statusCode(SC_OK)
- .contentType(JSON)
- .extract
- .body
- .asString
+ awaitAtMostTenSeconds.untilAsserted { () =>
+ val response = `given`
+ .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .body(request)
+ .when
+ .post
+ .`then`
+ .statusCode(SC_OK)
+ .contentType(JSON)
+ .extract
+ .body
+ .asString
- assertThatJson(response)
- .whenIgnoringPaths("methodResponses[0][1].newState", "methodResponses[1][1].state")
- .withOptions(new Options(IGNORING_ARRAY_ORDER))
- .isEqualTo(
- s"""{
- | "sessionState": "${SESSION_STATE.value}",
- | "methodResponses": [
- | [ "Mailbox/changes", {
- | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "oldState": "${oldState.getValue}",
- | "hasMoreChanges": false,
- | "updatedProperties": ["totalEmails", "unreadEmails", "totalThreads", "unreadThreads"],
- | "created": [],
- | "updated": ["$mailboxId"],
- | "destroyed": []
- | }, "c1"],
- | ["Mailbox/get", {
- | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "notFound": [],
- | "list": [
- | {
- | "id": "$mailboxId",
- | "totalEmails": 1,
- | "unreadEmails": 1,
- | "totalThreads": 1,
- | "unreadThreads": 1
- | }
- | ]
- | }, "c2"]
- | ]
- |}""".stripMargin)
+ assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].newState", "methodResponses[1][1].state")
+ .withOptions(new Options(IGNORING_ARRAY_ORDER))
+ .isEqualTo(
+ s"""{
+ | "sessionState": "${SESSION_STATE.value}",
+ | "methodResponses": [
+ | [ "Mailbox/changes", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "oldState": "${oldState.getValue}",
+ | "hasMoreChanges": false,
+ | "updatedProperties": ["totalEmails", "unreadEmails", "totalThreads", "unreadThreads"],
+ | "created": [],
+ | "updated": ["$mailboxId"],
+ | "destroyed": []
+ | }, "c1"],
+ | ["Mailbox/get", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "notFound": [],
+ | "list": [
+ | {
+ | "id": "$mailboxId",
+ | "totalEmails": 1,
+ | "unreadEmails": 1,
+ | "totalThreads": 1,
+ | "unreadThreads": 1
+ | }
+ | ]
+ | }, "c2"]
+ | ]
+ |}""".stripMargin)
+ }
}
@Test
def mailboxChangesShouldSupportBackReferenceWithNullUpdatedProperties(server: GuiceJamesServer): Unit = {
val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
+ val accountId: AccountId = AccountId.fromUsername(BOB)
- provisionSystemMailboxes(server)
+ val provisioningState: State = provisionSystemMailboxes(server)
val path1 = MailboxPath.forUser(BOB, "mailbox1")
val mailboxId1: String = mailboxProbe
.createMailbox(path1)
.serialize
- val oldState: State = storeReferenceState(server, BOB)
+ val oldState: State = waitForNextState(server, accountId, provisioningState)
val path2 = MailboxPath.forUser(BOB, "mailbox2")
val mailboxId2: String = mailboxProbe
@@ -1768,76 +1822,86 @@ trait MailboxChangesMethodContract {
| ]
|}""".stripMargin
- val response = `given`
- .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
- .body(request)
- .when
- .post
- .`then`
- .statusCode(SC_OK)
- .contentType(JSON)
- .extract
- .body
- .asString
+ awaitAtMostTenSeconds.untilAsserted { () =>
+ val response = `given`
+ .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .body(request)
+ .when
+ .post
+ .`then`
+ .statusCode(SC_OK)
+ .contentType(JSON)
+ .extract
+ .body
+ .asString
- assertThatJson(response)
- .whenIgnoringPaths("methodResponses[0][1].newState", "methodResponses[1][1].state")
- .withOptions(new Options(IGNORING_ARRAY_ORDER))
- .isEqualTo(
- s"""{
- | "sessionState": "${SESSION_STATE.value}",
- | "methodResponses": [
- | [ "Mailbox/changes", {
- | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "oldState": "${oldState.getValue}",
- | "hasMoreChanges": false,
- | "updatedProperties": null,
- | "created": ["$mailboxId2"],
- | "updated": ["$mailboxId1"],
- | "destroyed": []
- | }, "c1"],
- | ["Mailbox/get", {
- | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
- | "notFound": [],
- | "list": [
- | {
- | "id": "$mailboxId1",
- | "name": "mailbox1",
- | "sortOrder": 1000,
- | "totalEmails": 1,
- | "unreadEmails": 1,
- | "totalThreads": 1,
- | "unreadThreads": 1,
- | "myRights": {
- | "mayReadItems": true,
- | "mayAddItems": true,
- | "mayRemoveItems": true,
- | "maySetSeen": true,
- | "maySetKeywords": true,
- | "mayCreateChild": true,
- | "mayRename": true,
- | "mayDelete": true,
- | "maySubmit": true
- | },
- | "isSubscribed": false
- | }
- | ]
- | }, "c2"]
- | ]
- |}""".stripMargin)
+ assertThatJson(response)
+ .whenIgnoringPaths("methodResponses[0][1].newState", "methodResponses[1][1].state")
+ .withOptions(new Options(IGNORING_ARRAY_ORDER))
+ .isEqualTo(
+ s"""{
+ | "sessionState": "${SESSION_STATE.value}",
+ | "methodResponses": [
+ | [ "Mailbox/changes", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "oldState": "${oldState.getValue}",
+ | "hasMoreChanges": false,
+ | "updatedProperties": null,
+ | "created": ["$mailboxId2"],
+ | "updated": ["$mailboxId1"],
+ | "destroyed": []
+ | }, "c1"],
+ | ["Mailbox/get", {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "notFound": [],
+ | "list": [
+ | {
+ | "id": "$mailboxId1",
+ | "name": "mailbox1",
+ | "sortOrder": 1000,
+ | "totalEmails": 1,
+ | "unreadEmails": 1,
+ | "totalThreads": 1,
+ | "unreadThreads": 1,
+ | "myRights": {
+ | "mayReadItems": true,
+ | "mayAddItems": true,
+ | "mayRemoveItems": true,
+ | "maySetSeen": true,
+ | "maySetKeywords": true,
+ | "mayCreateChild": true,
+ | "mayRename": true,
+ | "mayDelete": true,
+ | "maySubmit": true
+ | },
+ | "isSubscribed": false
+ | }
+ | ]
+ | }, "c2"]
+ | ]
+ |}""".stripMargin)
+ }
}
- private def storeReferenceState(server: GuiceJamesServer, username: Username): State = {
- val state: State = stateFactory.generate()
+ private def waitForNextState(server: GuiceJamesServer, accountId: AccountId, initialState: State): State = {
val jmapGuiceProbe: JmapGuiceProbe = server.getProbe(classOf[JmapGuiceProbe])
+ awaitAtMostTenSeconds.untilAsserted {
+ () => assertThat(jmapGuiceProbe.getLastestState(accountId)).isNotEqualTo(initialState)
+ }
+
+ jmapGuiceProbe.getLastestState(accountId)
+ }
- jmapGuiceProbe.saveMailboxChange(MailboxChange.builder.accountId(AccountId.fromUsername(username)).state(state).date(ZonedDateTime.now()).isCountChange(false).updated(List(TestId.of(0)).asJava).build)
+ private def waitForNextStateWithDelegation(server: GuiceJamesServer, accountId: AccountId, initialState: State): State = {
+ val jmapGuiceProbe: JmapGuiceProbe = server.getProbe(classOf[JmapGuiceProbe])
+ awaitAtMostTenSeconds.untilAsserted{ () => assertThat(jmapGuiceProbe.getLastestStateWithDelegation(accountId)).isNotEqualTo(initialState) }
- state
+ jmapGuiceProbe.getLastestStateWithDelegation(accountId)
}
- private def provisionSystemMailboxes(server: GuiceJamesServer): Unit = {
+ private def provisionSystemMailboxes(server: GuiceJamesServer): State = {
val mailboxId: MailboxId = server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB))
+ val jmapGuiceProbe: JmapGuiceProbe = server.getProbe(classOf[JmapGuiceProbe])
val request =
s"""{
@@ -1859,5 +1923,42 @@ trait MailboxChangesMethodContract {
.`then`
.statusCode(SC_OK)
.contentType(JSON)
+
+ //Wait until all the system mailboxes are created
+ val request2 =
+ s"""{
+ | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"],
+ | "methodCalls": [[
+ | "Mailbox/changes",
+ | {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "sinceState": "${State.INITIAL.getValue.toString}"
+ | },
+ | "c1"]]
+ |}""".stripMargin
+
+ awaitAtMostTenSeconds.untilAsserted { () =>
+ val response1 = `given`
+ .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+ .body(request2)
+ .when
+ .post
+ .`then`
+ .statusCode(SC_OK)
+ .contentType(JSON)
+ .extract
+ .body
+ .asString
+
+ val createdSize = Json.parse(response1)
+ .\("methodResponses")
+ .\(0).\(1)
+ .\("created")
+ .get.asInstanceOf[JsArray].value.size
+
+ assertThat(createdSize).isEqualTo(5)
+ }
+
+ jmapGuiceProbe.getLastestState(AccountId.fromUsername(BOB))
}
}
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryMailboxChangesMethodTest.java b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryMailboxChangesMethodTest.java
index b01641a..df68a52 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryMailboxChangesMethodTest.java
+++ b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryMailboxChangesMethodTest.java
@@ -26,6 +26,8 @@ import org.apache.james.JamesServerBuilder;
import org.apache.james.JamesServerExtension;
import org.apache.james.jmap.api.change.State;
import org.apache.james.jmap.rfc8621.contract.MailboxChangesMethodContract;
+import org.apache.james.mailbox.inmemory.InMemoryId;
+import org.apache.james.mailbox.model.MailboxId;
import org.apache.james.modules.TestJMAPServerModule;
import org.junit.jupiter.api.extension.RegisterExtension;
@@ -42,4 +44,9 @@ public class MemoryMailboxChangesMethodTest implements MailboxChangesMethodContr
public State.Factory stateFactory() {
return new State.DefaultFactory();
}
+
+ @Override
+ public MailboxId generateMailboxId() {
+ return InMemoryId.of(0);
+ }
}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 17/24: JAMES-3202 ReIndexerPerformer in corrective
mode: add missing error handling
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 8630f345ccb9ab26e245c0d992c1f67eadfff7a4
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Wed Dec 30 17:01:10 2020 +0700
JAMES-3202 ReIndexerPerformer in corrective mode: add missing error handling
---
.../events/ElasticSearchListeningMessageSearchIndex.java | 1 -
.../java/org/apache/mailbox/tools/indexer/ReIndexerPerformer.java | 8 ++++++--
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndex.java b/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndex.java
index f3af769..6554bb6 100644
--- a/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndex.java
+++ b/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndex.java
@@ -62,7 +62,6 @@ import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
import org.apache.james.mailbox.store.mail.model.MailboxMessage;
import org.apache.james.mailbox.store.search.ListeningMessageSearchIndex;
import org.elasticsearch.action.get.GetResponse;
-import org.elasticsearch.index.IndexNotFoundException;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/mailbox/tools/indexer/src/main/java/org/apache/mailbox/tools/indexer/ReIndexerPerformer.java b/mailbox/tools/indexer/src/main/java/org/apache/mailbox/tools/indexer/ReIndexerPerformer.java
index bff8e27..2dd9cde 100644
--- a/mailbox/tools/indexer/src/main/java/org/apache/mailbox/tools/indexer/ReIndexerPerformer.java
+++ b/mailbox/tools/indexer/src/main/java/org/apache/mailbox/tools/indexer/ReIndexerPerformer.java
@@ -327,10 +327,14 @@ public class ReIndexerPerformer {
.flatMap(message -> isIndexUpToDate(entry.getMailbox(), message)
.flatMap(upToDate -> {
if (upToDate) {
- return Mono.just(Either.right(Result.COMPLETED));
+ return Mono.just(Either.<Failure, Result>right(Result.COMPLETED));
}
return correct(entry, message);
- }));
+ }))
+ .onErrorResume(e -> {
+ LOGGER.warn("ReIndexing failed for {} {}", entry.getMailbox().generateAssociatedPath(), entry.getUid(), e);
+ return Mono.just(Either.left(new MessageFailure(entry.getMailbox().getMailboxId(), entry.getUid())));
+ });
}
private Mono<Either<Failure, Result>> correct(ReIndexingEntry entry, MailboxMessage message) {
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 16/24: JAMES-3202 ReIndexerPerformer in corrective
mode should add missing messages in the index
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit b2c9553b600542e09360e4210f575e284b382c4f
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Wed Dec 30 16:55:52 2020 +0700
JAMES-3202 ReIndexerPerformer in corrective mode should add missing messages in the index
The messages were skept
---
.../ElasticSearchListeningMessageSearchIndex.java | 4 +--
...asticSearchListeningMessageSearchIndexTest.java | 6 ++---
.../mailbox/tools/indexer/ReIndexerPerformer.java | 3 ++-
.../mailbox/tools/indexer/ReIndexerImplTest.java | 31 ++++++++++++++++++++++
.../james/webadmin/routes/MailboxesRoutesTest.java | 8 +++---
.../webadmin/routes/UserMailboxesRoutesTest.java | 4 +--
6 files changed, 43 insertions(+), 13 deletions(-)
diff --git a/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndex.java b/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndex.java
index b6245a8..f3af769 100644
--- a/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndex.java
+++ b/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndex.java
@@ -233,9 +233,7 @@ public class ElasticSearchListeningMessageSearchIndex extends ListeningMessageSe
return elasticSearchIndexer.get(indexIdFor(mailbox.getMailboxId(), uid), routingKey)
.filter(GetResponse::isExists)
.map(GetResponse::getSourceAsMap)
- .map(this::extractFlags)
- .switchIfEmpty(Mono.error(() -> new IndexNotFoundException(
- String.format("Index for message %s in mailbox %s not found", uid.toString(), mailbox.getMailboxId().serialize()))));
+ .map(this::extractFlags);
}
private Flags extractFlags(Map<String, Object> source) {
diff --git a/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndexTest.java b/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndexTest.java
index 1c588af..fcfa31e 100644
--- a/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndexTest.java
+++ b/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndexTest.java
@@ -466,9 +466,9 @@ class ElasticSearchListeningMessageSearchIndexTest {
}
@Test
- void retrieveIndexedFlagsShouldPropagateExceptionWhenNotFound() {
- assertThatThrownBy(() -> testee.retrieveIndexedFlags(mailbox, MESSAGE_UID_4).block())
- .isInstanceOf(IndexNotFoundException.class);
+ void retrieveIndexedFlagsShouldReturnEmptyWhenNotFound() {
+ assertThat(testee.retrieveIndexedFlags(mailbox, MESSAGE_UID_4).blockOptional())
+ .isEmpty();
}
}
}
\ No newline at end of file
diff --git a/mailbox/tools/indexer/src/main/java/org/apache/mailbox/tools/indexer/ReIndexerPerformer.java b/mailbox/tools/indexer/src/main/java/org/apache/mailbox/tools/indexer/ReIndexerPerformer.java
index ad2f2f3..bff8e27 100644
--- a/mailbox/tools/indexer/src/main/java/org/apache/mailbox/tools/indexer/ReIndexerPerformer.java
+++ b/mailbox/tools/indexer/src/main/java/org/apache/mailbox/tools/indexer/ReIndexerPerformer.java
@@ -340,7 +340,8 @@ public class ReIndexerPerformer {
private Mono<Boolean> isIndexUpToDate(Mailbox mailbox, MailboxMessage message) {
return messageSearchIndex.retrieveIndexedFlags(mailbox, message.getUid())
- .map(flags -> isIndexUpToDate(message, flags));
+ .map(flags -> isIndexUpToDate(message, flags))
+ .switchIfEmpty(Mono.just(false));
}
private boolean isIndexUpToDate(MailboxMessage message, Flags flags) {
diff --git a/mailbox/tools/indexer/src/test/java/org/apache/mailbox/tools/indexer/ReIndexerImplTest.java b/mailbox/tools/indexer/src/test/java/org/apache/mailbox/tools/indexer/ReIndexerImplTest.java
index 32135ad..a47f208 100644
--- a/mailbox/tools/indexer/src/test/java/org/apache/mailbox/tools/indexer/ReIndexerImplTest.java
+++ b/mailbox/tools/indexer/src/test/java/org/apache/mailbox/tools/indexer/ReIndexerImplTest.java
@@ -242,6 +242,37 @@ public class ReIndexerImplTest {
}
@Test
+ void deltaReindexShouldUpdateMissingMessages() throws Exception {
+ MailboxSession systemSession = mailboxManager.createSystemSession(USERNAME);
+ MailboxId mailboxId = mailboxManager.createMailbox(INBOX, systemSession).get();
+ ComposedMessageId createdMessage = mailboxManager.getMailbox(INBOX, systemSession)
+ .appendMessage(
+ MessageManager.AppendCommand.builder().build("header: value\r\n\r\nbody"),
+ systemSession).getId();
+ when(messageSearchIndex.retrieveIndexedFlags(any(), any())).thenReturn(Mono.empty());
+ when(messageSearchIndex.delete(any(), any(), any())).thenReturn(Mono.empty());
+
+ reIndexer.reIndex(mailboxId,
+ RunningOptions.builder()
+ .mode(RunningOptions.Mode.FIX_OUTDATED)
+ .build())
+ .run();
+ ArgumentCaptor<MailboxMessage> messageCaptor = ArgumentCaptor.forClass(MailboxMessage.class);
+ ArgumentCaptor<Mailbox> mailboxCaptor = ArgumentCaptor.forClass(Mailbox.class);
+
+ verify(messageSearchIndex).retrieveIndexedFlags(any(), any());
+ verify(messageSearchIndex).delete(any(), any(), any());
+ verify(messageSearchIndex).add(any(MailboxSession.class), mailboxCaptor.capture(), messageCaptor.capture());
+ verifyNoMoreInteractions(messageSearchIndex);
+
+ assertThat(mailboxCaptor.getValue()).satisfies(mailbox -> assertThat(mailbox.getMailboxId()).isEqualTo(mailboxId));
+ assertThat(messageCaptor.getValue()).satisfies(message -> {
+ assertThat(message.getMailboxId()).isEqualTo(mailboxId);
+ assertThat(message.getUid()).isEqualTo(createdMessage.getUid());
+ });
+ }
+
+ @Test
void mailboxIdReIndexShouldOnlyDropSearchIndexWhenEmptyMailbox() throws Exception {
MailboxSession systemSession = mailboxManager.createSystemSession(USERNAME);
MailboxId mailboxId = mailboxManager.createMailbox(INBOX, systemSession).get();
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MailboxesRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MailboxesRoutesTest.java
index 1bbbbdf..ea4afe3 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MailboxesRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MailboxesRoutesTest.java
@@ -535,8 +535,8 @@ class MailboxesRoutesTest {
.when()
.get(taskId + "/await");
- assertThatThrownBy(() -> searchIndex.retrieveIndexedFlags(mailbox, uid).block())
- .isInstanceOf(IndexNotFoundException.class);
+ assertThat(searchIndex.retrieveIndexedFlags(mailbox, uid).blockOptional())
+ .isEmpty();
}
}
@@ -956,8 +956,8 @@ class MailboxesRoutesTest {
.when()
.get(taskId + "/await");
- assertThatThrownBy(() -> searchIndex.retrieveIndexedFlags(mailbox, uid).block())
- .isInstanceOf(IndexNotFoundException.class);
+ assertThat(searchIndex.retrieveIndexedFlags(mailbox, uid).blockOptional())
+ .isEmpty();
}
}
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java
index 7724fec..153641d 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java
@@ -1574,8 +1574,8 @@ class UserMailboxesRoutesTest {
.when()
.get(taskId + "/await");
- assertThatThrownBy(() -> searchIndex.retrieveIndexedFlags(mailbox, uid).block())
- .isInstanceOf(IndexNotFoundException.class);
+ assertThat(searchIndex.retrieveIndexedFlags(mailbox, uid).blockOptional())
+ .isEmpty();
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 15/24: JAMES-3485 MessageAppender should group
attachment reads too
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 7a7afdd1278d44d9c45187e5935df7ebb01569fe
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Fri Dec 25 22:49:19 2020 +0700
JAMES-3485 MessageAppender should group attachment reads too
---
.../james/jmap/draft/methods/MessageAppender.java | 28 +++++++++++++++-------
1 file changed, 19 insertions(+), 9 deletions(-)
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/MessageAppender.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/MessageAppender.java
index 611f612..81eb6d8 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/MessageAppender.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/MessageAppender.java
@@ -22,6 +22,7 @@ package org.apache.james.jmap.draft.methods;
import java.io.IOException;
import java.util.Date;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
import javax.inject.Inject;
@@ -39,15 +40,16 @@ import org.apache.james.mailbox.MailboxSession;
import org.apache.james.mailbox.MessageIdManager;
import org.apache.james.mailbox.MessageManager;
import org.apache.james.mailbox.MessageManager.AppendResult;
-import org.apache.james.mailbox.exception.AttachmentNotFoundException;
import org.apache.james.mailbox.exception.MailboxException;
import org.apache.james.mailbox.model.AttachmentId;
+import org.apache.james.mailbox.model.AttachmentMetadata;
import org.apache.james.mailbox.model.Cid;
import org.apache.james.mailbox.model.ComposedMessageId;
import org.apache.james.mailbox.model.MailboxId;
import org.apache.james.mailbox.model.MessageAttachmentMetadata;
import org.apache.james.mime4j.dom.Message;
import org.apache.james.mime4j.message.DefaultMessageWriter;
+import org.apache.james.util.OptionalUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -147,24 +149,32 @@ public class MessageAppender {
}
private ImmutableList<MessageAttachmentMetadata> getMessageAttachments(MailboxSession session, ImmutableList<Attachment> attachments) throws MailboxException {
- ThrowingFunction<Attachment, Optional<MessageAttachmentMetadata>> toMessageAttachment = att -> messageAttachment(session, att);
+ Map<AttachmentId, AttachmentMetadata> attachmentsById = attachmentManager.getAttachments(attachments.stream()
+ .map(attachment -> AttachmentId.from(attachment.getBlobId().getRawValue()))
+ .collect(Guavate.toImmutableList()), session)
+ .stream()
+ .collect(Guavate.toImmutableMap(AttachmentMetadata::getAttachmentId));
+
+ ThrowingFunction<Attachment, Optional<MessageAttachmentMetadata>> toMessageAttachment = att -> messageAttachment(att, attachmentsById);
+
+
return attachments.stream()
.map(Throwing.function(toMessageAttachment).sneakyThrow())
.flatMap(Optional::stream)
.collect(Guavate.toImmutableList());
}
- private Optional<MessageAttachmentMetadata> messageAttachment(MailboxSession session, Attachment attachment) throws MailboxException {
+ private Optional<MessageAttachmentMetadata> messageAttachment(Attachment attachment, Map<AttachmentId, AttachmentMetadata> attachmentsById) throws MailboxException {
try {
- return Optional.of(MessageAttachmentMetadata.builder()
- .attachment(attachmentManager.getAttachment(AttachmentId.from(attachment.getBlobId().getRawValue()), session))
+ AttachmentId attachmentId = AttachmentId.from(attachment.getBlobId().getRawValue());
+ return OptionalUtils.executeIfEmpty(Optional.ofNullable(attachmentsById.get(attachmentId))
+ .map(attachmentMetadata -> MessageAttachmentMetadata.builder()
+ .attachment(attachmentMetadata)
.name(attachment.getName().orElse(null))
.cid(attachment.getCid().map(Cid::from).orElse(null))
.isInline(attachment.isIsInline())
- .build());
- } catch (AttachmentNotFoundException e) {
- LOGGER.error(String.format("Attachment %s not found", attachment.getBlobId()), e);
- return Optional.empty();
+ .build()),
+ () -> LOGGER.error(String.format("Attachment %s not found", attachment.getBlobId())));
} catch (IllegalStateException e) {
LOGGER.error(String.format("Attachment %s is not well-formed", attachment.getBlobId()), e);
return Optional.empty();
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 04/24: JAMES-3486 Distributed MailboxChangeMethod
test
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 6efd140c5d7c1ac346cca060df935a5c3d22fd13
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Mon Dec 28 10:45:34 2020 +0700
JAMES-3486 Distributed MailboxChangeMethod test
---
.../DistributedMailboxChangeMethodTest.java | 67 ++++++++++++++++++++++
1 file changed, 67 insertions(+)
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedMailboxChangeMethodTest.java b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedMailboxChangeMethodTest.java
new file mode 100644
index 0000000..76d5c5f
--- /dev/null
+++ b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedMailboxChangeMethodTest.java
@@ -0,0 +1,67 @@
+/****************************************************************
+ * 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.jmap.rfc8621.distributed;
+
+import org.apache.james.CassandraExtension;
+import org.apache.james.CassandraRabbitMQJamesConfiguration;
+import org.apache.james.CassandraRabbitMQJamesServerMain;
+import org.apache.james.DockerElasticSearchExtension;
+import org.apache.james.JamesServerBuilder;
+import org.apache.james.JamesServerExtension;
+import org.apache.james.jmap.api.change.State;
+import org.apache.james.jmap.cassandra.change.CassandraStateFactory;
+import org.apache.james.jmap.rfc8621.contract.MailboxChangesMethodContract;
+import org.apache.james.mailbox.cassandra.ids.CassandraId;
+import org.apache.james.mailbox.model.MailboxId;
+import org.apache.james.modules.AwsS3BlobStoreExtension;
+import org.apache.james.modules.RabbitMQExtension;
+import org.apache.james.modules.TestJMAPServerModule;
+import org.apache.james.modules.blobstore.BlobStoreConfiguration;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+public class DistributedMailboxChangeMethodTest implements MailboxChangesMethodContract {
+ @RegisterExtension
+ static JamesServerExtension testExtension = new JamesServerBuilder<CassandraRabbitMQJamesConfiguration>(tmpDir ->
+ CassandraRabbitMQJamesConfiguration.builder()
+ .workingDirectory(tmpDir)
+ .configurationFromClasspath()
+ .blobStore(BlobStoreConfiguration.builder()
+ .s3()
+ .disableCache()
+ .deduplication())
+ .build())
+ .extension(new DockerElasticSearchExtension())
+ .extension(new CassandraExtension())
+ .extension(new RabbitMQExtension())
+ .extension(new AwsS3BlobStoreExtension())
+ .server(configuration -> CassandraRabbitMQJamesServerMain.createServer(configuration)
+ .overrideWith(new TestJMAPServerModule()))
+ .build();
+
+ @Override
+ public State.Factory stateFactory() {
+ return new CassandraStateFactory();
+ }
+
+ @Override
+ public MailboxId generateMailboxId() {
+ return CassandraId.timeBased();
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 23/24: JAMES-3471 Computing uids and message ids
from updated flags is easy
Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit ebad11e25667ba12b1cf344417584ea66cc06e99
Author: Rene Cordier <rc...@linagora.com>
AuthorDate: Mon Jan 4 11:43:00 2021 +0700
JAMES-3471 Computing uids and message ids from updated flags is easy
Thus we don't need to add additional fields to manage them in FlagsUpdated.
---
.../james/mailbox/events/MailboxListener.java | 23 ++++++++--------------
1 file changed, 8 insertions(+), 15 deletions(-)
diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/events/MailboxListener.java b/mailbox/api/src/main/java/org/apache/james/mailbox/events/MailboxListener.java
index 3517801..11bb4e6 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/events/MailboxListener.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/events/MailboxListener.java
@@ -587,31 +587,26 @@ public interface MailboxListener {
* A mailbox event related to updated flags
*/
class FlagsUpdated extends MessageEvent {
- private final List<MessageUid> uids;
- private final List<MessageId> messageIds;
private final List<UpdatedFlags> updatedFlags;
public FlagsUpdated(MailboxSession.SessionId sessionId, Username username, MailboxPath path,
MailboxId mailboxId, List<UpdatedFlags> updatedFlags, EventId eventId) {
super(sessionId, username, path, mailboxId, eventId);
this.updatedFlags = ImmutableList.copyOf(updatedFlags);
- this.uids = updatedFlags.stream()
- .map(UpdatedFlags::getUid)
- .collect(Guavate.toImmutableList());
- this.messageIds = updatedFlags.stream()
- .map(UpdatedFlags::getMessageId)
- .filter(Optional::isPresent)
- .map(Optional::get)
- .collect(Guavate.toImmutableList());
}
@Override
public Collection<MessageUid> getUids() {
- return uids;
+ return updatedFlags.stream()
+ .map(UpdatedFlags::getUid)
+ .collect(Guavate.toImmutableList());
}
public Collection<MessageId> getMessageIds() {
- return messageIds;
+ return updatedFlags.stream()
+ .map(UpdatedFlags::getMessageId)
+ .flatMap(Optional::stream)
+ .collect(Guavate.toImmutableList());
}
public List<UpdatedFlags> getUpdatedFlags() {
@@ -633,8 +628,6 @@ public interface MailboxListener {
&& Objects.equals(this.username, that.username)
&& Objects.equals(this.path, that.path)
&& Objects.equals(this.mailboxId, that.mailboxId)
- && Objects.equals(this.uids, that.uids)
- && Objects.equals(this.messageIds, that.messageIds)
&& Objects.equals(this.updatedFlags, that.updatedFlags);
}
return false;
@@ -642,7 +635,7 @@ public interface MailboxListener {
@Override
public final int hashCode() {
- return Objects.hash(eventId, sessionId, username, path, mailboxId, uids, messageIds, updatedFlags);
+ return Objects.hash(eventId, sessionId, username, path, mailboxId, updatedFlags);
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org