From 4721157f4cfe474f2a6724cd41b61b569dfdaa56 Mon Sep 17 00:00:00 2001
From: benwa <btellier@linagora.com>
Date: Wed, 6 May 2015 16:52:45 +0200
Subject: [PATCH] MAILBOX-11 Add filters on namespace and user for search
 results in StoreMailboxManager. Tests provided on memory module and Memory
 mailbox mapper should return only results in the requested Namespace for the
 given user

---
 .../james/mailbox/AbstractMailboxManagerTest.java  |   4 +-
 memory/pom.xml                                     |   5 +
 .../inmemory/mail/InMemoryMailboxMapper.java       |   8 +-
 .../inmemory/InMemoryMailboxManagerTest.java       |  38 +++++++-
 .../inmemory/InMemoryMailboxMapperTest.java        |  85 +++++++++++++++++
 .../james/mailbox/store/StoreMailboxManager.java   |  31 +++++--
 .../mailbox/store/StoreMailboxManagerTest.java     | 101 +++++++++++++++++++++
 7 files changed, 256 insertions(+), 16 deletions(-)
 create mode 100644 memory/src/test/java/org/apache/james/mailbox/inmemory/InMemoryMailboxMapperTest.java
 create mode 100644 store/src/test/java/org/apache/james/mailbox/store/StoreMailboxManagerTest.java

