You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by rc...@apache.org on 2023/04/06 02:17:27 UTC
[james-project] 02/03: IMAP - Make reactive SetACLProcessor
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 <vt...@linagora.com>
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: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org