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/06/08 03:12:33 UTC

[james-project] 12/16: JAMES-3171 Mailbox/get all implementation

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 d307d391ed2b32c5485749006ee72da08923f78e
Author: Rene Cordier <rc...@linagora.com>
AuthorDate: Fri May 22 16:47:09 2020 +0700

    JAMES-3171 Mailbox/get all implementation
---
 .../james/jmap/rfc8621/RFC8621MethodsModule.java   |  2 +
 .../org/apache/james/jmap/json/Serializer.scala    |  4 +
 .../james/jmap/method/MailboxGetMethod.scala       | 89 ++++++++++++++++++++++
 .../org/apache/james/jmap/model/Session.scala      |  2 +-
 .../apache/james/jmap/routes/JMAPApiRoutes.scala   |  3 +-
 5 files changed, 97 insertions(+), 3 deletions(-)

diff --git a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/rfc8621/RFC8621MethodsModule.java b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/rfc8621/RFC8621MethodsModule.java
index 8d855de..5cd2117 100644
--- a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/rfc8621/RFC8621MethodsModule.java
+++ b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/rfc8621/RFC8621MethodsModule.java
@@ -28,6 +28,7 @@ import org.apache.james.jmap.http.rfc8621.InjectionKeys;
 import org.apache.james.jmap.json.Serializer;
 import org.apache.james.jmap.jwt.JWTAuthenticationStrategy;
 import org.apache.james.jmap.method.CoreEchoMethod;
+import org.apache.james.jmap.method.MailboxGetMethod;
 import org.apache.james.jmap.method.Method;
 import org.apache.james.jmap.routes.JMAPApiRoutes;
 import org.apache.james.metrics.api.MetricFactory;
@@ -48,6 +49,7 @@ public class RFC8621MethodsModule extends AbstractModule {
 
         Multibinder<Method> methods = Multibinder.newSetBinder(binder(), Method.class);
         methods.addBinding().to(CoreEchoMethod.class);
+        methods.addBinding().to(MailboxGetMethod.class);
     }
 
     @ProvidesIntoSet
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 7e24a1a..6d374ed 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
@@ -244,4 +244,8 @@ class Serializer @Inject() (mailboxIdFactory: MailboxId.Factory) {
   def deserializeMailboxGetRequest(input: String): JsResult[MailboxGetRequest] = {
     Json.parse(input).validate[MailboxGetRequest]
   }
+
+  def deserializeMailboxGetRequest(input: JsValue): JsResult[MailboxGetRequest] = {
+    Json.fromJson[MailboxGetRequest](input)
+  }
 }
