JAMES-2585 Add Sieve script routes

Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/08aaabc5
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/08aaabc5
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/08aaabc5

Branch: refs/heads/master
Commit: 08aaabc5e40862d9a53c1b177521d506c52a87ad
Parents: 71872d1
Author: datph <dphamho...@linagora.com>
Authored: Mon Nov 5 21:00:23 2018 +0700
Committer: Benoit Tellier <btell...@linagora.com>
Committed: Wed Nov 14 16:27:09 2018 +0700

----------------------------------------------------------------------
 .../apache/james/CassandraJamesServerMain.java  |   4 +-
 .../org/apache/james/JPAJamesServerMain.java    |   4 +-
 .../org/apache/james/MemoryJamesServerMain.java |   4 +-
 .../modules/server/SieveQuotaRoutesModule.java  |  35 ---
 .../james/modules/server/SieveRoutesModule.java |  40 +++
 server/protocols/webadmin/webadmin-data/pom.xml |  10 +
 .../webadmin/routes/SieveScriptRoutes.java      | 192 ++++++++++++++
 .../webadmin/routes/SieveScriptRoutesTest.java  | 261 +++++++++++++++++++
 .../src/test/resources/sieve/my_sieve           |   5 +
 9 files changed, 514 insertions(+), 41 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/08aaabc5/server/container/guice/cassandra-guice/src/main/java/org/apache/james/CassandraJamesServerMain.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/CassandraJamesServerMain.java
 
b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/CassandraJamesServerMain.java
index 13cdd68..697c7d7 100644
--- 
a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/CassandraJamesServerMain.java
+++ 
b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/CassandraJamesServerMain.java
@@ -54,7 +54,7 @@ import 
org.apache.james.modules.server.MailRepositoriesRoutesModule;
 import org.apache.james.modules.server.MailboxRoutesModule;
 import org.apache.james.modules.server.MessageIdReIndexingModule;
 import org.apache.james.modules.server.ReIndexingModule;
-import org.apache.james.modules.server.SieveQuotaRoutesModule;
+import org.apache.james.modules.server.SieveRoutesModule;
 import org.apache.james.modules.server.SwaggerRoutesModule;
 import org.apache.james.modules.server.WebAdminServerModule;
 import org.apache.james.modules.spamassassin.SpamAssassinListenerModule;
@@ -74,7 +74,7 @@ public class CassandraJamesServerMain {
         new SwaggerRoutesModule(),
         new WebAdminServerModule(),
         new DLPRoutesModule(),
-        new SieveQuotaRoutesModule(),
+        new SieveRoutesModule(),
         new ReIndexingModule(),
         new MessageIdReIndexingModule());
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/08aaabc5/server/container/guice/jpa-guice/src/main/java/org/apache/james/JPAJamesServerMain.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/jpa-guice/src/main/java/org/apache/james/JPAJamesServerMain.java
 
b/server/container/guice/jpa-guice/src/main/java/org/apache/james/JPAJamesServerMain.java
index f12f7ec..30a6322 100644
--- 
a/server/container/guice/jpa-guice/src/main/java/org/apache/james/JPAJamesServerMain.java
+++ 
b/server/container/guice/jpa-guice/src/main/java/org/apache/james/JPAJamesServerMain.java
@@ -42,7 +42,7 @@ import org.apache.james.modules.server.MailboxRoutesModule;
 import org.apache.james.modules.server.NoJwtModule;
 import org.apache.james.modules.server.RawPostDequeueDecoratorModule;
 import org.apache.james.modules.server.ReIndexingModule;
-import org.apache.james.modules.server.SieveQuotaRoutesModule;
+import org.apache.james.modules.server.SieveRoutesModule;
 import org.apache.james.modules.server.SwaggerRoutesModule;
 import org.apache.james.modules.server.WebAdminServerModule;
 import org.apache.james.modules.spamassassin.SpamAssassinListenerModule;
