JAMES-2186 StoreMessageIdManager should rely on ACLs for right checking
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/49d36aaa Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/49d36aaa Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/49d36aaa Branch: refs/heads/master Commit: 49d36aaa8d44d3140dd06511b66db30afbf458c8 Parents: 465f5b6 Author: benwa <btell...@linagora.com> Authored: Mon Oct 16 16:44:00 2017 +0700 Committer: Matthieu Baechler <matth...@apache.org> Committed: Fri Oct 20 12:34:51 2017 +0200 ---------------------------------------------------------------------- .../CassandraMessageIdManagerStorageTest.java | 11 + .../CassandraMessageIdManagerTestSystem.java | 6 + .../cassandra/CassandraTestSystemFixture.java | 6 +- .../ElasticSearchIntegrationTest.java | 1 + .../search/LuceneMessageSearchIndexTest.java | 1 + .../InMemoryMessageIdManagerTestSystem.java | 6 + .../manager/InMemoryIntegrationResources.java | 1 + .../search/SimpleMessageSearchIndexTest.java | 1 + .../mailbox/store/StoreMessageIdManager.java | 61 ++- .../AbstractMessageIdManagerStorageTest.java | 369 +++++++++++++++++++ .../store/MessageIdManagerTestSystem.java | 3 + .../StoreMessageIdManagerSideEffectTest.java | 15 +- .../store/StoreMessageIdManagerTestSystem.java | 6 + 13 files changed, 448 insertions(+), 39 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/49d36aaa/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerStorageTest.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerStorageTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerStorageTest.java index 85b8dd9..d7b42d4 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerStorageTest.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerStorageTest.java @@ -22,6 +22,7 @@ package org.apache.james.mailbox.cassandra; import static org.mockito.Mockito.mock; import org.apache.james.backends.cassandra.CassandraCluster; +import org.apache.james.backends.cassandra.ContainerLifecycleConfiguration; import org.apache.james.backends.cassandra.DockerCassandraRule; import org.apache.james.backends.cassandra.init.CassandraModuleComposite; import org.apache.james.mailbox.MailboxListener; @@ -45,6 +46,8 @@ import org.apache.james.mailbox.store.quota.NoQuotaManager; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.rules.TestRule; public class CassandraMessageIdManagerStorageTest extends AbstractMessageIdManagerStorageTest { @@ -52,6 +55,14 @@ public class CassandraMessageIdManagerStorageTest extends AbstractMessageIdManag private CassandraCluster cassandra; + public static ContainerLifecycleConfiguration cassandraLifecycleConfiguration = ContainerLifecycleConfiguration.builder() + .iterationsBetweenRestart(20) + .container(cassandraServer.getRawContainer()) + .build(); + + @Rule + public TestRule cassandraLifecycleTestRule = cassandraLifecycleConfiguration.asTestRule(); + @Before public void setUp() throws Exception { CassandraModuleComposite modules = new CassandraModuleComposite( http://git-wip-us.apache.org/repos/asf/james-project/blob/49d36aaa/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerTestSystem.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerTestSystem.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerTestSystem.java index 174cca4..4f35016 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerTestSystem.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerTestSystem.java @@ -30,6 +30,7 @@ import org.apache.james.mailbox.MessageIdManager; import org.apache.james.mailbox.MessageUid; import org.apache.james.mailbox.cassandra.ids.CassandraMessageId; import org.apache.james.mailbox.exception.MailboxException; +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.MessageId; @@ -133,4 +134,9 @@ public class CassandraMessageIdManagerTestSystem extends MessageIdManagerTestSys public int getConstantMessageSize() { return MESSAGE_CONTENT.length; } + + @Override + public void setACL(MailboxId mailboxId, MailboxACL mailboxACL, MailboxSession session) throws MailboxException { + cassandraMailboxManager.setRights(mailboxId, mailboxACL, session); + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/49d36aaa/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraTestSystemFixture.java ---------------------------------------------------------------------- diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraTestSystemFixture.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraTestSystemFixture.java index 161c625..57e2f09 100644 --- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraTestSystemFixture.java +++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraTestSystemFixture.java @@ -58,8 +58,10 @@ public class CassandraTestSystemFixture { return cassandraMailboxManager; } - public static StoreMessageIdManager createMessageIdManager(CassandraMailboxSessionMapperFactory mapperFactory, QuotaManager quotaManager, MailboxEventDispatcher dispatcher) { - return new StoreMessageIdManager(mapperFactory, + public static StoreMessageIdManager createMessageIdManager(CassandraMailboxSessionMapperFactory mapperFactory, QuotaManager quotaManager, MailboxEventDispatcher dispatcher) throws Exception { + return new StoreMessageIdManager( + createMailboxManager(mapperFactory), + mapperFactory, dispatcher, new CassandraMessageId.Factory(), quotaManager, http://git-wip-us.apache.org/repos/asf/james-project/blob/49d36aaa/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/ElasticSearchIntegrationTest.java ---------------------------------------------------------------------- diff --git a/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/ElasticSearchIntegrationTest.java b/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/ElasticSearchIntegrationTest.java index 4f4ca72..0b0013c 100644 --- a/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/ElasticSearchIntegrationTest.java +++ b/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/ElasticSearchIntegrationTest.java @@ -143,6 +143,7 @@ public class ElasticSearchIntegrationTest extends AbstractMessageSearchIndexTest storeMailboxManager.setDelegatingMailboxListener(delegatingListener); messageIdManager = new StoreMessageIdManager( + storeMailboxManager, storeMailboxManager.getMapperFactory(), mailboxEventDispatcher, messageIdFactory, http://git-wip-us.apache.org/repos/asf/james-project/blob/49d36aaa/mailbox/lucene/src/test/java/org/apache/james/mailbox/lucene/search/LuceneMessageSearchIndexTest.java ---------------------------------------------------------------------- diff --git a/mailbox/lucene/src/test/java/org/apache/james/mailbox/lucene/search/LuceneMessageSearchIndexTest.java b/mailbox/lucene/src/test/java/org/apache/james/mailbox/lucene/search/LuceneMessageSearchIndexTest.java index 4da19c5..a60994b 100644 --- a/mailbox/lucene/src/test/java/org/apache/james/mailbox/lucene/search/LuceneMessageSearchIndexTest.java +++ b/mailbox/lucene/src/test/java/org/apache/james/mailbox/lucene/search/LuceneMessageSearchIndexTest.java @@ -64,6 +64,7 @@ public class LuceneMessageSearchIndexTest extends AbstractMessageSearchIndexTest storeMailboxManager.setDelegatingMailboxListener(delegatingListener); messageIdManager = new StoreMessageIdManager( + storeMailboxManager, storeMailboxManager.getMapperFactory(), mailboxEventDispatcher, messageIdFactory, http://git-wip-us.apache.org/repos/asf/james-project/blob/49d36aaa/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/InMemoryMessageIdManagerTestSystem.java ---------------------------------------------------------------------- diff --git a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/InMemoryMessageIdManagerTestSystem.java b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/InMemoryMessageIdManagerTestSystem.java index 01073e8..b7e7ca2 100644 --- a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/InMemoryMessageIdManagerTestSystem.java +++ b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/InMemoryMessageIdManagerTestSystem.java @@ -32,6 +32,7 @@ import org.apache.james.mailbox.MessageUid; import org.apache.james.mailbox.acl.SimpleGroupMembershipResolver; import org.apache.james.mailbox.exception.MailboxException; import org.apache.james.mailbox.inmemory.manager.InMemoryIntegrationResources; +import org.apache.james.mailbox.model.MailboxACL; import org.apache.james.mailbox.model.MailboxId; import org.apache.james.mailbox.model.MailboxMetaData; import org.apache.james.mailbox.model.MailboxPath; @@ -120,4 +121,9 @@ public class InMemoryMessageIdManagerTestSystem extends MessageIdManagerTestSyst public int getConstantMessageSize() { return CONTENT.length; } + + @Override + public void setACL(MailboxId mailboxId, MailboxACL mailboxAcl, MailboxSession session) throws MailboxException { + mailboxManager.setRights(mailboxId, mailboxAcl, session); + } } http://git-wip-us.apache.org/repos/asf/james-project/blob/49d36aaa/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/manager/InMemoryIntegrationResources.java ---------------------------------------------------------------------- diff --git a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/manager/InMemoryIntegrationResources.java b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/manager/InMemoryIntegrationResources.java index f8a8e56..07e592f 100644 --- a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/manager/InMemoryIntegrationResources.java +++ b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/manager/InMemoryIntegrationResources.java @@ -72,6 +72,7 @@ public class InMemoryIntegrationResources implements IntegrationResources<StoreM @Override public MessageIdManager createMessageIdManager(StoreMailboxManager mailboxManager) { return new StoreMessageIdManager( + mailboxManager, mailboxManager.getMapperFactory(), mailboxManager.getEventDispatcher(), new InMemoryMessageId.Factory(), http://git-wip-us.apache.org/repos/asf/james-project/blob/49d36aaa/mailbox/scanning-search/src/test/java/org/apache/james/mailbox/store/search/SimpleMessageSearchIndexTest.java ---------------------------------------------------------------------- diff --git a/mailbox/scanning-search/src/test/java/org/apache/james/mailbox/store/search/SimpleMessageSearchIndexTest.java b/mailbox/scanning-search/src/test/java/org/apache/james/mailbox/store/search/SimpleMessageSearchIndexTest.java index 358119c..1524da0 100644 --- a/mailbox/scanning-search/src/test/java/org/apache/james/mailbox/store/search/SimpleMessageSearchIndexTest.java +++ b/mailbox/scanning-search/src/test/java/org/apache/james/mailbox/store/search/SimpleMessageSearchIndexTest.java @@ -62,6 +62,7 @@ public class SimpleMessageSearchIndexTest extends AbstractMessageSearchIndexTest storeMailboxManager.setDelegatingMailboxListener(delegatingListener); messageIdManager = new StoreMessageIdManager( + storeMailboxManager, storeMailboxManager.getMapperFactory(), mailboxEventDispatcher, messageIdFactory, http://git-wip-us.apache.org/repos/asf/james-project/blob/49d36aaa/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageIdManager.java ---------------------------------------------------------------------- diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageIdManager.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageIdManager.java index a038d53..6e4bd60 100644 --- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageIdManager.java +++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageIdManager.java @@ -34,12 +34,14 @@ import javax.inject.Inject; import javax.mail.Flags; import javax.mail.internet.SharedInputStream; +import org.apache.james.mailbox.MailboxManager; import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.MessageIdManager; import org.apache.james.mailbox.MessageManager; import org.apache.james.mailbox.MessageUid; 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.MailboxId; import org.apache.james.mailbox.model.MessageAttachment; import org.apache.james.mailbox.model.MessageId; @@ -61,6 +63,7 @@ import org.apache.james.mailbox.store.quota.QuotaChecker; 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.ImmutableList; import com.google.common.collect.ImmutableSet; @@ -70,6 +73,7 @@ import com.google.common.collect.Sets.SetView; public class StoreMessageIdManager implements MessageIdManager { private static final Logger LOGGER = LoggerFactory.getLogger(StoreMessageIdManager.class); + private final MailboxManager mailboxManager; private final MailboxSessionMapperFactory mailboxSessionMapperFactory; private final MailboxEventDispatcher dispatcher; private final MessageId.Factory messageIdFactory; @@ -77,9 +81,10 @@ public class StoreMessageIdManager implements MessageIdManager { private final QuotaRootResolver quotaRootResolver; @Inject - public StoreMessageIdManager(MailboxSessionMapperFactory mailboxSessionMapperFactory, MailboxEventDispatcher dispatcher, - MessageId.Factory messageIdFactory, + public StoreMessageIdManager(MailboxManager mailboxManager, MailboxSessionMapperFactory mailboxSessionMapperFactory, + MailboxEventDispatcher dispatcher, MessageId.Factory messageIdFactory, QuotaManager quotaManager, QuotaRootResolver quotaRootResolver) { + this.mailboxManager = mailboxManager; this.mailboxSessionMapperFactory = mailboxSessionMapperFactory; this.dispatcher = dispatcher; this.messageIdFactory = messageIdFactory; @@ -90,9 +95,8 @@ public class StoreMessageIdManager implements MessageIdManager { @Override public void setFlags(Flags newState, MessageManager.FlagsUpdateMode replace, MessageId messageId, List<MailboxId> mailboxIds, MailboxSession mailboxSession) throws MailboxException { MessageIdMapper messageIdMapper = mailboxSessionMapperFactory.getMessageIdMapper(mailboxSession); - MailboxMapper mailboxMapper = mailboxSessionMapperFactory.getMailboxMapper(mailboxSession); - allowOnMailboxSession(mailboxIds, mailboxSession, mailboxMapper); + assertRightsOnMailboxes(mailboxIds, mailboxSession, MailboxACL.Right.Write); Map<MailboxId, UpdatedFlags> updatedFlags = messageIdMapper.setFlags(messageId, mailboxIds, newState, replace); for (Map.Entry<MailboxId, UpdatedFlags> entry : updatedFlags.entrySet()) { @@ -103,10 +107,9 @@ public class StoreMessageIdManager implements MessageIdManager { @Override public Set<MessageId> accessibleMessages(Collection<MessageId> messageIds, MailboxSession mailboxSession) throws MailboxException { MessageIdMapper messageIdMapper = mailboxSessionMapperFactory.getMessageIdMapper(mailboxSession); - MailboxMapper mailboxMapper = mailboxSessionMapperFactory.getMailboxMapper(mailboxSession); List<MailboxMessage> messageList = messageIdMapper.find(messageIds, MessageMapper.FetchType.Metadata); return messageList.stream() - .filter(message -> mailboxBelongsToUser(mailboxSession, mailboxMapper).test(message.getMailboxId())) + .filter(hasRightsOn(mailboxSession, MailboxACL.Right.Read)) .map(message -> message.getComposedMessageIdWithMetaData().getComposedMessageId().getMessageId()) .collect(Guavate.toImmutableSet()); } @@ -115,12 +118,12 @@ public class StoreMessageIdManager implements MessageIdManager { public List<MessageResult> getMessages(List<MessageId> messageIds, MessageResult.FetchGroup fetchGroup, MailboxSession mailboxSession) throws MailboxException { try { MessageIdMapper messageIdMapper = mailboxSessionMapperFactory.getMessageIdMapper(mailboxSession); - MailboxMapper mailboxMapper = mailboxSessionMapperFactory.getMailboxMapper(mailboxSession); List<MailboxMessage> messageList = messageIdMapper.find(messageIds, MessageMapper.FetchType.Full); ImmutableSet<MailboxId> allowedMailboxIds = messageList.stream() .map(MailboxMessage::getMailboxId) - .filter(mailboxBelongsToUser(mailboxSession, mailboxMapper)) + .distinct() + .filter(hasRightsOnMailbox(mailboxSession, MailboxACL.Right.Read)) .collect(Guavate.toImmutableSet()); return messageList.stream() @@ -137,7 +140,7 @@ public class StoreMessageIdManager implements MessageIdManager { MessageIdMapper messageIdMapper = mailboxSessionMapperFactory.getMessageIdMapper(mailboxSession); MailboxMapper mailboxMapper = mailboxSessionMapperFactory.getMailboxMapper(mailboxSession); - allowOnMailboxSession(mailboxIds, mailboxSession, mailboxMapper); + assertRightsOnMailboxes(mailboxIds, mailboxSession, MailboxACL.Right.DeleteMessages); ImmutableList<MetadataWithMailboxId> metadatasWithMailbox = messageIdMapper.find(ImmutableList.of(messageId), MessageMapper.FetchType.Metadata) .stream() @@ -159,11 +162,11 @@ public class StoreMessageIdManager implements MessageIdManager { MessageIdMapper messageIdMapper = mailboxSessionMapperFactory.getMessageIdMapper(mailboxSession); MailboxMapper mailboxMapper = mailboxSessionMapperFactory.getMailboxMapper(mailboxSession); - allowOnMailboxSession(mailboxIds, mailboxSession, mailboxMapper); - + assertRightsOnMailboxes(mailboxIds, mailboxSession, MailboxACL.Right.Read); + List<MailboxMessage> mailboxMessages = messageIdMapper.find(ImmutableList.of(messageId), MessageMapper.FetchType.Metadata) .stream() - .filter(messageBelongsToUser(mailboxSession, mailboxMapper)) + .filter(hasRightsOn(mailboxSession, MailboxACL.Right.Read)) .collect(Guavate.toImmutableList()); if (!mailboxMessages.isEmpty()) { @@ -175,6 +178,9 @@ public class StoreMessageIdManager implements MessageIdManager { List<MailboxId> mailboxesToRemove = ImmutableList.copyOf(Sets.difference(currentMailboxes, targetMailboxes)); SetView<MailboxId> mailboxesToAdd = Sets.difference(targetMailboxes, currentMailboxes); + assertRightsOnMailboxes(mailboxesToAdd, mailboxSession, MailboxACL.Right.Insert); + assertRightsOnMailboxes(mailboxesToRemove, mailboxSession, MailboxACL.Right.DeleteMessages); + MailboxMessage mailboxMessage = mailboxMessages.get(0); validateQuota(mailboxesToAdd, mailboxesToRemove, mailboxSession, mailboxMessage); @@ -273,26 +279,18 @@ public class StoreMessageIdManager implements MessageIdManager { return mailboxMessage -> mailboxIds.contains(mailboxMessage.getMailboxId()); } - private Predicate<MailboxId> mailboxBelongsToUser(MailboxSession mailboxSession, MailboxMapper mailboxMapper) { - return mailboxId -> { - try { - Mailbox currentMailbox = mailboxMapper.findMailboxById(mailboxId); - return belongsToCurrentUser(currentMailbox, mailboxSession); - } catch (MailboxException e) { - LOGGER.error(String.format("Can not retrieve mailboxPath associated with %s", mailboxId.serialize()), e); - return false; - } - }; + private Predicate<MailboxMessage> hasRightsOn(MailboxSession session, MailboxACL.Right... rights) { + return message -> hasRightsOnMailbox(session, rights).test(message.getMailboxId()); } - private Predicate<MailboxMessage> messageBelongsToUser(MailboxSession mailboxSession, MailboxMapper mailboxMapper) { - return mailboxMessage -> mailboxBelongsToUser(mailboxSession, mailboxMapper) - .test(mailboxMessage.getMailboxId()); + private Predicate<MailboxId> hasRightsOnMailbox(MailboxSession session, MailboxACL.Right... rights) { + return Throwing.predicate((MailboxId mailboxId) -> mailboxManager.myRights(mailboxId, session).contains(rights)) + .fallbackTo(any -> false); } - private void allowOnMailboxSession(List<MailboxId> mailboxIds, MailboxSession mailboxSession, MailboxMapper mailboxMapper) throws MailboxNotFoundException { + private void assertRightsOnMailboxes(Collection<MailboxId> mailboxIds, MailboxSession mailboxSession, MailboxACL.Right... rights) throws MailboxNotFoundException { Optional<MailboxId> mailboxForbidden = mailboxIds.stream() - .filter(isMailboxOfOtherUser(mailboxSession, mailboxMapper)) + .filter(hasRightsOnMailbox(mailboxSession, rights).negate()) .findFirst(); if (mailboxForbidden.isPresent()) { @@ -301,15 +299,6 @@ public class StoreMessageIdManager implements MessageIdManager { } } - private Predicate<MailboxId> isMailboxOfOtherUser(MailboxSession mailboxSession, MailboxMapper mailboxMapper) { - return mailboxBelongsToUser(mailboxSession, mailboxMapper) - .negate(); - } - - private boolean belongsToCurrentUser(Mailbox mailbox, MailboxSession session) { - return session.getUser().isSameUser(mailbox.getUser()); - } - private static class MetadataWithMailboxId { private final MessageMetaData messageMetaData; private final MailboxId mailboxId; http://git-wip-us.apache.org/repos/asf/james-project/blob/49d36aaa/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerStorageTest.java ---------------------------------------------------------------------- diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerStorageTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerStorageTest.java index 72bbfb8..d0e0cdb 100644 --- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerStorageTest.java +++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerStorageTest.java @@ -20,9 +20,11 @@ package org.apache.james.mailbox.store; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.function.Predicate; import javax.mail.Flags; @@ -36,6 +38,7 @@ import org.apache.james.mailbox.exception.MailboxNotFoundException; import org.apache.james.mailbox.fixture.MailboxFixture; import org.apache.james.mailbox.mock.MockMailboxSession; import org.apache.james.mailbox.model.FetchGroupImpl; +import org.apache.james.mailbox.model.MailboxACL; import org.apache.james.mailbox.model.MailboxId; import org.apache.james.mailbox.model.MessageId; import org.apache.james.mailbox.model.MessageResult; @@ -534,4 +537,370 @@ public abstract class AbstractMessageIdManagerStorageTest { return messageResult -> messageResult.getMailboxId().equals(mailboxId); } + @Test + public void getMessagesShouldReturnMessagesWhenReadDelegated() throws Exception { + testingData.setACL(aliceMailbox1.getMailboxId(), + MailboxACL.EMPTY.apply( + MailboxACL.command() + .forUser(MailboxFixture.OTHER_USER) + .rights(new MailboxACL.Rfc4314Rights(MailboxACL.Right.Read)) + .asAddition()), + aliceSession); + MessageId messageId = testingData.persist(aliceMailbox1.getMailboxId(), messageUid1, FLAGS, aliceSession); + + List<MessageResult> messages = messageIdManager.getMessages(ImmutableList.of(messageId), + FetchGroupImpl.MINIMAL, bobSession); + + assertThat(messages) + .extracting(MessageResult::getMessageId) + .containsOnly(messageId); + } + + @Test + public void getMessagesShouldNotReturnMessagesWhenNotReadDelegated() throws Exception { + testingData.setACL(aliceMailbox1.getMailboxId(), + MailboxACL.EMPTY.apply( + MailboxACL.command() + .forUser(MailboxFixture.OTHER_USER) + .rights(MailboxACL.Rfc4314Rights.allExcept(MailboxACL.Right.Read)) + .asAddition()), + aliceSession); + MessageId messageId = testingData.persist(aliceMailbox1.getMailboxId(), messageUid1, FLAGS, aliceSession); + + List<MessageResult> messages = messageIdManager.getMessages(ImmutableList.of(messageId), FetchGroupImpl.MINIMAL, bobSession); + + assertThat(messages) + .isEmpty(); + } + + @Test + public void setFlagsShouldUpdateFlagsWhenWriteDelegated() throws Exception { + testingData.setACL(aliceMailbox1.getMailboxId(), + MailboxACL.EMPTY.apply( + MailboxACL.command() + .forUser(MailboxFixture.OTHER_USER) + .rights(new MailboxACL.Rfc4314Rights(MailboxACL.Right.Write)) + .asAddition()), + aliceSession); + MessageId messageId = testingData.persist(aliceMailbox1.getMailboxId(), messageUid1, FLAGS, aliceSession); + + Flags newFlags = new Flags(Flags.Flag.SEEN); + messageIdManager.setFlags(newFlags, MessageManager.FlagsUpdateMode.REPLACE, + messageId, ImmutableList.of(aliceMailbox1.getMailboxId()), bobSession); + + List<MessageResult> messages = messageIdManager.getMessages(ImmutableList.of(messageId), FetchGroupImpl.MINIMAL, aliceSession); + assertThat(messages) + .extracting(MessageResult::getFlags) + .containsOnly(newFlags); + } + + @Test + public void setFlagsShouldNotUpdateFlagsWhenNotWriteDelegated() throws Exception { + testingData.setACL(aliceMailbox1.getMailboxId(), + MailboxACL.EMPTY.apply( + MailboxACL.command() + .forUser(MailboxFixture.OTHER_USER) + .rights(MailboxACL.Rfc4314Rights.allExcept(MailboxACL.Right.Write)) + .asAddition()), + aliceSession); + MessageId messageId = testingData.persist(aliceMailbox1.getMailboxId(), messageUid1, FLAGS, aliceSession); + + assertThatThrownBy(() -> + messageIdManager.setFlags(new Flags(Flags.Flag.SEEN), MessageManager.FlagsUpdateMode.REPLACE, + messageId, ImmutableList.of(aliceMailbox1.getMailboxId()), bobSession)) + .isInstanceOf(MailboxNotFoundException.class); + + List<MessageResult> messages = messageIdManager.getMessages(ImmutableList.of(messageId), FetchGroupImpl.MINIMAL, aliceSession); + assertThat(messages) + .extracting(MessageResult::getFlags) + .containsOnly(FLAGS); + } + + @Test + public void setInMailboxesShouldAllowCopyingMessageFromReadOnlySharedMailbox() throws Exception { + //Given + testingData.setACL(aliceMailbox1.getMailboxId(), + MailboxACL.EMPTY.apply( + MailboxACL.command() + .forUser(MailboxFixture.OTHER_USER) + .rights(new MailboxACL.Rfc4314Rights(MailboxACL.Right.Read)) + .asAddition()), + aliceSession); + MessageId messageId = testingData.persist(aliceMailbox1.getMailboxId(), messageUid1, FLAGS, aliceSession); + + //When + messageIdManager.setInMailboxes(messageId, ImmutableList.of(aliceMailbox1.getMailboxId(), bobMailbox1.getMailboxId()), bobSession); + + //Then + List<MessageResult> messages = messageIdManager.getMessages(ImmutableList.of(messageId), FetchGroupImpl.MINIMAL, bobSession); + assertThat(messages) + .extracting(MessageResult::getMessageId) + .containsOnly(messageId, messageId); + assertThat(messages) + .extracting(MessageResult::getMailboxId) + .containsOnly(aliceMailbox1.getMailboxId(), bobMailbox1.getMailboxId()); + } + + @Test + public void setInMailboxesShouldDenyCopyingMessageFromNotReadSharedMailbox() throws Exception { + //Given + testingData.setACL(aliceMailbox1.getMailboxId(), + MailboxACL.EMPTY.apply( + MailboxACL.command() + .forUser(MailboxFixture.OTHER_USER) + .rights(MailboxACL.Rfc4314Rights.allExcept(MailboxACL.Right.Read)) + .asAddition()), + aliceSession); + MessageId messageId = testingData.persist(aliceMailbox1.getMailboxId(), messageUid1, FLAGS, aliceSession); + + //When + assertThatThrownBy(() -> + messageIdManager.setInMailboxes(messageId, + ImmutableList.of(aliceMailbox1.getMailboxId(), bobMailbox1.getMailboxId()), + bobSession)) + .isInstanceOf(MailboxNotFoundException.class); + + //Then + List<MessageResult> messages = messageIdManager.getMessages( + ImmutableList.of(messageId), + FetchGroupImpl.MINIMAL, + bobSession); + assertThat(messages) + .isEmpty(); + } + + @Test + public void setInMailboxesShouldAllowCopyingToAInsertSharedMailbox() throws Exception { + //Given + testingData.setACL(aliceMailbox1.getMailboxId(), + MailboxACL.EMPTY.apply( + MailboxACL.command() + .forUser(MailboxFixture.OTHER_USER) + .rights(new MailboxACL.Rfc4314Rights(MailboxACL.Right.Insert, MailboxACL.Right.Read)) + .asAddition()), + aliceSession); + MessageId messageId = testingData.persist(bobMailbox1.getMailboxId(), messageUid1, FLAGS, bobSession); + + //When + messageIdManager.setInMailboxes(messageId, ImmutableList.of(aliceMailbox1.getMailboxId(), bobMailbox1.getMailboxId()), bobSession); + + //Then + List<MessageResult> messages = messageIdManager.getMessages( + ImmutableList.of(messageId), + FetchGroupImpl.MINIMAL, + aliceSession); + assertThat(messages) + .extracting(MessageResult::getMessageId) + .containsOnly(messageId); + assertThat(messages) + .extracting(MessageResult::getMailboxId) + .containsOnly(aliceMailbox1.getMailboxId()); + } + + @Test + public void setInMailboxesShouldDenyCopyingToANonInsertSharedMailbox() throws Exception { + //Given + testingData.setACL(aliceMailbox1.getMailboxId(), + MailboxACL.EMPTY.apply( + MailboxACL.command() + .forUser(MailboxFixture.OTHER_USER) + .rights(MailboxACL.Rfc4314Rights.allExcept(MailboxACL.Right.Insert)) + .asAddition()), + aliceSession); + MessageId messageId = testingData.persist(bobMailbox1.getMailboxId(), messageUid1, FLAGS, bobSession); + + //When + assertThatThrownBy(() -> + messageIdManager.setInMailboxes(messageId, + ImmutableList.of(aliceMailbox1.getMailboxId(), bobMailbox1.getMailboxId()), + bobSession)) + .isInstanceOf(MailboxNotFoundException.class); + + //Then + List<MessageResult> messages = messageIdManager.getMessages( + ImmutableList.of(messageId), + FetchGroupImpl.MINIMAL, + bobSession); + assertThat(messages) + .extracting(MessageResult::getMessageId) + .containsOnly(messageId); + assertThat(messages) + .extracting(MessageResult::getMailboxId) + .containsOnly(bobMailbox1.getMailboxId()); + } + + @Test + public void setInMailboxesShouldAllowMovingMessagesFromASharedMailboxWhenDeleteRight() throws Exception { + //Given + testingData.setACL(aliceMailbox1.getMailboxId(), + MailboxACL.EMPTY.apply( + MailboxACL.command() + .forUser(MailboxFixture.OTHER_USER) + .rights(new MailboxACL.Rfc4314Rights(MailboxACL.Right.Lookup, MailboxACL.Right.Read, MailboxACL.Right.DeleteMessages)) + .asAddition()), + aliceSession); + MessageId messageId = testingData.persist(aliceMailbox1.getMailboxId(), messageUid1, FLAGS, aliceSession); + + //When + messageIdManager.setInMailboxes(messageId, ImmutableList.of(bobMailbox1.getMailboxId()), bobSession); + + //Then + List<MessageResult> messages = messageIdManager.getMessages( + ImmutableList.of(messageId), + FetchGroupImpl.MINIMAL, + bobSession); + assertThat(messages) + .extracting(MessageResult::getMessageId) + .containsOnly(messageId); + assertThat(messages) + .extracting(MessageResult::getMailboxId) + .containsOnly(bobMailbox1.getMailboxId()); + } + + @Test + public void setInMailboxesShouldDenyMovingMessagesFromASharedMailboxWhenNoDeleteRight() throws Exception { + //Given + testingData.setACL(aliceMailbox1.getMailboxId(), + MailboxACL.EMPTY.apply( + MailboxACL.command() + .forUser(MailboxFixture.OTHER_USER) + .rights(MailboxACL.Rfc4314Rights.allExcept(MailboxACL.Right.DeleteMessages)) + .asAddition()), + aliceSession); + MessageId messageId = testingData.persist(aliceMailbox1.getMailboxId(), messageUid1, FLAGS, aliceSession); + + //When + assertThatThrownBy(() -> + messageIdManager.setInMailboxes(messageId, + ImmutableList.of(bobMailbox1.getMailboxId()), + bobSession)) + .isInstanceOf(MailboxNotFoundException.class); + + //Then + List<MessageResult> messages = messageIdManager.getMessages( + ImmutableList.of(messageId), + FetchGroupImpl.MINIMAL, + bobSession); + assertThat(messages) + .extracting(MessageResult::getMessageId) + .containsOnly(messageId); + assertThat(messages) + .extracting(MessageResult::getMailboxId) + .containsOnly(aliceMailbox1.getMailboxId()); + } + + @Test + public void setInMailboxShouldAllowDistinctMailboxSetForShareeAndOwner() throws Exception { + //Given + testingData.setACL(aliceMailbox2.getMailboxId(), + MailboxACL.EMPTY.apply( + MailboxACL.command() + .forUser(MailboxFixture.OTHER_USER) + .rights(MailboxACL.FULL_RIGHTS) + .asAddition()), + aliceSession); + MessageId messageId = testingData.persist(aliceMailbox1.getMailboxId(), messageUid1, FLAGS, aliceSession); + messageIdManager.setInMailboxes(messageId, ImmutableList.of(aliceMailbox1.getMailboxId(), aliceMailbox2.getMailboxId()), aliceSession); + + //When + messageIdManager.setInMailboxes(messageId, + ImmutableList.of(bobMailbox1.getMailboxId(), aliceMailbox2.getMailboxId()), + bobSession); + + //Then + List<MessageResult> messagesForSharee = messageIdManager.getMessages( + ImmutableList.of(messageId), + FetchGroupImpl.MINIMAL, + bobSession); + assertThat(messagesForSharee) + .extracting(MessageResult::getMessageId) + .containsOnly(messageId, messageId); + assertThat(messagesForSharee) + .extracting(MessageResult::getMailboxId) + .containsOnly(aliceMailbox2.getMailboxId(), bobMailbox1.getMailboxId()); + + List<MessageResult> messagesForOwner = messageIdManager.getMessages( + ImmutableList.of(messageId), + FetchGroupImpl.MINIMAL, + aliceSession); + assertThat(messagesForOwner) + .extracting(MessageResult::getMessageId) + .containsOnly(messageId, messageId); + assertThat(messagesForOwner) + .extracting(MessageResult::getMailboxId) + .containsOnly(aliceMailbox1.getMailboxId(), aliceMailbox2.getMailboxId()); + } + + @Test + public void deleteShouldRemoveMessagesFromSharedMailboxWhenAllowed() throws Exception { + testingData.setACL(aliceMailbox1.getMailboxId(), + MailboxACL.EMPTY.apply( + MailboxACL.command() + .forUser(MailboxFixture.OTHER_USER) + .rights(new MailboxACL.Rfc4314Rights(MailboxACL.Right.Read, MailboxACL.Right.Lookup, MailboxACL.Right.DeleteMessages)) + .asAddition()), + aliceSession); + MessageId messageId = testingData.persist(aliceMailbox1.getMailboxId(), messageUid1, FLAGS, aliceSession); + + messageIdManager.delete(messageId, ImmutableList.of(aliceMailbox1.getMailboxId()), bobSession); + + List<MessageResult> messages = messageIdManager.getMessages(ImmutableList.of(messageId), FetchGroupImpl.MINIMAL, aliceSession); + assertThat(messages) + .isEmpty(); + } + + @Test + public void deleteShouldNotRemoveMessagesFromSharedMailboxWhenNotAllowed() throws Exception { + testingData.setACL(aliceMailbox1.getMailboxId(), + MailboxACL.EMPTY.apply( + MailboxACL.command() + .forUser(MailboxFixture.OTHER_USER) + .rights(MailboxACL.Rfc4314Rights.allExcept(MailboxACL.Right.DeleteMessages)) + .asAddition()), + aliceSession); + MessageId messageId = testingData.persist(aliceMailbox1.getMailboxId(), messageUid1, FLAGS, aliceSession); + + assertThatThrownBy(() -> + messageIdManager.delete(messageId, ImmutableList.of(aliceMailbox1.getMailboxId()), bobSession)) + .isInstanceOf(MailboxNotFoundException.class); + + List<MessageResult> messages = messageIdManager.getMessages(ImmutableList.of(messageId), FetchGroupImpl.MINIMAL, aliceSession); + assertThat(messages) + .extracting(MessageResult::getMessageId) + .containsOnly(messageId); + } + + @Test + public void accessibleMessagesShouldReturnMessagesWhenReadDelegated() throws Exception { + testingData.setACL(aliceMailbox1.getMailboxId(), + MailboxACL.EMPTY.apply( + MailboxACL.command() + .forUser(MailboxFixture.OTHER_USER) + .rights(new MailboxACL.Rfc4314Rights(MailboxACL.Right.Read, MailboxACL.Right.Lookup)) + .asAddition()), + aliceSession); + MessageId messageId = testingData.persist(aliceMailbox1.getMailboxId(), messageUid1, FLAGS, aliceSession); + + Set<MessageId> messages = messageIdManager.accessibleMessages(ImmutableList.of(messageId), bobSession); + + assertThat(messages) + .containsOnly(messageId); + } + + @Test + public void accessibleMessagesShouldNotReturnMessagesWhenNotReadDelegated() throws Exception { + testingData.setACL(aliceMailbox1.getMailboxId(), + MailboxACL.EMPTY.apply( + MailboxACL.command() + .forUser(MailboxFixture.OTHER_USER) + .rights(MailboxACL.Rfc4314Rights.allExcept(MailboxACL.Right.Read)) + .asAddition()), + aliceSession); + MessageId messageId = testingData.persist(aliceMailbox1.getMailboxId(), messageUid1, FLAGS, aliceSession); + + Set<MessageId> messages = messageIdManager.accessibleMessages(ImmutableList.of(messageId), bobSession); + + assertThat(messages) + .isEmpty(); + } } http://git-wip-us.apache.org/repos/asf/james-project/blob/49d36aaa/mailbox/store/src/test/java/org/apache/james/mailbox/store/MessageIdManagerTestSystem.java ---------------------------------------------------------------------- diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/MessageIdManagerTestSystem.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/MessageIdManagerTestSystem.java index 0fb31dc..c04aed9 100644 --- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/MessageIdManagerTestSystem.java +++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/MessageIdManagerTestSystem.java @@ -25,6 +25,7 @@ import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.MessageIdManager; import org.apache.james.mailbox.MessageUid; import org.apache.james.mailbox.exception.MailboxException; +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.MessageId; @@ -61,4 +62,6 @@ public abstract class MessageIdManagerTestSystem { public abstract void deleteMailbox(MailboxId mailboxId, MailboxSession session); public abstract int getConstantMessageSize(); + + public abstract void setACL(MailboxId mailboxId, MailboxACL mailboxACL, MailboxSession session) throws MailboxException; } http://git-wip-us.apache.org/repos/asf/james-project/blob/49d36aaa/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMessageIdManagerSideEffectTest.java ---------------------------------------------------------------------- diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMessageIdManagerSideEffectTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMessageIdManagerSideEffectTest.java index 6fb614b..4349dce 100644 --- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMessageIdManagerSideEffectTest.java +++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMessageIdManagerSideEffectTest.java @@ -19,7 +19,15 @@ package org.apache.james.mailbox.store; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.apache.james.mailbox.MailboxManager; +import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.MessageIdManager; +import org.apache.james.mailbox.model.MailboxACL; +import org.apache.james.mailbox.model.MailboxId; import org.apache.james.mailbox.model.MessageId; import org.apache.james.mailbox.model.TestMessageId; import org.apache.james.mailbox.quota.QuotaManager; @@ -39,7 +47,12 @@ public class StoreMessageIdManagerSideEffectTest extends AbstractMessageIdManage TestMailboxSessionMapperFactory testMailboxSessionMapperFactory = new TestMailboxSessionMapperFactory(); MessageId.Factory messageIdFactory = new TestMessageId.Factory(); - MessageIdManager messageIdManager = new StoreMessageIdManager(testMailboxSessionMapperFactory, dispatcher, messageIdFactory, + MailboxManager mailboxManager = mock(MailboxManager.class); + when(mailboxManager.myRights(any(MailboxId.class), any(MailboxSession.class))) + .thenReturn(MailboxACL.FULL_RIGHTS); + + MessageIdManager messageIdManager = new StoreMessageIdManager(mailboxManager, + testMailboxSessionMapperFactory, dispatcher, messageIdFactory, quotaManager, new DefaultQuotaRootResolver(testMailboxSessionMapperFactory)); return new StoreMessageIdManagerTestSystem(messageIdManager, http://git-wip-us.apache.org/repos/asf/james-project/blob/49d36aaa/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMessageIdManagerTestSystem.java ---------------------------------------------------------------------- diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMessageIdManagerTestSystem.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMessageIdManagerTestSystem.java index c312921..251d0d4 100644 --- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMessageIdManagerTestSystem.java +++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMessageIdManagerTestSystem.java @@ -34,6 +34,7 @@ import org.apache.james.mailbox.MessageIdManager; import org.apache.james.mailbox.MessageUid; import org.apache.james.mailbox.exception.MailboxException; import org.apache.james.mailbox.mock.MockMailboxSession; +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.MessageId; @@ -104,4 +105,9 @@ public class StoreMessageIdManagerTestSystem extends MessageIdManagerTestSystem public int getConstantMessageSize() { throw new NotImplementedException(); } + + @Override + public void setACL(MailboxId mailboxId, MailboxACL mailboxACL, MailboxSession session) throws MailboxException { + throw new NotImplementedException(); + } } --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org