You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by bt...@apache.org on 2023/05/26 09:33:55 UTC
[james-project] branch master updated (375aebbd21 -> 6d3033b362)
This is an automated email from the ASF dual-hosted git repository.
btellier pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
from 375aebbd21 JAMES-3909 Add listing failedUsers to task additional information
new 61c48097aa DeletedMessagesVault API - make public some methods/constructors for easier invoke in another module
new 6d3033b362 DeletedMessagesVault API - support limit query
The 2 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:
.../vault/blob/BlobStoreDeletedMessageVault.java | 5 ++-
.../org/apache/james/vault/dto/query/QueryDTO.java | 23 +++++++++--
.../james/vault/dto/query/QueryTranslator.java | 4 +-
.../java/org/apache/james/vault/search/Query.java | 23 +++++++++++
.../james/vault/DeletedMessageVaultContract.java | 16 ++++++++
.../dto/query/QueryElementSerializerTest.java | 7 +++-
.../james/vault/dto/query/QueryTranslatorTest.java | 19 +++++++++-
.../docs/modules/ROOT/pages/operate/webadmin.adoc | 10 +++++
.../vault/DeletedMessageVaultIntegrationTest.java | 26 +++++++++++++
.../routes/DeletedMessagesVaultRestoreTask.java | 4 +-
.../webadmin/vault/routes/RestoreService.java | 4 +-
.../routes/DeletedMessagesVaultRoutesTest.java | 44 ++++++++++++++++++++++
.../WebadminApiQuerySerializationContractTest.java | 23 +++++------
src/site/markdown/server/manage-webadmin.md | 9 +++++
14 files changed, 192 insertions(+), 25 deletions(-)
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 01/02: DeletedMessagesVault API - make public some methods/constructors for easier invoke in another module
Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 61c48097aae271266c71772d15a4431ad8729035
Author: Tung Tran <vt...@linagora.com>
AuthorDate: Wed May 24 11:14:21 2023 +0700
DeletedMessagesVault API - make public some methods/constructors for easier invoke in another module
---
.../james/webadmin/vault/routes/DeletedMessagesVaultRestoreTask.java | 4 ++--
.../java/org/apache/james/webadmin/vault/routes/RestoreService.java | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/main/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRestoreTask.java b/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/main/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRestoreTask.java
index b4025f0ce7..c3736b1381 100644
--- a/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/main/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRestoreTask.java
+++ b/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/main/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRestoreTask.java
@@ -39,7 +39,7 @@ import com.google.common.annotations.VisibleForTesting;
public class DeletedMessagesVaultRestoreTask implements Task {
- static final TaskType TYPE = TaskType.of("deleted-messages-restore");
+ public static final TaskType TYPE = TaskType.of("deleted-messages-restore");
public static class AdditionalInformation implements TaskExecutionDetails.AdditionalInformation {
private final Username username;
@@ -81,7 +81,7 @@ public class DeletedMessagesVaultRestoreTask implements Task {
@VisibleForTesting
final Query query;
- DeletedMessagesVaultRestoreTask(RestoreService vaultRestore, Username userToRestore, Query query) {
+ public DeletedMessagesVaultRestoreTask(RestoreService vaultRestore, Username userToRestore, Query query) {
this.query = query;
this.userToRestore = userToRestore;
this.vaultRestore = vaultRestore;
diff --git a/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/main/java/org/apache/james/webadmin/vault/routes/RestoreService.java b/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/main/java/org/apache/james/webadmin/vault/routes/RestoreService.java
index e2fcd4890f..554e273434 100644
--- a/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/main/java/org/apache/james/webadmin/vault/routes/RestoreService.java
+++ b/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/main/java/org/apache/james/webadmin/vault/routes/RestoreService.java
@@ -51,7 +51,7 @@ import com.github.fge.lambdas.Throwing;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
-class RestoreService {
+public class RestoreService {
enum RestoreResult {
RESTORE_SUCCEED,
@@ -74,7 +74,7 @@ class RestoreService {
this.vaultConfiguration = vaultConfiguration;
}
- Flux<RestoreResult> restore(Username usernameToRestore, Query searchQuery) throws MailboxException {
+ public Flux<RestoreResult> restore(Username usernameToRestore, Query searchQuery) throws MailboxException {
MailboxSession session = mailboxManager.createSystemSession(usernameToRestore);
MessageManager restoreMessageManager = restoreMailboxManager(session);
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org
[james-project] 02/02: DeletedMessagesVault API - support limit query
Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 6d3033b36288a502243e7f256f6a708d4c615085
Author: Tung Tran <vt...@linagora.com>
AuthorDate: Wed May 24 11:21:13 2023 +0700
DeletedMessagesVault API - support limit query
---
.../vault/blob/BlobStoreDeletedMessageVault.java | 5 ++-
.../org/apache/james/vault/dto/query/QueryDTO.java | 23 +++++++++--
.../james/vault/dto/query/QueryTranslator.java | 4 +-
.../java/org/apache/james/vault/search/Query.java | 23 +++++++++++
.../james/vault/DeletedMessageVaultContract.java | 16 ++++++++
.../dto/query/QueryElementSerializerTest.java | 7 +++-
.../james/vault/dto/query/QueryTranslatorTest.java | 19 +++++++++-
.../docs/modules/ROOT/pages/operate/webadmin.adoc | 10 +++++
.../vault/DeletedMessageVaultIntegrationTest.java | 26 +++++++++++++
.../routes/DeletedMessagesVaultRoutesTest.java | 44 ++++++++++++++++++++++
.../WebadminApiQuerySerializationContractTest.java | 23 +++++------
src/site/markdown/server/manage-webadmin.md | 9 +++++
12 files changed, 188 insertions(+), 21 deletions(-)
diff --git a/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/blob/BlobStoreDeletedMessageVault.java b/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/blob/BlobStoreDeletedMessageVault.java
index c1b7a2ddd8..c3bfbf13c8 100644
--- a/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/blob/BlobStoreDeletedMessageVault.java
+++ b/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/blob/BlobStoreDeletedMessageVault.java
@@ -139,10 +139,13 @@ public class BlobStoreDeletedMessageVault implements DeletedMessageVault {
}
private Flux<DeletedMessage> searchOn(Username username, Query query) {
- return Flux.from(messageMetadataVault.listRelatedBuckets())
+ Flux<DeletedMessage> filterPublisher = Flux.from(messageMetadataVault.listRelatedBuckets())
.concatMap(bucketName -> messageMetadataVault.listMessages(bucketName, username))
.map(DeletedMessageWithStorageInformation::getDeletedMessage)
.filter(query.toPredicate());
+ return query.getLimit()
+ .map(filterPublisher::take)
+ .orElse(filterPublisher);
}
@Override
diff --git a/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/dto/query/QueryDTO.java b/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/dto/query/QueryDTO.java
index f72ff0ccae..7f56275ec6 100644
--- a/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/dto/query/QueryDTO.java
+++ b/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/dto/query/QueryDTO.java
@@ -21,6 +21,7 @@ package org.apache.james.vault.dto.query;
import java.util.List;
import java.util.Objects;
+import java.util.Optional;
import org.apache.james.vault.search.Combinator;
@@ -35,16 +36,25 @@ public class QueryDTO implements QueryElement {
@VisibleForTesting
static QueryDTO and(QueryElement... queryElements) {
- return new QueryDTO(Combinator.AND.getValue(), ImmutableList.copyOf(queryElements));
+ return new QueryDTO(Combinator.AND.getValue(), ImmutableList.copyOf(queryElements), Optional.empty());
+ }
+
+ @VisibleForTesting
+ static QueryDTO and(Long limit, QueryElement... queryElements) {
+ return new QueryDTO(Combinator.AND.getValue(), ImmutableList.copyOf(queryElements), Optional.ofNullable(limit));
}
private final String combinator;
private final List<QueryElement> criteria;
+ private final Optional<Long> limit;
@JsonCreator
- public QueryDTO(@JsonProperty("combinator") String combinator, @JsonProperty("criteria") List<QueryElement> criteria) {
+ public QueryDTO(@JsonProperty("combinator") String combinator,
+ @JsonProperty("criteria") List<QueryElement> criteria,
+ @JsonProperty("limit") Optional<Long> limit) {
this.combinator = combinator;
this.criteria = criteria;
+ this.limit = Optional.ofNullable(limit).orElse(Optional.empty());
}
public String getCombinator() {
@@ -55,19 +65,24 @@ public class QueryDTO implements QueryElement {
return criteria;
}
+ public Optional<Long> getLimit() {
+ return limit;
+ }
+
@Override
public final boolean equals(Object o) {
if (o instanceof QueryDTO) {
QueryDTO queryDTO = (QueryDTO) o;
return Objects.equals(this.combinator, queryDTO.getCombinator())
- && Objects.equals(this.criteria, queryDTO.getCriteria());
+ && Objects.equals(this.criteria, queryDTO.getCriteria())
+ && Objects.equals(this.limit, queryDTO.getLimit());
}
return false;
}
@Override
public final int hashCode() {
- return Objects.hash(combinator, criteria);
+ return Objects.hash(combinator, criteria, limit);
}
}
diff --git a/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/dto/query/QueryTranslator.java b/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/dto/query/QueryTranslator.java
index 6619c8c845..2ed94abc74 100644
--- a/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/dto/query/QueryTranslator.java
+++ b/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/dto/query/QueryTranslator.java
@@ -198,7 +198,7 @@ public class QueryTranslator {
List<QueryElement> queryElements = query.getCriteria().stream()
.map(this::toDTO)
.collect(ImmutableList.toImmutableList());
- return new QueryDTO(Combinator.AND.getValue(), queryElements);
+ return new QueryDTO(Combinator.AND.getValue(), queryElements, query.getLimit());
}
private CriterionDTO toDTO(Criterion<?> criterion) {
@@ -224,7 +224,7 @@ public class QueryTranslator {
return Query.and(queryDTO.getCriteria().stream()
.map(queryElement -> (CriterionDTO) queryElement)
.map(Throwing.function(this::translate))
- .collect(ImmutableList.toImmutableList()));
+ .collect(ImmutableList.toImmutableList()), queryDTO.getLimit());
}
private boolean combinatorIsValid(String combinator) {
diff --git a/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/search/Query.java b/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/search/Query.java
index f73e067ecd..779f3ac9f8 100644
--- a/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/search/Query.java
+++ b/mailbox/plugin/deleted-messages-vault/src/main/java/org/apache/james/vault/search/Query.java
@@ -20,10 +20,12 @@
package org.apache.james.vault.search;
import java.util.List;
+import java.util.Optional;
import java.util.function.Predicate;
import org.apache.james.vault.DeletedMessage;
+import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
public class Query {
@@ -34,14 +36,31 @@ public class Query {
return new Query(criteria);
}
+ public static Query and(List<Criterion<?>> criteria, Optional<Long> limit) {
+ return new Query(criteria, limit.orElse(null));
+ }
+
public static Query of(Criterion<?>... criteria) {
return new Query(ImmutableList.copyOf(criteria));
}
+ public static Query of(long limit, List<Criterion<?>> criteria) {
+ return new Query(criteria, limit);
+ }
+
private final List<Criterion<?>> criteria;
+ private final Optional<Long> limit;
+
private Query(List<Criterion<?>> criteria) {
this.criteria = criteria;
+ this.limit = Optional.empty();
+ }
+
+ public Query(List<Criterion<?>> criteria, Long limit) {
+ Preconditions.checkArgument(limit == null || limit > 0, "Limit should be strictly positive");
+ this.criteria = criteria;
+ this.limit = Optional.ofNullable(limit);
}
public Predicate<DeletedMessage> toPredicate() {
@@ -54,4 +73,8 @@ public class Query {
public List<Criterion<?>> getCriteria() {
return criteria;
}
+
+ public Optional<Long> getLimit() {
+ return limit;
+ }
}
diff --git a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageVaultContract.java b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageVaultContract.java
index 7d3e9d953e..cf82d47a4a 100644
--- a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageVaultContract.java
+++ b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageVaultContract.java
@@ -37,6 +37,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
import java.io.ByteArrayInputStream;
import java.time.Clock;
import java.time.Duration;
+import java.util.List;
import org.apache.james.mailbox.inmemory.InMemoryMessageId;
import org.apache.james.task.Task;
@@ -127,6 +128,21 @@ public interface DeletedMessageVaultContract {
.containsOnly(DELETED_MESSAGE, DELETED_MESSAGE_2);
}
+ @Test
+ default void searchAllShouldSupportLimitQuery() {
+ Mono.from(getVault().append(DELETED_MESSAGE, new ByteArrayInputStream(CONTENT))).block();
+ Mono.from(getVault().append(DELETED_MESSAGE_2, new ByteArrayInputStream(CONTENT))).block();
+ DeletedMessage deletedMessage3 = DELETED_MESSAGE_GENERATOR.apply(InMemoryMessageId.of(33).getRawId());
+ Mono.from(getVault().append(deletedMessage3, new ByteArrayInputStream(CONTENT))).block();
+
+ assertThat(Flux.from(getVault().search(USERNAME, Query.of(1, List.of()))).collectList().block())
+ .hasSize(1);
+ assertThat(Flux.from(getVault().search(USERNAME, Query.of(3, List.of()))).collectList().block())
+ .containsExactlyInAnyOrder(DELETED_MESSAGE, DELETED_MESSAGE_2, deletedMessage3);
+ assertThat(Flux.from(getVault().search(USERNAME, Query.of(4, List.of()))).collectList().block())
+ .containsExactlyInAnyOrder(DELETED_MESSAGE, DELETED_MESSAGE_2, deletedMessage3);
+ }
+
@Test
default void searchShouldReturnMatchingItems() {
Mono.from(getVault().append(DELETED_MESSAGE_2, new ByteArrayInputStream(CONTENT))).block();
diff --git a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/dto/query/QueryElementSerializerTest.java b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/dto/query/QueryElementSerializerTest.java
index cc983fd7b1..77ba5f63e9 100644
--- a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/dto/query/QueryElementSerializerTest.java
+++ b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/dto/query/QueryElementSerializerTest.java
@@ -22,6 +22,7 @@ package org.apache.james.vault.dto.query;
import static org.apache.james.vault.DeletedMessageFixture.SUBJECT;
import static org.apache.mailet.base.MailAddressFixture.SENDER;
+import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import org.apache.james.vault.search.FieldName;
import org.apache.james.vault.search.Operator;
import org.junit.jupiter.api.BeforeEach;
@@ -38,6 +39,7 @@ class QueryElementSerializerTest {
@BeforeEach
void beforeEach() {
ObjectMapper objectMapper = new ObjectMapper();
+ objectMapper.registerModule(new Jdk8Module());
queryElementSerializer = new QueryElementSerializer(objectMapper);
}
@@ -54,9 +56,11 @@ class QueryElementSerializerTest {
JsonAssertions.assertThatJson(queryElementSerializer.serialize(queryDTO))
.isEqualTo("{ " +
" \"combinator\": \"and\", " +
+ " \"limit\": null, " +
" \"criteria\": [ " +
" { " +
" \"combinator\": \"and\", " +
+ " \"limit\": null, " +
" \"criteria\": [ " +
" {\"fieldName\": \"subject\", \"operator\": \"contains\", \"value\": \"" + SUBJECT + "\"}," +
" {\"fieldName\": \"sender\", \"operator\": \"equals\", \"value\": \"" + SENDER.asString() + "\"}" +
@@ -70,7 +74,7 @@ class QueryElementSerializerTest {
@Test
void shouldSerializeFlattenStructure() throws Exception {
- QueryDTO queryDTO = QueryDTO.and(
+ QueryDTO queryDTO = QueryDTO.and(1L,
CriterionDTO.from(FieldName.SUBJECT, Operator.CONTAINS, SUBJECT),
CriterionDTO.from(FieldName.SENDER, Operator.EQUALS, SENDER.asString()),
CriterionDTO.from(FieldName.HAS_ATTACHMENT, Operator.EQUALS, "true")
@@ -79,6 +83,7 @@ class QueryElementSerializerTest {
JsonAssertions.assertThatJson(queryElementSerializer.serialize(queryDTO))
.isEqualTo("{ " +
" \"combinator\": \"and\", " +
+ " \"limit\": 1, " +
" \"criteria\": [ " +
" {\"fieldName\": \"subject\", \"operator\": \"contains\", \"value\": \"" + SUBJECT + "\"}," +
" {\"fieldName\": \"sender\", \"operator\": \"equals\", \"value\": \"" + SENDER.asString() + "\"}," +
diff --git a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/dto/query/QueryTranslatorTest.java b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/dto/query/QueryTranslatorTest.java
index 301d720c28..6450b33a82 100644
--- a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/dto/query/QueryTranslatorTest.java
+++ b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/dto/query/QueryTranslatorTest.java
@@ -24,6 +24,8 @@ import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import java.time.ZonedDateTime;
+import java.util.List;
+import java.util.Optional;
import org.apache.james.core.MailAddress;
import org.apache.james.mailbox.inmemory.InMemoryId;
@@ -48,7 +50,7 @@ class QueryTranslatorTest {
@Test
void translateShouldThrowWhenPassingNotAndOperator() {
- assertThatThrownBy(() -> queryTranslator.translate(new QueryDTO("or", ImmutableList.of())))
+ assertThatThrownBy(() -> queryTranslator.translate(new QueryDTO("or", ImmutableList.of(), Optional.empty())))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("combinator 'or' is not yet handled");
}
@@ -56,7 +58,7 @@ class QueryTranslatorTest {
@Test
void translateShouldNotThrowWhenPassingNullOperator() {
String nullOperator = null;
- assertThatCode(() -> queryTranslator.translate(new QueryDTO(nullOperator, ImmutableList.of())))
+ assertThatCode(() -> queryTranslator.translate(new QueryDTO(nullOperator, ImmutableList.of(), Optional.empty())))
.doesNotThrowAnyException();
}
@@ -216,4 +218,17 @@ class QueryTranslatorTest {
new CriterionDTO(FieldName.HAS_ATTACHMENT.getValue(), Operator.EQUALS.getValue(), "true")
));
}
+
+ @Test
+ void toDTOShouldSuccessWhenHasLimitQuery() throws Exception {
+ Query query = Query.of(11,
+ List.of(CriterionFactory.subject().contains("james"),
+ CriterionFactory.hasSender(new MailAddress("user@james.org")),
+ CriterionFactory.hasAttachment(true)));
+
+ assertThat(queryTranslator.toDTO(query)).isEqualTo(QueryDTO.and(11L,
+ new CriterionDTO(FieldName.SUBJECT.getValue(), Operator.CONTAINS.getValue(), "james"),
+ new CriterionDTO(FieldName.SENDER.getValue(), Operator.EQUALS.getValue(), "user@james.org"),
+ new CriterionDTO(FieldName.HAS_ATTACHMENT.getValue(), Operator.EQUALS.getValue(), "true")));
+ }
}
\ No newline at end of file
diff --git a/server/apps/distributed-app/docs/modules/ROOT/pages/operate/webadmin.adoc b/server/apps/distributed-app/docs/modules/ROOT/pages/operate/webadmin.adoc
index fa1a311569..72a4d6bb0f 100644
--- a/server/apps/distributed-app/docs/modules/ROOT/pages/operate/webadmin.adoc
+++ b/server/apps/distributed-app/docs/modules/ROOT/pages/operate/webadmin.adoc
@@ -4610,6 +4610,16 @@ criterion list to represent `matching all deleted messages`:
}
....
+* For limiting the number of restored messages, you can use the `limit` query property:
+
+....
+{
+ "combinator": "and",
+ "limit": 99
+ "criteria": []
+}
+....
+
*Warning*: Current web-admin uses `US` locale as the default. Therefore,
there might be some conflicts when using String `containsIgnoreCase`
comparators to apply on the String data of other special locales stored
diff --git a/server/protocols/webadmin-integration-test/webadmin-integration-test-common/src/main/java/org/apache/james/webadmin/integration/vault/DeletedMessageVaultIntegrationTest.java b/server/protocols/webadmin-integration-test/webadmin-integration-test-common/src/main/java/org/apache/james/webadmin/integration/vault/DeletedMessageVaultIntegrationTest.java
index 466fb8e05b..89695a57d3 100644
--- a/server/protocols/webadmin-integration-test/webadmin-integration-test-common/src/main/java/org/apache/james/webadmin/integration/vault/DeletedMessageVaultIntegrationTest.java
+++ b/server/protocols/webadmin-integration-test/webadmin-integration-test-common/src/main/java/org/apache/james/webadmin/integration/vault/DeletedMessageVaultIntegrationTest.java
@@ -350,6 +350,32 @@ public abstract class DeletedMessageVaultIntegrationTest {
.isEqualTo(0);
}
+ @Test
+ void postShouldRestoreMatchingMessagesWhenQueryLimit() {
+ bartSendMessageToHomerWithSubject("aaaa");
+ bartSendMessageToHomerWithSubject("aaaa");
+ WAIT_TWO_MINUTES.untilAsserted(() -> assertThat(listMessageIdsForAccount(homerAccessToken)).hasSize(2));
+
+ homerDeletesMessages(listMessageIdsForAccount(homerAccessToken));
+
+ WAIT_TWO_MINUTES.untilAsserted(() -> assertThat(listMessageIdsForAccount(homerAccessToken)).hasSize(0));
+
+ String query = "{" +
+ " \"combinator\": \"and\"," +
+ " \"limit\": 1," +
+ " \"criteria\": [" +
+ " {" +
+ " \"fieldName\": \"subject\"," +
+ " \"operator\": \"equals\"," +
+ " \"value\": \"aaaa\"" +
+ " }" +
+ " ]" +
+ "}";
+ restoreMessagesForUserWithQuery(webAdminApi, HOMER, query);
+
+ WAIT_TWO_MINUTES.untilAsserted(() -> assertThat(listMessageIdsForAccount(homerAccessToken)).hasSize(1));
+ }
+
@Test
void imapMovedMessageShouldNotEndUpInTheVault(GuiceJamesServer jmapServer) throws Exception {
bartSendMessageToHomer();
diff --git a/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutesTest.java
index 88032e17eb..39571fd587 100644
--- a/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutesTest.java
@@ -25,6 +25,7 @@ import static io.restassured.RestAssured.with;
import static org.apache.james.vault.DeletedMessageFixture.CONTENT;
import static org.apache.james.vault.DeletedMessageFixture.DELETED_MESSAGE;
import static org.apache.james.vault.DeletedMessageFixture.DELETED_MESSAGE_2;
+import static org.apache.james.vault.DeletedMessageFixture.DELETED_MESSAGE_GENERATOR;
import static org.apache.james.vault.DeletedMessageFixture.DELETION_DATE;
import static org.apache.james.vault.DeletedMessageFixture.DELIVERY_DATE;
import static org.apache.james.vault.DeletedMessageFixture.FINAL_STAGE;
@@ -1793,6 +1794,49 @@ class DeletedMessagesVaultRoutesTest {
.isFalse();
}
+ @Test
+ void restoreShouldSupportLimitQuery() throws Exception {
+ Mono.from(vault.append(FINAL_STAGE.get()
+ .subject("subject contains should match")
+ .build(), new ByteArrayInputStream(CONTENT))).block();
+
+ DeletedMessage deletedMessage2 = DELETED_MESSAGE_GENERATOR.apply(InMemoryMessageId.of(22).getRawId());
+
+ Mono.from(vault.append(deletedMessage2, new ByteArrayInputStream(CONTENT))).block();
+
+ String query = "{" +
+ " \"combinator\": \"and\"," +
+ " \"limit\": 1," +
+ " \"criteria\": [" +
+ " {" +
+ " \"fieldName\": \"sender\"," +
+ " \"operator\": \"equals\"," +
+ " \"value\": \"" + SENDER.asString() + "\"" +
+ " }" +
+ " ]" +
+ "}";
+
+ String taskId =
+ given()
+ .queryParam("action", "restore")
+ .body(query)
+ .when()
+ .post(BOB_PATH)
+ .jsonPath()
+ .get("taskId");
+
+ given()
+ .basePath(TasksRoutes.BASE)
+ .when()
+ .get(taskId + "/await")
+ .then()
+ .body("status", is("completed"))
+ .body("additionalInformation.successfulRestoreCount", is(1));
+
+ assertThat(restoreMessageContents(USERNAME))
+ .hasSize(1);
+ }
+
}
@Nested
diff --git a/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/WebadminApiQuerySerializationContractTest.java b/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/WebadminApiQuerySerializationContractTest.java
index 7446c165b7..aadc8d736d 100644
--- a/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/WebadminApiQuerySerializationContractTest.java
+++ b/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/WebadminApiQuerySerializationContractTest.java
@@ -19,6 +19,7 @@
package org.apache.james.webadmin.vault.routes;
import java.time.ZonedDateTime;
+import java.util.Optional;
import java.util.stream.Stream;
import org.apache.james.mailbox.model.MailboxId;
@@ -48,47 +49,47 @@ class WebadminApiQuerySerializationContractTest {
private static final String HAS_ATTACHMENT_FILE = "has_attachment.json";
private static final QueryDTO HAS_ATTACHMENT_DTO = new QueryDTO(AND,
- ImmutableList.of(new CriterionDTO(FieldName.HAS_ATTACHMENT.getValue(), Operator.EQUALS.getValue(), "true")));
+ ImmutableList.of(new CriterionDTO(FieldName.HAS_ATTACHMENT.getValue(), Operator.EQUALS.getValue(), "true")), Optional.empty());
private static final String HAS_NO_ATTACHMENT_FILE = "has_no_attachment.json";
private static final QueryDTO HAS_NO_ATTACHMENT_DTO = new QueryDTO(AND,
- ImmutableList.of(new CriterionDTO(FieldName.HAS_ATTACHMENT.getValue(), Operator.EQUALS.getValue(), "false")));
+ ImmutableList.of(new CriterionDTO(FieldName.HAS_ATTACHMENT.getValue(), Operator.EQUALS.getValue(), "false")), Optional.empty());
private static final String HAS_SENDER_FILE = "has_sender.json";
private static final QueryDTO HAS_SENDER_DTO = new QueryDTO(AND,
- ImmutableList.of(new CriterionDTO(FieldName.SENDER.getValue(), Operator.EQUALS.getValue(), USER_JAMES)));
+ ImmutableList.of(new CriterionDTO(FieldName.SENDER.getValue(), Operator.EQUALS.getValue(), USER_JAMES)), Optional.empty());
private static final String CONTAINS_RECIPIENT_FILE = "contains_recipient.json";
private static final QueryDTO CONTAINS_RECIPIENT_DTO = new QueryDTO(AND,
- ImmutableList.of(new CriterionDTO(FieldName.RECIPIENTS.getValue(), Operator.CONTAINS.getValue(), USER_JAMES)));
+ ImmutableList.of(new CriterionDTO(FieldName.RECIPIENTS.getValue(), Operator.CONTAINS.getValue(), USER_JAMES)), Optional.empty());
private static final String CONTAINS_ORIGIN_MAILBOX_FILE = "contains_origin_mailbox.json";
private static final QueryDTO CONTAINS_ORIGIN_MAILBOX_DTO = new QueryDTO(AND,
- ImmutableList.of(new CriterionDTO(FieldName.ORIGIN_MAILBOXES.getValue(), Operator.CONTAINS.getValue(), MAILBOX_1_ID.serialize())));
+ ImmutableList.of(new CriterionDTO(FieldName.ORIGIN_MAILBOXES.getValue(), Operator.CONTAINS.getValue(), MAILBOX_1_ID.serialize())), Optional.empty());
private static final String DELIVERY_BEFORE_FILE = "zoned_date_time_before_or_equals.json";
private static final QueryDTO DELIVERY_BEFORE_DTO = new QueryDTO(AND,
- ImmutableList.of(new CriterionDTO(FieldName.DELIVERY_DATE.getValue(), Operator.BEFORE_OR_EQUALS.getValue(), ZONED_DATE_TIME.toString())));
+ ImmutableList.of(new CriterionDTO(FieldName.DELIVERY_DATE.getValue(), Operator.BEFORE_OR_EQUALS.getValue(), ZONED_DATE_TIME.toString())), Optional.empty());
private static final String DELETED_AFTER_FILE = "zoned_date_time_after_or_equals.json";
private static final QueryDTO DELETED_AFTER_DTO = new QueryDTO(AND,
- ImmutableList.of(new CriterionDTO(FieldName.DELETION_DATE.getValue(), Operator.AFTER_OR_EQUALS.getValue(), ZONED_DATE_TIME.toString())));
+ ImmutableList.of(new CriterionDTO(FieldName.DELETION_DATE.getValue(), Operator.AFTER_OR_EQUALS.getValue(), ZONED_DATE_TIME.toString())), Optional.empty());
private static final String SUBJECT_CONTAINS_FILE = "string_contains.json";
private static final QueryDTO SUBJECT_CONTAINS_DTO = new QueryDTO(AND,
- ImmutableList.of(new CriterionDTO(FieldName.SUBJECT.getValue(), Operator.CONTAINS.getValue(), SUBJECT)));
+ ImmutableList.of(new CriterionDTO(FieldName.SUBJECT.getValue(), Operator.CONTAINS.getValue(), SUBJECT)), Optional.empty());
private static final String SUBJECT_CONTAINS_IGNORE_CASE_FILE = "string_contains_ignore_case.json";
private static final QueryDTO SUBJECT_CONTAINS_IGNORE_CASE_DTO = new QueryDTO(AND,
- ImmutableList.of(new CriterionDTO(FieldName.SUBJECT.getValue(), Operator.CONTAINS_IGNORE_CASE.getValue(), SUBJECT)));
+ ImmutableList.of(new CriterionDTO(FieldName.SUBJECT.getValue(), Operator.CONTAINS_IGNORE_CASE.getValue(), SUBJECT)), Optional.empty());
private static final String SUBJECT_EQUALS_FILE = "string_equals.json";
private static final QueryDTO SUBJECT_EQUALS_DTO = new QueryDTO(AND,
- ImmutableList.of(new CriterionDTO(FieldName.SUBJECT.getValue(), Operator.EQUALS.getValue(), SUBJECT)));
+ ImmutableList.of(new CriterionDTO(FieldName.SUBJECT.getValue(), Operator.EQUALS.getValue(), SUBJECT)), Optional.empty());
private static final String SUBJECT_EQUALS_IGNORE_CASE_FILE = "string_equals_ignore_case.json";
private static final QueryDTO SUBJECT_EQUALS_IGNORE_CASE_DTO = new QueryDTO(AND,
- ImmutableList.of(new CriterionDTO(FieldName.SUBJECT.getValue(), Operator.EQUALS_IGNORE_CASE.getValue(), SUBJECT)));
+ ImmutableList.of(new CriterionDTO(FieldName.SUBJECT.getValue(), Operator.EQUALS_IGNORE_CASE.getValue(), SUBJECT)), Optional.empty());
private static final TestId.Factory mailboxIdFactory = new TestId.Factory();
private static final QueryTranslator queryTranslator = new QueryTranslator(mailboxIdFactory);
diff --git a/src/site/markdown/server/manage-webadmin.md b/src/site/markdown/server/manage-webadmin.md
index 5ea35c2dd3..8c78ca3518 100644
--- a/src/site/markdown/server/manage-webadmin.md
+++ b/src/site/markdown/server/manage-webadmin.md
@@ -4267,6 +4267,15 @@ Messages in the Deleted Messages Vault of a specified user that are matched with
"criteria": []
}
```
+- For limiting the number of restored messages, you can use the `limit` query property:
+
+```
+{
+ "combinator": "and",
+ "limit": 99
+ "criteria": []
+}
+```
**Warning**: Current web-admin uses `US` locale as the default. Therefore, there might be some conflicts when using String `containsIgnoreCase` comparators to apply
on the String data of other special locales stored in the Vault. More details at [JIRA](https://issues.apache.org/jira/browse/MAILBOX-384)
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org