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 bt...@apache.org on 2020/08/19 07:38:33 UTC

[james-project] 04/11: JAMES-3356 Allow the use of Mailbox CreationId for parentId

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 5aaedd129fd3c358701cd4d494b3f910ace033ad
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Fri Aug 14 10:51:13 2020 +0700

    JAMES-3356 Allow the use of Mailbox CreationId for parentId
---
 .../contract/MailboxSetMethodContract.scala        | 120 ++++++++++++++++++++-
 .../org/apache/james/jmap/mail/MailboxSet.scala    |   2 +-
 .../james/jmap/method/MailboxSetMethod.scala       |  35 +++---
 3 files changed, 139 insertions(+), 18 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/MailboxSetMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxSetMethodContract.scala
index becc612..28bd5fd 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxSetMethodContract.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxSetMethodContract.scala
@@ -219,7 +219,7 @@ trait MailboxSetMethodContract {
          |      "notCreated": {
          |        "C42": {
          |          "type": "invalidArguments",
-         |          "description": "'/parentId' property in mailbox object is not valid"
+         |          "description": "'/parentId' property in mailbox object is not valid: Predicate isEmpty() did not fail."
          |        }
          |      }
          |    },
@@ -1195,6 +1195,124 @@ trait MailboxSetMethodContract {
   }
 
   @Test
