You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by bt...@apache.org on 2021/02/09 04:29:54 UTC

[james-project] 26/33: JAMES-3491 Enabling push should not reject unhandled data types

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 ebc6e0e3aa62c210b5bd00c1a3711c9ef3495081
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Fri Feb 5 12:09:18 2021 +0700

    JAMES-3491 Enabling push should not reject unhandled data types
    
    Rejection of specified data types we do not yet send notifications for would cause a breaking behaviours in clients registrating them.
---
 .../jmap/rfc8621/contract/WebSocketContract.scala  | 70 ++++++++++++++++++++++
 .../org/apache/james/jmap/change/StateChange.scala | 17 +++++-
 .../james/jmap/json/ResponseSerializer.scala       |  7 ++-
 3 files changed, 92 insertions(+), 2 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/WebSocketContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/WebSocketContract.scala
index 750c12f..5fd55a0 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/WebSocketContract.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/WebSocketContract.scala
@@ -502,6 +502,76 @@ trait WebSocketContract {
   }
 
   @Test
+  // For client compatibility purposes
+  def specifiedUnHandledDataTypesShouldNotBeRejected(server: GuiceJamesServer): Unit = {
+    val bobPath = MailboxPath.inbox(BOB)
+    val accountId: AccountId = AccountId.fromUsername(BOB)
+    val mailboxId = server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath)
+
+    Thread.sleep(100)
+
+    val response: Either[String, List[String]] =
+      authenticatedRequest(server)
+        .response(asWebSocket[Identity, List[String]] {
+          ws =>
+            ws.send(WebSocketFrame.text(
+              """{
+                |  "@type": "WebSocketPushEnable",
+                |  "dataTypes": ["Mailbox", "Email", "VacationResponse", "Thread", "Identity", "EmailSubmission", "EmailDelivery"]
+                |}""".stripMargin))
+
+            Thread.sleep(100)
+
+            ws.send(WebSocketFrame.text(
+              s"""{
+                 |  "@type": "Request",
+                 |  "requestId": "req-36",
+                 |  "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"],
+                 |  "methodCalls": [
+                 |    ["Email/set", {
+                 |      "accountId": "$ACCOUNT_ID",
+                 |      "create": {
+                 |        "aaaaaa":{
+                 |          "mailboxIds": {
+                 |             "${mailboxId.serialize}": true
+                 |          }
+                 |        }
+                 |      }
+                 |    }, "c1"]]
+                 |}""".stripMargin))
+
+            List(
+              ws.receive()
+                .map { case t: Text =>
+                  t.payload
+                },
+              ws.receive()
+                .map { case t: Text =>
+                  t.payload
+                },
+              ws.receive()
+                .map { case t: Text =>
+                  t.payload
+                })
+        })
+        .send(backend)
+        .body
+
+    Thread.sleep(100)
+
+    val jmapGuiceProbe: JmapGuiceProbe = server.getProbe(classOf[JmapGuiceProbe])
+    val emailState: String = jmapGuiceProbe.getLatestEmailState(accountId).getValue.toString
+    val mailboxState: String = jmapGuiceProbe.getLatestMailboxState(accountId).getValue.toString
+
+    val mailboxStateChange: String = s"""{"@type":"StateChange","changed":{"$ACCOUNT_ID":{"Mailbox":"$mailboxState"}}}"""
+    val emailStateChange: String = s"""{"@type":"StateChange","changed":{"$ACCOUNT_ID":{"Email":"$emailState"}}}"""
+
+    assertThat(response.toOption.get.asJava)
+      .hasSize(3) // email notification + mailbox notification + API response
+      .contains(mailboxStateChange, emailStateChange)
+  }
+
+  @Test
   def dataTypesShouldDefaultToAll(server: GuiceJamesServer): Unit = {
     val bobPath = MailboxPath.inbox(BOB)
     val accountId: AccountId = AccountId.fromUsername(BOB)
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/change/StateChange.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/change/StateChange.scala
index 73ab7e2..faffe49 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/change/StateChange.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/change/StateChange.scala
@@ -25,7 +25,7 @@ import org.apache.james.events.Event.EventId
 import org.apache.james.jmap.core.{AccountId, State, StateChange}
 
 object TypeName {
-  val ALL: Set[TypeName] = Set(EmailTypeName, MailboxTypeName)
+  val ALL: Set[TypeName] = Set(EmailTypeName, MailboxTypeName, ThreadTypeName, IdentityTypeName, EmailSubmissionTypeName, EmailDeliveryTypeName)
 }
 
 sealed trait TypeName {
@@ -41,6 +41,21 @@ case object MailboxTypeName extends TypeName {
 case object EmailTypeName extends TypeName {
   override val asString: String = "Email"
 }
+case object ThreadTypeName extends TypeName {
+  override val asString: String = "Thread"
+}
+case object IdentityTypeName extends TypeName {
+  override val asString: String = "Identity"
+}
+case object EmailSubmissionTypeName extends TypeName {
+  override val asString: String = "EmailSubmission"
+}
+case object EmailDeliveryTypeName extends TypeName {
+  override val asString: String = "EmailDelivery"
+}
+case object VacationResponseTypeName extends TypeName {
+  override val asString: String = "VacationResponse"
+}
 
 case class TypeState(changes: Map[TypeName, State]) {
 
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/ResponseSerializer.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/ResponseSerializer.scala
index b1454c6..042d4d8 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/ResponseSerializer.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/ResponseSerializer.scala
@@ -25,7 +25,7 @@ import java.net.URL
 import eu.timepit.refined.refineV
 import io.netty.handler.codec.http.HttpResponseStatus
 import org.apache.james.core.Username
-import org.apache.james.jmap.change.{EmailTypeName, MailboxTypeName, TypeName, TypeState}
+import org.apache.james.jmap.change.{EmailDeliveryTypeName, EmailSubmissionTypeName, EmailTypeName, IdentityTypeName, MailboxTypeName, ThreadTypeName, TypeName, TypeState, VacationResponseTypeName}
 import org.apache.james.jmap.core
 import org.apache.james.jmap.core.CapabilityIdentifier.CapabilityIdentifier
 import org.apache.james.jmap.core.Id.IdConstraint
@@ -189,6 +189,11 @@ object ResponseSerializer {
   private implicit val typeNameReads: Reads[TypeName] = {
     case JsString(MailboxTypeName.asString) => JsSuccess(MailboxTypeName)
     case JsString(EmailTypeName.asString) => JsSuccess(EmailTypeName)
+    case JsString(ThreadTypeName.asString) => JsSuccess(ThreadTypeName)
+    case JsString(IdentityTypeName.asString) => JsSuccess(IdentityTypeName)
+    case JsString(EmailSubmissionTypeName.asString) => JsSuccess(EmailSubmissionTypeName)
+    case JsString(EmailDeliveryTypeName.asString) => JsSuccess(EmailDeliveryTypeName)
+    case JsString(VacationResponseTypeName.asString) => JsSuccess(VacationResponseTypeName)
     case _ => JsError("Expecting a JsString as typeName")
   }
   private implicit val webSocketPushEnableReads: Reads[WebSocketPushEnable] = Json.reads[WebSocketPushEnable]


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