This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git


The following commit(s) were added to refs/heads/master by this push:
     new 9b18644177 JAMES 3551 - implement naive mailbox query changes (#1624)
9b18644177 is described below

commit 9b18644177bb8ef3797793f1cb4046c3df7aa61b
Author: hungphan227 <[email protected]>
AuthorDate: Thu Jul 6 08:30:22 2023 +0700

    JAMES 3551 - implement naive mailbox query changes (#1624)
---
 .../james/jmap/rfc8621/RFC8621MethodsModule.java   |   2 +
 .../DistributedMailboxQueryChangesMethodTest.java  |  25 +++
 .../contract/MailboxQueryChangesContract.scala     | 179 +++++++++++++++++++++
 .../MemoryMailboxQueryChangesMethodTest.java       |  25 +++
 .../james/jmap/json/MailboxQuerySerializer.scala   |   4 +-
 .../james/jmap/mail/MailboxQueryChanges.scala      |  30 ++++
 .../jmap/method/MailboxQueryChangesMethod.scala    |  50 ++++++
 7 files changed, 314 insertions(+), 1 deletion(-)

diff --git 
a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/rfc8621/RFC8621MethodsModule.java
 
b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/rfc8621/RFC8621MethodsModule.java
index 4a5ab902af..fe5ac86d43 100644
--- 
a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/rfc8621/RFC8621MethodsModule.java
+++ 
b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/rfc8621/RFC8621MethodsModule.java
@@ -65,6 +65,7 @@ import org.apache.james.jmap.method.MDNParseMethod;
 import org.apache.james.jmap.method.MDNSendMethod;
 import org.apache.james.jmap.method.MailboxChangesMethod;
 import org.apache.james.jmap.method.MailboxGetMethod;
+import org.apache.james.jmap.method.MailboxQueryChangesMethod;
 import org.apache.james.jmap.method.MailboxQueryMethod;
 import org.apache.james.jmap.method.MailboxSetMethod;
 import org.apache.james.jmap.method.Method;
@@ -164,6 +165,7 @@ public class RFC8621MethodsModule extends AbstractModule {
         methods.addBinding().to(DelegateGetMethod.class);
         methods.addBinding().to(DelegateSetMethod.class);
         methods.addBinding().to(DelegatedAccountSetMethod.class);
+        methods.addBinding().to(MailboxQueryChangesMethod.class);
 
         Multibinder<JMAPRoutes> routes = Multibinder.newSetBinder(binder(), 
JMAPRoutes.class);
         routes.addBinding().to(SessionRoutes.class);
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/DistributedMailboxQueryChangesMethodTest.java
 
b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedMailboxQueryChangesMethodTest.java
new file mode 100644
index 0000000000..c188ab8d57
--- /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/DistributedMailboxQueryChangesMethodTest.java
@@ -0,0 +1,25 @@
+/****************************************************************
+ * 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.jmap.rfc8621.contract.MailboxQueryChangesContract;
+
+public class DistributedMailboxQueryChangesMethodTest extends DistributedBase 
implements MailboxQueryChangesContract {
+}
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/MailboxQueryChangesContract.scala
 
b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxQueryChangesContract.scala
new file mode 100644
index 0000000000..1b93800b5d
--- /dev/null
+++ 
b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxQueryChangesContract.scala
@@ -0,0 +1,179 @@
+/****************************************************************
+ * 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.contract
+
+import io.netty.handler.codec.http.HttpHeaderNames.ACCEPT
+import io.restassured.RestAssured.{`given`, requestSpecification}
+import io.restassured.http.ContentType.JSON
+import net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson
+import org.apache.http.HttpStatus.{SC_BAD_REQUEST, SC_OK}
+import org.apache.james.GuiceJamesServer
+import org.apache.james.jmap.core.ResponseObject.SESSION_STATE
+import org.apache.james.jmap.http.UserCredential
+import 
org.apache.james.jmap.rfc8621.contract.Fixture.{ACCEPT_RFC8621_VERSION_HEADER, 
ANDRE, ANDRE_PASSWORD, BOB, BOB_PASSWORD, DOMAIN, authScheme, 
baseRequestSpecBuilder}
+import org.apache.james.utils.DataProbeImpl
+import org.junit.jupiter.api.{BeforeEach, Test}
+
+trait MailboxQueryChangesContract {
+  @BeforeEach
+  def setUp(server: GuiceJamesServer): Unit = {
+    server.getProbe(classOf[DataProbeImpl])
+      .fluent
+      .addDomain(DOMAIN.asString)
+      .addDomain("domain-alias.tld")
+      .addUser(BOB.asString, BOB_PASSWORD)
+      .addUser(ANDRE.asString, ANDRE_PASSWORD)
+
+    requestSpecification = baseRequestSpecBuilder(server)
+      .setAuth(authScheme(UserCredential(BOB, BOB_PASSWORD)))
+      .build
+  }
+
+  @Test
+  def shouldReturnCannotCalculateChanges(): Unit = {
+    val request =
+      s"""{
+         |  "using": ["urn:ietf:params:jmap:core", 
"urn:ietf:params:jmap:mail"],
+         |  "methodCalls": [[
+         |    "Mailbox/queryChanges",
+         |    {
+         |      "accountId": 
"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+         |      "sinceQueryState": "2c9f1b12-b35a-43e6-9af2-0106fb53a941",
+         |      "calculateTotal": false
+         |    },
+         |    "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)
+      .isEqualTo(
+        s"""{
+           |    "sessionState": "${SESSION_STATE.value}",
+           |    "methodResponses": [
+           |        [
+           |            "error",
+           |            {
+           |                "type": "cannotCalculateChanges",
+           |                "description": "Naive implementation for 
Mailbox/queryChanges"
+           |            },
+           |            "c1"
+           |        ]
+           |    ]
+           |}""".stripMargin)
+  }
+
+  @Test
+  def wrongAccountIdShouldBeRejected(): Unit = {
+    val request =
+      s"""{
+         |  "using": ["urn:ietf:params:jmap:core", 
"urn:ietf:params:jmap:mail"],
+         |  "methodCalls": [[
+         |    "Mailbox/queryChanges",
+         |    {
+         |      "accountId": 
"1e8584548eca20f26faf6becc1704a0f352839f12c208a47fbd486d60f491f7c",
+         |      "sinceQueryState": "2c9f1b12-b35a-43e6-9af2-0106fb53a941",
+         |      "calculateTotal": false
+         |    },
+         |    "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)
+      .isEqualTo(
+        s"""{
+           |    "sessionState": "${SESSION_STATE.value}",
+           |    "methodResponses": [
+           |        [
+           |            "error",
+           |            {
+           |                "type": "accountNotFound"
+           |            },
+           |            "c1"
+           |        ]
+           |    ]
+           |}""".stripMargin)
+  }
+
+  @Test
+  def missCapabilities(): Unit = {
+    val request =
+      s"""{
+         |  "using": ["urn:ietf:params:jmap:core"],
+         |  "methodCalls": [[
+         |    "Mailbox/queryChanges",
+         |    {
+         |      "accountId": 
"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+         |      "sinceQueryState": "2c9f1b12-b35a-43e6-9af2-0106fb53a941",
+         |      "calculateTotal": false
+         |    },
+         |    "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)
+      .isEqualTo(
+        s"""{
+           |    "sessionState": "${SESSION_STATE.value}",
+           |    "methodResponses": [
+           |        [
+           |            "error",
+           |            {
+           |                "type": "unknownMethod",
+           |                "description": "Missing capability(ies): 
urn:ietf:params:jmap:mail"
+           |            },
+           |            "c1"
+           |        ]
+           |    ]
+           |}""".stripMargin)
+  }
+}
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/MemoryMailboxQueryChangesMethodTest.java
 
b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryMailboxQueryChangesMethodTest.java
new file mode 100644
index 0000000000..9b4442e163
--- /dev/null
+++ 
b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryMailboxQueryChangesMethodTest.java
@@ -0,0 +1,25 @@
+/****************************************************************
+ * 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.memory;
+
+import org.apache.james.jmap.rfc8621.contract.MailboxQueryChangesContract;
+
+public class MemoryMailboxQueryChangesMethodTest extends MemoryBase implements 
MailboxQueryChangesContract {
+}
diff --git 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/MailboxQuerySerializer.scala
 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/MailboxQuerySerializer.scala
index b184f6189f..71cafd7d53 100644
--- 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/MailboxQuerySerializer.scala
+++ 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/MailboxQuerySerializer.scala
@@ -20,7 +20,7 @@
 package org.apache.james.jmap.json
 
 import org.apache.james.jmap.core.{CanCalculateChanges, QueryState}
-import org.apache.james.jmap.mail.{MailboxFilter, MailboxQueryRequest, 
MailboxQueryResponse}
+import org.apache.james.jmap.mail.{MailboxFilter, MailboxQueryChangesRequest, 
MailboxQueryRequest, MailboxQueryResponse}
 import org.apache.james.mailbox.Role
 import org.apache.james.mailbox.model.MailboxId
 import play.api.libs.json._
@@ -52,10 +52,12 @@ object MailboxQuerySerializer {
 
   private implicit val emailQueryRequestReads: Reads[MailboxQueryRequest] = 
Json.reads[MailboxQueryRequest]
   private implicit val queryStateWrites: Writes[QueryState] = 
Json.valueWrites[QueryState]
+  private implicit val mailboxQueryChangesReads: 
Reads[MailboxQueryChangesRequest] = Json.reads[MailboxQueryChangesRequest]
 
   private implicit val mailboxQueryResponseWrites: 
OWrites[MailboxQueryResponse] = Json.writes[MailboxQueryResponse]
 
   def serialize(mailboxQueryResponse: MailboxQueryResponse): JsObject = 
Json.toJsObject(mailboxQueryResponse)
 
   def deserialize(input: JsValue): JsResult[MailboxQueryRequest] = 
Json.fromJson[MailboxQueryRequest](input)
+  def deserializeMailboxQueryChanges(input: JsValue): 
JsResult[MailboxQueryChangesRequest] = 
Json.fromJson[MailboxQueryChangesRequest](input)
 }
\ No newline at end of file
diff --git 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/MailboxQueryChanges.scala
 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/MailboxQueryChanges.scala
new file mode 100644
index 0000000000..0c69e9a5cf
--- /dev/null
+++ 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/MailboxQueryChanges.scala
@@ -0,0 +1,30 @@
+/****************************************************************
+ * 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.mail
+
+import org.apache.james.jmap.api.change.Limit
+import org.apache.james.jmap.core.{AccountId, UuidState}
+import org.apache.james.jmap.method.WithAccountId
+
+case class MailboxQueryChangesRequest(accountId: AccountId,
+                                      sinceQueryState: UuidState,
+                                      maxChanges: Option[Limit],
+                                      upToId: Option[AccountId],
+                                      calculateTotal: Boolean) extends 
WithAccountId
\ No newline at end of file
diff --git 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxQueryChangesMethod.scala
 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxQueryChangesMethod.scala
new file mode 100644
index 0000000000..f1a960751e
--- /dev/null
+++ 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxQueryChangesMethod.scala
@@ -0,0 +1,50 @@
+/****************************************************************
+ * 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.method
+
+import eu.timepit.refined.auto._
+import javax.inject.Inject
+import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, 
JMAP_CORE, JMAP_MAIL}
+import org.apache.james.jmap.core.Invocation.MethodName
+import org.apache.james.jmap.core.{ErrorCode, Invocation, SessionTranslator}
+import org.apache.james.jmap.json.MailboxQuerySerializer
+import org.apache.james.jmap.mail.MailboxQueryChangesRequest
+import org.apache.james.jmap.routes.SessionSupplier
+import org.apache.james.mailbox.MailboxSession
+import org.apache.james.metrics.api.MetricFactory
+import org.reactivestreams.Publisher
+import reactor.core.scala.publisher.SMono
+
+class MailboxQueryChangesMethod @Inject()(val metricFactory: MetricFactory,
+                                          val sessionSupplier: SessionSupplier,
+                                          val sessionTranslator: 
SessionTranslator) extends MethodRequiringAccountId[MailboxQueryChangesRequest] 
{
+  override val methodName: MethodName = MethodName("Mailbox/queryChanges")
+  override val requiredCapabilities: Set[CapabilityIdentifier] = 
Set(JMAP_CORE, JMAP_MAIL)
+
+  override def doProcess(capabilities: Set[CapabilityIdentifier], invocation: 
InvocationWithContext,
+                         mailboxSession: MailboxSession, request: 
MailboxQueryChangesRequest): Publisher[InvocationWithContext] =
+    
SMono.just(InvocationWithContext(Invocation.error(ErrorCode.CannotCalculateChanges,
+      "Naive implementation for Mailbox/queryChanges",
+      invocation.invocation.methodCallId),
+      invocation.processingContext))
+
+  override def getRequest(mailboxSession: MailboxSession, invocation: 
Invocation): Either[Exception, MailboxQueryChangesRequest] =
+    
MailboxQuerySerializer.deserializeMailboxQueryChanges(invocation.arguments.value).asEitherRequest
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to