You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by bt...@apache.org on 2020/05/07 02:12:37 UTC

[james-project] 13/22: JAMES-3148 ACL cleanUp upon mailbox deletion

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

commit 456e83e544a0dc98780e3af3fcb64b4a120a962b
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Sun Apr 12 16:53:20 2020 +0700

    JAMES-3148 ACL cleanUp upon mailbox deletion
---
 .../CassandraMailboxSessionMapperFactory.java      |  2 +-
 .../mailbox/cassandra/DeleteMessageListener.java   | 32 +++++++---
 .../cassandra/CassandraMailboxManagerTest.java     | 71 ++++++++++++++++++++++
 3 files changed, 95 insertions(+), 10 deletions(-)

diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java
index 7d29e36..b61508b 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/CassandraMailboxSessionMapperFactory.java
@@ -204,6 +204,6 @@ public class CassandraMailboxSessionMapperFactory extends MailboxSessionMapperFa
     }
 
     public DeleteMessageListener deleteMessageListener() {
-        return new DeleteMessageListener(imapUidDAO, messageIdDAO, messageDAO, attachmentDAOV2, ownerDAO, attachmentMessageIdDAO);
+        return new DeleteMessageListener(imapUidDAO, messageIdDAO, messageDAO, attachmentDAOV2, ownerDAO, attachmentMessageIdDAO, aclMapper, userMailboxRightsDAO);
     }
 }
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/DeleteMessageListener.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/DeleteMessageListener.java
index 81afcd1..1831416 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/DeleteMessageListener.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/DeleteMessageListener.java
@@ -25,20 +25,24 @@ import java.util.Optional;
 
 import javax.inject.Inject;
 
+import org.apache.james.mailbox.acl.ACLDiff;
 import org.apache.james.mailbox.cassandra.ids.CassandraId;
 import org.apache.james.mailbox.cassandra.ids.CassandraMessageId;
+import org.apache.james.mailbox.cassandra.mail.CassandraACLMapper;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAOV2;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentMessageIdDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentOwnerDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraMessageDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraMessageIdDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraMessageIdToImapUidDAO;
+import org.apache.james.mailbox.cassandra.mail.CassandraUserMailboxRightsDAO;
 import org.apache.james.mailbox.cassandra.mail.MessageAttachmentRepresentation;
 import org.apache.james.mailbox.cassandra.mail.MessageRepresentation;
 import org.apache.james.mailbox.events.Event;
 import org.apache.james.mailbox.events.Group;
 import org.apache.james.mailbox.events.MailboxListener;
 import org.apache.james.mailbox.model.ComposedMessageIdWithMetaData;
+import org.apache.james.mailbox.model.MailboxACL;
 import org.apache.james.mailbox.model.MessageMetaData;
 import org.apache.james.mailbox.model.MessageRange;
 import org.apache.james.mailbox.store.mail.MessageMapper;
@@ -53,25 +57,29 @@ public class DeleteMessageListener implements MailboxListener.GroupMailboxListen
 
     }
 
+    private final CassandraMessageIdToImapUidDAO imapUidDAO;
+    private final CassandraMessageIdDAO messageIdDAO;
+    private final CassandraMessageDAO messageDAO;
+    private final CassandraAttachmentDAOV2 attachmentDAO;
+    private final CassandraAttachmentOwnerDAO ownerDAO;
+    private final CassandraAttachmentMessageIdDAO attachmentMessageIdDAO;
+    private final CassandraACLMapper aclMapper;
+    private final CassandraUserMailboxRightsDAO rightsDAO;
+
     @Inject
     public DeleteMessageListener(CassandraMessageIdToImapUidDAO imapUidDAO, CassandraMessageIdDAO messageIdDAO, CassandraMessageDAO messageDAO,
                                  CassandraAttachmentDAOV2 attachmentDAO, CassandraAttachmentOwnerDAO ownerDAO,
-                                 CassandraAttachmentMessageIdDAO attachmentMessageIdDAO) {
+                                 CassandraAttachmentMessageIdDAO attachmentMessageIdDAO, CassandraACLMapper aclMapper, CassandraUserMailboxRightsDAO rightsDAO) {
         this.imapUidDAO = imapUidDAO;
         this.messageIdDAO = messageIdDAO;
         this.messageDAO = messageDAO;
         this.attachmentDAO = attachmentDAO;
         this.ownerDAO = ownerDAO;
         this.attachmentMessageIdDAO = attachmentMessageIdDAO;
+        this.aclMapper = aclMapper;
+        this.rightsDAO = rightsDAO;
     }
 