\ 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
new file mode 100644
index 0000000..ca9f2e7
--- /dev/null
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxGetMethod.scala
@@ -0,0 +1,89 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.jmap.method
+
+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.Invocation.{Arguments, MethodName}
+import org.apache.james.jmap.model.State.INSTANCE
+import org.apache.james.jmap.model.{Invocation, MailboxFactory}
+import org.apache.james.jmap.utils.quotas.QuotaLoaderWithPreloadedDefaultFactory
+import org.apache.james.mailbox.model.MailboxMetaData
+import org.apache.james.mailbox.model.search.MailboxQuery
+import org.apache.james.mailbox.{MailboxManager, MailboxSession}
+import org.reactivestreams.Publisher
+import play.api.libs.json.{JsError, JsObject, JsSuccess, Json}
+import reactor.core.scala.publisher.{SFlux, SMono}
+import reactor.core.scheduler.Schedulers
+
+class MailboxGetMethod @Inject() (serializer: Serializer,
+                                  mailboxManager: MailboxManager,
+                                  quotaFactory : QuotaLoaderWithPreloadedDefaultFactory,
+                                  mailboxFactory: MailboxFactory) extends Method {
+  override val methodName: MethodName = MethodName("Mailbox/get")
+
+  override def process(invocation: Invocation, mailboxSession: MailboxSession): Publisher[Invocation] = {
+    asMailboxGetRequest(invocation.arguments)
+        .flatMap(mailboxGetRequest => getMailboxes(mailboxGetRequest, mailboxSession)
+          .collectSeq()
+          .map(_.sortBy(_.sortOrder))
+          .map(mailboxes => MailboxGetResponse(
+            accountId = mailboxGetRequest.accountId,
+            state = INSTANCE,
+            list = mailboxes.toList,
+            notFound = NotFound(Nil)))
+          .map(mailboxGetResponse => Invocation(
+            methodName = methodName,
+            arguments = Arguments(serializer.serialize(mailboxGetResponse).as[JsObject]),
+            methodCallId = invocation.methodCallId)))
+  }
+
+  private def asMailboxGetRequest(arguments: Arguments): SMono[MailboxGetRequest] = {
+    serializer.deserializeMailboxGetRequest(arguments.value) match {
+      case JsSuccess(mailboxGetRequest, _) => SMono.just(mailboxGetRequest)
+      case JsError(errors) => SMono.raiseError(new IllegalArgumentException("Invalid MailboxGetRequest")) //FIXME MOB
+    }
+  }
+
+  private def getMailboxes(mailboxGetRequest: MailboxGetRequest, mailboxSession: MailboxSession): SFlux[Mailbox] = mailboxGetRequest.ids match {
+    case None => getAllMailboxes(mailboxSession)
+    case _ => SFlux.raiseError(new NotImplementedError("Getting mailboxes by Ids is not supported yet"))
+  }
+
+  private def getAllMailboxes(mailboxSession: MailboxSession): SFlux[Mailbox] = {
+    quotaFactory.loadFor(mailboxSession)
+      .subscribeOn(Schedulers.elastic)
+      .flatMapMany(quotaLoader =>
+        getAllMailboxesMetaData(mailboxSession).flatMapMany(mailboxesMetaData =>
+          SFlux.fromIterable(mailboxesMetaData)
+            .flatMap(mailboxMetaData =>
+              mailboxFactory.create(
+                mailboxMetaData = mailboxMetaData,
+                mailboxSession = mailboxSession,
+                allMailboxesMetadata = mailboxesMetaData,
+                quotaLoader = quotaLoader))))
+  }
+
+  private def getAllMailboxesMetaData(mailboxSession: MailboxSession): SMono[Seq[MailboxMetaData]] =
+    SFlux.fromPublisher(mailboxManager.searchReactive(MailboxQuery.builder.matchesAllMailboxNames.build, mailboxSession))
+      .collectSeq()
+}
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/model/Session.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/model/Session.scala
index 1b09946..fb53ae3 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/model/Session.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/model/Session.scala
@@ -75,7 +75,7 @@ final case class Account private(accountId: AccountId,
                                  accountCapabilities: Set[_ <: Capability])
 
 object State {
-  private[model] val INSTANCE: State = "000001"
+  val INSTANCE: State = "000001"
 
   type State = String Refined NonEmpty
 }
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 478cdcc..dc918c6 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
@@ -47,7 +47,6 @@ import reactor.core.scala.publisher.{SFlux, SMono}
 import reactor.core.scheduler.Schedulers
 import reactor.netty.http.server.{HttpServerRequest, HttpServerResponse}
 
-import scala.collection.mutable
 import scala.jdk.CollectionConverters._
 
 object JMAPApiRoutes {
@@ -130,7 +129,7 @@ class JMAPApiRoutes (val authenticator: Authenticator,
     case exception: IllegalArgumentException => SMono.fromPublisher(httpServerResponse.status(SC_BAD_REQUEST)
       .header(CONTENT_TYPE, JSON_CONTENT_TYPE)
       .sendString(SMono.fromCallable(() => exception.getMessage), StandardCharsets.UTF_8)
-      .`then`())
+      .`then`)
     case exception: UnauthorizedException => SMono(handleAuthenticationFailure(httpServerResponse, JMAPApiRoutes.LOGGER, exception))
     case _ => SMono.fromPublisher(handleInternalError(httpServerResponse, throwable))
   }


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