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