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 10c96e699b6c819d988106a30b9baecb74791de6
Author: Benoit TELLIER <btell...@linagora.com>
AuthorDate: Thu Oct 17 17:07:37 2024 +0200

    JAMES-2182 Fix rights for STORE
---
 .../james/mailbox/store/StoreMessageManager.java   | 77 +++++++++++++++-------
 .../james/imap/scripts/SharingAccessLRI.test       | 12 ++--
 .../james/imap/scripts/SharingAccessLRS.test       | 11 ++--
 .../james/imap/scripts/SharingAccessLRT.test       |  9 +--
 .../james/imap/scripts/SharingAccessLRTE.test      |  9 +--
 .../james/imap/scripts/SharingAccessLRW.test       | 11 ++--
 .../imap/processor/AbstractSelectionProcessor.java |  3 +-
 .../james/imap/processor/StatusProcessor.java      |  3 +-
 8 files changed, 76 insertions(+), 59 deletions(-)

diff --git 
a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java
 
b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java
index 61e5fe4a41..699974a7af 100644
--- 
a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java
+++ 
b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java
@@ -679,12 +679,43 @@ public class StoreMessageManager implements 
MessageManager {
 
     }
 
-    @Override
-    public Map<MessageUid, Flags> setFlags(final Flags flags, final 
FlagsUpdateMode flagsUpdateMode, final MessageRange set, MailboxSession 
mailboxSession) throws MailboxException {
+    public Optional<MailboxException> ensureFlagsWrite(Flags flags, 
FlagsUpdateMode flagsUpdateMode, MailboxSession mailboxSession) {
+        MailboxACL.Rfc4314Rights myRights = 
storeRightManager.myRights(mailbox, mailboxSession);
 
-        if (!isWriteable(mailboxSession)) {
-            throw new ReadOnlyException(getMailboxPath());
+        if (flagsUpdateMode.equals(FlagsUpdateMode.REPLACE)) {
+            if (!myRights.contains(MailboxACL.Right.Write, 
MailboxACL.Right.WriteSeenFlag, MailboxACL.Right.DeleteMessages)) {
+                return Optional.of(new InsufficientRightsException("'stw' 
rights are needed to reset flags"));
+            }
+            return Optional.empty();
+        }
+
+        if (flags.contains(Flag.SEEN) && 
!myRights.contains(MailboxACL.Right.WriteSeenFlag)) {
+            return Optional.of(new InsufficientRightsException("'s' right is 
needed to modify seen flag"));
+        }
+
+        if (flags.contains(Flag.DELETED) && 
!myRights.contains(MailboxACL.Right.DeleteMessages)) {
+            return Optional.of(new InsufficientRightsException("'t' right is 
needed to modify deleted flag"));
+        }
+
+        boolean hasOtherFlagChanges = flags.getUserFlags().length > 0
+            || flags.contains(Flag.FLAGGED)
+            || flags.contains(Flag.DRAFT)
+            || flags.contains(Flag.ANSWERED)
+            || flags.contains(Flag.RECENT);
+
+        if (hasOtherFlagChanges && !myRights.contains(MailboxACL.Right.Write)) 
{
+            return Optional.of(new InsufficientRightsException("'w' right is 
needed to modify arbitrary flags"));
         }
+        return Optional.empty();
+    }
+
+    @Override
+    public Map<MessageUid, Flags> setFlags(Flags flags, FlagsUpdateMode 
flagsUpdateMode, MessageRange set, MailboxSession mailboxSession) throws 
MailboxException {
+
+        ensureFlagsWrite(flags, flagsUpdateMode, mailboxSession)
+            .ifPresent(Throwing.<MailboxException>consumer(e -> {
+                throw e;
+            }).sneakyThrow());
 
         trimFlags(flags, mailboxSession);
 
@@ -709,25 +740,25 @@ public class StoreMessageManager implements 
MessageManager {
 
     @Override
     public Publisher<Map<MessageUid, Flags>> setFlagsReactive(Flags flags, 
FlagsUpdateMode flagsUpdateMode, MessageRange set, MailboxSession 
mailboxSession) {
-        if (!isWriteable(mailboxSession)) {
-            return Mono.error(new ReadOnlyException(getMailboxPath()));
-        }
-
-        trimFlags(flags, mailboxSession);
-
-        MessageMapper messageMapper = 
mapperFactory.getMessageMapper(mailboxSession);
-
-        return 
messageMapper.executeReactive(messageMapper.updateFlagsReactive(getMailboxEntity(),
 new FlagsUpdateCalculator(flags, flagsUpdateMode), set))
-            .flatMap(updatedFlags -> 
eventBus.dispatch(EventFactory.flagsUpdated()
-                    .randomEventId()
-                    .mailboxSession(mailboxSession)
-                    .mailbox(getMailboxEntity())
-                    .updatedFlags(updatedFlags)
-                    .build(),
-                new MailboxIdRegistrationKey(mailbox.getMailboxId()))
-                
.thenReturn(updatedFlags.stream().collect(ImmutableMap.toImmutableMap(
-                    UpdatedFlags::getUid,
-                    UpdatedFlags::getNewFlags))));
+        return ensureFlagsWrite(flags, flagsUpdateMode, mailboxSession)
+            .map(Mono::<Map<MessageUid, Flags>>error)
+            .orElseGet(() -> {
+                trimFlags(flags, mailboxSession);
+
+                MessageMapper messageMapper = 
mapperFactory.getMessageMapper(mailboxSession);
+
+                return 
messageMapper.executeReactive(messageMapper.updateFlagsReactive(getMailboxEntity(),
 new FlagsUpdateCalculator(flags, flagsUpdateMode), set))
+                    .flatMap(updatedFlags -> 
eventBus.dispatch(EventFactory.flagsUpdated()
+                                .randomEventId()
+                                .mailboxSession(mailboxSession)
+                                .mailbox(getMailboxEntity())
+                                .updatedFlags(updatedFlags)
+                                .build(),
+                            new 
MailboxIdRegistrationKey(mailbox.getMailboxId()))
+                        
.thenReturn(updatedFlags.stream().collect(ImmutableMap.toImmutableMap(
+                            UpdatedFlags::getUid,
+                            UpdatedFlags::getNewFlags))));
+            });
     }
 
     /**
diff --git 
a/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/SharingAccessLRI.test
 
b/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/SharingAccessLRI.test
index fc1bf6cdd6..860b3038f6 100644
--- 
a/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/SharingAccessLRI.test
+++ 
b/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/SharingAccessLRI.test
@@ -84,21 +84,17 @@ C: F11 FETCH 1 FLAGS
 S: \* 1 FETCH \(FLAGS \(\\Recent\)\)
 S: F11 OK FETCH completed.
 
-# TODO Insert is not flags
 C: F12 STORE 1 +FLAGS (\Deleted)
-S: \* 1 FETCH \(FLAGS \(\\Deleted \\Recent\)\)
-S: F12 OK STORE completed.
+S: F12 NO STORE failed. Save failed.
 
 C: F13 STORE 1 +FLAGS (\Seen)
-S: \* 1 FETCH \(FLAGS \(\\Deleted \\Recent \\Seen\)\)
-S: F13 OK STORE completed.
+S: F13 NO STORE failed. Save failed.
 
 C: F14 STORE 1 +FLAGS (\Flagged)
-S: \* 1 FETCH \(FLAGS \(\\Deleted \\Flagged \\Recent \\Seen\)\)
-S: F14 OK STORE completed.
+S: F14 NO STORE failed. Save failed.
 
 C: F11 FETCH 1 FLAGS
-S: \* 1 FETCH \(FLAGS \(\\Deleted \\Flagged \\Recent \\Seen\)\)
+S: \* 1 FETCH \(FLAGS \(\\Recent\)\)
 S: F11 OK FETCH completed.
 
 C: F15 EXPUNGE
diff --git 
a/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/SharingAccessLRS.test
 
b/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/SharingAccessLRS.test
index d2bb291817..f6e06a156e 100644
--- 
a/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/SharingAccessLRS.test
+++ 
b/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/SharingAccessLRS.test
@@ -86,21 +86,18 @@ C: F11 FETCH 1 FLAGS
 S: \* 1 FETCH \(FLAGS \(\\Recent\)\)
 S: F11 OK FETCH completed.
 
-# TODO I shall only be able to manipulate \\Seen...
 C: F12 STORE 1 +FLAGS (\Deleted)
-S: \* 1 FETCH \(FLAGS \(\\Deleted \\Recent\)\)
-S: F12 OK STORE completed.
+S: F12 NO STORE failed. Save failed.
 
 C: F13 STORE 1 +FLAGS (\Seen)
-S: \* 1 FETCH \(FLAGS \(\\Deleted \\Recent \\Seen\)\)
+S: \* 1 FETCH \(FLAGS \(\\Recent \\Seen\)\)
 S: F13 OK STORE completed.
 
 C: F14 STORE 1 +FLAGS (\Flagged)
-S: \* 1 FETCH \(FLAGS \(\\Deleted \\Flagged \\Recent \\Seen\)\)
-S: F14 OK STORE completed.
+S: F14 NO STORE failed. Save failed.
 
 C: F11 FETCH 1 FLAGS
-S: \* 1 FETCH \(FLAGS \(\\Deleted \\Flagged \\Recent \\Seen\)\)
+S: \* 1 FETCH \(FLAGS \(\\Recent \\Seen\)\)
 S: F11 OK FETCH completed.
 
 C: F15 EXPUNGE
diff --git 
a/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/SharingAccessLRT.test
 
b/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/SharingAccessLRT.test
index 579e7905ff..be41d2cac4 100644
--- 
a/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/SharingAccessLRT.test
+++ 
b/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/SharingAccessLRT.test
@@ -90,17 +90,14 @@ C: F12 STORE 1 +FLAGS (\Deleted)
 S: \* 1 FETCH \(FLAGS \(\\Deleted \\Recent\)\)
 S: F12 OK STORE completed.
 
-# TODO I shall only be able to manipulate \\Deleted...
 C: F13 STORE 1 +FLAGS (\Seen)
-S: \* 1 FETCH \(FLAGS \(\\Deleted \\Recent \\Seen\)\)
-S: F13 OK STORE completed.
+S: F13 NO STORE failed. Save failed.
 
 C: F14 STORE 1 +FLAGS (\Flagged)
-S: \* 1 FETCH \(FLAGS \(\\Deleted \\Flagged \\Recent \\Seen\)\)
-S: F14 OK STORE completed.
+S: F14 NO STORE failed. Save failed.
 
 C: F11 FETCH 1 FLAGS
-S: \* 1 FETCH \(FLAGS \(\\Deleted \\Flagged \\Recent \\Seen\)\)
+S: \* 1 FETCH \(FLAGS \(\\Deleted \\Recent\)\)
 S: F11 OK FETCH completed.
 
 C: F15 EXPUNGE
diff --git 
a/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/SharingAccessLRTE.test
 
b/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/SharingAccessLRTE.test
index eef28d57b9..892cdaab8f 100644
--- 
a/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/SharingAccessLRTE.test
+++ 
b/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/SharingAccessLRTE.test
@@ -90,17 +90,14 @@ C: F12 STORE 1 +FLAGS (\Deleted)
 S: \* 1 FETCH \(FLAGS \(\\Deleted \\Recent\)\)
 S: F12 OK STORE completed.
 
-# TODO I shall only be able to manipulate \\Deleted...
 C: F13 STORE 1 +FLAGS (\Seen)
-S: \* 1 FETCH \(FLAGS \(\\Deleted \\Recent \\Seen\)\)
-S: F13 OK STORE completed.
+S: F13 NO STORE failed. Save failed.
 
 C: F14 STORE 1 +FLAGS (\Flagged)
-S: \* 1 FETCH \(FLAGS \(\\Deleted \\Flagged \\Recent \\Seen\)\)
-S: F14 OK STORE completed.
+S: F14 NO STORE failed. Save failed.
 
 C: F11 FETCH 1 FLAGS
-S: \* 1 FETCH \(FLAGS \(\\Deleted \\Flagged \\Recent \\Seen\)\)
+S: \* 1 FETCH \(FLAGS \(\\Deleted \\Recent\)\)
 S: F11 OK FETCH completed.
 
 C: F15 EXPUNGE
diff --git 
a/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/SharingAccessLRW.test
 
b/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/SharingAccessLRW.test
index 569879821d..cb96dcf0d2 100644
--- 
a/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/SharingAccessLRW.test
+++ 
b/mpt/impl/imap-mailbox/core/src/main/resources/org/apache/james/imap/scripts/SharingAccessLRW.test
@@ -86,21 +86,18 @@ C: F11 FETCH 1 FLAGS
 S: \* 1 FETCH \(FLAGS \(\\Recent\)\)
 S: F11 OK FETCH completed.
 
-# TODO I shall only be able to manipulate \\Seen...
 C: F12 STORE 1 +FLAGS (\Deleted)
-S: \* 1 FETCH \(FLAGS \(\\Deleted \\Recent\)\)
-S: F12 OK STORE completed.
+S: F12 NO STORE failed. Save failed.
 
 C: F13 STORE 1 +FLAGS (\Seen)
-S: \* 1 FETCH \(FLAGS \(\\Deleted \\Recent \\Seen\)\)
-S: F13 OK STORE completed.
+S: F13 NO STORE failed. Save failed.
 
 C: F14 STORE 1 +FLAGS (\Flagged)
-S: \* 1 FETCH \(FLAGS \(\\Deleted \\Flagged \\Recent \\Seen\)\)
+S: \* 1 FETCH \(FLAGS \(\\Flagged \\Recent\)\)
 S: F14 OK STORE completed.
 
 C: F11 FETCH 1 FLAGS
-S: \* 1 FETCH \(FLAGS \(\\Deleted \\Flagged \\Recent \\Seen\)\)
+S: \* 1 FETCH \(FLAGS \(\\Flagged \\Recent\)\)
 S: F11 OK FETCH completed.
 
 C: F15 EXPUNGE
diff --git 
a/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractSelectionProcessor.java
 
b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractSelectionProcessor.java
index cd32c1ad30..1ca548e699 100644
--- 
a/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractSelectionProcessor.java
+++ 
b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractSelectionProcessor.java
@@ -404,8 +404,9 @@ abstract class AbstractSelectionProcessor<R extends 
AbstractMailboxSelectionRequ
             .<MessageManager>handle(Throwing.biConsumer((mailbox, sink) -> {
                 if (mailboxManager.hasRight(mailbox.getMailboxEntity(), 
MailboxACL.Right.Read, mailboxSession)) {
                     sink.next(mailbox);
+                } else {
+                    sink.error(new InsufficientRightsException("'r' right is 
needed to select a mailbox"));
                 }
-                sink.error(new InsufficientRightsException("'r' right is 
needed to select a mailbox"));
             }))
             .flatMap(Throwing.function(mailbox -> selectMailbox(session, 
responder, mailbox, currentMailbox)
                 .flatMap(Throwing.function(sessionMailbox ->
diff --git 
a/protocols/imap/src/main/java/org/apache/james/imap/processor/StatusProcessor.java
 
b/protocols/imap/src/main/java/org/apache/james/imap/processor/StatusProcessor.java
index 361fc8f5b0..bade56b99b 100644
--- 
a/protocols/imap/src/main/java/org/apache/james/imap/processor/StatusProcessor.java
+++ 
b/protocols/imap/src/main/java/org/apache/james/imap/processor/StatusProcessor.java
@@ -127,8 +127,9 @@ public class StatusProcessor extends 
AbstractMailboxProcessor<StatusRequest> imp
             .<MessageManager>handle(Throwing.biConsumer((mailbox, sink) -> {
                 if (getMailboxManager().hasRight(mailbox.getMailboxEntity(), 
MailboxACL.Right.Read, mailboxSession)) {
                     sink.next(mailbox);
+                } else {
+                    sink.error(new InsufficientRightsException("'r' right is 
needed to status a mailbox"));
                 }
-                sink.error(new InsufficientRightsException("'r' right is 
needed to status a mailbox"));
             }))
             .flatMap(mailbox -> sendStatus(mailbox, statusDataItems, 
responder, session, mailboxSession));
     }


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

Reply via email to