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 7d73351309942cefbb3997519f3ec2697695c6fa
Author: Rene Cordier <[email protected]>
AuthorDate: Wed Sep 23 11:42:51 2020 +0700

    JAMES-3384 anchor and anchorOffset request parameters are not supported for 
Email/query
---
 .../contract/EmailQueryMethodContract.scala        | 76 ++++++++++++++++++++++
 .../james/jmap/json/EmailQuerySerializer.scala     |  4 +-
 .../org/apache/james/jmap/mail/EmailQuery.scala    |  7 +-
 .../james/jmap/method/EmailQueryMethod.scala       | 15 ++++-
 4 files changed, 98 insertions(+), 4 deletions(-)

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/EmailQueryMethodContract.scala
 
b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailQueryMethodContract.scala
index c835a00..a3ec48c 100644
--- 
a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailQueryMethodContract.scala
+++ 
b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailQueryMethodContract.scala
@@ -1014,6 +1014,82 @@ trait EmailQueryMethodContract {
   }
 
   @Test
+  def listMailsShouldReturnInvalidArgumentsWhenAnchorParameterIsPresent(): 
Unit = {
+    val request =
+      s"""{
+         |  "using": [
+         |    "urn:ietf:params:jmap:core",
+         |    "urn:ietf:params:jmap:mail"],
+         |  "methodCalls": [[
+         |    "Email/query",
+         |    {
+         |      "accountId": 
"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+         |      "anchor": "123"
+         |    },
+         |    "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)
+      .inPath("$.methodResponses[0][1]")
+      .isEqualTo(s"""
+       {
+          "type": "invalidArguments",
+          "description": "The following parameter anchor is syntactically 
valid, but is not supported by the server."
+       }
+       """)
+  }
+
+  @Test
+  def 
listMailsShouldReturnInvalidArgumentsWhenAnchorOffsetParameterIsPresent(): Unit 
= {
+    val request =
+      s"""{
+         |  "using": [
+         |    "urn:ietf:params:jmap:core",
+         |    "urn:ietf:params:jmap:mail"],
+         |  "methodCalls": [[
+         |    "Email/query",
+         |    {
+         |      "accountId": 
"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+         |      "anchorOffset": 0
+         |    },
+         |    "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)
+      .inPath("$.methodResponses[0][1]")
+      .isEqualTo(s"""
+       {
+          "type": "invalidArguments",
+          "description": "The following parameter anchorOffset is 
syntactically valid, but is not supported by the server."
+       }
+       """)
+  }
+
+  @Test
   def 
shouldReturnIllegalArgumentErrorForAnUnknownSpecificUserMailboxes(server: 
GuiceJamesServer): Unit = {
     val message: Message = Message.Builder
       .of
diff --git 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/EmailQuerySerializer.scala
 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/EmailQuerySerializer.scala
index 57d1810..5d491dd 100644
--- 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/EmailQuerySerializer.scala
+++ 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/EmailQuerySerializer.scala
@@ -20,7 +20,7 @@
 package org.apache.james.jmap.json
 
 import javax.inject.Inject
-import org.apache.james.jmap.mail.{AllInThreadHaveKeywordSortProperty, 
CollapseThreads, Collation, Comparator, EmailQueryRequest, EmailQueryResponse, 
FilterCondition, HasAttachment, IsAscending, ReceivedAtSortProperty, 
SomeInThreadHaveKeywordSortProperty, SortProperty}
+import org.apache.james.jmap.mail.{AllInThreadHaveKeywordSortProperty, Anchor, 
AnchorOffset, CollapseThreads, Collation, Comparator, EmailQueryRequest, 
EmailQueryResponse, FilterCondition, HasAttachment, IsAscending, 
ReceivedAtSortProperty, SomeInThreadHaveKeywordSortProperty, SortProperty}
 import org.apache.james.jmap.model.{AccountId, CanCalculateChanges, Keyword, 
LimitUnparsed, PositionUnparsed, QueryState}
 import org.apache.james.mailbox.model.{MailboxId, MessageId}
 import play.api.libs.json._
@@ -72,6 +72,8 @@ class EmailQuerySerializer @Inject()(mailboxIdFactory: 
MailboxId.Factory) {
   private implicit val collationFormat: Format[Collation] = 
Json.valueFormat[Collation]
   private implicit val comparatorFormat: Format[Comparator] = 
Json.format[Comparator]
   private implicit val collapseThreadsReads: Reads[CollapseThreads] = 
Json.valueReads[CollapseThreads]
+  private implicit val anchorReads: Reads[Anchor] = Json.valueReads[Anchor]
+  private implicit val anchorOffsetReads: Reads[AnchorOffset] = 
Json.valueReads[AnchorOffset]
 
   private implicit val emailQueryRequestReads: Reads[EmailQueryRequest] = 
Json.reads[EmailQueryRequest]
 
diff --git 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/EmailQuery.scala
 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/EmailQuery.scala
index f6f3041..093030e 100644
--- 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/EmailQuery.scala
+++ 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/EmailQuery.scala
@@ -29,6 +29,7 @@ import org.apache.james.mailbox.model.{MailboxId, MessageId, 
SearchQuery}
 
 case class UnsupportedSortException(unsupportedSort: String) extends 
UnsupportedOperationException
 case class UnsupportedFilterException(unsupportedFilter: String) extends 
UnsupportedOperationException
+case class UnsupportedRequestParameterException(unsupportedParam: String) 
extends UnsupportedOperationException
 
 case class FilterCondition(inMailbox: Option[MailboxId],
                            inMailboxOtherThan: Option[Seq[MailboxId]],
@@ -48,7 +49,9 @@ case class EmailQueryRequest(accountId: AccountId,
                              limit: Option[LimitUnparsed],
                              filter: Option[FilterCondition],
                              comparator: Option[Set[Comparator]],
-                             collapseThreads: Option[CollapseThreads])
+                             collapseThreads: Option[CollapseThreads],
+                             anchor: Option[Anchor],
+                             anchorOffset: Option[AnchorOffset])
 
 sealed trait SortProperty {
   def toSortClause: Either[UnsupportedSortException, SortClause]
@@ -93,6 +96,8 @@ case class Comparator(property: SortProperty,
 }
 
 case class CollapseThreads(value: Boolean) extends AnyVal
+case class Anchor(value: String) extends AnyVal
+case class AnchorOffset(value: Int) extends AnyVal
 
 case class EmailQueryResponse(accountId: AccountId,
                               queryState: QueryState,
diff --git 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailQueryMethod.scala
 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailQueryMethod.scala
index 0c4e16a..6bee1dc 100644
--- 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailQueryMethod.scala
+++ 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailQueryMethod.scala
@@ -22,7 +22,7 @@ import cats.implicits._
 import eu.timepit.refined.auto._
 import javax.inject.Inject
 import org.apache.james.jmap.json.{EmailQuerySerializer, ResponseSerializer}
-import org.apache.james.jmap.mail.{Comparator, EmailQueryRequest, 
EmailQueryResponse, UnsupportedFilterException, UnsupportedSortException}
+import org.apache.james.jmap.mail.{Comparator, EmailQueryRequest, 
EmailQueryResponse, UnsupportedFilterException, 
UnsupportedRequestParameterException, UnsupportedSortException}
 import org.apache.james.jmap.model.CapabilityIdentifier.CapabilityIdentifier
 import org.apache.james.jmap.model.DefaultCapabilities.{CORE_CAPABILITY, 
MAIL_CAPABILITY}
 import org.apache.james.jmap.model.Invocation.{Arguments, MethodName}
@@ -53,6 +53,10 @@ class EmailQueryMethod @Inject() (serializer: 
EmailQuerySerializer,
       asEmailQueryRequest(invocation.arguments)
         .flatMap(processRequest(mailboxSession, invocation, _))
         .onErrorResume {
+          case e: UnsupportedRequestParameterException => 
SMono.just(Invocation.error(
+            ErrorCode.InvalidArguments,
+            s"The following parameter ${e.unsupportedParam} is syntactically 
valid, but is not supported by the server.",
+            invocation.methodCallId))
           case e: UnsupportedSortException => SMono.just(Invocation.error(
             ErrorCode.UnsupportedSort,
             s"The sort ${e.unsupportedSort} is syntactically valid, but it 
includes a property the server does not support sorting on or a collation 
method it does not recognise.",
@@ -105,7 +109,14 @@ class EmailQueryMethod @Inject() (serializer: 
EmailQuerySerializer,
 
   private def asEmailQueryRequest(arguments: Arguments): 
SMono[EmailQueryRequest] =
     serializer.deserializeEmailQueryRequest(arguments.value) match {
-      case JsSuccess(emailQueryRequest, _) => SMono.just(emailQueryRequest)
+      case JsSuccess(emailQueryRequest, _) => 
validateRequestParameters(emailQueryRequest)
       case errors: JsError => SMono.raiseError(new 
IllegalArgumentException(ResponseSerializer.serialize(errors).toString))
     }
+
+  private def validateRequestParameters(request: EmailQueryRequest): 
SMono[EmailQueryRequest] =
+    (request.anchor, request.anchorOffset) match {
+      case (Some(anchor), _) => 
SMono.raiseError(UnsupportedRequestParameterException("anchor"))
+      case (_, Some(anchorOffset)) => 
SMono.raiseError(UnsupportedRequestParameterException("anchorOffset"))
+      case _ => SMono.just(request)
+    }
 }
\ No newline at end of file


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

Reply via email to