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 6139b01d25b5527f698d714a3cef9d69af869c54 Author: Rémi KOWALSKI <[email protected]> AuthorDate: Wed Jul 1 12:01:47 2020 +0200 JAMES-3096 filter properties depending on client provided capabilities --- .../contract/MailboxGetMethodContract.scala | 299 ++++++++++++++++++++- .../org/apache/james/jmap/json/Serializer.scala | 24 +- .../apache/james/jmap/method/CoreEchoMethod.scala | 3 +- .../james/jmap/method/MailboxGetMethod.scala | 17 +- .../org/apache/james/jmap/method/Method.scala | 3 +- .../org/apache/james/jmap/model/Capability.scala | 6 +- .../apache/james/jmap/routes/JMAPApiRoutes.scala | 7 +- .../jmap/json/MailboxGetSerializationTest.scala | 4 +- .../james/jmap/json/MailboxSerializationTest.scala | 4 +- .../james/jmap/method/CoreEchoMethodTest.scala | 8 +- 10 files changed, 346 insertions(+), 29 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 b079138..e5e9b1f 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 @@ -65,6 +65,52 @@ object MailboxGetMethodContract { | }, | "c1"]] |}""".stripMargin + + private val GET_ALL_MAILBOXES_REQUEST_WITH_QUOTA: String = + """{ + | "using": [ + | "urn:ietf:params:jmap:core", + | "urn:ietf:params:jmap:mail", + | "urn:apache:james:params:jmap:mail:quota"], + | "methodCalls": [[ + | "Mailbox/get", + | { + | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", + | "ids": null + | }, + | "c1"]] + |}""".stripMargin + + private val GET_ALL_MAILBOXES_REQUEST_WITH_SHARES: String = + """{ + | "using": [ + | "urn:ietf:params:jmap:core", + | "urn:ietf:params:jmap:mail", + | "urn:apache:james:params:jmap:mail:shares"], + | "methodCalls": [[ + | "Mailbox/get", + | { + | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", + | "ids": null + | }, + | "c1"]] + |}""".stripMargin + + private val GET_ALL_MAILBOXES_REQUEST_WITH_BOTH: String = + """{ + | "using": [ + | "urn:ietf:params:jmap:core", + | "urn:ietf:params:jmap:mail", + | "urn:apache:james:params:jmap:mail:quota", + | "urn:apache:james:params:jmap:mail:shares"], + | "methodCalls": [[ + | "Mailbox/get", + | { + | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", + | "ids": null + | }, + | "c1"]] + |}""".stripMargin } trait MailboxGetMethodContract { @@ -131,6 +177,179 @@ trait MailboxGetMethodContract { | "mayDelete": true, | "maySubmit": true | }, + | "isSubscribed": false + | } + | ], + | "notFound": [] + | }, + | "c1"]] + |}""".stripMargin) + } + + @Test + def getMailboxesShouldIncludeRightsAndNamespaceIfSharesCapabilityIsUsed(server: GuiceJamesServer): Unit = { + val mailboxId: String = server.getProbe(classOf[MailboxProbeImpl]) + .createMailbox(MailboxPath.forUser(BOB, "custom")) + .serialize + + val response: String = `given` + .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) + .body(GET_ALL_MAILBOXES_REQUEST_WITH_SHARES) + .when + .post + .`then` + .statusCode(SC_OK) + .contentType(JSON) + .extract + .body + .asString + + assertThatJson(response).isEqualTo( + s"""{ + | "sessionState": "75128aab4b1b", + | "methodResponses": [[ + | "Mailbox/get", + | { + | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", + | "state": "000001", + | "list": [ + | { + | "id": "${mailboxId}", + | "name": "custom", + | "sortOrder": 1000, + | "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": false, + | "namespace": "Personal", + | "rights": {} + | } + | ], + | "notFound": [] + | }, + | "c1"]] + |}""".stripMargin) + } + + @Test + def getMailboxesShouldIncludeQuotasIfQuotaCapabilityIsUsed(server: GuiceJamesServer): Unit = { + val mailboxId: String = server.getProbe(classOf[MailboxProbeImpl]) + .createMailbox(MailboxPath.forUser(BOB, "custom")) + .serialize + + val response: String = `given` + .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) + .body(GET_ALL_MAILBOXES_REQUEST_WITH_QUOTA) + .when + .post + .`then` + .statusCode(SC_OK) + .contentType(JSON) + .extract + .body + .asString + + assertThatJson(response).isEqualTo( + s"""{ + | "sessionState": "75128aab4b1b", + | "methodResponses": [[ + | "Mailbox/get", + | { + | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", + | "state": "000001", + | "list": [ + | { + | "id": "${mailboxId}", + | "name": "custom", + | "sortOrder": 1000, + | "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": false, + | "quotas": { + | "#private&[email protected]": { + | "Storage": { "used": 0}, + | "Message": {"used": 0} + | } + | } + | } + | ], + | "notFound": [] + | }, + | "c1"]] + |}""".stripMargin) + } + + @Test + def getMailboxesShouldIncludeBothQuotasAndRightsIfUsed(server: GuiceJamesServer): Unit = { + val mailboxId: String = server.getProbe(classOf[MailboxProbeImpl]) + .createMailbox(MailboxPath.forUser(BOB, "custom")) + .serialize + + val response: String = `given` + .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) + .body(GET_ALL_MAILBOXES_REQUEST_WITH_BOTH) + .when + .post + .`then` + .statusCode(SC_OK) + .contentType(JSON) + .extract + .body + .asString + + assertThatJson(response).isEqualTo( + s"""{ + | "sessionState": "75128aab4b1b", + | "methodResponses": [[ + | "Mailbox/get", + | { + | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", + | "state": "000001", + | "list": [ + | { + | "id": "${mailboxId}", + | "name": "custom", + | "sortOrder": 1000, + | "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": false, | "namespace": "Personal", | "rights": {}, @@ -225,7 +444,7 @@ trait MailboxGetMethodContract { `given` .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) - .body(GET_ALL_MAILBOXES_REQUEST) + .body(GET_ALL_MAILBOXES_REQUEST_WITH_SHARES) .when .post .`then` @@ -250,7 +469,7 @@ trait MailboxGetMethodContract { `given` .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) - .body(GET_ALL_MAILBOXES_REQUEST) + .body(GET_ALL_MAILBOXES_REQUEST_WITH_SHARES) .when .post .`then` @@ -278,7 +497,7 @@ trait MailboxGetMethodContract { `given` .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) - .body(GET_ALL_MAILBOXES_REQUEST) + .body(GET_ALL_MAILBOXES_REQUEST_WITH_SHARES) .when .post .`then` @@ -389,7 +608,7 @@ trait MailboxGetMethodContract { `given` .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) - .body(GET_ALL_MAILBOXES_REQUEST) + .body(GET_ALL_MAILBOXES_REQUEST_WITH_QUOTA) .when .post .`then` @@ -415,7 +634,7 @@ trait MailboxGetMethodContract { `given` .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) - .body(GET_ALL_MAILBOXES_REQUEST) + .body(GET_ALL_MAILBOXES_REQUEST_WITH_QUOTA) .when .post .`then` @@ -462,7 +681,9 @@ trait MailboxGetMethodContract { .body(s"""{ | "using": [ | "urn:ietf:params:jmap:core", - | "urn:ietf:params:jmap:mail"], + | "urn:ietf:params:jmap:mail", + | "urn:apache:james:params:jmap:mail:quota", + | "urn:apache:james:params:jmap:mail:shares"], | "methodCalls": [[ | "Mailbox/get", | { @@ -526,6 +747,72 @@ trait MailboxGetMethodContract { } @Test + def getMailboxesByIdsShouldReturnCorrespondingMailboxWithoutPropertiesFromNotProvidedCapabilities(server: GuiceJamesServer): Unit = { + val mailboxId: String = server.getProbe(classOf[MailboxProbeImpl]) + .createMailbox(MailboxPath.forUser(BOB, "custom")) + .serialize + + val response: String = `given` + .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) + .body(s"""{ + | "using": [ + | "urn:ietf:params:jmap:core", + | "urn:ietf:params:jmap:mail"], + | "methodCalls": [[ + | "Mailbox/get", + | { + | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", + | "ids": ["${mailboxId}"] + | }, + | "c1"]] + |}""".stripMargin) + .when + .post + .`then` + .statusCode(SC_OK) + .contentType(JSON) + .extract + .body + .asString + + assertThatJson(response).isEqualTo( + s"""{ + | "sessionState": "75128aab4b1b", + | "methodResponses": [[ + | "Mailbox/get", + | { + | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", + | "state": "000001", + | "list": [ + | { + | "id": "${mailboxId}", + | "name": "custom", + | "sortOrder": 1000, + | "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": false + | } + | ], + | "notFound": [] + | }, + | "c1"]] + |}""".stripMargin) + } + + @Test def getMailboxesByIdsShouldReturnOnlyRequestedMailbox(server: GuiceJamesServer): Unit = { val mailboxName: String = "custom" val mailboxId: String = server.getProbe(classOf[MailboxProbeImpl]) diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/Serializer.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/Serializer.scala index e6d26e3..ad6b6b5 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/Serializer.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/Serializer.scala @@ -201,7 +201,8 @@ class Serializer @Inject() (mailboxIdFactory: MailboxId.Factory) { }) } - private implicit val mailboxWrites: Writes[Mailbox] = Json.writes[Mailbox] + implicit def mailboxWrites(propertiesToHide: Set[String]): Writes[Mailbox] = Json.writes[Mailbox] + .transform((o: JsObject) => JsObject(o.fields.filterNot(entry => propertiesToHide.contains(entry._1)))) private implicit val idsRead: Reads[Ids] = Json.valueReads[Ids] private implicit val propertiesRead: Reads[Properties] = Json.valueReads[Properties] @@ -210,7 +211,7 @@ class Serializer @Inject() (mailboxIdFactory: MailboxId.Factory) { private implicit def notFoundWrites(implicit mailboxIdWrites: Writes[MailboxId]): Writes[NotFound] = notFound => JsArray(notFound.value.toList.map(mailboxIdWrites.writes)) - private implicit val mailboxGetResponseWrites: Writes[MailboxGetResponse] = Json.writes[MailboxGetResponse] + private implicit def mailboxGetResponseWrites(implicit mailboxWrites: Writes[Mailbox]): Writes[MailboxGetResponse] = Json.writes[MailboxGetResponse] private implicit val jsonValidationErrorWrites: Writes[JsonValidationError] = error => JsString(error.message) @@ -229,6 +230,17 @@ class Serializer @Inject() (mailboxIdFactory: MailboxId.Factory) { }) } + private def mailboxWritesWithFilteredProperties(capabilities: Set[CapabilityIdentifier]): Writes[Mailbox] = { + val propertiesForCapabitilites: Map[CapabilityIdentifier, Set[String]] = Map( + CapabilityIdentifier.JAMES_QUOTA -> Set("quotas"), + CapabilityIdentifier.JAMES_SHARES -> Set("namespace", "rights") + ) + val propertiesToHide = propertiesForCapabitilites.filterNot(entry => capabilities.contains(entry._1)) + .flatMap(_._2) + .toSet + mailboxWrites(propertiesToHide) + } + private implicit def jsErrorWrites: Writes[JsError] = Json.writes[JsError] def serialize(session: Session): JsValue = Json.toJson(session) @@ -237,9 +249,13 @@ class Serializer @Inject() (mailboxIdFactory: MailboxId.Factory) { def serialize(responseObject: ResponseObject): JsValue = Json.toJson(responseObject) - def serialize(mailbox: Mailbox): JsValue = Json.toJson(mailbox) + def serialize(mailbox: Mailbox)(implicit mailboxWrites: Writes[Mailbox]): JsValue = Json.toJson(mailbox) - def serialize(mailboxGetResponse: MailboxGetResponse): JsValue = Json.toJson(mailboxGetResponse) + def serialize(mailboxGetResponse: MailboxGetResponse)(implicit mailboxWrites: Writes[Mailbox]): JsValue = Json.toJson(mailboxGetResponse) + + def serialize(mailboxGetResponse: MailboxGetResponse, capabilities: Set[CapabilityIdentifier]): JsValue = { + serialize(mailboxGetResponse)(mailboxWritesWithFilteredProperties(capabilities)) + } def serialize(errors: JsError): JsValue = Json.toJson(errors) diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/CoreEchoMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/CoreEchoMethod.scala index fad57d8..d1dd286 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/CoreEchoMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/CoreEchoMethod.scala @@ -20,6 +20,7 @@ package org.apache.james.jmap.method import eu.timepit.refined.auto._ +import org.apache.james.jmap.model.CapabilityIdentifier.CapabilityIdentifier import org.apache.james.jmap.model.Invocation import org.apache.james.jmap.model.Invocation.MethodName import org.apache.james.mailbox.MailboxSession @@ -29,5 +30,5 @@ import reactor.core.scala.publisher.SMono class CoreEchoMethod extends Method { override val methodName = MethodName("Core/echo") - override def process(invocation: Invocation, mailboxSession: MailboxSession): Publisher[Invocation] = SMono.just(invocation) + override def process(capabilities: Set[CapabilityIdentifier], invocation: Invocation, mailboxSession: MailboxSession): Publisher[Invocation] = SMono.just(invocation) } \ No newline at end of file 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 b3c66c1..168b095 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 @@ -23,6 +23,7 @@ import eu.timepit.refined.auto._ import javax.inject.Inject import org.apache.james.jmap.json.Serializer 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} @@ -53,7 +54,7 @@ class MailboxGetMethod @Inject() (serializer: Serializer, def merge(other: MailboxGetResults): MailboxGetResults = MailboxGetResults(this.mailboxes ++ other.mailboxes, this.notFound.merge(other.notFound)) } - override def process(invocation: Invocation, mailboxSession: MailboxSession): Publisher[Invocation] = { + 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) @@ -65,7 +66,7 @@ class MailboxGetMethod @Inject() (serializer: Serializer, notFound = mailboxes.notFound)) .map(mailboxGetResponse => Invocation( methodName = methodName, - arguments = Arguments(serializer.serialize(mailboxGetResponse).as[JsObject]), + arguments = Arguments(serializer.serialize(mailboxGetResponse, capabilities).as[JsObject]), methodCallId = invocation.methodCallId)))) } @@ -76,11 +77,13 @@ class MailboxGetMethod @Inject() (serializer: Serializer, } } - private def getMailboxes(mailboxGetRequest: MailboxGetRequest, mailboxSession: MailboxSession): SFlux[MailboxGetResults] = mailboxGetRequest.ids match { - case None => getAllMailboxes(mailboxSession).map(MailboxGetResults.found) - case Some(ids) => SFlux.fromIterable(ids.value) - .flatMap(id => getMailboxResultById(id, mailboxSession)) - } + private def getMailboxes(mailboxGetRequest: MailboxGetRequest, + mailboxSession: MailboxSession): SFlux[MailboxGetResults] = + mailboxGetRequest.ids match { + case None => getAllMailboxes(mailboxSession).map(MailboxGetResults.found) + case Some(ids) => SFlux.fromIterable(ids.value) + .flatMap(id => getMailboxResultById(id, mailboxSession)) + } private def getMailboxResultById(mailboxId: MailboxId, mailboxSession: MailboxSession): SMono[MailboxGetResults] = quotaFactory.loadFor(mailboxSession) diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/Method.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/Method.scala index 02751dc..078929e 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/Method.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/Method.scala @@ -19,6 +19,7 @@ package org.apache.james.jmap.method +import org.apache.james.jmap.model.CapabilityIdentifier.CapabilityIdentifier import org.apache.james.jmap.model.Invocation import org.apache.james.jmap.model.Invocation.MethodName import org.apache.james.mailbox.MailboxSession @@ -29,6 +30,6 @@ trait Method { val methodName: MethodName - def process(invocation: Invocation, mailboxSession: MailboxSession): Publisher[Invocation] + def process(capabilities: Set[CapabilityIdentifier], invocation: Invocation, mailboxSession: MailboxSession): Publisher[Invocation] } diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/model/Capability.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/model/Capability.scala index 17517fe..6fd841c 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/model/Capability.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/model/Capability.scala @@ -30,8 +30,10 @@ import org.apache.james.jmap.model.UnsignedInt.UnsignedInt object CapabilityIdentifier { type CapabilityIdentifier = String Refined Uri - private[model] val JMAP_CORE: CapabilityIdentifier = "urn:ietf:params:jmap:core" - private[model] val JMAP_MAIL: CapabilityIdentifier = "urn:ietf:params:jmap:mail" + val JMAP_CORE: CapabilityIdentifier = "urn:ietf:params:jmap:core" + val JMAP_MAIL: CapabilityIdentifier = "urn:ietf:params:jmap:mail" + val JAMES_QUOTA: CapabilityIdentifier = "urn:apache:james:params:jmap:mail:quota" + val JAMES_SHARES: CapabilityIdentifier = "urn:apache:james:params:jmap:mail:shares" } sealed trait CapabilityProperties diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/routes/JMAPApiRoutes.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/routes/JMAPApiRoutes.scala index dc918c6..0a89a16 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/routes/JMAPApiRoutes.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/routes/JMAPApiRoutes.scala @@ -36,6 +36,7 @@ import org.apache.james.jmap.http.Authenticator import org.apache.james.jmap.http.rfc8621.InjectionKeys import org.apache.james.jmap.json.Serializer import org.apache.james.jmap.method.Method +import org.apache.james.jmap.model.CapabilityIdentifier.CapabilityIdentifier import org.apache.james.jmap.model.Invocation.{Arguments, MethodName} import org.apache.james.jmap.model.{Invocation, RequestObject, ResponseObject} import org.apache.james.jmap.{Endpoint, JMAPRoute, JMAPRoutes} @@ -104,7 +105,7 @@ class JMAPApiRoutes (val authenticator: Authenticator, mailboxSession: MailboxSession): SMono[Void] = requestObject .methodCalls - .map(invocation => this.processMethodWithMatchName(invocation, mailboxSession)) + .map(invocation => this.processMethodWithMatchName(requestObject.using.toSet, invocation, mailboxSession)) .foldLeft(SFlux.empty[Invocation]) { (flux: SFlux[Invocation], mono: SMono[Invocation]) => flux.mergeWith(mono) } .collectSeq() .flatMap((invocations: Seq[Invocation]) => @@ -117,9 +118,9 @@ class JMAPApiRoutes (val authenticator: Authenticator, ).`then`()) ) - private def processMethodWithMatchName(invocation: Invocation, mailboxSession: MailboxSession): SMono[Invocation] = + private def processMethodWithMatchName(capabilities: Set[CapabilityIdentifier], invocation: Invocation, mailboxSession: MailboxSession): SMono[Invocation] = SMono.justOrEmpty(methodsByName.get(invocation.methodName)) - .flatMap(method => SMono.fromPublisher(method.process(invocation, mailboxSession))) + .flatMap(method => SMono.fromPublisher(method.process(capabilities, invocation, mailboxSession))) .switchIfEmpty(SMono.just(new Invocation( MethodName("error"), Arguments(Json.obj("type" -> "Not implemented")), diff --git a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/json/MailboxGetSerializationTest.scala b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/json/MailboxGetSerializationTest.scala index b27f06b..c2da125 100644 --- a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/json/MailboxGetSerializationTest.scala +++ b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/json/MailboxGetSerializationTest.scala @@ -42,6 +42,8 @@ object MailboxGetSerializationTest { private val MAILBOX_ID_2: MailboxId = FACTORY.fromString("2") private val PROPERTIES: Properties = Properties(List("name", "role")) + + private val NO_PROPERTY_FILTERING: Set[String] = Set.empty } class MailboxGetSerializationTest extends AnyWordSpec with Matchers { @@ -205,7 +207,7 @@ class MailboxGetSerializationTest extends AnyWordSpec with Matchers { |} |""".stripMargin - assertThatJson(Json.stringify(SERIALIZER.serialize(actualValue))).isEqualTo(expectedJson) + assertThatJson(Json.stringify(SERIALIZER.serialize(actualValue)(SERIALIZER.mailboxWrites(NO_PROPERTY_FILTERING)))).isEqualTo(expectedJson) } } } diff --git a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/json/MailboxSerializationTest.scala b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/json/MailboxSerializationTest.scala index c5b49d8..99455a6 100644 --- a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/json/MailboxSerializationTest.scala +++ b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/json/MailboxSerializationTest.scala @@ -129,7 +129,9 @@ class MailboxSerializationTest extends AnyWordSpec with Matchers { | } |}""".stripMargin - assertThatJson(Json.stringify(new Serializer(new TestId.Factory).serialize(MAILBOX))).isEqualTo(expectedJson) + val serializer = new Serializer(new TestId.Factory) + val noPropertyFiltering: Set[String] = Set.empty + assertThatJson(Json.stringify(serializer.serialize(MAILBOX)(serializer.mailboxWrites(noPropertyFiltering)))).isEqualTo(expectedJson) } } } diff --git a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/method/CoreEchoMethodTest.scala b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/method/CoreEchoMethodTest.scala index 583e832..9415c16 100644 --- a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/method/CoreEchoMethodTest.scala +++ b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/method/CoreEchoMethodTest.scala @@ -19,7 +19,8 @@ package org.apache.james.jmap.method import org.apache.james.jmap.json.Fixture.{invocation1, invocation2} -import org.apache.james.jmap.model.Invocation +import org.apache.james.jmap.model.CapabilityIdentifier.CapabilityIdentifier +import org.apache.james.jmap.model.{CapabilityIdentifier, Invocation} import org.apache.james.mailbox.MailboxSession import org.mockito.Mockito.mock import org.scalatest.matchers.should.Matchers @@ -29,19 +30,20 @@ import reactor.core.scala.publisher.SMono class CoreEchoMethodTest extends AnyWordSpec with Matchers { private val echoMethod: CoreEchoMethod = new CoreEchoMethod() private val mockedSession: MailboxSession = mock(classOf[MailboxSession]) + private val capabilities: Set[CapabilityIdentifier] = Set(CapabilityIdentifier.JMAP_CORE, CapabilityIdentifier.JMAP_MAIL) "CoreEcho" should { "Process" should { "success and return the same with parameters as the invocation request" in { val expectedResponse: Invocation = invocation1 - val dataResponse = SMono.fromPublisher(echoMethod.process(invocation1, mockedSession)).block() + val dataResponse = SMono.fromPublisher(echoMethod.process(capabilities, invocation1, mockedSession)).block() dataResponse shouldBe expectedResponse } "success and not return anything else different than the original invocation" in { val wrongExpected: Invocation = invocation2 - val dataResponse = SMono.fromPublisher(echoMethod.process(invocation1, mockedSession)).block() + val dataResponse = SMono.fromPublisher(echoMethod.process(capabilities, invocation1, mockedSession)).block() dataResponse should not be(wrongExpected) } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