-    private final CassandraMessageIdToImapUidDAO imapUidDAO;
-    private final CassandraMessageIdDAO messageIdDAO;
-    private final CassandraMessageDAO messageDAO;
-    private final CassandraAttachmentDAOV2 attachmentDAO;
-    private final CassandraAttachmentOwnerDAO ownerDAO;
-    private final CassandraAttachmentMessageIdDAO attachmentMessageIdDAO;
-
     @Override
     public Group getDefaultGroup() {
         return new DeleteMessageListenerGroup();
@@ -105,11 +113,17 @@ public class DeleteMessageListener implements MailboxListener.GroupMailboxListen
                 .concatMap(metadata -> handleDeletion((CassandraMessageId) metadata.getMessageId(), mailboxId)
                     .then(imapUidDAO.delete((CassandraMessageId) metadata.getMessageId(), mailboxId))
                     .then(messageIdDAO.delete(mailboxId, metadata.getUid())))
-                .then()
+                .then(deleteAcl(mailboxId))
                 .block();
         }
     }
 
+    private Mono<Void> deleteAcl(CassandraId mailboxId) {
+        return aclMapper.getACL(mailboxId)
+            .flatMap(acl -> rightsDAO.update(mailboxId, ACLDiff.computeDiff(acl, MailboxACL.EMPTY)))
+            .then(aclMapper.delete(mailboxId));
+    }
+
     private Mono<Void> handleDeletion(CassandraMessageId messageId) {
         return Mono.just(messageId)
             .filterWhen(this::isReferenced)
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java
index 8d14e71..b08c9a0 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java
@@ -24,8 +24,11 @@ import static org.mockito.Mockito.mock;
 import java.util.Collection;
 import java.util.Optional;
 
+import org.apache.commons.lang3.tuple.Pair;
 import org.apache.james.backends.cassandra.CassandraCluster;
 import org.apache.james.backends.cassandra.CassandraClusterExtension;
+import org.apache.james.backends.cassandra.init.configuration.CassandraConfiguration;
+import org.apache.james.backends.cassandra.utils.CassandraUtils;
 import org.apache.james.blob.api.BlobStore;
 import org.apache.james.blob.api.HashBlobId;
 import org.apache.james.core.Username;
@@ -34,17 +37,20 @@ import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.MessageManager;
 import org.apache.james.mailbox.cassandra.ids.CassandraId;
 import org.apache.james.mailbox.cassandra.ids.CassandraMessageId;
+import org.apache.james.mailbox.cassandra.mail.CassandraACLMapper;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentDAOV2;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentMessageIdDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraAttachmentOwnerDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraMessageDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraMessageIdDAO;
 import org.apache.james.mailbox.cassandra.mail.CassandraMessageIdToImapUidDAO;
+import org.apache.james.mailbox.cassandra.mail.CassandraUserMailboxRightsDAO;
 import org.apache.james.mailbox.cassandra.mail.MailboxAggregateModule;
 import org.apache.james.mailbox.events.EventBus;
 import org.apache.james.mailbox.model.AttachmentId;
 import org.apache.james.mailbox.model.ComposedMessageId;
 import org.apache.james.mailbox.model.FetchGroup;
+import org.apache.james.mailbox.model.MailboxACL;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.MessageAttachment;
@@ -65,6 +71,7 @@ import org.testcontainers.shaded.com.google.common.collect.ImmutableList;
 import com.github.fge.lambdas.Throwing;
 
 public class CassandraMailboxManagerTest extends MailboxManagerTest<CassandraMailboxManager> {
+    public static final Username BOB = Username.of("Bob");
     @RegisterExtension
     static CassandraClusterExtension cassandra = new CassandraClusterExtension(MailboxAggregateModule.MODULE_WITH_QUOTA);
 
@@ -518,6 +525,70 @@ public class CassandraMailboxManagerTest extends MailboxManagerTest<CassandraMai
             });
         }
 
