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 <[email protected]> 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: [email protected] For additional commands, e-mail: [email protected]
