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


The following commit(s) were added to refs/heads/master by this push:
     new fcc8181eb4 [JMAP] - Fix - The `Mailbox/set` method for shared 
mailboxes must require share capability (#2647)
fcc8181eb4 is described below

commit fcc8181eb4f4d441f7f798cefc46c373aedf3a8c
Author: vttran <vtt...@linagora.com>
AuthorDate: Mon Feb 24 20:04:54 2025 +0700

    [JMAP] - Fix - The `Mailbox/set` method for shared mailboxes must require 
share capability (#2647)
---
 .../contract/MailboxSetMethodContract.scala        | 18 ++--
 .../jmap/method/MailboxSetCreatePerformer.scala    | 36 ++++----
 .../jmap/method/MailboxSetDeletePerformer.scala    | 17 ++--
 .../james/jmap/method/MailboxSetMethod.scala       | 15 +++-
 .../jmap/method/MailboxSetUpdatePerformer.scala    | 95 ++++++++++++----------
 5 files changed, 104 insertions(+), 77 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/MailboxSetMethodContract.scala
 
b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxSetMethodContract.scala
index 2e92c93fd1..735e509507 100644
--- 
a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxSetMethodContract.scala
+++ 
b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxSetMethodContract.scala
@@ -2122,7 +2122,7 @@ trait MailboxSetMethodContract {
     val request =
       s"""
         |{
-        |   "using": [ "urn:ietf:params:jmap:core", 
"urn:ietf:params:jmap:mail" ],
+        |   "using": [ "urn:ietf:params:jmap:core", 
"urn:ietf:params:jmap:mail", "urn:apache:james:params:jmap:mail:shares" ],
         |   "methodCalls": [
         |       [
         |           "Mailbox/set",
@@ -2185,7 +2185,7 @@ trait MailboxSetMethodContract {
     val request =
       s"""
         |{
-        |   "using": [ "urn:ietf:params:jmap:core", 
"urn:ietf:params:jmap:mail" ],
+        |   "using": [ "urn:ietf:params:jmap:core", 
"urn:ietf:params:jmap:mail", "urn:apache:james:params:jmap:mail:shares" ],
         |   "methodCalls": [
         |       [
         |           "Mailbox/set",
@@ -2643,7 +2643,7 @@ trait MailboxSetMethodContract {
     val request =
       s"""
         |{
-        |   "using": [ "urn:ietf:params:jmap:core", 
"urn:ietf:params:jmap:mail" ],
+        |   "using": [ "urn:ietf:params:jmap:core", 
"urn:ietf:params:jmap:mail", "urn:apache:james:params:jmap:mail:shares" ],
         |   "methodCalls": [
         |       [
         |           "Mailbox/set",
@@ -2691,7 +2691,7 @@ trait MailboxSetMethodContract {
   }
 
   @Test
-  def deleteShouldSuccessWhenHasRight(server: GuiceJamesServer): Unit = {
+  def deleteSharedMailboxShouldSuccessWhenHasRight(server: GuiceJamesServer): 
Unit = {
     val path = MailboxPath.forUser(ANDRE, "mailbox")
     val mailboxId: MailboxId = 
server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path)
     server.getProbe(classOf[ACLProbeImpl])
@@ -2700,7 +2700,7 @@ trait MailboxSetMethodContract {
     val request =
       s"""
          |{
-         |   "using": [ "urn:ietf:params:jmap:core", 
"urn:ietf:params:jmap:mail" ],
+         |   "using": [ "urn:ietf:params:jmap:core", 
"urn:ietf:params:jmap:mail", "urn:apache:james:params:jmap:mail:shares" ],
          |   "methodCalls": [
          |       [
          |           "Mailbox/set",
@@ -3791,7 +3791,7 @@ trait MailboxSetMethodContract {
     val request =
       s"""
         |{
-        |   "using": [ "urn:ietf:params:jmap:core", 
"urn:ietf:params:jmap:mail" ],
+        |   "using": [ "urn:ietf:params:jmap:core", 
"urn:ietf:params:jmap:mail", "urn:apache:james:params:jmap:mail:shares" ],
         |   "methodCalls": [
         |       ["Mailbox/set",
         |           {
@@ -8121,7 +8121,7 @@ trait MailboxSetMethodContract {
 
     val request = s"""
         |{
-        |   "using": [ "urn:ietf:params:jmap:core", 
"urn:ietf:params:jmap:mail" ],
+        |   "using": [ "urn:ietf:params:jmap:core", 
"urn:ietf:params:jmap:mail", "urn:apache:james:params:jmap:mail:shares" ],
         |   "methodCalls": [
         |       [
         |           "Mailbox/set",
@@ -8184,7 +8184,7 @@ trait MailboxSetMethodContract {
 
     val request = s"""
         |{
-        |   "using": [ "urn:ietf:params:jmap:core", 
"urn:ietf:params:jmap:mail" ],
+        |   "using": [ "urn:ietf:params:jmap:core", 
"urn:ietf:params:jmap:mail", "urn:apache:james:params:jmap:mail:shares" ],
         |   "methodCalls": [
         |       [
         |           "Mailbox/set",
@@ -8247,7 +8247,7 @@ trait MailboxSetMethodContract {
 
     val request = s"""
         |{
-        |   "using": [ "urn:ietf:params:jmap:core", 
"urn:ietf:params:jmap:mail" ],
+        |   "using": [ "urn:ietf:params:jmap:core", 
"urn:ietf:params:jmap:mail", "urn:apache:james:params:jmap:mail:shares" ],
         |   "methodCalls": [
         |       [
         |           "Mailbox/set",
diff --git 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetCreatePerformer.scala
 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetCreatePerformer.scala
index a44db74a71..b12554d2a5 100644
--- 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetCreatePerformer.scala
+++ 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetCreatePerformer.scala
@@ -93,30 +93,29 @@ class MailboxSetCreatePerformer @Inject()(serializer: 
MailboxSerializer,
                                           val metricFactory: MetricFactory,
                                           val sessionSupplier: 
SessionSupplier) {
 
-
-
   def createMailboxes(mailboxSession: MailboxSession,
-                              mailboxSetRequest: MailboxSetRequest,
-                              processingContext: ProcessingContext): 
SMono[(MailboxCreationResults, ProcessingContext)] = {
+                      mailboxSetRequest: MailboxSetRequest,
+                      processingContext: ProcessingContext,
+                      supportSharedMailbox: Boolean): 
SMono[(MailboxCreationResults, ProcessingContext)] =
     SFlux.fromIterable(mailboxSetRequest.create
-      .getOrElse(Map.empty)
-      .view)
-      .fold((MailboxCreationResults(Nil), processingContext)){
-        (acc : (MailboxCreationResults, ProcessingContext), elem: 
(MailboxCreationId, JsObject)) => {
+        .getOrElse(Map.empty)
+        .view)
+      .fold((MailboxCreationResults(Nil), processingContext)) {
+        (acc: (MailboxCreationResults, ProcessingContext), elem: 
(MailboxCreationId, JsObject)) => {
           val (mailboxCreationId, jsObject) = elem
-          val (creationResult, updatedProcessingContext) = 
createMailbox(mailboxSession, mailboxCreationId, jsObject, acc._2)
+          val (creationResult, updatedProcessingContext) = 
createMailbox(mailboxSession, mailboxCreationId, jsObject, acc._2, 
supportSharedMailbox)
           (MailboxCreationResults(acc._1.created :+ creationResult), 
updatedProcessingContext)
         }
       }
       .subscribeOn(ReactorUtils.BLOCKING_CALL_WRAPPER)
-  }
 
   private def createMailbox(mailboxSession: MailboxSession,
                             mailboxCreationId: MailboxCreationId,
                             jsObject: JsObject,
-                            processingContext: ProcessingContext): 
(MailboxCreationResult, ProcessingContext) = {
+                            processingContext: ProcessingContext,
+                            supportSharedMailbox: Boolean): 
(MailboxCreationResult, ProcessingContext) = {
     parseCreate(jsObject)
-      .flatMap(mailboxCreationRequest => resolvePath(mailboxSession, 
mailboxCreationRequest)
+      .flatMap(mailboxCreationRequest => resolvePath(mailboxSession, 
mailboxCreationRequest, supportSharedMailbox)
         .flatMap(path => createMailbox(mailboxSession = mailboxSession,
           path = path,
           mailboxCreationRequest = mailboxCreationRequest)))
@@ -136,7 +135,8 @@ class MailboxSetCreatePerformer @Inject()(serializer: 
MailboxSerializer,
       })
 
   private def resolvePath(mailboxSession: MailboxSession,
-                          mailboxCreationRequest: MailboxCreationRequest): 
Either[Exception, MailboxPath] = {
+                          mailboxCreationRequest: MailboxCreationRequest,
+                          supportSharedMailbox: Boolean): Either[Exception, 
MailboxPath] = {
     if 
(mailboxCreationRequest.name.value.contains(mailboxSession.getPathDelimiter)) {
       return Left(new MailboxNameException(s"The mailbox 
'${mailboxCreationRequest.name.value}' contains an illegal character: 
'${mailboxSession.getPathDelimiter}'"))
     }
@@ -146,7 +146,8 @@ class MailboxSetCreatePerformer @Inject()(serializer: 
MailboxSerializer,
           .toEither
           .left
           .map(e => new IllegalArgumentException(e.getMessage, e))
-        parentPath <- retrievePath(parentId, mailboxSession)
+        parentPathPreAssert <- retrievePath(parentId, mailboxSession)
+        parentPath <- validateCapabilityIfSharedMailbox(mailboxSession, 
parentId, supportSharedMailbox).apply(parentPathPreAssert)
       } yield {
         parentPath.child(mailboxCreationRequest.name, 
mailboxSession.getPathDelimiter)
       })
@@ -159,6 +160,13 @@ class MailboxSetCreatePerformer @Inject()(serializer: 
MailboxSerializer,
     case e: Exception => Left(e)
   }
 
+  private def validateCapabilityIfSharedMailbox(mailboxSession: 
MailboxSession, id: MailboxId, supportSharedMailbox: Boolean): MailboxPath => 
Either[Exception, MailboxPath] =
+    mailboxPath => if (!mailboxPath.belongsTo(mailboxSession) && 
!supportSharedMailbox) {
+      Left(new MailboxNotFoundException(id))
+    } else {
+      Right(mailboxPath)
+    }
+
   private def recordCreationIdInProcessingContext(mailboxCreationId: 
MailboxCreationId,
                                                   processingContext: 
ProcessingContext,
                                                   mailboxId: MailboxId): 
Either[IllegalArgumentException, ProcessingContext] =
diff --git 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetDeletePerformer.scala
 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetDeletePerformer.scala
index acf75a7b90..692fae435f 100644
--- 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetDeletePerformer.scala
+++ 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetDeletePerformer.scala
@@ -26,6 +26,7 @@ import org.apache.james.jmap.core.SetError
 import org.apache.james.jmap.core.SetError.SetErrorDescription
 import org.apache.james.jmap.mail.{MailboxGet, MailboxSetError, 
MailboxSetRequest, RemoveEmailsOnDestroy, UnparsedMailboxId}
 import 
org.apache.james.jmap.method.MailboxSetDeletePerformer.{MailboxDeletionFailure, 
MailboxDeletionResult, MailboxDeletionResults, MailboxDeletionSuccess}
+import 
org.apache.james.jmap.method.MailboxSetMethod.assertCapabilityIfSharedMailbox
 import org.apache.james.mailbox.exception.{InsufficientRightsException, 
MailboxNotFoundException}
 import org.apache.james.mailbox.model.{FetchGroup, MailboxId, MessageRange}
 import org.apache.james.mailbox.{MailboxManager, MailboxSession, 
MessageManager, Role, SubscriptionManager}
@@ -85,24 +86,25 @@ class MailboxSetDeletePerformer @Inject()(mailboxManager: 
MailboxManager,
                                           subscriptionManager: 
SubscriptionManager,
                                           mailboxIdFactory: MailboxId.Factory) 
{
 
-  def deleteMailboxes(mailboxSession: MailboxSession, mailboxSetRequest: 
MailboxSetRequest): SMono[MailboxDeletionResults] =
+  def deleteMailboxes(mailboxSession: MailboxSession, mailboxSetRequest: 
MailboxSetRequest, supportSharedMailbox: Boolean): 
SMono[MailboxDeletionResults] =
     SFlux.fromIterable(mailboxSetRequest.destroy.getOrElse(Seq()).toSet)
-      .flatMap(id => delete(mailboxSession, id, 
mailboxSetRequest.onDestroyRemoveEmails.getOrElse(RemoveEmailsOnDestroy(false)))
+      .flatMap(id => delete(mailboxSession, id, 
mailboxSetRequest.onDestroyRemoveEmails.getOrElse(RemoveEmailsOnDestroy(false)),
 supportSharedMailbox)
         .onErrorRecover(e => MailboxDeletionFailure(id, e)),
         maxConcurrency = 5)
       .collectSeq()
       .map(MailboxDeletionResults)
       .doOnSuccess(auditTrail(mailboxSession, _))
 
-  private def delete(mailboxSession: MailboxSession, id: UnparsedMailboxId, 
onDestroy: RemoveEmailsOnDestroy): SMono[MailboxDeletionResult] =
+  private def delete(mailboxSession: MailboxSession, id: UnparsedMailboxId, 
onDestroy: RemoveEmailsOnDestroy, supportSharedMailbox: Boolean): 
SMono[MailboxDeletionResult] =
     MailboxGet.parse(mailboxIdFactory)(id)
       .fold(e => SMono.error(e),
-        id => doDelete(mailboxSession, id, onDestroy)
+        id => doDelete(mailboxSession, id, onDestroy, supportSharedMailbox)
           
.`then`(SMono.just[MailboxDeletionResult](MailboxDeletionSuccess(id))))
 
-  private def doDelete(mailboxSession: MailboxSession, id: MailboxId, 
onDestroy: RemoveEmailsOnDestroy): SMono[Unit] =
+  private def doDelete(mailboxSession: MailboxSession, id: MailboxId, 
onDestroy: RemoveEmailsOnDestroy, supportSharedMailbox: Boolean): SMono[Unit] =
     SMono(mailboxManager.getMailboxReactive(id, mailboxSession))
-      .flatMap((mailbox: MessageManager) =>
+      .filterWhen(assertCapabilityIfSharedMailbox(mailboxSession, id, 
supportSharedMailbox))
+      .flatMap((mailbox: MessageManager) => {
         SMono(mailboxManager.hasChildrenReactive(mailbox.getMailboxPath, 
mailboxSession))
           .flatMap(hasChildren => {
             if (isASystemMailbox(mailbox)) {
@@ -128,7 +130,8 @@ class MailboxSetDeletePerformer @Inject()(mailboxManager: 
MailboxManager,
                   .flatMap(deletedMailbox => 
SMono(subscriptionManager.unsubscribeReactive(deletedMailbox.generateAssociatedPath(),
 mailboxSession)))
                   .`then`())
             }
-          }))
+          })
+      })
 
   private def auditTrail(mailboxSession: MailboxSession, 
mailboxDeletionResults: MailboxDeletionResults): Unit = {
     if (mailboxDeletionResults.destroyed.nonEmpty) {
diff --git 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetMethod.scala
 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetMethod.scala
index cb5d1884c7..fea82b2674 100644
--- 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetMethod.scala
+++ 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetMethod.scala
@@ -32,8 +32,9 @@ import 
org.apache.james.jmap.method.MailboxSetCreatePerformer.MailboxCreationRes
 import 
org.apache.james.jmap.method.MailboxSetDeletePerformer.MailboxDeletionResults
 import 
org.apache.james.jmap.method.MailboxSetUpdatePerformer.MailboxUpdateResults
 import org.apache.james.jmap.routes.SessionSupplier
-import org.apache.james.mailbox.MailboxSession
+import org.apache.james.mailbox.exception.MailboxNotFoundException
 import org.apache.james.mailbox.model.MailboxId
+import org.apache.james.mailbox.{MailboxSession, MessageManager}
 import org.apache.james.metrics.api.MetricFactory
 import play.api.libs.json.JsObject
 import reactor.core.scala.publisher.SMono
@@ -44,6 +45,13 @@ case class LoopInMailboxGraphException(mailboxId: MailboxId) 
extends Exception
 case class MailboxHasChildException(mailboxId: MailboxId) extends Exception
 case class MailboxCreationParseException(setError: SetError) extends Exception
 
+object MailboxSetMethod {
+  def assertCapabilityIfSharedMailbox(mailboxSession: MailboxSession, id: 
MailboxId, supportSharedMailbox: Boolean): MessageManager => SMono[Boolean] =
+    mailbox => if (!mailbox.getMailboxPath.belongsTo(mailboxSession) && 
!supportSharedMailbox)
+      SMono.error(new MailboxNotFoundException(id))
+    else SMono.just(true)
+}
+
 class MailboxSetMethod @Inject()(serializer: MailboxSerializer,
                                  createPerformer: MailboxSetCreatePerformer,
                                  deletePerformer: MailboxSetDeletePerformer,
@@ -58,9 +66,10 @@ class MailboxSetMethod @Inject()(serializer: 
MailboxSerializer,
 
   override def doProcess(capabilities: Set[CapabilityIdentifier], invocation: 
InvocationWithContext, mailboxSession: MailboxSession, request: 
MailboxSetRequest): SMono[InvocationWithContext] = for {
     oldState <- retrieveState(capabilities, mailboxSession)
-    creationResults <- createPerformer.createMailboxes(mailboxSession, 
request, invocation.processingContext)
+    supportSharedMailbox = capabilities.contains(JAMES_SHARES)
+    creationResults <- createPerformer.createMailboxes(mailboxSession, 
request, invocation.processingContext, supportSharedMailbox)
     updateResults <- updatePerformer.updateMailboxes(mailboxSession, request, 
capabilities)
-    deletionResults <- deletePerformer.deleteMailboxes(mailboxSession, request)
+    deletionResults <- deletePerformer.deleteMailboxes(mailboxSession, 
request, supportSharedMailbox)
     newState <- retrieveState(capabilities, mailboxSession)
     response = createResponse(capabilities, invocation.invocation, request, 
creationResults._1, deletionResults, updateResults, oldState, newState)
   } yield InvocationWithContext(response, creationResults._2)
diff --git 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetUpdatePerformer.scala
 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetUpdatePerformer.scala
index ad9844c45e..a757ca9e62 100644
--- 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetUpdatePerformer.scala
+++ 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetUpdatePerformer.scala
@@ -22,7 +22,7 @@ package org.apache.james.jmap.method
 import com.google.common.collect.ImmutableMap
 import eu.timepit.refined.auto._
 import jakarta.inject.Inject
-import org.apache.james.jmap.core.CapabilityIdentifier.CapabilityIdentifier
+import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, 
JAMES_SHARES}
 import org.apache.james.jmap.core.SetError.SetErrorDescription
 import org.apache.james.jmap.core.{Properties, SetError}
 import org.apache.james.jmap.json.MailboxSerializer
@@ -114,8 +114,8 @@ class MailboxSetUpdatePerformer @Inject()(serializer: 
MailboxSerializer,
                                           mailboxIdFactory: MailboxId.Factory) 
{
 
   def updateMailboxes(mailboxSession: MailboxSession,
-                              mailboxSetRequest: MailboxSetRequest,
-                              capabilities: Set[CapabilityIdentifier]): 
SMono[MailboxUpdateResults] = {
+                      mailboxSetRequest: MailboxSetRequest,
+                      capabilities: Set[CapabilityIdentifier]): 
SMono[MailboxUpdateResults] =
     SFlux.fromIterable(mailboxSetRequest.update.getOrElse(Seq()))
       .flatMap({
         case (unparsedMailboxId: UnparsedMailboxId, patch: MailboxPatchObject) 
=>
@@ -127,7 +127,6 @@ class MailboxSetUpdatePerformer @Inject()(serializer: 
MailboxSerializer,
       }, maxConcurrency = 5)
       .collectSeq()
       .map(MailboxUpdateResults)
-  }
 
   private def updateMailbox(mailboxSession: MailboxSession,
                             mailboxId: MailboxId,
@@ -135,23 +134,25 @@ class MailboxSetUpdatePerformer @Inject()(serializer: 
MailboxSerializer,
                             patch: MailboxPatchObject,
                             capabilities: Set[CapabilityIdentifier]): 
SMono[MailboxUpdateResult] = {
     patch.validate(mailboxIdFactory, serializer, capabilities, mailboxSession)
-      .fold(e => SMono.error(e), validatedPatch =>
-        updateMailboxRights(mailboxId, validatedPatch, mailboxSession)
-          .`then`(updateSubscription(mailboxId, validatedPatch, 
mailboxSession))
-          .`then`(updateMailboxPath(mailboxId, unparsedMailboxId, 
validatedPatch, mailboxSession)))
+      .fold(e => SMono.error(e), validatedPatch => {
+        val supportSharedMailbox: Boolean = capabilities.contains(JAMES_SHARES)
+        getMessageManager(supportSharedMailbox, mailboxId, mailboxSession)
+          .flatMap(messageManager => updateMailboxRights(mailboxId, 
validatedPatch, mailboxSession)
+            .`then`(updateSubscription(mailboxId, validatedPatch, 
mailboxSession, messageManager))
+            .`then`(updateMailboxPath(mailboxId, unparsedMailboxId, 
validatedPatch, mailboxSession, messageManager, supportSharedMailbox)))
+      })
   }
 
-  private def updateSubscription(mailboxId: MailboxId, validatedPatch: 
ValidatedMailboxPatchObject, mailboxSession: MailboxSession): 
SMono[MailboxUpdateResult] = {
+  private def updateSubscription(mailboxId: MailboxId, validatedPatch: 
ValidatedMailboxPatchObject, mailboxSession: MailboxSession, messageManager: 
MessageManager): SMono[MailboxUpdateResult] = {
     validatedPatch.isSubscribedUpdate.map(isSubscribedUpdate => {
       SMono.fromCallable(() => {
-        val mailbox = mailboxManager.getMailbox(mailboxId, mailboxSession)
-        val isOwner = mailbox.getMailboxPath.belongsTo(mailboxSession)
+        val isOwner = messageManager.getMailboxPath.belongsTo(mailboxSession)
         val shouldSubscribe = 
isSubscribedUpdate.isSubscribed.map(_.value).getOrElse(isOwner)
 
         if (shouldSubscribe) {
-          subscriptionManager.subscribe(mailboxSession, mailbox.getMailboxPath)
+          subscriptionManager.subscribe(mailboxSession, 
messageManager.getMailboxPath)
         } else {
-          subscriptionManager.unsubscribe(mailboxSession, 
mailbox.getMailboxPath)
+          subscriptionManager.unsubscribe(mailboxSession, 
messageManager.getMailboxPath)
         }
       
}).`then`(SMono.just[MailboxUpdateResult](MailboxUpdateSuccess(mailboxId)))
         .subscribeOn(ReactorUtils.BLOCKING_CALL_WRAPPER)
@@ -162,44 +163,44 @@ class MailboxSetUpdatePerformer @Inject()(serializer: 
MailboxSerializer,
   private def updateMailboxPath(mailboxId: MailboxId,
                                 unparsedMailboxId: UnparsedMailboxId,
                                 validatedPatch: ValidatedMailboxPatchObject,
-                                mailboxSession: MailboxSession): 
SMono[MailboxUpdateResult] = {
+                                mailboxSession: MailboxSession,
+                                mailbox: MessageManager,
+                                supportSharedMailbox: Boolean): 
SMono[MailboxUpdateResult] = {
     if (validatedPatch.shouldUpdateMailboxPath) {
-      SMono(mailboxManager.getMailboxReactive(mailboxId, mailboxSession))
-        .flatMap(mailbox =>
-          SMono.fromCallable[MailboxUpdateResult](() => {
-            try {
-              if (isASystemMailbox(mailbox) && 
!DefaultMailboxes.INBOX.equalsIgnoreCase(mailbox.getMailboxPath.getName)) {
-                throw SystemMailboxChangeException(mailboxId)
-              }
-              if 
(validatedPatch.parentIdUpdate.flatMap(_.newId).contains(mailboxId)) {
-                throw LoopInMailboxGraphException(mailboxId)
-              }
-              val oldPath = mailbox.getMailboxPath
-              val newPath = applyParentIdUpdate(mailboxId, 
validatedPatch.parentIdUpdate, mailboxSession)
-                .andThen(applyNameUpdate(validatedPatch.nameUpdate, 
mailboxSession))
-                .apply(oldPath)
-              if (!oldPath.equals(newPath)) {
-                mailboxManager.renameMailbox(mailboxId,
-                  newPath,
-                  RenameOption.RENAME_SUBSCRIPTIONS,
-                  mailboxSession)
-              }
-              MailboxUpdateSuccess(mailboxId)
-            } catch {
-              case e: Exception => MailboxUpdateFailure(unparsedMailboxId, e, 
Some(validatedPatch))
+      SMono.fromCallable[MailboxUpdateResult](() => {
+          try {
+            if (isASystemMailbox(mailbox) && 
!DefaultMailboxes.INBOX.equalsIgnoreCase(mailbox.getMailboxPath.getName)) {
+              throw SystemMailboxChangeException(mailboxId)
+            }
+            if 
(validatedPatch.parentIdUpdate.flatMap(_.newId).contains(mailboxId)) {
+              throw LoopInMailboxGraphException(mailboxId)
+            }
+            val oldPath = mailbox.getMailboxPath
+            val newPath = applyParentIdUpdate(mailboxId, 
validatedPatch.parentIdUpdate, mailboxSession, supportSharedMailbox)
+              .andThen(applyNameUpdate(validatedPatch.nameUpdate, 
mailboxSession))
+              .apply(oldPath)
+            if (!oldPath.equals(newPath)) {
+              mailboxManager.renameMailbox(mailboxId,
+                newPath,
+                RenameOption.RENAME_SUBSCRIPTIONS,
+                mailboxSession)
             }
-          }).subscribeOn(ReactorUtils.BLOCKING_CALL_WRAPPER)
-            .flatMap(updateResult => 
createInboxIfNeeded(mailbox.getMailboxPath, mailboxSession)
-              .`then`(SMono.just(updateResult))))
+            MailboxUpdateSuccess(mailboxId)
+          } catch {
+            case e: Exception => MailboxUpdateFailure(unparsedMailboxId, e, 
Some(validatedPatch))
+          }
+        }).subscribeOn(ReactorUtils.BLOCKING_CALL_WRAPPER)
+        .flatMap(updateResult => createInboxIfNeeded(mailbox.getMailboxPath, 
mailboxSession)
+          .`then`(SMono.just(updateResult)))
     } else {
       SMono.just[MailboxUpdateResult](MailboxUpdateSuccess(mailboxId))
     }
   }
 
-  private def applyParentIdUpdate(mailboxId: MailboxId, maybeParentIdUpdate: 
Option[ParentIdUpdate], mailboxSession: MailboxSession): MailboxPath => 
MailboxPath = {
-    maybeParentIdUpdate.map(parentIdUpdate => applyParentIdUpdate(mailboxId, 
parentIdUpdate, mailboxSession))
+  private def applyParentIdUpdate(mailboxId: MailboxId, maybeParentIdUpdate: 
Option[ParentIdUpdate],
+                                  mailboxSession: MailboxSession, 
supportSharedMailbox: Boolean): MailboxPath => MailboxPath =
+    maybeParentIdUpdate.map(parentIdUpdate => applyParentIdUpdate(mailboxId, 
parentIdUpdate, mailboxSession, supportSharedMailbox))
       .getOrElse(x => x)
-  }
 
   private def applyNameUpdate(maybeNameUpdate: Option[NameUpdate], 
mailboxSession: MailboxSession): MailboxPath => MailboxPath = {
     originalPath => maybeNameUpdate.map(nameUpdate => {
@@ -213,7 +214,8 @@ class MailboxSetUpdatePerformer @Inject()(serializer: 
MailboxSerializer,
     }).getOrElse(originalPath)
   }
 
-  private def applyParentIdUpdate(mailboxId: MailboxId, parentIdUpdate: 
ParentIdUpdate, mailboxSession: MailboxSession): MailboxPath => MailboxPath = {
+  private def applyParentIdUpdate(mailboxId: MailboxId, parentIdUpdate: 
ParentIdUpdate,
+                                  mailboxSession: MailboxSession, 
supportSharedMailbox: Boolean): MailboxPath => MailboxPath = {
     originalPath => {
       val currentName = originalPath.getName(mailboxSession.getPathDelimiter)
       parentIdUpdate.newId
@@ -233,12 +235,17 @@ class MailboxSetUpdatePerformer @Inject()(serializer: 
MailboxSerializer,
             throw LoopInMailboxGraphException(mailboxId)
           }
           val parentPath = mailboxManager.getMailbox(id, 
mailboxSession).getMailboxPath
+          if (!parentPath.belongsTo(mailboxSession) && !supportSharedMailbox) 
throw new MailboxNotFoundException(id)
           parentPath.child(currentName, mailboxSession.getPathDelimiter)
         })
         .getOrElse(MailboxPath.forUser(originalPath.getUser, currentName))
     }
   }
 
+  private def getMessageManager(supportSharedMailbox: Boolean, mailboxId: 
MailboxId, mailboxSession: MailboxSession): SMono[MessageManager] =
+    SMono(mailboxManager.getMailboxReactive(mailboxId, mailboxSession))
+      
.filterWhen(MailboxSetMethod.assertCapabilityIfSharedMailbox(mailboxSession, 
mailboxId, supportSharedMailbox))
+
   private def updateMailboxRights(mailboxId: MailboxId,
                                   validatedPatch: ValidatedMailboxPatchObject,
                                   mailboxSession: MailboxSession): 
SMono[MailboxUpdateResult] = {


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

Reply via email to