+        @Test
+        void deleteMailboxShouldCleanupACL(CassandraCluster cassandraCluster) throws Exception {
+            mailboxManager.setRights(inboxId, new MailboxACL(
+                Pair.of(MailboxACL.EntryKey.createUserEntryKey(BOB), new MailboxACL.Rfc4314Rights(MailboxACL.Right.Read))), session);
+
+            mailboxManager.deleteMailbox(inbox, session);
+
+            SoftAssertions.assertSoftly(softly -> {
+                CassandraId id = (CassandraId) this.inboxId;
+
+                softly.assertThat(aclMapper(cassandraCluster).getACL(id).blockOptional()).isEmpty();
+
+                softly.assertThat(rightsDAO(cassandraCluster).listRightsForUser(BOB).collectList().block()).isEmpty();
+            });
+        }
+
+        @Test
+        void deleteMailboxShouldCleanupACLWhenRightDeleteFails(CassandraCluster cassandraCluster) throws Exception {
+            mailboxManager.setRights(inboxId, new MailboxACL(
+                Pair.of(MailboxACL.EntryKey.createUserEntryKey(BOB), new MailboxACL.Rfc4314Rights(MailboxACL.Right.Read))), session);
+
+            cassandraCluster.getConf().registerScenario(fail()
+                .times(1)
+                .whenQueryStartsWith("DELETE FROM UserMailboxACL WHERE userName=:userName AND mailboxid=:mailboxid;"));
+
+            mailboxManager.deleteMailbox(inbox, session);
+
+            SoftAssertions.assertSoftly(softly -> {
+                CassandraId id = (CassandraId) this.inboxId;
+
+                softly.assertThat(aclMapper(cassandraCluster).getACL(id).blockOptional()).isEmpty();
+
+                softly.assertThat(rightsDAO(cassandraCluster).listRightsForUser(BOB).collectList().block()).isEmpty();
+            });
+        }
+
+        @Test
+        void deleteMailboxShouldCleanupACLWhenACLDeleteFails(CassandraCluster cassandraCluster) throws Exception {
+            mailboxManager.setRights(inboxId, new MailboxACL(
+                Pair.of(MailboxACL.EntryKey.createUserEntryKey(BOB), new MailboxACL.Rfc4314Rights(MailboxACL.Right.Read))), session);
+
+            cassandraCluster.getConf().registerScenario(fail()
+                .times(1)
+                .whenQueryStartsWith("DELETE FROM acl WHERE id=:id IF EXISTS;"));
+
+            mailboxManager.deleteMailbox(inbox, session);
+
+            SoftAssertions.assertSoftly(softly -> {
+                CassandraId id = (CassandraId) this.inboxId;
+
+                softly.assertThat(aclMapper(cassandraCluster).getACL(id).blockOptional()).isEmpty();
+
+                softly.assertThat(rightsDAO(cassandraCluster).listRightsForUser(BOB).collectList().block()).isEmpty();
+            });
+        }
+
+        private CassandraACLMapper aclMapper(CassandraCluster cassandraCluster) {
+            return new CassandraACLMapper(cassandraCluster.getConf(), rightsDAO(cassandraCluster), CassandraConfiguration.DEFAULT_CONFIGURATION);
+        }
+
+        private CassandraUserMailboxRightsDAO rightsDAO(CassandraCluster cassandraCluster) {
+            return new CassandraUserMailboxRightsDAO(cassandraCluster.getConf(), CassandraUtils.WITH_DEFAULT_CONFIGURATION);
+        }
+
         private CassandraAttachmentMessageIdDAO attachmentMessageIdDAO(CassandraCluster cassandraCluster) {
             return new CassandraAttachmentMessageIdDAO(cassandraCluster.getConf(), new CassandraMessageId.Factory());
         }


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