@@ -60,7 +60,7 @@ public class JPAJamesServerMain {
         new MailQueueRoutesModule(),
         new MailRepositoriesRoutesModule(),
         new SwaggerRoutesModule(),
-        new SieveQuotaRoutesModule(),
+        new SieveRoutesModule(),
         new ReIndexingModule());
 
     public static final Module PROTOCOLS = Modules.combine(

http://git-wip-us.apache.org/repos/asf/james-project/blob/08aaabc5/server/container/guice/memory-guice/src/main/java/org/apache/james/MemoryJamesServerMain.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/memory-guice/src/main/java/org/apache/james/MemoryJamesServerMain.java
 
b/server/container/guice/memory-guice/src/main/java/org/apache/james/MemoryJamesServerMain.java
index 18a3f2f..b72810e 100644
--- 
a/server/container/guice/memory-guice/src/main/java/org/apache/james/MemoryJamesServerMain.java
+++ 
b/server/container/guice/memory-guice/src/main/java/org/apache/james/MemoryJamesServerMain.java
@@ -41,7 +41,7 @@ import 
org.apache.james.modules.server.MailRepositoriesRoutesModule;
 import org.apache.james.modules.server.MailboxRoutesModule;
 import org.apache.james.modules.server.MemoryMailQueueModule;
 import org.apache.james.modules.server.RawPostDequeueDecoratorModule;
-import org.apache.james.modules.server.SieveQuotaRoutesModule;
+import org.apache.james.modules.server.SieveRoutesModule;
 import org.apache.james.modules.server.SwaggerRoutesModule;
 import org.apache.james.modules.server.WebAdminServerModule;
 import org.apache.james.modules.spamassassin.SpamAssassinListenerModule;
@@ -60,7 +60,7 @@ public class MemoryJamesServerMain {
         new MailRepositoriesRoutesModule(),
         new SwaggerRoutesModule(),
         new DLPRoutesModule(),
-        new SieveQuotaRoutesModule());
+        new SieveRoutesModule());
 
     public static final Module PROTOCOLS = Modules.combine(
         new IMAPServerModule(),

http://git-wip-us.apache.org/repos/asf/james-project/blob/08aaabc5/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/SieveQuotaRoutesModule.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/SieveQuotaRoutesModule.java
 
b/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/SieveQuotaRoutesModule.java
deleted file mode 100644
index 27fdcbb..0000000
--- 
a/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/SieveQuotaRoutesModule.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/****************************************************************
- * 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.modules.server;
-
-import org.apache.james.webadmin.Routes;
-import org.apache.james.webadmin.routes.SieveQuotaRoutes;
-
-import com.google.inject.AbstractModule;
-import com.google.inject.multibindings.Multibinder;
-
-public class SieveQuotaRoutesModule extends AbstractModule {
-    @Override
-    protected void configure() {
-        Multibinder.newSetBinder(binder(), Routes.class)
-            .addBinding()
-            .to(SieveQuotaRoutes.class);
-    }
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/08aaabc5/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/SieveRoutesModule.java
----------------------------------------------------------------------
diff --git 
a/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/SieveRoutesModule.java
 
b/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/SieveRoutesModule.java
new file mode 100644
index 0000000..31193e7
--- /dev/null
+++ 
b/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/SieveRoutesModule.java
@@ -0,0 +1,40 @@
+/****************************************************************
+ * 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.modules.server;
+
+import org.apache.james.webadmin.Routes;
+import org.apache.james.webadmin.routes.SieveQuotaRoutes;
+import org.apache.james.webadmin.routes.SieveScriptRoutes;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.multibindings.Multibinder;
+
+public class SieveRoutesModule extends AbstractModule {
+    @Override
+    protected void configure() {
+        Multibinder.newSetBinder(binder(), Routes.class)
+            .addBinding()
+            .to(SieveQuotaRoutes.class);
+
+        Multibinder.newSetBinder(binder(), Routes.class)
+            .addBinding()
+            .to(SieveScriptRoutes.class);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/08aaabc5/server/protocols/webadmin/webadmin-data/pom.xml
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/webadmin-data/pom.xml 
b/server/protocols/webadmin/webadmin-data/pom.xml
index 3a17b66..73c8f05 100644
--- a/server/protocols/webadmin/webadmin-data/pom.xml
+++ b/server/protocols/webadmin/webadmin-data/pom.xml
@@ -107,6 +107,16 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>org.apache.james</groupId>
+            <artifactId>james-server-data-file</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.james</groupId>
+            <artifactId>james-server-testing</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>org.assertj</groupId>
             <artifactId>assertj-core</artifactId>
             <scope>test</scope>

http://git-wip-us.apache.org/repos/asf/james-project/blob/08aaabc5/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/SieveScriptRoutes.java
----------------------------------------------------------------------
diff --git 
a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/SieveScriptRoutes.java
 
b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/SieveScriptRoutes.java
new file mode 100644
index 0000000..2fa7a44
--- /dev/null
+++ 
b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/SieveScriptRoutes.java
@@ -0,0 +1,192 @@
+/****************************************************************
+ * 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.webadmin.routes;
+
+import static org.apache.james.webadmin.Constants.SEPARATOR;
+import static spark.Spark.halt;
+
+import java.util.Optional;
+
+import javax.inject.Inject;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+
+import org.apache.james.core.User;
+import org.apache.james.sieverepository.api.ScriptContent;
+import org.apache.james.sieverepository.api.ScriptName;
+import org.apache.james.sieverepository.api.SieveRepository;
+import org.apache.james.sieverepository.api.exception.QuotaExceededException;
+import org.apache.james.sieverepository.api.exception.ScriptNotFoundException;
+import org.apache.james.sieverepository.api.exception.StorageException;
+import org.apache.james.user.api.UsersRepository;
+import org.apache.james.user.api.UsersRepositoryException;
+import org.apache.james.webadmin.Routes;
+import org.apache.james.webadmin.utils.ErrorResponder;
+import org.eclipse.jetty.http.HttpStatus;
+
+import com.google.common.base.Joiner;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import spark.HaltException;
+import spark.Request;
+import spark.Response;
+import spark.Service;
+import spark.utils.StringUtils;
+
+@Api(tags = "SieveScript")
+@Path(value = "/sieve")
+public class SieveScriptRoutes implements Routes {
+
+    public static final String ROOT_PATH = "/sieve";
+    public static final String SCRIPTS = "scripts";
+    private static final String USER_NAME = "userName";
+    private static final String SCRIPT_NAME = "scriptName";
+    private static final String ACTIVATE_PARAMS = "activate";
+    private static final String USER_SCRIPT_PATH = Joiner.on(SEPARATOR)
+        .join(ROOT_PATH, ":" + USER_NAME, SCRIPTS, ":" + SCRIPT_NAME);
+
+    private final SieveRepository sieveRepository;
+    private final UsersRepository usersRepository;
+
+    @Inject
+    public SieveScriptRoutes(SieveRepository sieveRepository, UsersRepository 
usersRepository) {
+        this.sieveRepository = sieveRepository;
+        this.usersRepository = usersRepository;
+    }
+
+    @Override
+    public String getBasePath() {
+        return ROOT_PATH;
+    }
+
+    @Override
+    public void define(Service service) {
+        defineAddActiveSieveScript(service);
+    }
+
+    @PUT
+    @ApiOperation(value = "Upload a new Sieve Script")
+    @Path(value = ROOT_PATH + "/{" + USER_NAME + "}/" + SCRIPTS + "/{" + 
SCRIPT_NAME + "}")
+    @ApiResponses(value = {
+        @ApiResponse(code = HttpStatus.NO_CONTENT_204, message = "OK"),
+        @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "Invalid 
username"),
+        @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "Invalid 
Sieve script name"),
+        @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "Empty 
script is not accepted"),
+        @ApiResponse(code = HttpStatus.NOT_FOUND_404, message = "User not 
found")
+    })
+    @ApiImplicitParams({
+        @ApiImplicitParam(
+            name = USER_NAME,
+            required = true,
+            paramType = "path",
+            dataType = "String",
+            example = ROOT_PATH + "/userNameA/" + SCRIPTS + "/scriptName1",
+            value = "Username"),
+        @ApiImplicitParam(
+            name = SCRIPT_NAME,
+            required = true,
+            paramType = "path",
+            dataType = "String",
+            example = ROOT_PATH + "/userNameA/" + SCRIPTS + "/scriptName1",
+            value = "Script name"),
+        @ApiImplicitParam(
+            required = false,
+            paramType = "query parameter",
+            dataType = "Boolean",
+            defaultValue = "False",
+            example = "?activate=true",
+            value = "If present, automatically activating the script.")
+    })
+    public void defineAddActiveSieveScript(Service service) {
+        service.put(USER_SCRIPT_PATH, this::addActiveSieveScript);
+    }
+
+    private HaltException addActiveSieveScript(Request request, Response 
response) throws UsersRepositoryException, QuotaExceededException, 
StorageException, ScriptNotFoundException {
+        User user = extractUser(request);
+        ScriptName script = extractScriptName(request);
+        boolean isActivated = 
isActivated(request.queryParams(ACTIVATE_PARAMS));
+        sieveRepository.putScript(user, script, 
extractSieveScriptFromRequest(request));
+        if (isActivated) {
+            sieveRepository.setActive(user, script);
+        }
+        return halt(HttpStatus.NO_CONTENT_204);
+    }
+
+    private User extractUser(Request request) throws UsersRepositoryException {
+        String userName = Optional.ofNullable(request.params(USER_NAME))
+            .map(String::trim)
+            .filter(StringUtils::isNotEmpty)
+            .orElseThrow(() -> throw400withInvalidArgument("Invalid 
username"));
+
+        if (!usersRepository.contains(userName)) {
+            throw404("User not found");
+        }
+        return User.fromUsername(userName);
+    }
+
+    private ScriptName extractScriptName(Request request) {
+        return Optional.ofNullable(request.params(SCRIPT_NAME))
+            .map(String::trim)
+            .filter(StringUtils::isNotEmpty)
+            .map(ScriptName::new)
+            .orElseThrow(() -> throw400withInvalidArgument("Invalid Sieve 
script name"));
+    }
+
+    private ScriptContent extractSieveScriptFromRequest(Request request) {
+        return new ScriptContent(request.body());
+    }
+
+    private boolean isActivated(String activateParam) {
+        return Optional.ofNullable(activateParam)
+            .map(String::trim)
+            .map(this::parseActivateParam)
+            .orElse(false);
+    }
+
+    private boolean parseActivateParam(String activateParam) {
+        if (activateParam.equalsIgnoreCase(Boolean.TRUE.toString())
+            || activateParam.equalsIgnoreCase(Boolean.FALSE.toString())) {
+            return Boolean.parseBoolean(activateParam);
+        }
+
+        throw throw400withInvalidArgument("Invalid activate query parameter");
+    }
+
+    private HaltException throw400withInvalidArgument(String message) {
+        throw ErrorResponder.builder()
+            .statusCode(HttpStatus.BAD_REQUEST_400)
+            .type(ErrorResponder.ErrorType.INVALID_ARGUMENT)
+            .message(message)
+            .haltError();
+    }
+
+    private HaltException throw404(String message) {
+        throw ErrorResponder.builder()
+            .statusCode(HttpStatus.NOT_FOUND_404)
+            .type(ErrorResponder.ErrorType.NOT_FOUND)
+            .message(message)
+            .haltError();
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/08aaabc5/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/SieveScriptRoutesTest.java
----------------------------------------------------------------------
diff --git 
a/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/SieveScriptRoutesTest.java
 
b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/SieveScriptRoutesTest.java
new file mode 100644
index 0000000..5c3fb28
--- /dev/null
+++ 
b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/SieveScriptRoutesTest.java
@@ -0,0 +1,261 @@
+/****************************************************************
+ * 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.webadmin.routes;
+
+import static io.restassured.RestAssured.given;
+import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson;
+import static org.apache.james.webadmin.WebAdminServer.NO_CONFIGURATION;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.hamcrest.Matchers.equalTo;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.io.IOUtils;
+import org.apache.james.core.User;
+import org.apache.james.filesystem.api.FileSystem;
+import org.apache.james.junit.TemporaryFolderExtension;
+import org.apache.james.metrics.logger.DefaultMetricFactory;
+import org.apache.james.sieverepository.api.ScriptContent;
+import org.apache.james.sieverepository.api.ScriptName;
+import org.apache.james.sieverepository.api.SieveRepository;
+import org.apache.james.sieverepository.api.exception.ScriptNotFoundException;
+import org.apache.james.sieverepository.api.exception.StorageException;
+import org.apache.james.sieverepository.file.SieveFileRepository;
+import org.apache.james.user.api.UsersRepository;
+import org.apache.james.user.api.UsersRepositoryException;
+import org.apache.james.user.memory.MemoryUsersRepository;
+import org.apache.james.webadmin.WebAdminServer;
+import org.apache.james.webadmin.WebAdminUtils;
+import org.eclipse.jetty.http.HttpStatus;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import io.restassured.RestAssured;
+
+@ExtendWith(TemporaryFolderExtension.class)
+public class SieveScriptRoutesTest {
+
+    private FileSystem fileSystem;
+    private WebAdminServer webAdminServer;
+    private SieveRepository sieveRepository;
+    private UsersRepository usersRepository;
+    private String sieveContent;
+
+    @BeforeEach
+    public void setUp(TemporaryFolderExtension.TemporaryFolder 
temporaryFolder) throws ConfigurationException, IOException, 
UsersRepositoryException {
+        this.fileSystem = new FileSystem() {
+            @Override
+            public File getBasedir() {
+                return temporaryFolder.getTempDir();
+            }
+
+            @Override
+            public InputStream getResource(String url) throws IOException {
+                return new FileInputStream(getFile(url));
+            }
+
+            @Override
+            public File getFile(String fileURL) {
+                return new File(getBasedir(), 
fileURL.substring(FileSystem.FILE_PROTOCOL.length()));
+            }
+        };
+
+        sieveRepository = new SieveFileRepository(fileSystem);
+        usersRepository = MemoryUsersRepository.withoutVirtualHosting();
+        usersRepository.addUser("userA", "password");
+
+        URL sieveResource = ClassLoader.getSystemResource("sieve/my_sieve");
+        sieveContent = IOUtils.toString(sieveResource, StandardCharsets.UTF_8);
+
+        webAdminServer = WebAdminUtils.createWebAdminServer(
+            new DefaultMetricFactory(),
+            new SieveScriptRoutes(sieveRepository, usersRepository));
+        webAdminServer.configure(NO_CONFIGURATION);
+        webAdminServer.await();
+
+        RestAssured.requestSpecification = WebAdminUtils
+            .buildRequestSpecification(webAdminServer)
+            .build();
+    }
+
+    @AfterEach
+    public void tearDown() {
+        webAdminServer.destroy();
+    }
+
+    @Test
+    public void 
defineAddActiveSieveScriptShouldReturnNotFoundWhenUserNotExisted() throws 
IOException {
+        given()
+            .pathParam("userName", "unknown")
+            .pathParam("scriptName", "scriptA")
+            .body(sieveContent)
+        .when()
+            .put("sieve/{userName}/scripts/{scriptName}")
+        .then()
+            .statusCode(HttpStatus.NOT_FOUND_404);
+    }
+
+    @Test
+    public void 
defineAddActiveSieveScriptShouldReturnNotFoundWhenScriptNameIsWhiteSpace() 
throws IOException {
+        String errorBody =
+            "{\"statusCode\": 400," +
+            " \"type\":\"InvalidArgument\"," +
+            " \"message\":\"Invalid Sieve script name\"," +
+            " \"details\":null" +
+            "}";
+        String body = given()
+            .pathParam("userName", "userA")
+            .pathParam("scriptName", " ")
+            .body(sieveContent)
+        .when()
+            .put("sieve/{userName}/scripts/{scriptName}")
+        .then()
+            .statusCode(HttpStatus.BAD_REQUEST_400)
+            .extract()
+            .body().asString();
+
+        assertThatJson(body).isEqualTo(errorBody);
+    }
+
+    @Test
+    public void 
defineAddActiveSieveScriptShouldReturnNotFoundWhenUserNameWhiteSpace() {
+        String errorBody =
+            "{\"statusCode\": 400," +
+            " \"type\":\"InvalidArgument\"," +
+            " \"message\":\"Invalid username\"," +
+            " \"details\":null" +
+            "}";
+        String body = given()
+            .pathParam("userName", " ")
+            .pathParam("scriptName", "scriptA")
+            .body(sieveContent)
+        .when()
+            .put("sieve/{userName}/scripts/{scriptName}")
+        .then()
+            .statusCode(HttpStatus.BAD_REQUEST_400)
+            .extract()
+            .body().asString();
+
+        assertThatJson(body).isEqualTo(errorBody);
+    }
+
+    @Test
+    public void 
defineAddActiveSieveScriptShouldReturnInternalErrorWhenScriptIsNotSet() {
+        given()
+            .pathParam("userName", "userA")
+            .pathParam("scriptName", "scriptA")
+        .when()
+            .put("sieve/{userName}/scripts/{scriptName}")
+        .then()
+            .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500);
+    }
+
+    @Test
+    public void 
defineAddActiveSieveScriptShouldReturnSucceededWhenScriptIsWhiteSpace() throws 
ScriptNotFoundException, StorageException, IOException {
+        given()
+            .pathParam("userName", "userA")
+            .pathParam("scriptName", "scriptA")
+            .body(" ")
+        .when()
+            .put("sieve/{userName}/scripts/{scriptName}")
+        .then()
+            .statusCode(HttpStatus.NO_CONTENT_204);
+
+        assertThat(getScriptContent(sieveRepository
+            .getScript(User.fromUsername("userA"), new ScriptName("scriptA"))))
+            .isEqualTo(new ScriptContent(" "));
+    }
+
+    @Test
+    public void 
defineAddActiveSieveScriptAddScriptSucceededOneWhenNotAddActivateParam() throws 
Exception {
+        given()
+            .pathParam("userName", "userA")
+            .pathParam("scriptName", "scriptA")
+            .body(sieveContent)
+        .when()
+            .put("sieve/{userName}/scripts/{scriptName}")
+        .then()
+            .statusCode(HttpStatus.NO_CONTENT_204);
+
+        assertThat(getScriptContent(sieveRepository
+            .getScript(User.fromUsername("userA"), new ScriptName("scriptA"))))
+            .isEqualTo(new ScriptContent(sieveContent));
+    }
+
+    @Test
+    public void 
defineAddActiveSieveScriptSetActiveTrueWhenAddActivateParamTrue() throws 
Exception {
+        given()
+            .pathParam("userName", "userA")
+            .pathParam("scriptName", "scriptA")
+            .queryParam("activate", true)
+            .body(sieveContent)
+        .when()
+            .put("sieve/{userName}/scripts/{scriptName}")
+        .then()
+            .statusCode(HttpStatus.NO_CONTENT_204);
+
+        assertThat(getScriptContent(sieveRepository
+            .getActive(User.fromUsername("userA"))))
+            .isEqualTo(new ScriptContent(sieveContent));
+    }
+
+    @Test
+    public void 
defineAddActiveSieveScriptGetActiveShouldThrowsExceptionWhenAddActivateParamFalse()
 {
+        given()
+            .pathParam("userName", "userA")
+            .pathParam("scriptName", "scriptA")
+            .queryParam("activate", false)
+            .body(sieveContent)
+        .when()
+            .put("sieve/{userName}/scripts/{scriptName}")
+        .then()
+            .statusCode(HttpStatus.NO_CONTENT_204);
+
+        assertThatThrownBy(() -> 
sieveRepository.getActive(User.fromUsername("userA")))
+            .isInstanceOf(ScriptNotFoundException.class);
+    }
+
+    @Test
+    public void 
defineAddActiveSieveScriptInvokeShouldReturnBadRequestWhenAddActivateParamWithNotBooleanValue()
 {
+        given()
+            .pathParam("userName", "userA")
+            .pathParam("scriptName", "scriptA")
+            .queryParam("activate", "activate")
+            .body(sieveContent)
+        .when()
+            .put("sieve/{userName}/scripts/{scriptName}")
+        .then()
+            .statusCode(HttpStatus.BAD_REQUEST_400)
+            .body("message", equalTo("Invalid activate query parameter"));
+    }
+
+    protected ScriptContent getScriptContent(InputStream inputStream) throws 
IOException {
+        return new ScriptContent(IOUtils.toString(inputStream, 
StandardCharsets.UTF_8));
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/08aaabc5/server/protocols/webadmin/webadmin-data/src/test/resources/sieve/my_sieve
----------------------------------------------------------------------
diff --git 
a/server/protocols/webadmin/webadmin-data/src/test/resources/sieve/my_sieve 
b/server/protocols/webadmin/webadmin-data/src/test/resources/sieve/my_sieve
new file mode 100644
index 0000000..eb859b0
--- /dev/null
+++ b/server/protocols/webadmin/webadmin-data/src/test/resources/sieve/my_sieve
@@ -0,0 +1,5 @@
+require ["reject"];
+
+if size :over 100K {
+   reject "Email too big";
+}
\ No newline at end of file


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

Reply via email to