You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by rc...@apache.org on 2020/07/17 10:24:16 UTC

[james-project] 07/09: JAMES-3098 return error if invalid property requested

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 a8b7894ae047a7a6458404659b4bbf955efe422a
Author: RĂ©mi Kowalski <rk...@linagora.com>
AuthorDate: Thu Jul 16 12:01:28 2020 +0200

    JAMES-3098 return error if invalid property requested
---
 .../contract/MailboxGetMethodContract.scala        |  5 ++--
 .../org/apache/james/jmap/mail/MailboxGet.scala    |  5 +++-
 .../james/jmap/method/MailboxGetMethod.scala       | 34 ++++++++++++++--------
 .../org/apache/james/jmap/model/Invocation.scala   | 20 +++++++++++++
 4 files changed, 48 insertions(+), 16 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/MailboxGetMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxGetMethodContract.scala
index 40471f3..6a255a2 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxGetMethodContract.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxGetMethodContract.scala
@@ -41,7 +41,7 @@ import org.apache.james.mime4j.dom.Message
 import org.apache.james.modules.{ACLProbeImpl, MailboxProbeImpl, QuotaProbesImpl}
 import org.apache.james.utils.DataProbeImpl
 import org.hamcrest.Matchers._
-import org.junit.jupiter.api.{BeforeEach, Disabled, Tag, Test}
+import org.junit.jupiter.api.{BeforeEach, Tag, Test}
 
 object MailboxGetMethodContract {
   private val ARGUMENTS: String = "methodResponses[0][1]"
@@ -680,7 +680,6 @@ trait MailboxGetMethodContract {
          |}""".stripMargin)
   }
 
-  @Disabled("TODO")
   @Test
   def getMailboxesShouldNotIncludeNamespaceIfSharesCapabilityIsUsedAndNamespaceIsNotRequested(server: GuiceJamesServer): Unit = {
     val mailboxId: String = server.getProbe(classOf[MailboxProbeImpl])
@@ -743,7 +742,7 @@ trait MailboxGetMethodContract {
          |  "methodResponses": [[
          |   "error", {
          |     "type": "invalidArguments",
-         |     "description": "The following properties [invalidProperty] do not exist"
+         |     "description": "The following properties [invalidProperty] do not exist."
          |},
          |    "c1"]]
          |}""".stripMargin)
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/MailboxGet.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/MailboxGet.scala
index 5d9b971..613d418 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/MailboxGet.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/MailboxGet.scala
@@ -26,7 +26,10 @@ import org.apache.james.mailbox.model.MailboxId
 
 case class Ids(value: List[MailboxId])
 
