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