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:15 UTC
[james-project] 06/09: JAMES-3098 filter properties from response
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 9b1c3888d5d6765b2aa8547c00a3e1c42b03aa5e
Author: RĂ©mi Kowalski <rk...@linagora.com>
AuthorDate: Wed Jul 15 16:34:24 2020 +0200
JAMES-3098 filter properties from response
---
.../contract/MailboxGetMethodContract.scala | 128 +++++++++++++++++++--
.../org/apache/james/jmap/json/Serializer.scala | 19 +--
.../scala/org/apache/james/jmap/mail/Mailbox.scala | 25 +++-
.../james/jmap/method/MailboxGetMethod.scala | 2 +-
.../jmap/json/MailboxGetSerializationTest.scala | 4 +-
.../james/jmap/json/MailboxSerializationTest.scala | 3 +-
6 files changed, 149 insertions(+), 32 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 3f51a4b..40471f3 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
@@ -81,6 +81,21 @@ object MailboxGetMethodContract {
| "c1"]]
|}""".stripMargin
+ private val GET_ALL_MAILBOXES_REQUEST_EMPTY_PROPERTIES: String =
+ """{
+ | "using": [
+ | "urn:ietf:params:jmap:core",
+ | "urn:ietf:params:jmap:mail"],
+ | "methodCalls": [[
+ | "Mailbox/get",
+ | {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "properties": [],
+ | "ids": null
+ | },
+ | "c1"]]
+ |}""".stripMargin
+
private val GET_ALL_MAILBOXES_REQUEST_NAME_AND_ID_PROPERTIES: String =
"""{
| "using": [
@@ -156,6 +171,22 @@ object MailboxGetMethodContract {
| "c1"]]
|}""".stripMargin
+ private val GET_ALL_MAILBOXES_REQUEST_WITH_SHARES_WITH_ONLY_ID_NAME_AND_RIGHTS: String =
+ """{
+ | "using": [
+ | "urn:ietf:params:jmap:core",
+ | "urn:ietf:params:jmap:mail",
+ | "urn:apache:james:params:jmap:mail:shares"],
+ | "methodCalls": [[
+ | "Mailbox/get",
+ | {
+ | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+ | "properties": ["id", "name", "rights"],
+ | "ids": null
+ | },
+ | "c1"]]
+ |}""".stripMargin
+
private val GET_ALL_MAILBOXES_REQUEST_WITH_BOTH: String =
"""{
| "using": [
@@ -436,9 +467,9 @@ trait MailboxGetMethodContract {
val response: String = `given`
.header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
.body(GET_ALL_MAILBOXES_REQUEST)
- .when
+ .when
.post
- .`then`
+ .`then`
.statusCode(SC_OK)
.contentType(JSON)
.extract
@@ -491,9 +522,9 @@ trait MailboxGetMethodContract {
val response: String = `given`
.header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
.body(GET_ALL_MAILBOXES_REQUEST_NULL_PROPERTIES)
- .when
+ .when
.post
- .`then`
+ .`then`
.statusCode(SC_OK)
.contentType(JSON)
.extract
@@ -537,7 +568,42 @@ trait MailboxGetMethodContract {
|}""".stripMargin)
}
- @Disabled("TODO")
+ @Test
+ def getMailboxesShouldReturnIdWhenNoPropertiesRequested(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_EMPTY_PROPERTIES)
+ .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}"
+ | }
+ | ],
+ | "notFound": []
+ | },
+ | "c1"]]
+ |}""".stripMargin)
+ }
@Test
def getMailboxesShouldReturnOnlyNameAndIdWhenPropertiesRequested(server: GuiceJamesServer): Unit = {
val mailboxId: String = server.getProbe(classOf[MailboxProbeImpl])
@@ -547,9 +613,9 @@ trait MailboxGetMethodContract {
val response: String = `given`
.header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
.body(GET_ALL_MAILBOXES_REQUEST_NAME_AND_ID_PROPERTIES)
- .when
+ .when
.post
- .`then`
+ .`then`
.statusCode(SC_OK)
.contentType(JSON)
.extract
@@ -576,7 +642,6 @@ trait MailboxGetMethodContract {
|}""".stripMargin)
}
- @Disabled("TODO")
@Test
def getMailboxesShouldAlwaysReturnIdEvenIfNotRequested(server: GuiceJamesServer): Unit = {
val mailboxId: String = server.getProbe(classOf[MailboxProbeImpl])
@@ -586,9 +651,9 @@ trait MailboxGetMethodContract {
val response: String = `given`
.header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
.body(GET_ALL_MAILBOXES_REQUEST_NAME_PROPERTIES)
- .when
+ .when
.post
- .`then`
+ .`then`
.statusCode(SC_OK)
.contentType(JSON)
.extract
@@ -617,6 +682,45 @@ trait MailboxGetMethodContract {
@Disabled("TODO")
@Test
+ def getMailboxesShouldNotIncludeNamespaceIfSharesCapabilityIsUsedAndNamespaceIsNotRequested(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_WITH_ONLY_ID_NAME_AND_RIGHTS)
+ .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",
+ | "rights": {}
+ | }
+ | ],
+ | "notFound": []
+ | },
+ | "c1"]]
+ |}""".stripMargin)
+ }
+
+ @Test
def getMailboxesShouldReturnInvalidArgumentsErrorWhenInvalidProperty(server: GuiceJamesServer): Unit = {
server.getProbe(classOf[MailboxProbeImpl])
.createMailbox(MailboxPath.forUser(BOB, "custom"))
@@ -624,9 +728,9 @@ trait MailboxGetMethodContract {
val response: String = `given`
.header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
.body(GET_ALL_MAILBOXES_REQUEST_INVALID_PROPERTIES)
- .when
+ .when
.post
- .`then`
+ .`then`
.statusCode(SC_OK)
.contentType(JSON)
.extract
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 ad6b6b5..b31e0b5 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,8 +201,8 @@ class Serializer @Inject() (mailboxIdFactory: MailboxId.Factory) {
})
}
- implicit def mailboxWrites(propertiesToHide: Set[String]): Writes[Mailbox] = Json.writes[Mailbox]
- .transform((o: JsObject) => JsObject(o.fields.filterNot(entry => propertiesToHide.contains(entry._1))))
+ implicit def mailboxWrites(properties: Set[String]): Writes[Mailbox] = Json.writes[Mailbox]
+ .transform((o: JsObject) => JsObject(o.fields.filter(entry => properties.contains(entry._1))))
private implicit val idsRead: Reads[Ids] = Json.valueReads[Ids]
private implicit val propertiesRead: Reads[Properties] = Json.valueReads[Properties]
@@ -230,15 +230,8 @@ 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 def mailboxWritesWithFilteredProperties(properties: Option[Properties], capabilities: Set[CapabilityIdentifier]): Writes[Mailbox] = {
+ mailboxWrites(Mailbox.propertiesFiltered(properties, capabilities))
}
private implicit def jsErrorWrites: Writes[JsError] = Json.writes[JsError]
@@ -253,8 +246,8 @@ class Serializer @Inject() (mailboxIdFactory: MailboxId.Factory) {
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(mailboxGetResponse: MailboxGetResponse, properties: Option[Properties], capabilities: Set[CapabilityIdentifier]): JsValue = {
+ serialize(mailboxGetResponse)(mailboxWritesWithFilteredProperties(properties, capabilities))
}
def serialize(errors: JsError): JsValue = Json.toJson(errors)
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/Mailbox.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/Mailbox.scala
index 9f3cd6a..23782bb 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/Mailbox.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/Mailbox.scala
@@ -25,6 +25,8 @@ import eu.timepit.refined.auto._
import eu.timepit.refined.collection.NonEmpty
import org.apache.james.core.Username
import org.apache.james.jmap.mail.MailboxName.MailboxName
+import org.apache.james.jmap.model.CapabilityIdentifier
+import org.apache.james.jmap.model.CapabilityIdentifier.CapabilityIdentifier
import org.apache.james.jmap.model.UnsignedInt.UnsignedInt
import org.apache.james.mailbox.Role
import org.apache.james.mailbox.model.MailboxId
@@ -142,4 +144,25 @@ case class Mailbox(id: MailboxId,
def hasRole(role: Role): Boolean = this.role.contains(role)
val hasSystemRole: Boolean = role.exists(_.isSystemRole)
-}
\ No newline at end of file
+}
+
+object Mailbox {
+ def allProperties: Set[String] = Set("id", "name", "parentId", "role", "sortOrder", "totalEmails", "unreadEmails",
+ "totalThreads", "unreadThreads", "myRights", "isSubscribed", "namespace", "rights", "quotas")
+
+ def propertiesFiltered(requestedProperties: Option[Properties], allowedCapabilities : Set[CapabilityIdentifier]) : Set[String] = {
+ val propertiesForCapabilities: Map[CapabilityIdentifier, Set[String]] = Map(
+ CapabilityIdentifier.JAMES_QUOTA -> Set("quotas"),
+ CapabilityIdentifier.JAMES_SHARES -> Set("namespace", "rights")
+ )
+
+ val propertiesToHide = propertiesForCapabilities.filterNot(entry => allowedCapabilities.contains(entry._1))
+ .flatMap(_._2)
+ .toSet
+
+ requestedProperties match {
+ case None => allProperties -- propertiesToHide
+ case Some(requested) => (Set("id") ++ requested.value.map(_.toString()).toSet) -- propertiesToHide
+ }
+ }
+}
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 168b095..b48e7a6 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
@@ -66,7 +66,7 @@ class MailboxGetMethod @Inject() (serializer: Serializer,
notFound = mailboxes.notFound))
.map(mailboxGetResponse => Invocation(
methodName = methodName,
- arguments = Arguments(serializer.serialize(mailboxGetResponse, capabilities).as[JsObject]),
+ arguments = Arguments(serializer.serialize(mailboxGetResponse, mailboxGetRequest.properties, capabilities).as[JsObject]),
methodCallId = invocation.methodCallId))))
}
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 c2da125..aa22699 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,8 +42,6 @@ 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 {
@@ -207,7 +205,7 @@ class MailboxGetSerializationTest extends AnyWordSpec with Matchers {
|}
|""".stripMargin
- assertThatJson(Json.stringify(SERIALIZER.serialize(actualValue)(SERIALIZER.mailboxWrites(NO_PROPERTY_FILTERING)))).isEqualTo(expectedJson)
+ assertThatJson(Json.stringify(SERIALIZER.serialize(actualValue)(SERIALIZER.mailboxWrites(Mailbox.allProperties)))).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 99455a6..c3a6a1a 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
@@ -130,8 +130,7 @@ class MailboxSerializationTest extends AnyWordSpec with Matchers {
|}""".stripMargin
val serializer = new Serializer(new TestId.Factory)
- val noPropertyFiltering: Set[String] = Set.empty
- assertThatJson(Json.stringify(serializer.serialize(MAILBOX)(serializer.mailboxWrites(noPropertyFiltering)))).isEqualTo(expectedJson)
+ assertThatJson(Json.stringify(serializer.serialize(MAILBOX)(serializer.mailboxWrites(Mailbox.allProperties)))).isEqualTo(expectedJson)
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org