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