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/07/06 01:37:07 UTC
[james-project] 05/05: JAMES-3096 filter properties depending on
client provided capabilities
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 <rk...@linagora.com>
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&bob@domain.tld": {
+ | "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: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org