+  def createParentIdShouldAcceptCreationIdsWithinTheSameRequest(server: GuiceJamesServer): Unit = {
+    val request =
+      s"""
+        |{
+        |   "using": [ "urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail" ],
+        |   "methodCalls": [
+        |       ["Mailbox/set",
+        |           {
+        |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+        |                "create": {
+        |                    "C42": {
+        |                      "name": "parent"
+        |                    }
+        |                }
+        |           },
+        |    "c1"],
+        |       ["Mailbox/set",
+        |           {
+        |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+        |                "create": {
+        |                    "C43": {
+        |                      "name": "child",
+        |                      "parentId": "#C42"
+        |                    }
+        |                }
+        |           },
+        |    "c2"]
+        |   ]
+        |}
+        |""".stripMargin
+
+    val response = `given`
+      .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+      .body(request)
+      .when
+      .post
+      .`then`
+      .log().ifValidationFails()
+      .statusCode(SC_OK)
+      .contentType(JSON)
+      .extract
+      .body
+      .asString
+
+    val parentId: String = server.getProbe(classOf[MailboxProbeImpl])
+      .getMailboxId("#private", BOB.asString(), "parent")
+      .serialize()
+    val childId: String = server.getProbe(classOf[MailboxProbeImpl])
+      .getMailboxId("#private", BOB.asString(), "parent.child")
+      .serialize()
+
+    assertThatJson(response).isEqualTo(
+      s"""{
+         |    "sessionState": "75128aab4b1b",
+         |    "methodResponses": [
+         |        [
+         |            "Mailbox/set",
+         |            {
+         |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+         |                "newState": "000001",
+         |                "created": {
+         |                    "C42": {
+         |                        "id": "$parentId",
+         |                        "totalEmails": 0,
+         |                        "unreadEmails": 0,
+         |                        "totalThreads": 0,
+         |                        "unreadThreads": 0,
+         |                        "myRights": {
+         |                            "mayReadItems": true,
+         |                            "mayAddItems": true,
+         |                            "mayRemoveItems": true,
+         |                            "maySetSeen": true,
+         |                            "maySetKeywords": true,
+         |                            "mayCreateChild": true,
+         |                            "mayRename": true,
+         |                            "mayDelete": true,
+         |                            "maySubmit": true
+         |                        },
+         |                        "isSubscribed": true
+         |                    }
+         |                }
+         |            },
+         |            "c1"
+         |        ],
+         |        [
+         |            "Mailbox/set",
+         |            {
+         |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+         |                "newState": "000001",
+         |                "created": {
+         |                    "C43": {
+         |                        "id": "$childId",
+         |                        "totalEmails": 0,
+         |                        "unreadEmails": 0,
+         |                        "totalThreads": 0,
+         |                        "unreadThreads": 0,
+         |                        "myRights": {
+         |                            "mayReadItems": true,
+         |                            "mayAddItems": true,
+         |                            "mayRemoveItems": true,
+         |                            "maySetSeen": true,
+         |                            "maySetKeywords": true,
+         |                            "mayCreateChild": true,
+         |                            "mayRename": true,
+         |                            "mayDelete": true,
+         |                            "maySubmit": true
+         |                        },
+         |                        "isSubscribed": true
+         |                    }
+         |                }
+         |            },
+         |            "c2"
+         |        ]
+         |    ]
+         |}""".stripMargin)
+  }
+
+  @Test
   def creationIdReferencesShouldFailWhenWrongOrder(server: GuiceJamesServer): Unit = {
     val request =
       s"""
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/MailboxSet.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/MailboxSet.scala
index 2b2fc13..fdf2d18 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/MailboxSet.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/MailboxSet.scala
@@ -43,7 +43,7 @@ object MailboxSetRequest {
 }
 
 case class RemoveEmailsOnDestroy(value: Boolean) extends AnyVal
-case class MailboxCreationRequest(name: MailboxName, parentId: Option[MailboxId])
+case class MailboxCreationRequest(name: MailboxName, parentId: Option[UnparsedMailboxId])
 
 case class MailboxPatchObject(value: Map[String, JsObject])
 
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetMethod.scala
index 94b64b2..61f8452 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetMethod.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetMethod.scala
@@ -114,19 +114,6 @@ class MailboxSetMethod @Inject()(serializer: Serializer,
         }))
   }
 
-  def parseCreate(jsObject: JsObject): Either[MailboxCreationParseException, MailboxCreationRequest] =
-    Json.fromJson(jsObject)(serializer.mailboxCreationRequest) match {
-      case JsSuccess(creationRequest, _) => Right(creationRequest)
-      case JsError(errors) => Left(MailboxCreationParseException(mailboxSetError(errors)))
-    }
-
-  private def mailboxSetError(errors: collection.Seq[(JsPath, collection.Seq[JsonValidationError])]): MailboxSetError =
-    errors.head match {
-      case (path, Seq()) => MailboxSetError.invalidArgument(Some(SetErrorDescription(s"'$path' property in mailbox object is not valid")), None)
-      case (path, Seq(JsonValidationError(Seq("error.path.missing")))) => MailboxSetError("invalidArguments", Some(SetErrorDescription(s"Missing '$path' property in mailbox object")), None)
-      case (path, _) => MailboxSetError.invalidArgument(Some(SetErrorDescription(s"Unknown error on property '$path'")), None)
-    }
-
   private def deleteMailboxes(mailboxSession: MailboxSession, mailboxSetRequest: MailboxSetRequest, processingContext: ProcessingContext): SMono[DeletionResults] = {
     SFlux.fromIterable(mailboxSetRequest.destroy.getOrElse(Seq()))
       .flatMap(id => delete(mailboxSession, processingContext, id)
@@ -176,11 +163,25 @@ class MailboxSetMethod @Inject()(serializer: Serializer,
                             jsObject: JsObject,
                             processingContext: ProcessingContext): CreationResult = {
     parseCreate(jsObject)
-        .flatMap(mailboxCreationRequest => resolvePath(mailboxSession, mailboxCreationRequest))
+      .flatMap(mailboxCreationRequest => resolvePath(mailboxSession, mailboxCreationRequest, processingContext))
       .map(path => createMailbox(mailboxSession, mailboxCreationId, processingContext, path))
       .fold(e => CreationFailure(mailboxCreationId, e), r => r)
   }
 
+  private def parseCreate(jsObject: JsObject): Either[MailboxCreationParseException, MailboxCreationRequest] =
+    Json.fromJson(jsObject)(serializer.mailboxCreationRequest) match {
+      case JsSuccess(creationRequest, _) => Right(creationRequest)
+      case JsError(errors) => Left(MailboxCreationParseException(mailboxSetError(errors)))
+    }
+
+  private def mailboxSetError(errors: collection.Seq[(JsPath, collection.Seq[JsonValidationError])]): MailboxSetError =
+    errors.head match {
+      case (path, Seq()) => MailboxSetError.invalidArgument(Some(SetErrorDescription(s"'$path' property in mailbox object is not valid")), None)
+      case (path, Seq(JsonValidationError(Seq("error.path.missing")))) => MailboxSetError("invalidArguments", Some(SetErrorDescription(s"Missing '$path' property in mailbox object")), None)
+      case (path, Seq(JsonValidationError(Seq(message)))) => MailboxSetError("invalidArguments", Some(SetErrorDescription(s"'$path' property in mailbox object is not valid: $message")), None)
+      case (path, _) => MailboxSetError.invalidArgument(Some(SetErrorDescription(s"Unknown error on property '$path'")), None)
+    }
+
   private def createMailbox(mailboxSession: MailboxSession,
                             mailboxCreationId: MailboxCreationId,
                             processingContext: ProcessingContext,
@@ -207,9 +208,11 @@ class MailboxSetMethod @Inject()(serializer: Serializer,
   }
 
   private def resolvePath(mailboxSession: MailboxSession,
-                          mailboxCreationRequest: MailboxCreationRequest): Either[Exception, MailboxPath] = {
+                          mailboxCreationRequest: MailboxCreationRequest,
+                          processingContext: ProcessingContext): Either[Exception, MailboxPath] = {
     mailboxCreationRequest.parentId
-      .map(parentId => for {
+      .map(maybeParentId => for {
+        parentId <- processingContext.resolveMailboxId(maybeParentId, mailboxIdFactory)
         parentPath <- retrievePath(parentId, mailboxSession)
       } yield {
         parentPath.child(mailboxCreationRequest.name, mailboxSession.getPathDelimiter)


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