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:31 UTC
[james-project] 10/16: JAMES-3171 Port MailboxFactory to
jmap-rfc8621
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 24482cc489fbeb65be1cf57de51dd63390fc4f14
Author: Rene Cordier <rc...@linagora.com>
AuthorDate: Thu May 21 10:18:20 2020 +0700
JAMES-3171 Port MailboxFactory to jmap-rfc8621
---
.../scala/org/apache/james/jmap/mail/Mailbox.scala | 48 ++++++--
.../apache/james/jmap/model/MailboxFactory.scala | 125 +++++++++++++++++++++
.../james/jmap/json/MailboxSerializationTest.scala | 2 +-
3 files changed, 162 insertions(+), 13 deletions(-)
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 aaff40e..fc03a7b 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
@@ -19,11 +19,12 @@
package org.apache.james.jmap.mail
+import eu.timepit.refined
import eu.timepit.refined.api.Refined
import eu.timepit.refined.auto._
import eu.timepit.refined.collection.NonEmpty
import org.apache.james.core.Username
-import org.apache.james.jmap.mail.Mailbox.MailboxName
+import org.apache.james.jmap.mail.MailboxName.MailboxName
import org.apache.james.jmap.model.UnsignedInt.UnsignedInt
import org.apache.james.mailbox.Role
import org.apache.james.mailbox.model.MailboxId
@@ -38,15 +39,29 @@ case class MayRename(value: Boolean) extends AnyVal
case class MayDelete(value: Boolean) extends AnyVal
case class MaySubmit(value: Boolean) extends AnyVal
+object MailboxRights {
+ val FULL: MailboxRights = MailboxRights(
+ mayReadItems = MayReadItems(true),
+ mayAddItems = MayAddItems(true),
+ mayRemoveItems = MayRemoveItems(true),
+ maySetSeen = MaySetSeen(true),
+ maySetKeywords = MaySetKeywords(true),
+ mayCreateChild = MayCreateChild(true),
+ mayRename = MayRename(true),
+ mayDelete = MayDelete(true),
+ maySubmit = MaySubmit(true),
+ )
+}
+
case class MailboxRights(mayReadItems: MayReadItems,
- mayAddItems: MayAddItems,
- mayRemoveItems: MayRemoveItems,
- maySetSeen: MaySetSeen,
- maySetKeywords: MaySetKeywords,
- mayCreateChild: MayCreateChild,
- mayRename: MayRename,
- mayDelete: MayDelete,
- maySubmit: MaySubmit)
+ mayAddItems: MayAddItems,
+ mayRemoveItems: MayRemoveItems,
+ maySetSeen: MaySetSeen,
+ maySetKeywords: MaySetKeywords,
+ mayCreateChild: MayCreateChild,
+ mayRename: MayRename,
+ mayDelete: MayDelete,
+ maySubmit: MaySubmit)
object MailboxNamespace {
def delegated(owner: Username) = DelegatedNamespace(owner)
@@ -61,6 +76,8 @@ case class PersonalNamespace() extends MailboxNamespace
case class DelegatedNamespace(owner: Username) extends MailboxNamespace
object SortOrder {
+ val defaultSortOrder: SortOrder = SortOrder(1000L)
+
private val defaultSortOrders = Map(
Role.INBOX -> SortOrder(10L),
Role.ARCHIVE -> SortOrder(20L),
@@ -71,7 +88,7 @@ object SortOrder {
Role.SPAM -> SortOrder(70L),
Role.TEMPLATES -> SortOrder(80L),
Role.RESTORED_MESSAGES -> SortOrder(90L))
- .withDefaultValue(SortOrder(1000L))
+ .withDefaultValue(defaultSortOrder)
def getSortOrder(role: Role): SortOrder = defaultSortOrders(role)
}
@@ -97,8 +114,15 @@ sealed trait QuotasExtension extends MailboxExtensionAdditionalFields {
def quotas: Quotas
}
-object Mailbox {
- type MailboxName = String Refined NonEmpty
+object MailboxName {
+ type MailboxNameConstraint = NonEmpty
+ type MailboxName = String Refined MailboxNameConstraint
+
+ def liftOrThrow(value: String): MailboxName =
+ refined.refineV[MailboxNameConstraint](value) match {
+ case scala.util.Right(value) => value
+ case Left(error) => throw new IllegalArgumentException(error)
+ }
}
case class Mailbox(id: MailboxId,
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/model/MailboxFactory.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/model/MailboxFactory.scala
new file mode 100644
index 0000000..caf9046
--- /dev/null
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/model/MailboxFactory.scala
@@ -0,0 +1,125 @@
+/****************************************************************
+ * 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.model
+
+import javax.inject.Inject
+import org.apache.james.jmap.mail.MailboxName.MailboxName
+import org.apache.james.jmap.mail._
+import org.apache.james.jmap.utils.quotas.QuotaLoader
+import org.apache.james.mailbox.model.MailboxACL.EntryKey
+import org.apache.james.mailbox.model.{MailboxCounters, MailboxId, MailboxMetaData, MailboxPath, MailboxACL => JavaMailboxACL}
+import org.apache.james.mailbox.{MailboxSession, Role, SubscriptionManager}
+import reactor.core.scala.publisher.SMono
+
+import scala.jdk.CollectionConverters._
+import scala.jdk.OptionConverters._
+
+sealed trait MailboxConstructionOrder
+
+class Factory
+
+class MailboxFactory @Inject() (subscriptionManager: SubscriptionManager) {
+
+ def create(mailboxMetaData: MailboxMetaData,
+ mailboxSession: MailboxSession,
+ allMailboxesMetadata: Seq[MailboxMetaData],
+ quotaLoader: QuotaLoader): SMono[Mailbox] = {
+
+ val id: MailboxId = mailboxMetaData.getId
+
+ val name: MailboxName = MailboxName.liftOrThrow(mailboxMetaData.getPath
+ .getName
+ .split(mailboxSession.getPathDelimiter)
+ .last)
+
+ val role: Option[Role] = Role.from(mailboxMetaData.getPath.getName)
+ .filter(_ => mailboxMetaData.getPath.belongsTo(mailboxSession)).toScala
+ val sortOrder: SortOrder = role.map(SortOrder.getSortOrder).getOrElse(SortOrder.defaultSortOrder)
+ val quotas: SMono[Quotas] = quotaLoader.getQuotas(mailboxMetaData.getPath)
+ val rights: Rights = Rights.fromACL(MailboxACL.fromJava(mailboxMetaData.getResolvedAcls))
+
+ val sanitizedCounters: MailboxCounters = mailboxMetaData.getCounters.sanitize()
+ val unreadEmails: UnreadEmails = UnreadEmails(UnsignedInt.liftOrThrow(sanitizedCounters.getUnseen))
+ val unreadThreads: UnreadThreads = UnreadThreads(UnsignedInt.liftOrThrow(sanitizedCounters.getUnseen))
+ val totalEmails: TotalEmails = TotalEmails(UnsignedInt.liftOrThrow(sanitizedCounters.getCount))
+ val totalThreads: TotalThreads = TotalThreads(UnsignedInt.liftOrThrow(sanitizedCounters.getCount))
+
+ val isOwner = mailboxMetaData.getPath.belongsTo(mailboxSession)
+ val aclEntryKey: EntryKey = EntryKey.createUserEntryKey(mailboxSession.getUser)
+
+ val namespace: MailboxNamespace = if (isOwner) {
+ PersonalNamespace()
+ } else {
+ DelegatedNamespace(mailboxMetaData.getPath.getUser)
+ }
+
+ val parentPath: Option[MailboxPath] =
+ mailboxMetaData.getPath
+ .getHierarchyLevels(mailboxSession.getPathDelimiter)
+ .asScala
+ .reverse
+ .drop(1)
+ .headOption
+
+ val parentId: Option[MailboxId] = allMailboxesMetadata.filter(otherMetadata => parentPath.contains(otherMetadata.getPath))
+ .map(_.getId)
+ .headOption
+
+ val myRights: MailboxRights = if (isOwner) {
+ MailboxRights.FULL
+ } else {
+ val rights = Rfc4314Rights.fromJava(mailboxMetaData.getResolvedAcls
+ .getEntries
+ .getOrDefault(aclEntryKey, JavaMailboxACL.NO_RIGHTS))
+ .toRights
+ MailboxRights(
+ mayReadItems = MayReadItems(rights.contains(Right.Read)),
+ mayAddItems = MayAddItems(rights.contains(Right.Insert)),
+ mayRemoveItems = MayRemoveItems(rights.contains(Right.DeleteMessages)),
+ maySetSeen = MaySetSeen(rights.contains(Right.Seen)),
+ maySetKeywords = MaySetKeywords(rights.contains(Right.Write)),
+ mayCreateChild = MayCreateChild(false),
+ mayRename = MayRename(false),
+ mayDelete = MayDelete(false),
+ maySubmit = MaySubmit(false))
+ }
+
+ def retrieveIsSubscribed: IsSubscribed = IsSubscribed(subscriptionManager
+ .subscriptions(mailboxSession)
+ .contains(mailboxMetaData.getPath.getName))
+
+ SMono.fromPublisher(quotas)
+ .map(quotas => Mailbox(
+ id = id,
+ name = name,
+ parentId = parentId,
+ role = role,
+ sortOrder = sortOrder,
+ unreadEmails = unreadEmails,
+ totalEmails = totalEmails,
+ unreadThreads = unreadThreads,
+ totalThreads = totalThreads,
+ myRights = myRights,
+ namespace = namespace,
+ rights = rights,
+ quotas = quotas,
+ isSubscribed = retrieveIsSubscribed))
+ }
+}
\ No newline at end of file
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 940d29a..c5b49d8 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
@@ -23,7 +23,7 @@ import eu.timepit.refined.auto._
import net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson
import org.apache.james.core.{Domain, Username}
import org.apache.james.jmap.json.MailboxSerializationTest.MAILBOX
-import org.apache.james.jmap.mail.Mailbox.MailboxName
+import org.apache.james.jmap.mail.MailboxName.MailboxName
import org.apache.james.jmap.mail.{IsSubscribed, Mailbox, MailboxNamespace, MailboxRights, MayAddItems, MayCreateChild, MayDelete, MayReadItems, MayRemoveItems, MayRename, MaySetKeywords, MaySetSeen, MaySubmit, PersonalNamespace, Quota, QuotaId, QuotaRoot, Quotas, Right, Rights, SortOrder, TotalEmails, TotalThreads, UnreadEmails, UnreadThreads, Value}
import org.apache.james.mailbox.Role
import org.apache.james.mailbox.model.{MailboxId, TestId}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org