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 1d7dfd874ed925350378b2520e2d361ee6a3bb16
Author: Tung Van TRAN <[email protected]>
AuthorDate: Wed Mar 29 16:45:34 2023 +0700

    IMAP - Make reactive SetACLProcessor
---
 .../james/imap/processor/SetACLProcessor.java      | 150 +++++++++++----------
 .../james/imap/processor/SetACLProcessorTest.java  |  42 +++---
 2 files changed, 100 insertions(+), 92 deletions(-)

diff --git 
a/protocols/imap/src/main/java/org/apache/james/imap/processor/SetACLProcessor.java
 
b/protocols/imap/src/main/java/org/apache/james/imap/processor/SetACLProcessor.java
index 269963abc0..cda9a652f7 100644
--- 
a/protocols/imap/src/main/java/org/apache/james/imap/processor/SetACLProcessor.java
+++ 
b/protocols/imap/src/main/java/org/apache/james/imap/processor/SetACLProcessor.java
@@ -19,10 +19,14 @@
 
 package org.apache.james.imap.processor;
 
+import static org.apache.james.util.ReactorUtils.logOnError;
+
 import java.util.List;
 
 import javax.inject.Inject;
 
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.api.message.Capability;
@@ -41,12 +45,15 @@ import org.apache.james.mailbox.model.MailboxACL.EntryKey;
 import org.apache.james.mailbox.model.MailboxACL.Rfc4314Rights;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.metrics.api.MetricFactory;
+import org.apache.james.util.FunctionalUtils;
 import org.apache.james.util.MDCBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.collect.ImmutableList;
 
+import reactor.core.publisher.Mono;
+
 /**
  * SETACL Processor.
  */
@@ -62,19 +69,39 @@ public class SetACLProcessor extends 
AbstractMailboxProcessor<SetACLRequest> imp
     }
 
     @Override
