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 2021/01/05 04:55:50 UTC

[james-project] 11/24: JAMES-3485 Group attachment right checking together

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 9fe885b27a0791a8e2f700adb210faf3dd4b045e
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Fri Dec 25 19:14:30 2020 +0700

    JAMES-3485 Group attachment right checking together
    
    A common JMAP pattern is to save a message being a copy of
    another one (draft update).
    
    Updating a draft with several attachment will lead to right
    checking to happen for each attachment independently despite them
    to be related to the same message.
    
    So here are the reads being performed:
     - From attachmentId retrieve the owner -> miss
     - From attachmentId retrieve the messageId
     - From the messageId retrieve the message (and its mailbox
       context) - imapUidTable + messageV3 table
     - Then read the mailbox to validate the ACLs (mailbox + aclV2)
---
 .../mailbox/store/StoreAttachmentManager.java      | 48 ++++++++++++++++++++--
 1 file changed, 45 insertions(+), 3 deletions(-)

diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreAttachmentManager.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreAttachmentManager.java
index 7a4efe2..4044b4c 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreAttachmentManager.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreAttachmentManager.java
@@ -23,9 +23,13 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Stream;
 
 import javax.inject.Inject;
 
+import org.apache.commons.lang3.tuple.Pair;
 import org.apache.james.core.Username;
 import org.apache.james.mailbox.AttachmentManager;
 import org.apache.james.mailbox.MailboxSession;
@@ -41,7 +45,10 @@ import org.reactivestreams.Publisher;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.github.fge.lambdas.Throwing;
 import com.github.steveash.guavate.Guavate;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
 
 public class StoreAttachmentManager implements AttachmentManager {
     private static final Logger LOGGER = LoggerFactory.getLogger(StoreAttachmentManager.class);
@@ -70,9 +77,7 @@ public class StoreAttachmentManager implements AttachmentManager {
 
     @Override
     public List<AttachmentMetadata> getAttachments(List<AttachmentId> attachmentIds, MailboxSession mailboxSession) throws MailboxException {
-        List<AttachmentId> accessibleAttachmentIds = attachmentIds.stream()
-            .filter(attachmentId -> userHasAccessToAttachment(attachmentId, mailboxSession))
-            .collect(Guavate.toImmutableList());
+        Collection<AttachmentId> accessibleAttachmentIds = keepAccessible(attachmentIds, mailboxSession);
 
         return attachmentMapperFactory.getAttachmentMapper(mailboxSession).getAttachments(accessibleAttachmentIds);
     }
@@ -93,6 +98,24 @@ public class StoreAttachmentManager implements AttachmentManager {
         }
     }
 
+    private Collection<AttachmentId> keepAccessible(Collection<AttachmentId> attachmentIds, MailboxSession mailboxSession) {
+        try {
+            Set<AttachmentId> referencedByMessages = referencedInUserMessages(attachmentIds, mailboxSession);
+            ImmutableSet<AttachmentId> owned = Sets.difference(ImmutableSet.copyOf(attachmentIds), referencedByMessages)
+                .stream()
+                .filter(Throwing.<AttachmentId>predicate(id -> isExplicitlyAOwner(id, mailboxSession)).sneakyThrow())
+                .collect(Guavate.toImmutableSet());
+
+            return ImmutableSet.<AttachmentId>builder()
+                .addAll(referencedByMessages)
+                .addAll(owned)
+                .build();
+        } catch (MailboxException e) {
+            LOGGER.warn("Error while checking attachment related accessible message ids", e);
+            throw new RuntimeException(e);
+        }
+    }
+
     private boolean isReferencedInUserMessages(AttachmentId attachmentId, MailboxSession mailboxSession) throws MailboxException {
         Collection<MessageId> relatedMessageIds = getRelatedMessageIds(attachmentId, mailboxSession);
         return !messageIdManager
@@ -100,6 +123,25 @@ public class StoreAttachmentManager implements AttachmentManager {
             .isEmpty();
     }
 
+    private Set<AttachmentId> referencedInUserMessages(Collection<AttachmentId> attachmentIds, MailboxSession mailboxSession) throws MailboxException {
+        Map<MessageId, Collection<AttachmentId>> entries = attachmentIds.stream()
+            .flatMap(Throwing.<AttachmentId, Stream<Pair<MessageId, AttachmentId>>>function(
+                attachmentId -> getRelatedMessageIds(attachmentId, mailboxSession).stream()
+                    .map(messageId -> Pair.of(messageId, attachmentId)))
+                .sneakyThrow())
+            .collect(Guavate.toImmutableListMultimap(
+                Pair::getKey,
+                Pair::getValue))
+            .asMap();
+
+        Set<MessageId> accessibleMessages = messageIdManager.accessibleMessages(entries.keySet(), mailboxSession);
+
+        return entries.entrySet().stream()
+            .filter(entry -> accessibleMessages.contains(entry.getKey()))
+            .flatMap(entry -> entry.getValue().stream())
+            .collect(Guavate.toImmutableSet());
+    }
+
     private boolean isExplicitlyAOwner(AttachmentId attachmentId, MailboxSession mailboxSession) throws MailboxException {
         Collection<Username> explicitOwners = attachmentMapperFactory.getAttachmentMapper(mailboxSession)
             .getOwners(attachmentId);


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