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]
