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 <[email protected]> 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: [email protected] For additional commands, e-mail: [email protected]