-case class Properties(value: List[NonEmptyString])
+case class Properties(value: List[NonEmptyString]) {
+  def asSetOfString: Set[String] = value.map(_.toString()).toSet
+}
+
 
 case class MailboxGetRequest(accountId: AccountId,
                              ids: Option[Ids],
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxGetMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxGetMethod.scala
index b48e7a6..2423978 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxGetMethod.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxGetMethod.scala
@@ -26,7 +26,7 @@ import org.apache.james.jmap.mail._
 import org.apache.james.jmap.model.CapabilityIdentifier.CapabilityIdentifier
 import org.apache.james.jmap.model.Invocation.{Arguments, MethodName}
 import org.apache.james.jmap.model.State.INSTANCE
-import org.apache.james.jmap.model.{Invocation, MailboxFactory}
+import org.apache.james.jmap.model.{ErrorCode, Invocation, MailboxFactory}
 import org.apache.james.jmap.utils.quotas.{QuotaLoader, QuotaLoaderWithPreloadedDefaultFactory}
 import org.apache.james.mailbox.exception.MailboxNotFoundException
 import org.apache.james.mailbox.model.search.MailboxQuery
@@ -57,17 +57,27 @@ class MailboxGetMethod @Inject() (serializer: Serializer,
   override def process(capabilities: Set[CapabilityIdentifier], invocation: Invocation, mailboxSession: MailboxSession): Publisher[Invocation] = {
     metricFactory.decoratePublisherWithTimerMetricLogP99(JMAP_RFC8621_PREFIX + methodName.value,
       asMailboxGetRequest(invocation.arguments)
-        .flatMap(mailboxGetRequest => getMailboxes(mailboxGetRequest, mailboxSession)
-          .reduce(MailboxGetResults(Set.empty, NotFound(Set.empty)), (result1: MailboxGetResults, result2: MailboxGetResults) => result1.merge(result2))
-          .map(mailboxes => MailboxGetResponse(
-            accountId = mailboxGetRequest.accountId,
-            state = INSTANCE,
-            list = mailboxes.mailboxes.toList.sortBy(_.sortOrder),
-            notFound = mailboxes.notFound))
-          .map(mailboxGetResponse => Invocation(
-            methodName = methodName,
-            arguments = Arguments(serializer.serialize(mailboxGetResponse, mailboxGetRequest.properties, capabilities).as[JsObject]),
-            methodCallId = invocation.methodCallId))))
+        .flatMap(mailboxGetRequest => {
+          mailboxGetRequest.properties match {
+            case Some(properties) if !properties.asSetOfString.subsetOf(Mailbox.allProperties) =>
+              SMono.just(Invocation.error(errorCode = ErrorCode.InvalidArguments,
+                description = Some(s"The following properties [${properties.asSetOfString.diff(Mailbox.allProperties).mkString(", ")}] do not exist."),
+                methodCallId = invocation.methodCallId))
+            case _ => getMailboxes(mailboxGetRequest, mailboxSession)
+              .reduce(MailboxGetResults(Set.empty, NotFound(Set.empty)), (result1: MailboxGetResults, result2: MailboxGetResults) => result1.merge(result2))
+              .map(mailboxes => MailboxGetResponse(
+                accountId = mailboxGetRequest.accountId,
+                state = INSTANCE,
+                list = mailboxes.mailboxes.toList.sortBy(_.sortOrder),
+                notFound = mailboxes.notFound))
+              .map(mailboxGetResponse => Invocation(
+                methodName = methodName,
+                arguments = Arguments(serializer.serialize(mailboxGetResponse, mailboxGetRequest.properties, capabilities).as[JsObject]),
+                methodCallId = invocation.methodCallId))
+
+          }
+        }
+        ))
   }
 
   private def asMailboxGetRequest(arguments: Arguments): SMono[MailboxGetRequest] = {
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/model/Invocation.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/model/Invocation.scala
index c46d95b..5e8ec02 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/model/Invocation.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/model/Invocation.scala
@@ -18,6 +18,7 @@
  * ***************************************************************/
 package org.apache.james.jmap.model
 
+import eu.timepit.refined.auto._
 import eu.timepit.refined.types.string.NonEmptyString
 import org.apache.james.jmap.model.Invocation.{Arguments, MethodCallId, MethodName}
 import play.api.libs.json._
@@ -33,4 +34,23 @@ object Invocation {
   case class Arguments(value: JsObject) extends AnyVal
   case class MethodCallId(value: NonEmptyString)
 
+
+  def error(errorCode: ErrorCode, description: Option[String], methodCallId: MethodCallId): Invocation = {
+    Invocation(MethodName("error"),
+      Arguments(JsObject(Seq("type" -> JsString(errorCode.code), "description" -> JsString(description.getOrElse(errorCode.defaultDescription))))),
+      methodCallId)
+  }
+}
+
+sealed trait ErrorCode {
+  def code: String
+  def defaultDescription: String
+}
+
+object ErrorCode {
+  case object InvalidArguments extends ErrorCode {
+    override def code: String = "invalidArguments"
+
+    override def defaultDescription: String = "One of the arguments is of the wrong type or otherwise invalid, or a required argument is missing."
+  }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org