-    protected void processRequest(SetACLRequest request, ImapSession session, 
Responder responder) {
-
+    protected Mono<Void> processRequestReactive(SetACLRequest request, 
ImapSession session, Responder responder) {
         final MailboxManager mailboxManager = getMailboxManager();
         final MailboxSession mailboxSession = session.getMailboxSession();
         final String mailboxName = request.getMailboxName();
         final String identifier = request.getIdentifier();
-        try {
-            
-            /* parsing the rights is the the cheapest thing to begin with */
-            EditMode editMode = EditMode.REPLACE;
-            String rights = request.getRights();
-            if (rights != null && rights.length() > 0) {
-                switch (rights.charAt(0)) {
+        MailboxPath mailboxPath = 
PathConverter.forSession(session).buildFullPath(mailboxName);
+
+        return checkLookupRight(request, responder, mailboxManager, 
mailboxSession, mailboxPath)
+            .filter(FunctionalUtils.identityPredicate())
+            .flatMap(hasLookupRight -> checkAdminRight(request, responder, 
mailboxManager, mailboxSession, mailboxName, mailboxPath))
+            .filter(FunctionalUtils.identityPredicate())
+            .flatMap(hasAdminRight -> applyRight(mailboxManager, 
mailboxSession, identifier, request, mailboxPath)
+                .then(Mono.fromRunnable(() -> okComplete(request, responder)))
+                .then())
+            .onErrorResume(UnsupportedRightException.class,
+                error -> Mono.fromRunnable(() -> taggedBad(request, responder,
+                    new HumanReadableText(
+                        HumanReadableText.UNSUPPORTED_RIGHT_KEY,
+                        HumanReadableText.UNSUPPORTED_RIGHT_DEFAULT_VALUE,
+                        error.getUnsupportedRight()))))
+            .onErrorResume(MailboxNotFoundException.class,
+                error -> Mono.fromRunnable(() -> no(request, responder, 
HumanReadableText.MAILBOX_NOT_FOUND)))
+            .doOnEach(logOnError(MailboxException.class, e -> LOGGER.error("{} 
failed for mailbox {}", request.getCommand().getName(), mailboxName, e)))
+            .onErrorResume(MailboxException.class,
+                error -> Mono.fromRunnable(() -> no(request, responder, 
HumanReadableText.GENERIC_FAILURE_DURING_PROCESSING)));
+    }
+
+    /* parsing the rights is the cheapest thing to begin with */
+    private Pair<Rfc4314Rights, EditMode> 
parsingRightAndEditMode(SetACLRequest request) throws UnsupportedRightException 
{
+        EditMode editMode = EditMode.REPLACE;
+        String rights = request.getRights();
+        if (StringUtils.isNotEmpty(rights)) {
+            switch (rights.charAt(0)) {
                 case MailboxACL.ADD_RIGHTS_MARKER:
                     editMode = EditMode.ADD;
                     rights = rights.substring(1);
@@ -83,74 +110,49 @@ public class SetACLProcessor extends 
AbstractMailboxProcessor<SetACLRequest> imp
                     editMode = EditMode.REMOVE;
                     rights = rights.substring(1);
                     break;
-                }
-            }
-            Rfc4314Rights mailboxAclRights = 
Rfc4314Rights.fromSerializedRfc4314Rights(rights);
-
-            MailboxPath mailboxPath = 
PathConverter.forSession(session).buildFullPath(mailboxName);
-            // Check that mailbox exists
-            mailboxManager.getMailbox(mailboxPath, mailboxSession);
-
-            /*
-             * RFC 4314 section 6.
-             * An implementation MUST make sure the ACL commands themselves do
-             * not give information about mailboxes with appropriately
-             * restricted ACLs. For example, when a user agent executes a 
GETACL
-             * command on a mailbox that the user has no permission to LIST, 
the
-             * server would respond to that request with the same error that
-             * would be used if the mailbox did not exist, thus revealing no
-             * existence information, much less the mailbox’s ACL.
-             */
-            if (!mailboxManager.hasRight(mailboxPath, MailboxACL.Right.Lookup, 
mailboxSession)) {
-                no(request, responder, HumanReadableText.MAILBOX_NOT_FOUND);
-            } else if (!mailboxManager.hasRight(mailboxPath, 
MailboxACL.Right.Administer, mailboxSession)) {
-                /* RFC 4314 section 4. */
-                Object[] params = new Object[] {
-                        MailboxACL.Right.Administer.toString(),
-                        request.getCommand().getName(),
-                        mailboxName
-                };
-                HumanReadableText text = new 
HumanReadableText(HumanReadableText.UNSUFFICIENT_RIGHTS_KEY, 
HumanReadableText.UNSUFFICIENT_RIGHTS_DEFAULT_VALUE, params);
-                no(request, responder, text);
-            } else {
-                
-                EntryKey key = EntryKey.deserialize(identifier);
-                
-                // FIXME check if identifier is a valid user or group
-                // FIXME Servers, when processing a command that has an 
identifier as a
-                // parameter (i.e., any of SETACL, DELETEACL, and LISTRIGHTS 
commands),
-                // SHOULD first prepare the received identifier using 
"SASLprep" profile
-                // [SASLprep] of the "stringprep" algorithm [Stringprep].  If 
the
-                // preparation of the identifier fails or results in an empty 
string,
-                // the server MUST refuse to perform the command with a BAD 
response.
-                // Note that Section 6 recommends additional identifier’s 
verification
-                // steps.
-
-                mailboxManager.applyRightsCommand(mailboxPath,
-                    
MailboxACL.command().key(key).mode(editMode).rights(mailboxAclRights).build(),
-                    mailboxSession);
-
-                okComplete(request, responder);
-                // FIXME should we send unsolicited responses here?
-                // unsolicitedResponses(session, responder, false);
             }
-        } catch (UnsupportedRightException e) {
-            /*
-             * RFc 4314, section 3.1
-             * Note that an unrecognized right MUST cause the command to 
return the
-             * BAD response.  In particular, the server MUST NOT silently 
ignore
-             * unrecognized rights.
-             * */
-            Object[] params = new Object[] {e.getUnsupportedRight()};
-            HumanReadableText text = new 
HumanReadableText(HumanReadableText.UNSUPPORTED_RIGHT_KEY, 
HumanReadableText.UNSUPPORTED_RIGHT_DEFAULT_VALUE, params);
-            taggedBad(request, responder, text);
-        } catch (MailboxNotFoundException e) {
-            no(request, responder, HumanReadableText.MAILBOX_NOT_FOUND);
-        } catch (MailboxException e) {
-            LOGGER.error("{} failed for mailbox {}", 
request.getCommand().getName(), mailboxName, e);
-            no(request, responder, 
HumanReadableText.GENERIC_FAILURE_DURING_PROCESSING);
         }
+        return Pair.of(Rfc4314Rights.fromSerializedRfc4314Rights(rights), 
editMode);
+    }
+
+    private Mono<Void> applyRight(MailboxManager mailboxManager,
+                                  MailboxSession mailboxSession,
+                                  String identifier,
+                                  SetACLRequest request,
+                                  MailboxPath mailboxPath) {
+        return Mono.fromCallable(() -> parsingRightAndEditMode(request))
+            .flatMap(rightAndEditMode -> 
Mono.from(mailboxManager.applyRightsCommandReactive(
+                mailboxPath,
+                MailboxACL.command()
+                    .key(EntryKey.deserialize(identifier))
+                    .mode(rightAndEditMode.getRight())
+                    .rights(rightAndEditMode.getLeft())
+                    .build(),
+                mailboxSession)));
+    }
 
+    private Mono<Boolean> checkAdminRight(SetACLRequest request, Responder 
responder, MailboxManager mailboxManager, MailboxSession mailboxSession, String 
mailboxName, MailboxPath mailboxPath) {
+        return Mono.from(mailboxManager.hasRightReactive(mailboxPath, 
MailboxACL.Right.Administer, mailboxSession))
+            .doOnNext(hasRight -> {
+                if (!hasRight) {
+                    no(request, responder,
+                        new HumanReadableText(
+                            HumanReadableText.UNSUFFICIENT_RIGHTS_KEY,
+                            
HumanReadableText.UNSUFFICIENT_RIGHTS_DEFAULT_VALUE,
+                            MailboxACL.Right.Administer.toString(),
+                            request.getCommand().getName(),
+                            mailboxName));
+                }
+            });
+    }
+
+    private Mono<Boolean> checkLookupRight(SetACLRequest request, Responder 
responder, MailboxManager mailboxManager, MailboxSession mailboxSession, 
MailboxPath mailboxPath) {
+        return Mono.from(mailboxManager.hasRightReactive(mailboxPath, 
MailboxACL.Right.Lookup, mailboxSession))
+            .doOnNext(hasRight -> {
+                if (!hasRight) {
+                    no(request, responder, 
HumanReadableText.MAILBOX_NOT_FOUND);
+                }
+            });
     }
 
     @Override
diff --git 
a/protocols/imap/src/test/java/org/apache/james/imap/processor/SetACLProcessorTest.java
 
b/protocols/imap/src/test/java/org/apache/james/imap/processor/SetACLProcessorTest.java
index 791fb347d0..847d3fe223 100644
--- 
a/protocols/imap/src/test/java/org/apache/james/imap/processor/SetACLProcessorTest.java
+++ 
b/protocols/imap/src/test/java/org/apache/james/imap/processor/SetACLProcessorTest.java
@@ -41,7 +41,6 @@ import org.apache.james.mailbox.MailboxSessionUtil;
 import org.apache.james.mailbox.MessageManager;
 import org.apache.james.mailbox.MessageManager.MailboxMetaData;
 import org.apache.james.mailbox.MessageManager.MailboxMetaData.FetchGroup;
-import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.exception.MailboxNotFoundException;
 import org.apache.james.mailbox.model.MailboxACL;
 import org.apache.james.mailbox.model.MailboxACL.EditMode;
@@ -109,11 +108,13 @@ class SetACLProcessorTest {
     }
     
     @Test
-    void testUnsupportedRight() throws Exception {
+    void testUnsupportedRight() {
         SetACLRequest setACLRequest = new SetACLRequest(TAG, MAILBOX_NAME, 
USER_1.asString(), UNSUPPORTED_RIGHT);
 
-        when(mailboxManager.hasRight(path, MailboxACL.Right.Lookup, 
mailboxSession))
-            .thenReturn(false);
+        when(mailboxManager.hasRightReactive(path, MailboxACL.Right.Lookup, 
mailboxSession))
+            .thenReturn(Mono.just(true));
+        when(mailboxManager.hasRightReactive(path, 
MailboxACL.Right.Administer, mailboxSession))
+            .thenReturn(Mono.just(true));
 
         subject.doProcess(setACLRequest, responder, imapSession).block();
 
@@ -127,11 +128,11 @@ class SetACLProcessorTest {
     }
     
     @Test
-    void testNoAdminRight() throws Exception {
-        when(mailboxManager.hasRight(path, MailboxACL.Right.Lookup, 
mailboxSession))
-            .thenReturn(true);
-        when(mailboxManager.hasRight(path, MailboxACL.Right.Administer, 
mailboxSession))
-            .thenReturn(false);
+    void testNoAdminRight() {
+        when(mailboxManager.hasRightReactive(path, MailboxACL.Right.Lookup, 
mailboxSession))
+            .thenReturn(Mono.just(true));
+        when(mailboxManager.hasRightReactive(path, 
MailboxACL.Right.Administer, mailboxSession))
+            .thenReturn(Mono.just(false));
 
         subject.doProcess(replaceAclRequest, responder, imapSession).block();
 
@@ -145,9 +146,10 @@ class SetACLProcessorTest {
     }
     
     @Test
-    void testInexistentMailboxName() throws Exception {
-        when(mailboxManager.getMailbox(any(MailboxPath.class), 
any(MailboxSession.class)))
-            .thenThrow(new MailboxNotFoundException(""));
+    void testInexistentMailboxName() {
+        when(mailboxManager.hasRightReactive(any(MailboxPath.class),
+            any(),any(MailboxSession.class)))
+            .thenReturn(Mono.error(new MailboxNotFoundException("")));
 
         subject.doProcess(replaceAclRequest, responder, imapSession).block();
 
@@ -175,16 +177,20 @@ class SetACLProcessorTest {
         testOp("", EditMode.REPLACE);
     }
     
-    private void testOp(String prefix, EditMode editMode) throws 
MailboxException {
-        when(mailboxManager.hasRight(path, MailboxACL.Right.Lookup, 
mailboxSession))
-            .thenReturn(true);
-        when(mailboxManager.hasRight(path, MailboxACL.Right.Administer, 
mailboxSession))
-            .thenReturn(true);
+    private void testOp(String prefix, EditMode editMode) {
+        when(mailboxManager.hasRightReactive(path, MailboxACL.Right.Lookup, 
mailboxSession))
+            .thenReturn(Mono.just(true));
+        when(mailboxManager.hasRightReactive(path, 
MailboxACL.Right.Administer, mailboxSession))
+            .thenReturn(Mono.just(true));
+        when(mailboxManager.applyRightsCommandReactive(path,
+            
MailboxACL.command().key(user1Key).rights(setRights).mode(editMode).build(),
+            mailboxSession))
+            .thenReturn(Mono.empty());
 
         SetACLRequest r = new SetACLRequest(TAG, MAILBOX_NAME, 
USER_1.asString(), prefix + SET_RIGHTS);
         subject.doProcess(r, responder, imapSession).block();
 
-        verify(mailboxManager).applyRightsCommand(path,
+        verify(mailboxManager).applyRightsCommandReactive(path,
             
MailboxACL.command().key(user1Key).rights(setRights).mode(editMode).build(),
             mailboxSession);
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to