diff --git a/api/src/test/java/org/apache/james/mailbox/AbstractMailboxManagerTest.java b/api/src/test/java/org/apache/james/mailbox/AbstractMailboxManagerTest.java
index 839a736..7a358c5 100644
--- a/api/src/test/java/org/apache/james/mailbox/AbstractMailboxManagerTest.java
+++ b/api/src/test/java/org/apache/james/mailbox/AbstractMailboxManagerTest.java
@@ -45,8 +45,8 @@ import org.slf4j.LoggerFactory;
  */
 public abstract class AbstractMailboxManagerTest {
     
-    private final static String USER_1 = "USER_1";
-    private final static String USER_2 = "USER_2";
+    public final static String USER_1 = "USER_1";
+    public final static String USER_2 = "USER_2";
 
     /**
      * The mailboxManager that needs to get instanciated
diff --git a/memory/pom.xml b/memory/pom.xml
index 25b6150..7ee075f 100644
--- a/memory/pom.xml
+++ b/memory/pom.xml
@@ -70,5 +70,10 @@
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 </project>
diff --git a/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryMailboxMapper.java b/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryMailboxMapper.java
index bb84761..7578e48 100644
--- a/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryMailboxMapper.java
+++ b/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryMailboxMapper.java
@@ -79,13 +79,19 @@ public class InMemoryMailboxMapper implements MailboxMapper<Long> {
         final String regex = path.getName().replace("%", ".*");
         List<Mailbox<Long>> results = new ArrayList<Mailbox<Long>>();
         for (final Mailbox<Long> mailbox:mailboxesById.values()) {
-            if (mailbox.getName().matches(regex)) {
+            if (mailboxMatchesRegex(mailbox, path, regex)) {
                 results.add(mailbox);
             }
         }
         return results;
     }
 
+    private boolean mailboxMatchesRegex(Mailbox<Long> mailbox, MailboxPath path, String regex) {
+        return mailbox.getNamespace().equals(path.getNamespace())
+            && mailbox.getUser().equals(path.getUser())
+            && mailbox.getName().matches(regex);
+    }
+
     /**
      * @see org.apache.james.mailbox.store.mail.MailboxMapper#save(org.apache.james.mailbox.store.mail.model.Mailbox)
      */
diff --git a/memory/src/test/java/org/apache/james/mailbox/inmemory/InMemoryMailboxManagerTest.java b/memory/src/test/java/org/apache/james/mailbox/inmemory/InMemoryMailboxManagerTest.java
index b9be470..a777392 100644
--- a/memory/src/test/java/org/apache/james/mailbox/inmemory/InMemoryMailboxManagerTest.java
+++ b/memory/src/test/java/org/apache/james/mailbox/inmemory/InMemoryMailboxManagerTest.java
@@ -18,6 +18,8 @@
  ****************************************************************/
 package org.apache.james.mailbox.inmemory;
 
+import static org.assertj.core.api.Assertions.assertThat;
+
 import org.apache.james.mailbox.AbstractMailboxManagerTest;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.acl.GroupMembershipResolver;
@@ -26,17 +28,25 @@ import org.apache.james.mailbox.acl.SimpleGroupMembershipResolver;
 import org.apache.james.mailbox.acl.UnionMailboxACLResolver;
 import org.apache.james.mailbox.exception.BadCredentialsException;
 import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.model.MailboxMetaData;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.MailboxQuery;
 import org.apache.james.mailbox.store.MockAuthenticator;
 import org.apache.james.mailbox.store.StoreMailboxManager;
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Test;
 import org.slf4j.LoggerFactory;
 
+import java.util.List;
+
 /**
  * InMemoryMailboxManagerTest that extends the MailboxManagerTest.
  */
 public class InMemoryMailboxManagerTest extends AbstractMailboxManagerTest {
-    
+
+    private MailboxSession session;
+
     /**
      * Setup the mailboxManager.
      * 
@@ -45,6 +55,9 @@ public class InMemoryMailboxManagerTest extends AbstractMailboxManagerTest {
     @Before
     public void setup() throws Exception {
         createMailboxManager();
+
+        session = getMailboxManager().createSystemSession(USER_1, LoggerFactory.getLogger("Test"));
+        getMailboxManager().startProcessingRequest(session);
     }
     
     /**
@@ -55,8 +68,9 @@ public class InMemoryMailboxManagerTest extends AbstractMailboxManagerTest {
      */
     @After
     public void tearDown() throws BadCredentialsException, MailboxException {
-        MailboxSession session = getMailboxManager().createSystemSession("test", LoggerFactory.getLogger("Test"));
-        session.close();
+        getMailboxManager().logout(session, true);
+        getMailboxManager().endProcessingRequest(session);
+        getMailboxManager().createSystemSession("test", LoggerFactory.getLogger("Test")).close();
     }
 
     /* (non-Javadoc)
@@ -75,5 +89,23 @@ public class InMemoryMailboxManagerTest extends AbstractMailboxManagerTest {
         setMailboxManager(mailboxManager);
 
     }
+
+    @Test
+    public void searchShouldNotReturnResultsFromOtherNamespaces() throws Exception {
+        getMailboxManager().createMailbox(new MailboxPath("#namespace", USER_1, "Other"), session);
+        getMailboxManager().createMailbox(MailboxPath.inbox(session), session);
+        List<MailboxMetaData> metaDatas = getMailboxManager().search(new MailboxQuery(new MailboxPath("#private", USER_1, ""), "*", '.'), session);
+        assertThat(metaDatas).hasSize(1);
+        assertThat(metaDatas.get(0).getPath()).isEqualTo(MailboxPath.inbox(session));
+    }
+
+    @Test
+    public void searchShouldNotReturnResultsFromOtherUsers() throws Exception {
+        getMailboxManager().createMailbox(new MailboxPath("#namespace", USER_2, "Other"), session);
+        getMailboxManager().createMailbox(MailboxPath.inbox(session), session);
+        List<MailboxMetaData> metaDatas = getMailboxManager().search(new MailboxQuery(new MailboxPath("#private", USER_1, ""), "*", '.'), session);
+        assertThat(metaDatas).hasSize(1);
+        assertThat(metaDatas.get(0).getPath()).isEqualTo(MailboxPath.inbox(session));
+    }
     
 }
diff --git a/memory/src/test/java/org/apache/james/mailbox/inmemory/InMemoryMailboxMapperTest.java b/memory/src/test/java/org/apache/james/mailbox/inmemory/InMemoryMailboxMapperTest.java
new file mode 100644
index 0000000..bffbcfe
--- /dev/null
+++ b/memory/src/test/java/org/apache/james/mailbox/inmemory/InMemoryMailboxMapperTest.java
@@ -0,0 +1,85 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mailbox.inmemory;
+
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.mock.MockMailboxSession;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.store.mail.MailboxMapper;
+import org.apache.james.mailbox.store.mail.model.Mailbox;
+import org.apache.james.mailbox.store.mail.model.impl.SimpleMailbox;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class InMemoryMailboxMapperTest {
+
+    public static final int UID_VALIDITY = 10;
+
+    private MailboxPath user1InboxPath;
+    private MailboxPath user1SubMailbox1Path;
+    private MailboxPath user1SubMailbox2Path;
+    private MailboxPath user2OtherBoxPath;
+    private MailboxPath user1OtherNamespacePath;
+
+    private Mailbox<Long> user1Inbox;
+    private Mailbox<Long> user1SubMailbox1;
+    private Mailbox<Long> user1SubMailbox2;
+
+    private MailboxMapper<Long> mapper;
+
+    @Before
+    public void setUp() throws MailboxException {
+        user1InboxPath = new MailboxPath("#private", "user1", "INBOX");
+        user1SubMailbox1Path = new MailboxPath("#private", "user1", "INBOX.sub1");
+        user1SubMailbox2Path = new MailboxPath("#private", "user1", "INBOX.sub2");
+        user2OtherBoxPath = new MailboxPath("#private", "user2", "other.user");
+        user1OtherNamespacePath = new MailboxPath("#namspace", "user1", "other.namespace");
+        user1Inbox = new SimpleMailbox<Long>(user1InboxPath, UID_VALIDITY);
+        user1SubMailbox1 = new SimpleMailbox<Long>(user1SubMailbox1Path, UID_VALIDITY);
+        user1SubMailbox2 = new SimpleMailbox<Long>(user1SubMailbox2Path, UID_VALIDITY);
+        mapper = new InMemoryMailboxSessionMapperFactory().createMailboxMapper(new MockMailboxSession("user"));
+        mapper.save(user1Inbox);
+        mapper.save(user1SubMailbox1);
+        mapper.save(user1SubMailbox2);
+        mapper.save(new SimpleMailbox<Long>(user2OtherBoxPath, UID_VALIDITY));
+        mapper.save(new SimpleMailbox<Long>(user1OtherNamespacePath, UID_VALIDITY));
+    }
+
+    @Test
+    public void findMailboxWithPatchLikeOnAllMaillboxesShouldReturnMailboxesBelongingToThisNamespaceAndUser() throws MailboxException{
+        assertThat(mapper.findMailboxWithPathLike(new MailboxPath("#private", "user1", "%")))
+            .containsOnly(user1Inbox, user1SubMailbox1, user1SubMailbox2);
+    }
+
+    @Test
+    public void findMailboxWithPatchLikeBasedOnInboxShouldReturnItsChildren() throws MailboxException{
+        assertThat(mapper.findMailboxWithPathLike(new MailboxPath("#private", "user1", "INBOX.%")))
+            .containsOnly(user1SubMailbox1, user1SubMailbox2);
+    }
+
+    @Test
+    public void findMailboxWithPatchLikeBasedOnAStringShouldReturnMailboxesStartingWithThisString() throws MailboxException{
+        assertThat(mapper.findMailboxWithPathLike(new MailboxPath("#private", "user1", "IN%")))
+            .containsOnly(user1Inbox, user1SubMailbox1, user1SubMailbox2);
+    }
+
+}
diff --git a/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java b/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java
index 6fd108c..1b1def6 100644
--- a/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java
+++ b/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java
@@ -512,17 +512,19 @@ public class StoreMailboxManager<Id> implements MailboxManager {
         final List<MailboxMetaData> results = new ArrayList<MailboxMetaData>(mailboxes.size());
         for (Mailbox<Id> mailbox : mailboxes) {
             final String name = mailbox.getName();
-            if (name.startsWith(baseName)) {
-                final String match = name.substring(baseLength);
-                if (mailboxExpression.isExpressionMatch(match)) {
-                    final MailboxMetaData.Children inferiors;
-                    if (mapper.hasChildren(mailbox, session.getPathDelimiter())) {
-                        inferiors = MailboxMetaData.Children.HAS_CHILDREN;
-                    } else {
-                        inferiors = MailboxMetaData.Children.HAS_NO_CHILDREN;
+            if(belongsToNamespaceAndUser(mailboxExpression.getBase(), mailbox)) {
+                if (name.startsWith(baseName)) {
+                    final String match = name.substring(baseLength);
+                    if (mailboxExpression.isExpressionMatch(match)) {
+                        final MailboxMetaData.Children inferiors;
+                        if (mapper.hasChildren(mailbox, session.getPathDelimiter())) {
+                            inferiors = MailboxMetaData.Children.HAS_CHILDREN;
+                        } else {
+                            inferiors = MailboxMetaData.Children.HAS_NO_CHILDREN;
+                        }
+                        MailboxPath mailboxPath = new MailboxPath(mailbox.getNamespace(), mailbox.getUser(), name);
+                        results.add(new SimpleMailboxMetaData(mailboxPath, getDelimiter(), inferiors, Selectability.NONE));
                     }
-                    MailboxPath mailboxPath = new MailboxPath(mailbox.getNamespace(), mailbox.getUser(), name);
-                    results.add(new SimpleMailboxMetaData(mailboxPath, getDelimiter(), inferiors, Selectability.NONE));
                 }
             }
         }
@@ -530,6 +532,15 @@ public class StoreMailboxManager<Id> implements MailboxManager {
         return results;
     }
 
+    public boolean belongsToNamespaceAndUser(MailboxPath base, Mailbox<Id> mailbox) {
+        if (mailbox.getUser() == null) {
+            return  base.getUser() == null
+                && mailbox.getNamespace().equals(base.getNamespace());
+        }
+        return mailbox.getNamespace().equals(base.getNamespace())
+            && mailbox.getUser().equals(base.getUser());
+    }
+
     @Override
     public boolean mailboxExists(MailboxPath mailboxPath, MailboxSession session) throws MailboxException {
         try {
diff --git a/store/src/test/java/org/apache/james/mailbox/store/StoreMailboxManagerTest.java b/store/src/test/java/org/apache/james/mailbox/store/StoreMailboxManagerTest.java
new file mode 100644
index 0000000..0987370
--- /dev/null
+++ b/store/src/test/java/org/apache/james/mailbox/store/StoreMailboxManagerTest.java
@@ -0,0 +1,101 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mailbox.store;
+
+import org.apache.james.mailbox.acl.SimpleGroupMembershipResolver;
+import org.apache.james.mailbox.acl.UnionMailboxACLResolver;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.store.mail.model.impl.SimpleMailbox;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class StoreMailboxManagerTest {
+
+    public static final int UID_VALIDITY = 42;
+    private StoreMailboxManager storeMailboxManager;
+
+    @Before
+    public void setUp() {
+        storeMailboxManager = new StoreMailboxManager(null, new MockAuthenticator(), new JVMMailboxPathLocker(), new UnionMailboxACLResolver(), new SimpleGroupMembershipResolver());
+    }
+
+    @Test
+    public void belongsToNamespaceAndUserShouldReturnTrueWithIdenticalMailboxes() {
+        MailboxPath path = new MailboxPath("namespace", "user", "name");
+        assertThat(storeMailboxManager.belongsToNamespaceAndUser(path, new SimpleMailbox(path, UID_VALIDITY))).isTrue();
+    }
+
+    @Test
+    public void belongsToNamespaceAndUserShouldReturnTrueWithIdenticalMailboxesWithNullUser() {
+        MailboxPath path = new MailboxPath("namespace", null, "name");
+        assertThat(storeMailboxManager.belongsToNamespaceAndUser(path, new SimpleMailbox(path, UID_VALIDITY))).isTrue();
+    }
+
+    @Test
+    public void belongsToNamespaceAndUserShouldReturnTrueWithIdenticalMailboxesWithNullNamespace() {
+        MailboxPath path = new MailboxPath(null, "user", "name");
+        assertThat(storeMailboxManager.belongsToNamespaceAndUser(path,
+            new SimpleMailbox(new MailboxPath(null, "user", "name"), UID_VALIDITY))).isTrue();
+    }
+
+    @Test
+    public void belongsToNamespaceAndUserShouldReturnTrueWithMailboxWithSameNamespaceAndUserWithNullUser() {
+        MailboxPath path = new MailboxPath("namespace", null, "name");
+        assertThat(storeMailboxManager.belongsToNamespaceAndUser(path,
+            new SimpleMailbox(new MailboxPath("namespace", null, "name2"), UID_VALIDITY))).isTrue();
+    }
+
+    @Test
+    public void belongsToNamespaceAndUserShouldReturnTrueWithMailboxWithSameNamespaceAndUser() {
+        MailboxPath path = new MailboxPath("namespace", "user", "name");
+        assertThat(storeMailboxManager.belongsToNamespaceAndUser(path,
+            new SimpleMailbox(new MailboxPath("namespace", "user", "name2"), UID_VALIDITY))).isTrue();
+    }
+
+    @Test
+    public void belongsToNamespaceAndUserShouldReturnFalseWithDifferentNamespace() {
+        MailboxPath path = new MailboxPath("namespace", "user", "name");
+        assertThat(storeMailboxManager.belongsToNamespaceAndUser(path,
+            new SimpleMailbox(new MailboxPath("namespace2", "user", "name"), UID_VALIDITY))).isFalse();
+    }
+
+    @Test
+    public void belongsToNamespaceAndUserShouldReturnFalseWithDifferentUser() {
+        MailboxPath path = new MailboxPath("namespace", "user", "name");
+        assertThat(storeMailboxManager.belongsToNamespaceAndUser(path,
+            new SimpleMailbox(new MailboxPath("namespace", "user2", "name"), UID_VALIDITY))).isFalse();
+    }
+    @Test
+    public void belongsToNamespaceAndUserShouldReturnFalseWithOneOfTheUserNull() {
+        MailboxPath path = new MailboxPath("namespace", null, "name");
+        assertThat(storeMailboxManager.belongsToNamespaceAndUser(path,
+            new SimpleMailbox(new MailboxPath("namespace", "user", "name"), UID_VALIDITY))).isFalse();
+    }
+    @Test
+    public void belongsToNamespaceAndUserShouldReturnFalseIfNamespaceAreDifferentWithNullUser() {
+        MailboxPath path = new MailboxPath("namespace", null, "name");
+        assertThat(storeMailboxManager.belongsToNamespaceAndUser(path,
+            new SimpleMailbox(new MailboxPath("namespace2", null, "name"), UID_VALIDITY))).isFalse();
+    }
+
+
+}
-- 
2.4.2

