You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by bt...@apache.org on 2017/03/15 10:01:47 UTC

[01/22] james-project git commit: JAMES-1958 Rely on this configuration object to start WebAdmin server

Repository: james-project
Updated Branches:
  refs/heads/master a43fbd41b -> e8b94d178


JAMES-1958 Rely on this configuration object to start WebAdmin server


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

Branch: refs/heads/master
Commit: da41f83ee2d33942c4090ab2b7c0ee104c26e8bd
Parents: 6ae498a
Author: benwa <bt...@linagora.com>
Authored: Wed Mar 8 14:25:58 2017 +0700
Committer: benwa <bt...@linagora.com>
Committed: Wed Mar 15 09:01:52 2017 +0700

----------------------------------------------------------------------
 .../modules/server/WebAdminServerModule.java    | 29 ++++++++------------
 .../WebAdminConfigurationModule.java            | 19 ++++---------
 .../apache/james/webadmin/WebAdminServer.java   | 27 ++++++++----------
 3 files changed, 29 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/da41f83e/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java b/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
index a9aed5c..8495797 100644
--- a/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
+++ b/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
@@ -20,21 +20,20 @@
 package org.apache.james.modules.server;
 
 import static org.apache.james.webadmin.WebAdminServer.NO_CONFIGURATION;
-import static org.apache.james.webadmin.WebAdminServer.WEBADMIN_ENABLED;
-import static org.apache.james.webadmin.WebAdminServer.WEBADMIN_PORT;
 
 import java.io.FileNotFoundException;
 import java.util.List;
 
 import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.PropertiesConfiguration;
 import org.apache.james.lifecycle.api.Configurable;
 import org.apache.james.utils.ConfigurationPerformer;
 import org.apache.james.utils.GuiceProbe;
 import org.apache.james.utils.PropertiesProvider;
 import org.apache.james.utils.WebAdminGuiceProbe;
 import org.apache.james.webadmin.FixedPort;
-import org.apache.james.webadmin.Port;
 import org.apache.james.webadmin.Routes;
+import org.apache.james.webadmin.WebAdminConfiguration;
 import org.apache.james.webadmin.WebAdminServer;
 import org.apache.james.webadmin.routes.DomainRoutes;
 import org.apache.james.webadmin.routes.UserMailboxesRoutes;
@@ -49,7 +48,6 @@ import com.google.inject.Provides;
 import com.google.inject.Scopes;
 import com.google.inject.Singleton;
 import com.google.inject.multibindings.Multibinder;
-import com.google.inject.name.Named;
 
 public class WebAdminServerModule extends AbstractModule {
 
@@ -68,22 +66,17 @@ public class WebAdminServerModule extends AbstractModule {
     }
 
     @Provides
-    @Named(WEBADMIN_PORT)
-    public Port provideWebAdminPort(PropertiesProvider propertiesProvider) throws Exception {
+    public WebAdminConfiguration provideWebAdminConfiguration(PropertiesProvider propertiesProvider) throws Exception {
         try {
-            return new FixedPort(propertiesProvider.getConfiguration("webadmin").getInt("port", WebAdminServer.DEFAULT_PORT));
+            PropertiesConfiguration configurationFile = propertiesProvider.getConfiguration("webadmin");
+            return WebAdminConfiguration.builder()
+                .enable(configurationFile.getBoolean("enabled", false))
+                .port(new FixedPort(configurationFile.getInt("port", WebAdminServer.DEFAULT_PORT)))
+                .build();
         } catch (FileNotFoundException e) {
-            return new FixedPort(WebAdminServer.DEFAULT_PORT);
-        }
-    }
-
-    @Provides
-    @Named(WEBADMIN_ENABLED)
-    public boolean provideWebAdminEnabled(PropertiesProvider propertiesProvider) throws Exception {
-        try {
-            return propertiesProvider.getConfiguration("webadmin").getBoolean("enabled", false);
-        } catch (FileNotFoundException e) {
-            return false;
+            return WebAdminConfiguration.builder()
+                .disabled()
+                .build();
         }
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/da41f83e/server/protocols/webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/WebAdminConfigurationModule.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/WebAdminConfigurationModule.java b/server/protocols/webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/WebAdminConfigurationModule.java
index f8728dd..d7ccc6d 100644
--- a/server/protocols/webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/WebAdminConfigurationModule.java
+++ b/server/protocols/webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/WebAdminConfigurationModule.java
@@ -19,15 +19,11 @@
 
 package org.apache.james.webadmin.integration;
 
-import static org.apache.james.webadmin.WebAdminServer.WEBADMIN_ENABLED;
-import static org.apache.james.webadmin.WebAdminServer.WEBADMIN_PORT;
-
-import org.apache.james.webadmin.Port;
 import org.apache.james.webadmin.RandomPort;
+import org.apache.james.webadmin.WebAdminConfiguration;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.Provides;
-import com.google.inject.name.Named;
 
 public class WebAdminConfigurationModule extends AbstractModule {
 
@@ -37,14 +33,11 @@ public class WebAdminConfigurationModule extends AbstractModule {
     }
 
     @Provides
-    @Named(WEBADMIN_PORT)
-    public Port provideWebAdminPort() throws Exception {
-        return new RandomPort();
+    public WebAdminConfiguration provideWebAdminConfiguration() throws Exception {
+        return WebAdminConfiguration.builder()
+            .enabled()
+            .port(new RandomPort())
+            .build();
     }
 
-    @Provides
-    @Named(WEBADMIN_ENABLED)
-    public boolean provideWebAdminEnabled() throws Exception {
-        return true;
-    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/da41f83e/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
index b777917..c70f318 100644
--- a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
+++ b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
@@ -24,7 +24,6 @@ import java.util.Set;
 
 import javax.annotation.PreDestroy;
 import javax.inject.Inject;
-import javax.inject.Named;
 
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.commons.configuration.HierarchicalConfiguration;
@@ -41,35 +40,33 @@ public class WebAdminServer implements Configurable {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(WebAdminServer.class);
     public static final HierarchicalConfiguration NO_CONFIGURATION = null;
-    public static final String WEBADMIN_PORT = "webadmin_port";
-    public static final String WEBADMIN_ENABLED = "webadmin_enabled";
     public static final int DEFAULT_PORT = 8080;
 
-    private final Port port;
+    private final WebAdminConfiguration configuration;
     private final Set<Routes> routesList;
-    private final boolean enabled;
     private final Service service;
 
     // Spark do not allow to retrieve allocated port when using a random port. Thus we generate the port.
-
-
     @Inject
-    private WebAdminServer(@Named(WEBADMIN_ENABLED) boolean enabled, @Named(WEBADMIN_PORT)Port port, Set<Routes> routesList) {
-        this.port = port;
+    private WebAdminServer(WebAdminConfiguration configuration, Set<Routes> routesList) {
+        this.configuration = configuration;
         this.routesList = routesList;
-        this.enabled = enabled;
         this.service = Service.ignite();
     }
 
     @VisibleForTesting
     public WebAdminServer(Routes... routes) throws IOException {
-        this(true, new RandomPort(), ImmutableSet.copyOf(routes));
+        this(WebAdminConfiguration.builder()
+            .enabled()
+            .port(new RandomPort())
+            .build(),
+            ImmutableSet.copyOf(routes));
     }
 
     @Override
     public void configure(HierarchicalConfiguration config) throws ConfigurationException {
-        if (enabled) {
-            service.port(port.toInt());
+        if (configuration.isEnabled()) {
+            service.port(configuration.getPort().toInt());
             routesList.forEach(routes -> routes.define(service));
             LOGGER.info("Web admin server started");
         }
@@ -77,7 +74,7 @@ public class WebAdminServer implements Configurable {
 
     @PreDestroy
     public void destroy() {
-        if (enabled) {
+        if (configuration.isEnabled()) {
             service.stop();
             LOGGER.info("Web admin server stopped");
         }
@@ -88,6 +85,6 @@ public class WebAdminServer implements Configurable {
     }
 
     public Port getPort() {
-        return port;
+        return configuration.getPort();
     }
 }


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


[19/22] james-project git commit: JAMES-1958 Rely on AssertJ extractions when asserting big Pojo

Posted by bt...@apache.org.
JAMES-1958 Rely on AssertJ extractions when asserting big Pojo


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

Branch: refs/heads/master
Commit: ef119a44f2103d3073c6558c26f18f5b8791f9ef
Parents: fd82c99
Author: benwa <bt...@linagora.com>
Authored: Mon Mar 13 17:57:42 2017 +0700
Committer: benwa <bt...@linagora.com>
Committed: Wed Mar 15 09:02:32 2017 +0700

----------------------------------------------------------------------
 .../webadmin/WebAdminConfigurationTest.java     | 74 ++++++++++----------
 1 file changed, 38 insertions(+), 36 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/ef119a44/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java b/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java
index 48df15e..dd46f34 100644
--- a/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java
+++ b/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java
@@ -46,11 +46,8 @@ public class WebAdminConfigurationTest {
         assertThat(WebAdminConfiguration.builder()
             .disabled()
             .build())
-            .isEqualTo(new WebAdminConfiguration(false,
-                null,
-                TlsConfiguration.builder().disabled().build(),
-                false,
-                "*"));
+            .extracting(WebAdminConfiguration::isEnabled)
+            .containsExactly(false);
     }
 
     @Test
@@ -61,18 +58,26 @@ public class WebAdminConfigurationTest {
     }
 
     @Test
-    public void builderShouldBuildRightObject() {
+    public void builderShouldBuildWithRightPort() {
         assertThat(
             WebAdminConfiguration.builder()
                 .enabled()
                 .port(PORT)
                 .build())
-            .isEqualTo(new WebAdminConfiguration(
-                true,
-                PORT,
-                TlsConfiguration.builder().disabled().build(),
-                false,
-                "*"));
+            .extracting(WebAdminConfiguration::getPort)
+            .containsExactly(PORT);
+    }
+
+
+    @Test
+    public void builderShouldBuildWithEnable() {
+        assertThat(
+            WebAdminConfiguration.builder()
+                .enabled()
+                .port(PORT)
+                .build())
+            .extracting(WebAdminConfiguration::isEnabled)
+            .containsExactly(true);
     }
 
     @Test
@@ -88,12 +93,8 @@ public class WebAdminConfigurationTest {
                 .https(tlsConfiguration)
                 .port(PORT)
                 .build())
-            .isEqualTo(new WebAdminConfiguration(
-                true,
-                PORT,
-                tlsConfiguration,
-                false,
-                "*"));
+            .extracting(WebAdminConfiguration::getTlsConfiguration)
+            .containsExactly(tlsConfiguration);
     }
 
     @Test
@@ -104,12 +105,21 @@ public class WebAdminConfigurationTest {
                 .port(PORT)
                 .CORSenabled()
                 .build())
-            .isEqualTo(new WebAdminConfiguration(
-                true,
-                PORT,
-                TlsConfiguration.builder().disabled().build(),
-                true,
-                "*"));
+            .extracting(WebAdminConfiguration::isEnableCORS)
+            .containsExactly(true);
+    }
+
+
+    @Test
+    public void builderShouldAcceptAllOriginsByDefault() {
+        assertThat(
+            WebAdminConfiguration.builder()
+                .enabled()
+                .port(PORT)
+                .CORSenabled()
+                .build())
+            .extracting(WebAdminConfiguration::getUrlCORSOrigin)
+            .containsExactly("*");
     }
 
     @Test
@@ -120,12 +130,8 @@ public class WebAdminConfigurationTest {
                 .port(PORT)
                 .CORSdisabled()
                 .build())
-            .isEqualTo(new WebAdminConfiguration(
-                true,
-                PORT,
-                TlsConfiguration.builder().disabled().build(),
-                false,
-                "*"));
+            .extracting(WebAdminConfiguration::isEnableCORS)
+            .containsExactly(false);
     }
 
     @Test
@@ -138,12 +144,8 @@ public class WebAdminConfigurationTest {
                 .CORSenabled()
                 .urlCORSOrigin(origin)
                 .build())
-            .isEqualTo(new WebAdminConfiguration(
-                true,
-                PORT,
-                TlsConfiguration.builder().disabled().build(),
-                true,
-                origin));
+            .extracting(WebAdminConfiguration::getUrlCORSOrigin)
+            .containsExactly(origin);
     }
 
     @Test


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


[02/22] james-project git commit: JAMES-1958 Define a configuration object for WebAdmin server

Posted by bt...@apache.org.
JAMES-1958 Define a configuration object for WebAdmin server


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

Branch: refs/heads/master
Commit: 6ae498a7c98ae9f61a2e51cf56c71f8fe6ee571b
Parents: 9d99b73
Author: benwa <bt...@linagora.com>
Authored: Wed Mar 8 14:09:26 2017 +0700
Committer: benwa <bt...@linagora.com>
Committed: Wed Mar 15 09:01:52 2017 +0700

----------------------------------------------------------------------
 server/protocols/webadmin/pom.xml               |  5 +
 .../org/apache/james/webadmin/FixedPort.java    | 16 ++++
 .../james/webadmin/WebAdminConfiguration.java   | 96 ++++++++++++++++++++
 .../apache/james/webadmin/FixedPortTest.java    |  7 ++
 .../webadmin/WebAdminConfigurationTest.java     | 74 +++++++++++++++
 5 files changed, 198 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/6ae498a7/server/protocols/webadmin/pom.xml
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/pom.xml b/server/protocols/webadmin/pom.xml
index 02cba3e..8ae6689 100644
--- a/server/protocols/webadmin/pom.xml
+++ b/server/protocols/webadmin/pom.xml
@@ -231,6 +231,11 @@
                     <artifactId>slf4j-api</artifactId>
                 </dependency>
                 <dependency>
+                    <groupId>nl.jqno.equalsverifier</groupId>
+                    <artifactId>equalsverifier</artifactId>
+                    <version>1.7.6</version>
+                </dependency>
+                <dependency>
                     <groupId>org.slf4j</groupId>
                     <artifactId>slf4j-simple</artifactId>
                     <scope>test</scope>

http://git-wip-us.apache.org/repos/asf/james-project/blob/6ae498a7/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/FixedPort.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/FixedPort.java b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/FixedPort.java
index e977f09..7ada8a1 100644
--- a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/FixedPort.java
+++ b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/FixedPort.java
@@ -19,6 +19,8 @@
 
 package org.apache.james.webadmin;
 
+import java.util.Objects;
+
 import com.google.common.base.Preconditions;
 
 public class FixedPort implements Port {
@@ -35,4 +37,18 @@ public class FixedPort implements Port {
         return port;
     }
 
+    @Override
+    public final boolean equals(Object o) {
+        if (o instanceof FixedPort) {
+            FixedPort that = (FixedPort) o;
+
+            return Objects.equals(this.port, that.port);
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(port);
+    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/6ae498a7/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
new file mode 100644
index 0000000..b21749c
--- /dev/null
+++ b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
@@ -0,0 +1,96 @@
+/****************************************************************
+ * 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;
+
+import java.util.Objects;
+import java.util.Optional;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+
+public class WebAdminConfiguration {
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    public static class Builder {
+        private Optional<Boolean> enabled = Optional.empty();
+        private Port port;
+
+        public Builder port(Port port) {
+            this.port = port;
+            return this;
+        }
+
+        public Builder enable(boolean isEnabled) {
+            this.enabled = Optional.of(isEnabled);
+            return this;
+        }
+
+        public Builder enabled() {
+            return enable(true);
+        }
+
+        public Builder disabled() {
+            return enable(false);
+        }
+
+        public WebAdminConfiguration build() {
+            Preconditions.checkState(enabled.isPresent(), "You need to explicitly enable or disable WebAdmin server");
+            Preconditions.checkState(!enabled.get() || port != null, "You need to specify a port for WebAdminConfiguration");
+            return new WebAdminConfiguration(enabled.get(), port);
+        }
+    }
+
+    private final boolean enabled;
+    private final Port port;
+
+    @VisibleForTesting
+    WebAdminConfiguration(boolean enabled, Port port) {
+        this.enabled = enabled;
+        this.port = port;
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public Port getPort() {
+        return port;
+    }
+
+    @Override
+    public final boolean equals(Object o) {
+        if (o instanceof WebAdminConfiguration) {
+            WebAdminConfiguration that = (WebAdminConfiguration) o;
+
+            return Objects.equals(this.enabled, that.enabled)
+                && Objects.equals(this.port, that.port);
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(enabled, port);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/6ae498a7/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/FixedPortTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/FixedPortTest.java b/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/FixedPortTest.java
index eb6abdb..2712daa 100644
--- a/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/FixedPortTest.java
+++ b/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/FixedPortTest.java
@@ -24,6 +24,8 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 import org.junit.Test;
 
+import nl.jqno.equalsverifier.EqualsVerifier;
+
 public class FixedPortTest {
 
     @Test
@@ -47,4 +49,9 @@ public class FixedPortTest {
         assertThat(new FixedPort(expectedPort).toInt()).isEqualTo(expectedPort);
     }
 
+    @Test
+    public void shouldMatchBeanContract() {
+        EqualsVerifier.forClass(FixedPort.class).verify();
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/6ae498a7/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java b/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java
new file mode 100644
index 0000000..01f3c2a
--- /dev/null
+++ b/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java
@@ -0,0 +1,74 @@
+/****************************************************************
+ * 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;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+
+public class WebAdminConfigurationTest {
+
+    public static final FixedPort PORT = new FixedPort(80);
+
+    @Rule
+    public ExpectedException expectedException = ExpectedException.none();
+
+    @Test
+    public void buildShouldThrowWhenNoPortButEnabled() {
+        expectedException.expect(IllegalStateException.class);
+
+        WebAdminConfiguration.builder().enabled().build();
+    }
+
+    @Test
+    public void buildShouldWorkWithoutPortWhenDisabled() {
+        assertThat(WebAdminConfiguration.builder()
+            .disabled()
+            .build())
+            .isEqualTo(new WebAdminConfiguration(false, null));
+    }
+
+    @Test
+    public void buildShouldFailOnNoEnable() {
+        expectedException.expect(IllegalStateException.class);
+
+        WebAdminConfiguration.builder().port(PORT).build();
+    }
+
+    @Test
+    public void builderShouldBuildRightObject() {
+        assertThat(
+            WebAdminConfiguration.builder()
+                .enabled()
+                .port(PORT)
+                .build())
+            .isEqualTo(new WebAdminConfiguration(true, PORT));
+    }
+
+    @Test
+    public void shouldMatchBeanContract() {
+        EqualsVerifier.forClass(WebAdminConfiguration.class).verify();
+    }
+
+}


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


[04/22] james-project git commit: JAMES-1961 Increase Spark version to get logs for 500

Posted by bt...@apache.org.
JAMES-1961 Increase Spark version to get logs for 500


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

Branch: refs/heads/master
Commit: 0fc16af0c1ad4d2d902eb74236c9b2e5a980cee2
Parents: a43fbd4
Author: benwa <bt...@linagora.com>
Authored: Thu Mar 9 16:16:48 2017 +0700
Committer: benwa <bt...@linagora.com>
Committed: Wed Mar 15 09:01:52 2017 +0700

----------------------------------------------------------------------
 server/protocols/webadmin/pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/0fc16af0/server/protocols/webadmin/pom.xml
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/pom.xml b/server/protocols/webadmin/pom.xml
index 3f9bae4..02cba3e 100644
--- a/server/protocols/webadmin/pom.xml
+++ b/server/protocols/webadmin/pom.xml
@@ -193,7 +193,7 @@
                 <dependency>
                     <groupId>com.sparkjava</groupId>
                     <artifactId>spark-core</artifactId>
-                    <version>2.5</version>
+                    <version>2.5.5</version>
                 </dependency>
                 <dependency>
                     <groupId>de.bechte.junit</groupId>


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


[09/22] james-project git commit: JAMES-1959 Extract JWT to an other maven project

Posted by bt...@apache.org.
JAMES-1959 Extract JWT to an other maven project


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

Branch: refs/heads/master
Commit: f1a087fa60217383969f2a281703f8cf0e0d8efb
Parents: 3ac2368
Author: benwa <bt...@linagora.com>
Authored: Wed Mar 8 17:25:54 2017 +0700
Committer: benwa <bt...@linagora.com>
Committed: Wed Mar 15 09:01:53 2017 +0700

----------------------------------------------------------------------
 .../java/org/apache/james/jmap/JMAPModule.java  |   7 +
 server/pom.xml                                  |   6 +
 server/protocols/jmap/pom.xml                   |   4 +
 .../james/jmap/JWTAuthenticationStrategy.java   |   2 +-
 .../james/jmap/crypto/JwtTokenVerifier.java     |  63 -----
 .../crypto/MissingOrInvalidKeyException.java    |  22 --
 .../james/jmap/crypto/PublicKeyProvider.java    |  44 ----
 .../james/jmap/crypto/PublicKeyReader.java      |  56 -----
 .../jmap/JWTAuthenticationStrategyTest.java     |   2 +-
 .../james/jmap/crypto/JwtTokenVerifierTest.java | 124 ----------
 .../jmap/crypto/PublicKeyProviderTest.java      |  74 ------
 .../james/jmap/crypto/PublicKeyReaderTest.java  |  62 -----
 server/protocols/jwt/pom.xml                    | 245 +++++++++++++++++++
 .../org/apache/james/jwt/JwtConfiguration.java  |  34 +++
 .../org/apache/james/jwt/JwtTokenVerifier.java  |  63 +++++
 .../james/jwt/MissingOrInvalidKeyException.java |  22 ++
 .../org/apache/james/jwt/PublicKeyProvider.java |  44 ++++
 .../org/apache/james/jwt/PublicKeyReader.java   |  56 +++++
 .../apache/james/jwt/JwtTokenVerifierTest.java  | 119 +++++++++
 .../apache/james/jwt/PublicKeyProviderTest.java |  67 +++++
 .../apache/james/jwt/PublicKeyReaderTest.java   |  62 +++++
 21 files changed, 731 insertions(+), 447 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/f1a087fa/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPModule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPModule.java b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPModule.java
index 7269cb1..eca11aa 100644
--- a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPModule.java
+++ b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPModule.java
@@ -34,6 +34,7 @@ import org.apache.james.jmap.utils.HtmlTextExtractor;
 import org.apache.james.jmap.utils.MailboxBasedHtmlTextExtractor;
 import org.apache.james.jmap.utils.SystemMailboxesProvider;
 import org.apache.james.jmap.utils.SystemMailboxesProviderImpl;
+import org.apache.james.jwt.JwtConfiguration;
 import org.apache.james.lifecycle.api.Configurable;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.MailboxManager.SearchCapabilities;
@@ -89,6 +90,12 @@ public class JMAPModule extends AbstractModule {
                 .build();
     }
 
+    @Provides
+    @Singleton
+    JwtConfiguration providesJwtConfiguration(JMAPConfiguration jmapConfiguration) {
+        return new JwtConfiguration(jmapConfiguration.getJwtPublicKeyPem());
+    }
+
     private Optional<String> loadPublicKey(FileSystem fileSystem, Optional<String> jwtPublickeyPemUrl) {
         return jwtPublickeyPemUrl.map(Throwing.function(url -> FileUtils.readFileToString(fileSystem.getFile(url))));
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/f1a087fa/server/pom.xml
----------------------------------------------------------------------
diff --git a/server/pom.xml b/server/pom.xml
index 4ceaa15..4b7d969 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -109,6 +109,7 @@
         <module>protocols/webadmin-integration-test</module>
 
         <module>testing</module>
+        <module>protocols/jwt</module>
     </modules>
 
     <distributionManagement>
@@ -807,6 +808,11 @@
             </dependency>
             <dependency>
                 <groupId>org.apache.james</groupId>
+                <artifactId>james-server-jwt</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.james</groupId>
                 <artifactId>james-server-protocols-lmtp</artifactId>
                 <version>${project.version}</version>
             </dependency>

http://git-wip-us.apache.org/repos/asf/james-project/blob/f1a087fa/server/protocols/jmap/pom.xml
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/pom.xml b/server/protocols/jmap/pom.xml
index 152dc79..287e428 100644
--- a/server/protocols/jmap/pom.xml
+++ b/server/protocols/jmap/pom.xml
@@ -217,6 +217,10 @@
                 </dependency>
                 <dependency>
                     <groupId>org.apache.james</groupId>
+                    <artifactId>james-server-jwt</artifactId>
+                </dependency>
+                <dependency>
+                    <groupId>org.apache.james</groupId>
                     <artifactId>james-server-lifecycle-api</artifactId>
                 </dependency>
                 <dependency>

http://git-wip-us.apache.org/repos/asf/james-project/blob/f1a087fa/server/protocols/jmap/src/main/java/org/apache/james/jmap/JWTAuthenticationStrategy.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/JWTAuthenticationStrategy.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/JWTAuthenticationStrategy.java
index a7e91be..9f4f609 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/JWTAuthenticationStrategy.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/JWTAuthenticationStrategy.java
@@ -23,10 +23,10 @@ import java.util.stream.Stream;
 import javax.inject.Inject;
 import javax.servlet.http.HttpServletRequest;
 
-import org.apache.james.jmap.crypto.JwtTokenVerifier;
 import org.apache.james.jmap.exceptions.MailboxSessionCreationException;
 import org.apache.james.jmap.exceptions.NoValidAuthHeaderException;
 import org.apache.james.jmap.utils.HeadersAuthenticationExtractor;
+import org.apache.james.jwt.JwtTokenVerifier;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.exception.MailboxException;

http://git-wip-us.apache.org/repos/asf/james-project/blob/f1a087fa/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/JwtTokenVerifier.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/JwtTokenVerifier.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/JwtTokenVerifier.java
deleted file mode 100644
index dea68af..0000000
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/JwtTokenVerifier.java
+++ /dev/null
@@ -1,63 +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.jmap.crypto;
-
-import javax.inject.Inject;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Strings;
-
-import io.jsonwebtoken.Claims;
-import io.jsonwebtoken.Jws;
-import io.jsonwebtoken.JwtException;
-import io.jsonwebtoken.Jwts;
-import io.jsonwebtoken.MalformedJwtException;
-
-public class JwtTokenVerifier {
-
-    private final PublicKeyProvider pubKeyProvider;
-
-    @Inject
-    @VisibleForTesting
-    JwtTokenVerifier(PublicKeyProvider pubKeyProvider) {
-        this.pubKeyProvider = pubKeyProvider;
-    }
-
-    public boolean verify(String token) throws JwtException {
-        String subject = extractLogin(token);
-        if (Strings.isNullOrEmpty(subject)) {
-            throw new MalformedJwtException("'subject' field in token is mandatory");
-        }
-        return true;
-    }
-
-    public String extractLogin(String token) throws JwtException {
-        Jws<Claims> jws = parseToken(token);
-        return jws
-                .getBody()
-                .getSubject();
-    }
-
-    private Jws<Claims> parseToken(String token) throws JwtException {
-        return Jwts
-                .parser()
-                .setSigningKey(pubKeyProvider.get())
-                .parseClaimsJws(token);
-    }
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/f1a087fa/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/MissingOrInvalidKeyException.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/MissingOrInvalidKeyException.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/MissingOrInvalidKeyException.java
deleted file mode 100644
index a98b7e3..0000000
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/MissingOrInvalidKeyException.java
+++ /dev/null
@@ -1,22 +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.jmap.crypto;
-
-public class MissingOrInvalidKeyException extends RuntimeException {
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/f1a087fa/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/PublicKeyProvider.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/PublicKeyProvider.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/PublicKeyProvider.java
deleted file mode 100644
index e88ffba..0000000
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/PublicKeyProvider.java
+++ /dev/null
@@ -1,44 +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.jmap.crypto;
-
-import com.google.common.annotations.VisibleForTesting;
-import org.apache.james.jmap.JMAPConfiguration;
-
-import javax.inject.Inject;
-import java.security.PublicKey;
-
-public class PublicKeyProvider {
-
-    private final JMAPConfiguration config;
-    private final PublicKeyReader reader;
-
-    @Inject
-    @VisibleForTesting
-    PublicKeyProvider(JMAPConfiguration config, PublicKeyReader reader) {
-        this.config = config;
-        this.reader = reader;
-    }
-
-    public PublicKey get() throws MissingOrInvalidKeyException {
-        return reader.fromPEM(config.getJwtPublicKeyPem())
-                .orElseThrow(() -> new MissingOrInvalidKeyException());
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/f1a087fa/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/PublicKeyReader.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/PublicKeyReader.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/PublicKeyReader.java
deleted file mode 100644
index b695c26..0000000
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/PublicKeyReader.java
+++ /dev/null
@@ -1,56 +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.jmap.crypto;
-
-import java.io.IOException;
-import java.io.StringReader;
-import java.security.PublicKey;
-import java.util.Optional;
-
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.openssl.PEMParser;
-import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
-import org.bouncycastle.util.io.pem.PemReader;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class PublicKeyReader {
-
-    private static final Logger LOGGER = LoggerFactory.getLogger(PublicKeyReader.class);
-
-    Optional<PublicKey> fromPEM(Optional<String> pemKey) {
-        return pemKey
-                .map(k -> new PEMParser(new PemReader(new StringReader(k))))
-                .flatMap(this::publicKeyFrom);
-    }
-
-    private Optional<PublicKey> publicKeyFrom(PEMParser reader) {
-        try {
-            Object readPEM = reader.readObject();
-            if (readPEM instanceof SubjectPublicKeyInfo) {
-                return Optional.of(new JcaPEMKeyConverter().getPublicKey((SubjectPublicKeyInfo) readPEM));
-            }
-            LOGGER.warn("Key is not an instance of SubjectPublicKeyInfo but of " + readPEM);
-            return Optional.empty();
-        } catch (IOException e) {
-            LOGGER.warn("Error when reading the PEM file", e);
-            return Optional.empty();
-        }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/f1a087fa/server/protocols/jmap/src/test/java/org/apache/james/jmap/JWTAuthenticationStrategyTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/JWTAuthenticationStrategyTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/JWTAuthenticationStrategyTest.java
index 4a60578..530fac4 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/JWTAuthenticationStrategyTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/JWTAuthenticationStrategyTest.java
@@ -29,10 +29,10 @@ import java.util.stream.Stream;
 
 import javax.servlet.http.HttpServletRequest;
 
-import org.apache.james.jmap.crypto.JwtTokenVerifier;
 import org.apache.james.jmap.exceptions.MailboxSessionCreationException;
 import org.apache.james.jmap.exceptions.NoValidAuthHeaderException;
 import org.apache.james.jmap.utils.HeadersAuthenticationExtractor;
+import org.apache.james.jwt.JwtTokenVerifier;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.exception.MailboxException;

http://git-wip-us.apache.org/repos/asf/james-project/blob/f1a087fa/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/JwtTokenVerifierTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/JwtTokenVerifierTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/JwtTokenVerifierTest.java
deleted file mode 100644
index e3fa5bd..0000000
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/JwtTokenVerifierTest.java
+++ /dev/null
@@ -1,124 +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.jmap.crypto;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
-import java.security.Security;
-import java.util.Optional;
-
-import org.apache.james.jmap.JMAPConfiguration;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import io.jsonwebtoken.MalformedJwtException;
-import io.jsonwebtoken.SignatureException;
-
-public class JwtTokenVerifierTest {
-
-    private static final String PUBLIC_PEM_KEY = "-----BEGIN PUBLIC KEY-----\n" +
-            "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtlChO/nlVP27MpdkG0Bh\n" +
-            "16XrMRf6M4NeyGa7j5+1UKm42IKUf3lM28oe82MqIIRyvskPc11NuzSor8HmvH8H\n" +
-            "lhDs5DyJtx2qp35AT0zCqfwlaDnlDc/QDlZv1CoRZGpQk1Inyh6SbZwYpxxwh0fi\n" +
-            "+d/4RpE3LBVo8wgOaXPylOlHxsDizfkL8QwXItyakBfMO6jWQRrj7/9WDhGf4Hi+\n" +
-            "GQur1tPGZDl9mvCoRHjFrD5M/yypIPlfMGWFVEvV5jClNMLAQ9bYFuOc7H1fEWw6\n" +
-            "U1LZUUbJW9/CH45YXz82CYqkrfbnQxqRb2iVbVjs/sHopHd1NTiCfUtwvcYJiBVj\n" +
-            "kwIDAQAB\n" +
-            "-----END PUBLIC KEY-----";
-    
-    private static final String VALID_TOKEN = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0.T04BTk" +
-            "LXkJj24coSZkK13RfG25lpvmSl2MJ7N10KpBk9_-95EGYZdog-BDAn3PJzqVw52z-Bwjh4VOj1-j7cURu0cT4jXehhUrlCxS4n7QHZD" +
-            "N_bsEYGu7KzjWTpTsUiHe-rN7izXVFxDGG1TGwlmBCBnPW-EFCf9ylUsJi0r2BKNdaaPRfMIrHptH1zJBkkUziWpBN1RNLjmvlAUf49" +
-            "t1Tbv21ZqYM5Ht2vrhJWczFbuC-TD-8zJkXhjTmA1GVgomIX5dx1cH-dZX1wANNmshUJGHgepWlPU-5VIYxPEhb219RMLJIELMY2qN" +
-            "OR8Q31ydinyqzXvCSzVJOf6T60-w";
-
-    private JwtTokenVerifier sut;
-
-    @BeforeClass
-    public static void init() {
-        Security.addProvider(new BouncyCastleProvider());
-    }
-
-    @Before
-    public void setup() {
-        PublicKeyProvider pubKeyProvider = new PublicKeyProvider(getJWTConfiguration(), new PublicKeyReader());
-        sut = new JwtTokenVerifier(pubKeyProvider);
-    }
-
-    private JMAPConfiguration getJWTConfiguration() {
-
-        return JMAPConfiguration.builder()
-                .keystore(".")
-                .secret(".")
-                .jwtPublicKeyPem(Optional.ofNullable(PUBLIC_PEM_KEY))
-                .build();
-    }
-
-    @Test
-    public void shouldReturnTrueOnValidSignature() {
-
-        assertThat(sut.verify(VALID_TOKEN)).isTrue();
-    }
-
-    @Test
-    public void shouldThrowOnMismatchingSigningKey() {
-        String invalidToken = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0.Pd6t82" +
-                "tPL3EZdkeYxw_DV2KimE1U2FvuLHmfR_mimJ5US3JFU4J2Gd94O7rwpSTGN1B9h-_lsTebo4ua4xHsTtmczZ9xa8a_kWKaSkqFjNFa" +
-                "Fp6zcoD6ivCu03SlRqsQzSRHXo6TKbnqOt9D6Y2rNa3C4igSwoS0jUE4BgpXbc0";
-
-        assertThatThrownBy(() -> sut.verify(invalidToken))
-            .isInstanceOf(SignatureException.class);
-    }
-
-    @Test
-    public void verifyShouldThrowWhenSubjectIsNull() {
-        String tokenWithNullSubject = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOm51bGwsIm5hbWUiOiJKb2huIERvZSJ9.EB" +
-                "_1grWDy_kFelXs3AQeiP13ay4eG_134dWB9XPRSeWsuPs8Mz2UY-VHDxLGD-fAqv-xKXr4QFEnS7iZkdpe0tPLNSwIjqeqkC6KqQln" +
-                "oC1okqWVWBDOcf7Acp1Jzp_cFTUhL5LkHvZDsyCdq5T9OOVVkzO4A9RrzIUsTrYPtRCBuYJ3ggR33cKpw191PulPGNH70rZqpUfDXe" +
-                "VPY3q15vWzZH9O9IJzB2KdHRMPxl2luRjzDbh4DLp56NhZuLX_2a9UAlmbV8MQX4Z_04ybhAYrcBfxR3MgJyr0jlxSibqSbXrkXuo-" +
-                "PyybfZCIhK_qXUlO5OS6sO7AQhKZO9p0MQ";
-
-        assertThatThrownBy(() -> sut.verify(tokenWithNullSubject))
-            .isInstanceOf(MalformedJwtException.class)
-            .hasMessage("'subject' field in token is mandatory");
-    }
-    
-    @Test
-    public void verifyShouldThrowWhenEmptySubject() {
-        String tokenWithEmptySubject = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIiLCJuYW1lIjoiSm9obiBEb2UifQ.UdY" +
-                "s2PPzFCegUYspoDCnlJR_bJm8_z1InOv4v3tq8SJETQUarOXlhb_n6y6ujVvmJiSx9dI24Hc3Czi3RGUOXbnBDj1WPfd0aVSiUSqZr" +
-                "MCHBt5vjCYqAseDaP3w4aiiFb6EV3tteJFeBLZx8XlKPYxlzRLLUADDyDSQvrFBBPxfsvCETZovKdo9ofIN64o-yx23ss63yE6oIOd" +
-                "zJZ1Id40KSR2d7l3kIQJPLKUWJDnro5RAh4DOGOWNSq0JSbMhk7Zn3cXIBUpv3R8p79tui1UQpzwHMC0e6OSuWEDNQHtq-Cz85u8GG" +
-                "sUSbogmgObA_BimNtUq_Q1p0SGtIYBXmQ";
-
-        assertThatThrownBy(() -> sut.verify(tokenWithEmptySubject))
-            .isInstanceOf(MalformedJwtException.class)
-            .hasMessage("'subject' field in token is mandatory");
-    }
-
-    @Test
-    public void shouldReturnUserLoginFromValidToken() {
-
-        assertThat(sut.extractLogin(VALID_TOKEN)).isEqualTo("1234567890");
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/f1a087fa/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/PublicKeyProviderTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/PublicKeyProviderTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/PublicKeyProviderTest.java
deleted file mode 100644
index 5db7d7b..0000000
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/PublicKeyProviderTest.java
+++ /dev/null
@@ -1,74 +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.jmap.crypto;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
-import java.security.Security;
-import java.security.interfaces.RSAPublicKey;
-import java.util.Optional;
-
-import org.apache.james.jmap.JMAPConfiguration;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-public class PublicKeyProviderTest {
-
-    private static final String PUBLIC_PEM_KEY = "-----BEGIN PUBLIC KEY-----\n" +
-            "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtlChO/nlVP27MpdkG0Bh\n" +
-            "16XrMRf6M4NeyGa7j5+1UKm42IKUf3lM28oe82MqIIRyvskPc11NuzSor8HmvH8H\n" +
-            "lhDs5DyJtx2qp35AT0zCqfwlaDnlDc/QDlZv1CoRZGpQk1Inyh6SbZwYpxxwh0fi\n" +
-            "+d/4RpE3LBVo8wgOaXPylOlHxsDizfkL8QwXItyakBfMO6jWQRrj7/9WDhGf4Hi+\n" +
-            "GQur1tPGZDl9mvCoRHjFrD5M/yypIPlfMGWFVEvV5jClNMLAQ9bYFuOc7H1fEWw6\n" +
-            "U1LZUUbJW9/CH45YXz82CYqkrfbnQxqRb2iVbVjs/sHopHd1NTiCfUtwvcYJiBVj\n" +
-            "kwIDAQAB\n" +
-            "-----END PUBLIC KEY-----";
-
-    @BeforeClass
-    public static void init() {
-        Security.addProvider(new BouncyCastleProvider());
-    }
-
-    @Test
-    public void getShouldNotThrowWhenPEMKeyProvided() {
-
-        JMAPConfiguration configWithPEMKey = JMAPConfiguration.builder()
-                .jwtPublicKeyPem(Optional.ofNullable(PUBLIC_PEM_KEY))
-                .keystore(".").secret(".")
-                .build();
-
-        PublicKeyProvider sut = new PublicKeyProvider(configWithPEMKey, new PublicKeyReader());
-
-        assertThat(sut.get()).isInstanceOf(RSAPublicKey.class);
-    }
-
-    @Test
-    public void getShouldThrowWhenPEMKeyNotProvided() {
-        JMAPConfiguration configWithPEMKey = JMAPConfiguration.builder()
-                .jwtPublicKeyPem(Optional.ofNullable(""))
-                .keystore(" ").secret(" ")
-                .build();
-
-        PublicKeyProvider sut = new PublicKeyProvider(configWithPEMKey, new PublicKeyReader());
-
-        assertThatThrownBy(() -> sut.get()).isExactlyInstanceOf(MissingOrInvalidKeyException.class);
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/f1a087fa/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/PublicKeyReaderTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/PublicKeyReaderTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/PublicKeyReaderTest.java
deleted file mode 100644
index 2765282..0000000
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/PublicKeyReaderTest.java
+++ /dev/null
@@ -1,62 +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.jmap.crypto;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import java.security.Security;
-import java.util.Optional;
-
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-public class PublicKeyReaderTest {
-
-    private static final String PUBLIC_PEM_KEY = "-----BEGIN PUBLIC KEY-----\n" +
-            "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtlChO/nlVP27MpdkG0Bh\n" +
-            "16XrMRf6M4NeyGa7j5+1UKm42IKUf3lM28oe82MqIIRyvskPc11NuzSor8HmvH8H\n" +
-            "lhDs5DyJtx2qp35AT0zCqfwlaDnlDc/QDlZv1CoRZGpQk1Inyh6SbZwYpxxwh0fi\n" +
-            "+d/4RpE3LBVo8wgOaXPylOlHxsDizfkL8QwXItyakBfMO6jWQRrj7/9WDhGf4Hi+\n" +
-            "GQur1tPGZDl9mvCoRHjFrD5M/yypIPlfMGWFVEvV5jClNMLAQ9bYFuOc7H1fEWw6\n" +
-            "U1LZUUbJW9/CH45YXz82CYqkrfbnQxqRb2iVbVjs/sHopHd1NTiCfUtwvcYJiBVj\n" +
-            "kwIDAQAB\n" +
-            "-----END PUBLIC KEY-----";
-
-    @BeforeClass
-    public static void init() {
-        Security.addProvider(new BouncyCastleProvider());
-    }
-
-    @Test
-    public void fromPEMShouldReturnEmptyWhenEmptyProvided() {
-        assertThat(new PublicKeyReader().fromPEM(Optional.empty())).isEmpty();
-    }
-
-    @Test
-    public void fromPEMShouldReturnEmptyWhenInvalidPEMKey() {
-        assertThat(new PublicKeyReader().fromPEM(Optional.of("blabla"))).isEmpty();
-    }
-
-    @Test
-    public void fromPEMShouldReturnRSAPublicKeyWhenValidPEMKey() {
-        assertThat(new PublicKeyReader().fromPEM(Optional.of(PUBLIC_PEM_KEY))).isPresent();
-    }
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/f1a087fa/server/protocols/jwt/pom.xml
----------------------------------------------------------------------
diff --git a/server/protocols/jwt/pom.xml b/server/protocols/jwt/pom.xml
new file mode 100644
index 0000000..85d17b9
--- /dev/null
+++ b/server/protocols/jwt/pom.xml
@@ -0,0 +1,245 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>james-server</artifactId>
+        <groupId>org.apache.james</groupId>
+        <version>3.0.0-beta6-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>james-server-jwt</artifactId>
+    <packaging>jar</packaging>
+
+    <name>Apache James :: Server :: JWT</name>
+
+    <profiles>
+        <profile>
+            <id>noTest</id>
+            <activation>
+                <os>
+                    <family>windows</family>
+                </os>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <configuration>
+                            <skipTests>true</skipTests>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>disable-build-for-older-jdk</id>
+            <activation>
+                <jdk>(,1.8)</jdk>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <artifactId>maven-jar-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>default-jar</id>
+                                <phase>none</phase>
+                            </execution>
+                            <execution>
+                                <id>jar</id>
+                                <phase>none</phase>
+                            </execution>
+                            <execution>
+                                <id>test-jar</id>
+                                <phase>none</phase>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <artifactId>maven-compiler-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>default-compile</id>
+                                <phase>none</phase>
+                            </execution>
+                            <execution>
+                                <id>default-testCompile</id>
+                                <phase>none</phase>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>default-test</id>
+                                <phase>none</phase>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <artifactId>maven-source-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>attach-sources</id>
+                                <phase>none</phase>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <artifactId>maven-install-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>default-install</id>
+                                <phase>none</phase>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <artifactId>maven-resources-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>default-resources</id>
+                                <phase>none</phase>
+                            </execution>
+                            <execution>
+                                <id>default-testResources</id>
+                                <phase>none</phase>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <artifactId>maven-site-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>attach-descriptor</id>
+                                <phase>none</phase>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>build-for-jdk-8</id>
+            <activation>
+                <jdk>[1.8,)</jdk>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>javax.inject</groupId>
+                    <artifactId>javax.inject</artifactId>
+                </dependency>
+                <dependency>
+                    <groupId>com.google.guava</groupId>
+                    <artifactId>guava</artifactId>
+                </dependency>
+                <dependency>
+                    <groupId>io.jsonwebtoken</groupId>
+                    <artifactId>jjwt</artifactId>
+                </dependency>
+                <dependency>
+                    <groupId>junit</groupId>
+                    <artifactId>junit</artifactId>
+                    <scope>test</scope>
+                </dependency>
+                <dependency>
+                    <groupId>org.assertj</groupId>
+                    <artifactId>assertj-core</artifactId>
+                    <version>${assertj-3.version}</version>
+                </dependency>
+                <dependency>
+                    <groupId>org.bouncycastle</groupId>
+                    <artifactId>bcpkix-jdk15on</artifactId>
+                </dependency>
+                <dependency>
+                    <groupId>org.bouncycastle</groupId>
+                    <artifactId>bcprov-jdk15on</artifactId>
+                </dependency>
+                <dependency>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </dependency>
+            </dependencies>
+            <build>
+                <plugins>
+                    <plugin>
+                        <artifactId>maven-assembly-plugin</artifactId>
+                        <configuration>
+                            <archive>
+                                <manifest>
+                                    <mainClass>fully.qualified.MainClass</mainClass>
+                                </manifest>
+                            </archive>
+                            <descriptorRefs>
+                                <descriptorRef>jar-with-dependencies</descriptorRef>
+                            </descriptorRefs>
+                        </configuration>
+                    </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-compiler-plugin</artifactId>
+                        <configuration>
+                            <source>1.8</source>
+                            <target>1.8</target>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>animal-sniffer-java-8</id>
+            <activation>
+                <jdk>[1.8,)</jdk>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>animal-sniffer-maven-plugin</artifactId>
+                        <configuration>
+                            <signature>
+                                <groupId>org.codehaus.mojo.signature</groupId>
+                                <artifactId>java18</artifactId>
+                                <version>1.0</version>
+                            </signature>
+                        </configuration>
+                        <executions>
+                            <execution>
+                                <id>check_java_8</id>
+                                <phase>test</phase>
+                                <goals>
+                                    <goal>check</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+
+
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/f1a087fa/server/protocols/jwt/src/main/java/org/apache/james/jwt/JwtConfiguration.java
----------------------------------------------------------------------
diff --git a/server/protocols/jwt/src/main/java/org/apache/james/jwt/JwtConfiguration.java b/server/protocols/jwt/src/main/java/org/apache/james/jwt/JwtConfiguration.java
new file mode 100644
index 0000000..3cfcfef
--- /dev/null
+++ b/server/protocols/jwt/src/main/java/org/apache/james/jwt/JwtConfiguration.java
@@ -0,0 +1,34 @@
+/****************************************************************
+ * 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.jwt;
+
+import java.util.Optional;
+
+public class JwtConfiguration {
+    private final Optional<String> jwtPublicKeyPem;
+
+    public JwtConfiguration(Optional<String> jwtPublicKeyPem) {
+        this.jwtPublicKeyPem = jwtPublicKeyPem;
+    }
+
+    public Optional<String> getJwtPublicKeyPem() {
+        return jwtPublicKeyPem;
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/f1a087fa/server/protocols/jwt/src/main/java/org/apache/james/jwt/JwtTokenVerifier.java
----------------------------------------------------------------------
diff --git a/server/protocols/jwt/src/main/java/org/apache/james/jwt/JwtTokenVerifier.java b/server/protocols/jwt/src/main/java/org/apache/james/jwt/JwtTokenVerifier.java
new file mode 100644
index 0000000..661302f
--- /dev/null
+++ b/server/protocols/jwt/src/main/java/org/apache/james/jwt/JwtTokenVerifier.java
@@ -0,0 +1,63 @@
+/****************************************************************
+ * 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.jwt;
+
+import javax.inject.Inject;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Strings;
+
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jws;
+import io.jsonwebtoken.JwtException;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.MalformedJwtException;
+
+public class JwtTokenVerifier {
+
+    private final PublicKeyProvider pubKeyProvider;
+
+    @Inject
+    @VisibleForTesting
+    JwtTokenVerifier(PublicKeyProvider pubKeyProvider) {
+        this.pubKeyProvider = pubKeyProvider;
+    }
+
+    public boolean verify(String token) throws JwtException {
+        String subject = extractLogin(token);
+        if (Strings.isNullOrEmpty(subject)) {
+            throw new MalformedJwtException("'subject' field in token is mandatory");
+        }
+        return true;
+    }
+
+    public String extractLogin(String token) throws JwtException {
+        Jws<Claims> jws = parseToken(token);
+        return jws
+                .getBody()
+                .getSubject();
+    }
+
+    private Jws<Claims> parseToken(String token) throws JwtException {
+        return Jwts
+                .parser()
+                .setSigningKey(pubKeyProvider.get())
+                .parseClaimsJws(token);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/f1a087fa/server/protocols/jwt/src/main/java/org/apache/james/jwt/MissingOrInvalidKeyException.java
----------------------------------------------------------------------
diff --git a/server/protocols/jwt/src/main/java/org/apache/james/jwt/MissingOrInvalidKeyException.java b/server/protocols/jwt/src/main/java/org/apache/james/jwt/MissingOrInvalidKeyException.java
new file mode 100644
index 0000000..b61de91
--- /dev/null
+++ b/server/protocols/jwt/src/main/java/org/apache/james/jwt/MissingOrInvalidKeyException.java
@@ -0,0 +1,22 @@
+/****************************************************************
+ * 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.jwt;
+
+public class MissingOrInvalidKeyException extends RuntimeException {
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/f1a087fa/server/protocols/jwt/src/main/java/org/apache/james/jwt/PublicKeyProvider.java
----------------------------------------------------------------------
diff --git a/server/protocols/jwt/src/main/java/org/apache/james/jwt/PublicKeyProvider.java b/server/protocols/jwt/src/main/java/org/apache/james/jwt/PublicKeyProvider.java
new file mode 100644
index 0000000..9ce7792
--- /dev/null
+++ b/server/protocols/jwt/src/main/java/org/apache/james/jwt/PublicKeyProvider.java
@@ -0,0 +1,44 @@
+/****************************************************************
+ * 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.jwt;
+
+import java.security.PublicKey;
+
+import javax.inject.Inject;
+
+import com.google.common.annotations.VisibleForTesting;
+
+public class PublicKeyProvider {
+
+    private final JwtConfiguration jwtConfiguration;
+    private final PublicKeyReader reader;
+
+    @Inject
+    @VisibleForTesting
+    PublicKeyProvider(JwtConfiguration jwtConfiguration, PublicKeyReader reader) {
+        this.jwtConfiguration = jwtConfiguration;
+        this.reader = reader;
+    }
+
+    public PublicKey get() throws MissingOrInvalidKeyException {
+        return reader.fromPEM(jwtConfiguration.getJwtPublicKeyPem())
+                .orElseThrow(MissingOrInvalidKeyException::new);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/f1a087fa/server/protocols/jwt/src/main/java/org/apache/james/jwt/PublicKeyReader.java
----------------------------------------------------------------------
diff --git a/server/protocols/jwt/src/main/java/org/apache/james/jwt/PublicKeyReader.java b/server/protocols/jwt/src/main/java/org/apache/james/jwt/PublicKeyReader.java
new file mode 100644
index 0000000..779fa1a
--- /dev/null
+++ b/server/protocols/jwt/src/main/java/org/apache/james/jwt/PublicKeyReader.java
@@ -0,0 +1,56 @@
+/****************************************************************
+ * 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.jwt;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.security.PublicKey;
+import java.util.Optional;
+
+import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.bouncycastle.openssl.PEMParser;
+import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
+import org.bouncycastle.util.io.pem.PemReader;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PublicKeyReader {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(PublicKeyReader.class);
+
+    Optional<PublicKey> fromPEM(Optional<String> pemKey) {
+        return pemKey
+                .map(k -> new PEMParser(new PemReader(new StringReader(k))))
+                .flatMap(this::publicKeyFrom);
+    }
+
+    private Optional<PublicKey> publicKeyFrom(PEMParser reader) {
+        try {
+            Object readPEM = reader.readObject();
+            if (readPEM instanceof SubjectPublicKeyInfo) {
+                return Optional.of(new JcaPEMKeyConverter().getPublicKey((SubjectPublicKeyInfo) readPEM));
+            }
+            LOGGER.warn("Key is not an instance of SubjectPublicKeyInfo but of " + readPEM);
+            return Optional.empty();
+        } catch (IOException e) {
+            LOGGER.warn("Error when reading the PEM file", e);
+            return Optional.empty();
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/f1a087fa/server/protocols/jwt/src/test/java/org/apache/james/jwt/JwtTokenVerifierTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jwt/src/test/java/org/apache/james/jwt/JwtTokenVerifierTest.java b/server/protocols/jwt/src/test/java/org/apache/james/jwt/JwtTokenVerifierTest.java
new file mode 100644
index 0000000..ac5cc94
--- /dev/null
+++ b/server/protocols/jwt/src/test/java/org/apache/james/jwt/JwtTokenVerifierTest.java
@@ -0,0 +1,119 @@
+/****************************************************************
+ * 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.jwt;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.security.Security;
+import java.util.Optional;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import io.jsonwebtoken.MalformedJwtException;
+import io.jsonwebtoken.SignatureException;
+
+public class JwtTokenVerifierTest {
+
+    private static final String PUBLIC_PEM_KEY = "-----BEGIN PUBLIC KEY-----\n" +
+            "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtlChO/nlVP27MpdkG0Bh\n" +
+            "16XrMRf6M4NeyGa7j5+1UKm42IKUf3lM28oe82MqIIRyvskPc11NuzSor8HmvH8H\n" +
+            "lhDs5DyJtx2qp35AT0zCqfwlaDnlDc/QDlZv1CoRZGpQk1Inyh6SbZwYpxxwh0fi\n" +
+            "+d/4RpE3LBVo8wgOaXPylOlHxsDizfkL8QwXItyakBfMO6jWQRrj7/9WDhGf4Hi+\n" +
+            "GQur1tPGZDl9mvCoRHjFrD5M/yypIPlfMGWFVEvV5jClNMLAQ9bYFuOc7H1fEWw6\n" +
+            "U1LZUUbJW9/CH45YXz82CYqkrfbnQxqRb2iVbVjs/sHopHd1NTiCfUtwvcYJiBVj\n" +
+            "kwIDAQAB\n" +
+            "-----END PUBLIC KEY-----";
+    
+    private static final String VALID_TOKEN = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0.T04BTk" +
+            "LXkJj24coSZkK13RfG25lpvmSl2MJ7N10KpBk9_-95EGYZdog-BDAn3PJzqVw52z-Bwjh4VOj1-j7cURu0cT4jXehhUrlCxS4n7QHZD" +
+            "N_bsEYGu7KzjWTpTsUiHe-rN7izXVFxDGG1TGwlmBCBnPW-EFCf9ylUsJi0r2BKNdaaPRfMIrHptH1zJBkkUziWpBN1RNLjmvlAUf49" +
+            "t1Tbv21ZqYM5Ht2vrhJWczFbuC-TD-8zJkXhjTmA1GVgomIX5dx1cH-dZX1wANNmshUJGHgepWlPU-5VIYxPEhb219RMLJIELMY2qN" +
+            "OR8Q31ydinyqzXvCSzVJOf6T60-w";
+
+    private JwtTokenVerifier sut;
+
+    @BeforeClass
+    public static void init() {
+        Security.addProvider(new BouncyCastleProvider());
+    }
+
+    @Before
+    public void setup() {
+        PublicKeyProvider pubKeyProvider = new PublicKeyProvider(getJWTConfiguration(), new PublicKeyReader());
+        sut = new JwtTokenVerifier(pubKeyProvider);
+    }
+
+    private JwtConfiguration getJWTConfiguration() {
+
+        return new JwtConfiguration(Optional.of(PUBLIC_PEM_KEY));
+    }
+
+    @Test
+    public void shouldReturnTrueOnValidSignature() {
+
+        assertThat(sut.verify(VALID_TOKEN)).isTrue();
+    }
+
+    @Test
+    public void shouldThrowOnMismatchingSigningKey() {
+        String invalidToken = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0.Pd6t82" +
+                "tPL3EZdkeYxw_DV2KimE1U2FvuLHmfR_mimJ5US3JFU4J2Gd94O7rwpSTGN1B9h-_lsTebo4ua4xHsTtmczZ9xa8a_kWKaSkqFjNFa" +
+                "Fp6zcoD6ivCu03SlRqsQzSRHXo6TKbnqOt9D6Y2rNa3C4igSwoS0jUE4BgpXbc0";
+
+        assertThatThrownBy(() -> sut.verify(invalidToken))
+            .isInstanceOf(SignatureException.class);
+    }
+
+    @Test
+    public void verifyShouldThrowWhenSubjectIsNull() {
+        String tokenWithNullSubject = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOm51bGwsIm5hbWUiOiJKb2huIERvZSJ9.EB" +
+                "_1grWDy_kFelXs3AQeiP13ay4eG_134dWB9XPRSeWsuPs8Mz2UY-VHDxLGD-fAqv-xKXr4QFEnS7iZkdpe0tPLNSwIjqeqkC6KqQln" +
+                "oC1okqWVWBDOcf7Acp1Jzp_cFTUhL5LkHvZDsyCdq5T9OOVVkzO4A9RrzIUsTrYPtRCBuYJ3ggR33cKpw191PulPGNH70rZqpUfDXe" +
+                "VPY3q15vWzZH9O9IJzB2KdHRMPxl2luRjzDbh4DLp56NhZuLX_2a9UAlmbV8MQX4Z_04ybhAYrcBfxR3MgJyr0jlxSibqSbXrkXuo-" +
+                "PyybfZCIhK_qXUlO5OS6sO7AQhKZO9p0MQ";
+
+        assertThatThrownBy(() -> sut.verify(tokenWithNullSubject))
+            .isInstanceOf(MalformedJwtException.class)
+            .hasMessage("'subject' field in token is mandatory");
+    }
+    
+    @Test
+    public void verifyShouldThrowWhenEmptySubject() {
+        String tokenWithEmptySubject = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIiLCJuYW1lIjoiSm9obiBEb2UifQ.UdY" +
+                "s2PPzFCegUYspoDCnlJR_bJm8_z1InOv4v3tq8SJETQUarOXlhb_n6y6ujVvmJiSx9dI24Hc3Czi3RGUOXbnBDj1WPfd0aVSiUSqZr" +
+                "MCHBt5vjCYqAseDaP3w4aiiFb6EV3tteJFeBLZx8XlKPYxlzRLLUADDyDSQvrFBBPxfsvCETZovKdo9ofIN64o-yx23ss63yE6oIOd" +
+                "zJZ1Id40KSR2d7l3kIQJPLKUWJDnro5RAh4DOGOWNSq0JSbMhk7Zn3cXIBUpv3R8p79tui1UQpzwHMC0e6OSuWEDNQHtq-Cz85u8GG" +
+                "sUSbogmgObA_BimNtUq_Q1p0SGtIYBXmQ";
+
+        assertThatThrownBy(() -> sut.verify(tokenWithEmptySubject))
+            .isInstanceOf(MalformedJwtException.class)
+            .hasMessage("'subject' field in token is mandatory");
+    }
+
+    @Test
+    public void shouldReturnUserLoginFromValidToken() {
+
+        assertThat(sut.extractLogin(VALID_TOKEN)).isEqualTo("1234567890");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/f1a087fa/server/protocols/jwt/src/test/java/org/apache/james/jwt/PublicKeyProviderTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jwt/src/test/java/org/apache/james/jwt/PublicKeyProviderTest.java b/server/protocols/jwt/src/test/java/org/apache/james/jwt/PublicKeyProviderTest.java
new file mode 100644
index 0000000..feb4b66
--- /dev/null
+++ b/server/protocols/jwt/src/test/java/org/apache/james/jwt/PublicKeyProviderTest.java
@@ -0,0 +1,67 @@
+/****************************************************************
+ * 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.jwt;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.security.Security;
+import java.security.interfaces.RSAPublicKey;
+import java.util.Optional;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class PublicKeyProviderTest {
+
+    private static final String PUBLIC_PEM_KEY = "-----BEGIN PUBLIC KEY-----\n" +
+            "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtlChO/nlVP27MpdkG0Bh\n" +
+            "16XrMRf6M4NeyGa7j5+1UKm42IKUf3lM28oe82MqIIRyvskPc11NuzSor8HmvH8H\n" +
+            "lhDs5DyJtx2qp35AT0zCqfwlaDnlDc/QDlZv1CoRZGpQk1Inyh6SbZwYpxxwh0fi\n" +
+            "+d/4RpE3LBVo8wgOaXPylOlHxsDizfkL8QwXItyakBfMO6jWQRrj7/9WDhGf4Hi+\n" +
+            "GQur1tPGZDl9mvCoRHjFrD5M/yypIPlfMGWFVEvV5jClNMLAQ9bYFuOc7H1fEWw6\n" +
+            "U1LZUUbJW9/CH45YXz82CYqkrfbnQxqRb2iVbVjs/sHopHd1NTiCfUtwvcYJiBVj\n" +
+            "kwIDAQAB\n" +
+            "-----END PUBLIC KEY-----";
+
+    @BeforeClass
+    public static void init() {
+        Security.addProvider(new BouncyCastleProvider());
+    }
+
+    @Test
+    public void getShouldNotThrowWhenPEMKeyProvided() {
+
+        JwtConfiguration configWithPEMKey = new JwtConfiguration(Optional.of(PUBLIC_PEM_KEY));
+
+        PublicKeyProvider sut = new PublicKeyProvider(configWithPEMKey, new PublicKeyReader());
+
+        assertThat(sut.get()).isInstanceOf(RSAPublicKey.class);
+    }
+
+    @Test
+    public void getShouldThrowWhenPEMKeyNotProvided() {
+        JwtConfiguration configWithPEMKey = new JwtConfiguration(Optional.of(""));
+
+        PublicKeyProvider sut = new PublicKeyProvider(configWithPEMKey, new PublicKeyReader());
+
+        assertThatThrownBy(() -> sut.get()).isExactlyInstanceOf(MissingOrInvalidKeyException.class);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/f1a087fa/server/protocols/jwt/src/test/java/org/apache/james/jwt/PublicKeyReaderTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jwt/src/test/java/org/apache/james/jwt/PublicKeyReaderTest.java b/server/protocols/jwt/src/test/java/org/apache/james/jwt/PublicKeyReaderTest.java
new file mode 100644
index 0000000..1b850d0
--- /dev/null
+++ b/server/protocols/jwt/src/test/java/org/apache/james/jwt/PublicKeyReaderTest.java
@@ -0,0 +1,62 @@
+/****************************************************************
+ * 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.jwt;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.security.Security;
+import java.util.Optional;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class PublicKeyReaderTest {
+
+    private static final String PUBLIC_PEM_KEY = "-----BEGIN PUBLIC KEY-----\n" +
+            "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtlChO/nlVP27MpdkG0Bh\n" +
+            "16XrMRf6M4NeyGa7j5+1UKm42IKUf3lM28oe82MqIIRyvskPc11NuzSor8HmvH8H\n" +
+            "lhDs5DyJtx2qp35AT0zCqfwlaDnlDc/QDlZv1CoRZGpQk1Inyh6SbZwYpxxwh0fi\n" +
+            "+d/4RpE3LBVo8wgOaXPylOlHxsDizfkL8QwXItyakBfMO6jWQRrj7/9WDhGf4Hi+\n" +
+            "GQur1tPGZDl9mvCoRHjFrD5M/yypIPlfMGWFVEvV5jClNMLAQ9bYFuOc7H1fEWw6\n" +
+            "U1LZUUbJW9/CH45YXz82CYqkrfbnQxqRb2iVbVjs/sHopHd1NTiCfUtwvcYJiBVj\n" +
+            "kwIDAQAB\n" +
+            "-----END PUBLIC KEY-----";
+
+    @BeforeClass
+    public static void init() {
+        Security.addProvider(new BouncyCastleProvider());
+    }
+
+    @Test
+    public void fromPEMShouldReturnEmptyWhenEmptyProvided() {
+        assertThat(new PublicKeyReader().fromPEM(Optional.empty())).isEmpty();
+    }
+
+    @Test
+    public void fromPEMShouldReturnEmptyWhenInvalidPEMKey() {
+        assertThat(new PublicKeyReader().fromPEM(Optional.of("blabla"))).isEmpty();
+    }
+
+    @Test
+    public void fromPEMShouldReturnRSAPublicKeyWhenValidPEMKey() {
+        assertThat(new PublicKeyReader().fromPEM(Optional.of(PUBLIC_PEM_KEY))).isPresent();
+    }
+}


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


[21/22] james-project git commit: JAMES-1950 Add time metrics on Remote Mail delivering

Posted by bt...@apache.org.
JAMES-1950 Add time metrics on Remote Mail delivering


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

Branch: refs/heads/master
Commit: 33b74fbca401d8aa78c8d931497fff5862b2240e
Parents: ca04fd6
Author: benwa <bt...@linagora.com>
Authored: Wed Mar 15 10:27:24 2017 +0700
Committer: benwa <bt...@linagora.com>
Committed: Wed Mar 15 16:57:31 2017 +0700

----------------------------------------------------------------------
 .../james/transport/mailets/RemoteDelivery.java    |  7 +++----
 .../mailets/remoteDelivery/DeliveryRunnable.java   | 17 +++++++++++++----
 .../remoteDelivery/DeliveryRunnableTest.java       |  8 +++++++-
 3 files changed, 23 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/33b74fbc/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RemoteDelivery.java
----------------------------------------------------------------------
diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RemoteDelivery.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RemoteDelivery.java
index 006c6bc..1019e30 100644
--- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RemoteDelivery.java
+++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RemoteDelivery.java
@@ -126,13 +126,12 @@ public class RemoteDelivery extends GenericMailet {
         DO_NOT_START_THREADS
     }
 
-    private static final String OUTGOING_MAILS = "outgoingMails";
     public static final String NAME_JUNCTION = "-to-";
 
     private final DNSService dnsServer;
     private final DomainList domainList;
     private final MailQueueFactory queueFactory;
-    private final Metric outgoingMailsMetric;
+    private final MetricFactory metricFactory;
     private final AtomicBoolean isDestroyed;
     private final THREAD_STATE startThreads;
 
@@ -150,7 +149,7 @@ public class RemoteDelivery extends GenericMailet {
         this.dnsServer = dnsServer;
         this.domainList = domainList;
         this.queueFactory = queueFactory;
-        this.outgoingMailsMetric = metricFactory.generate(OUTGOING_MAILS);
+        this.metricFactory = metricFactory;
         this.isDestroyed = new AtomicBoolean(false);
         this.startThreads = startThreads;
     }
@@ -177,7 +176,7 @@ public class RemoteDelivery extends GenericMailet {
                 new DeliveryRunnable(queue,
                     configuration,
                     dnsServer,
-                    outgoingMailsMetric,
+                    metricFactory,
                     logger,
                     getMailetContext(),
                     new Bouncer(configuration, getMailetContext(), logger),

http://git-wip-us.apache.org/repos/asf/james-project/blob/33b74fbc/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remoteDelivery/DeliveryRunnable.java
----------------------------------------------------------------------
diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remoteDelivery/DeliveryRunnable.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remoteDelivery/DeliveryRunnable.java
index a7cf23b..b34f3af 100644
--- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remoteDelivery/DeliveryRunnable.java
+++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remoteDelivery/DeliveryRunnable.java
@@ -26,6 +26,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
 import org.apache.james.dnsservice.api.DNSService;
 import org.apache.james.lifecycle.api.LifecycleUtil;
 import org.apache.james.metrics.api.Metric;
+import org.apache.james.metrics.api.MetricFactory;
+import org.apache.james.metrics.api.TimeMetric;
 import org.apache.james.queue.api.MailPrioritySupport;
 import org.apache.james.queue.api.MailQueue;
 import org.apache.mailet.Mail;
@@ -44,34 +46,38 @@ public class DeliveryRunnable implements Runnable {
         }
     };
     public static final AtomicBoolean DEFAULT_NOT_STARTED = new AtomicBoolean(false);
+    private static final String OUTGOING_MAILS = "outgoingMails";
+    public static final String REMOTE_DELIVERY_TRIAL = "RemoteDeliveryTrial";
 
     private final MailQueue queue;
     private final RemoteDeliveryConfiguration configuration;
     private final Metric outgoingMailsMetric;
+    private final MetricFactory metricFactory;
     private final Logger logger;
     private final Bouncer bouncer;
     private final MailDelivrer mailDelivrer;
     private final AtomicBoolean isDestroyed;
     private final Supplier<Date> dateSupplier;
 
-    public DeliveryRunnable(MailQueue queue, RemoteDeliveryConfiguration configuration, DNSService dnsServer, Metric outgoingMailsMetric,
+    public DeliveryRunnable(MailQueue queue, RemoteDeliveryConfiguration configuration, DNSService dnsServer, MetricFactory metricFactory,
                             Logger logger, MailetContext mailetContext, Bouncer bouncer, AtomicBoolean isDestroyed) {
-        this(queue, configuration, outgoingMailsMetric, logger, bouncer,
+        this(queue, configuration, metricFactory, logger, bouncer,
             new MailDelivrer(configuration, new MailDelivrerToHost(configuration, mailetContext, logger), dnsServer, bouncer, logger),
             isDestroyed, CURRENT_DATE_SUPPLIER);
     }
 
     @VisibleForTesting
-    DeliveryRunnable(MailQueue queue, RemoteDeliveryConfiguration configuration, Metric outgoingMailsMetric, Logger logger, Bouncer bouncer,
+    DeliveryRunnable(MailQueue queue, RemoteDeliveryConfiguration configuration, MetricFactory metricFactory, Logger logger, Bouncer bouncer,
                      MailDelivrer mailDelivrer, AtomicBoolean isDestroyeds, Supplier<Date> dateSupplier) {
         this.queue = queue;
         this.configuration = configuration;
-        this.outgoingMailsMetric = outgoingMailsMetric;
+        this.outgoingMailsMetric = metricFactory.generate(OUTGOING_MAILS);
         this.logger = logger;
         this.bouncer = bouncer;
         this.mailDelivrer = mailDelivrer;
         this.isDestroyed = isDestroyeds;
         this.dateSupplier = dateSupplier;
+        this.metricFactory = metricFactory;
     }
 
     @Override
@@ -87,6 +93,7 @@ public class DeliveryRunnable implements Runnable {
     }
 
     private void runStep() {
+        TimeMetric timeMetric = metricFactory.timer(REMOTE_DELIVERY_TRIAL);
         try {
             // Get the 'mail' object that is ready for deliverying. If no message is
             // ready, the 'accept' will block until message is ready.
@@ -116,6 +123,8 @@ public class DeliveryRunnable implements Runnable {
             if (!isDestroyed.get()) {
                 logger.error("Exception caught in RemoteDelivery.run()", e);
             }
+        } finally {
+            timeMetric.stopAndPublish();
         }
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/33b74fbc/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remoteDelivery/DeliveryRunnableTest.java
----------------------------------------------------------------------
diff --git a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remoteDelivery/DeliveryRunnableTest.java b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remoteDelivery/DeliveryRunnableTest.java
index f8dfd40..09554e1 100644
--- a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remoteDelivery/DeliveryRunnableTest.java
+++ b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remoteDelivery/DeliveryRunnableTest.java
@@ -20,6 +20,7 @@
 package org.apache.james.transport.mailets.remoteDelivery;
 
 import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
@@ -31,6 +32,8 @@ import java.util.concurrent.TimeUnit;
 
 import org.apache.james.domainlist.api.DomainList;
 import org.apache.james.metrics.api.Metric;
+import org.apache.james.metrics.api.MetricFactory;
+import org.apache.james.metrics.api.NoopMetricFactory;
 import org.apache.james.queue.api.MailQueue;
 import org.apache.mailet.Mail;
 import org.apache.mailet.base.test.FakeMail;
@@ -74,10 +77,13 @@ public class DeliveryRunnableTest {
 
         RemoteDeliveryConfiguration configuration = new RemoteDeliveryConfiguration(mailetConfig, mock(DomainList.class));
         outgoingMailsMetric = mock(Metric.class);
+        MetricFactory mockMetricFactory = mock(MetricFactory.class);
+        when(mockMetricFactory.generate(anyString())).thenReturn(outgoingMailsMetric);
+        when(mockMetricFactory.timer(anyString())).thenReturn(new NoopMetricFactory.NoopTimeMetric());
         bouncer = mock(Bouncer.class);
         mailDelivrer = mock(MailDelivrer.class);
         mailQueue = mock(MailQueue.class);
-        testee = new DeliveryRunnable(mailQueue, configuration, outgoingMailsMetric, LOGGER, bouncer, mailDelivrer, DeliveryRunnable.DEFAULT_NOT_STARTED, FIXED_DATE_SUPPLIER);
+        testee = new DeliveryRunnable(mailQueue, configuration, mockMetricFactory, LOGGER, bouncer, mailDelivrer, DeliveryRunnable.DEFAULT_NOT_STARTED, FIXED_DATE_SUPPLIER);
     }
 
     @Test


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


[20/22] james-project git commit: JAMES-1950 Add time measurement for JMS queues

Posted by bt...@apache.org.
JAMES-1950 Add time measurement for JMS queues


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

Branch: refs/heads/master
Commit: e8b94d178a0e23be25b7681900972b1bac48f543
Parents: a00d5e4
Author: benwa <bt...@linagora.com>
Authored: Wed Mar 15 10:44:50 2017 +0700
Committer: benwa <bt...@linagora.com>
Committed: Wed Mar 15 16:57:31 2017 +0700

----------------------------------------------------------------------
 .../james/queue/activemq/ActiveMQMailQueue.java       | 10 +++++-----
 .../queue/activemq/ActiveMQMailQueueFactory.java      |  2 +-
 .../james/queue/activemq/ActiveMQMailQueueTest.java   |  6 ++----
 .../java/org/apache/james/queue/jms/JMSMailQueue.java | 14 +++++++++++---
 .../apache/james/queue/jms/JMSMailQueueFactory.java   |  2 +-
 .../james/queue/jms/AbstractJMSMailQueueTest.java     |  5 ++---
 6 files changed, 22 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/e8b94d17/server/queue/queue-activemq/src/main/java/org/apache/james/queue/activemq/ActiveMQMailQueue.java
----------------------------------------------------------------------
diff --git a/server/queue/queue-activemq/src/main/java/org/apache/james/queue/activemq/ActiveMQMailQueue.java b/server/queue/queue-activemq/src/main/java/org/apache/james/queue/activemq/ActiveMQMailQueue.java
index 8a80ad3..56c25c1 100644
--- a/server/queue/queue-activemq/src/main/java/org/apache/james/queue/activemq/ActiveMQMailQueue.java
+++ b/server/queue/queue-activemq/src/main/java/org/apache/james/queue/activemq/ActiveMQMailQueue.java
@@ -43,7 +43,7 @@ import org.apache.activemq.util.JMSExceptionSupport;
 import org.apache.james.core.MimeMessageCopyOnWriteProxy;
 import org.apache.james.core.MimeMessageInputStream;
 import org.apache.james.core.MimeMessageSource;
-import org.apache.james.metrics.api.Metric;
+import org.apache.james.metrics.api.MetricFactory;
 import org.apache.james.queue.api.MailQueue;
 import org.apache.james.queue.api.MailQueueItemDecoratorFactory;
 import org.apache.james.queue.jms.JMSMailQueue;
@@ -93,8 +93,8 @@ public class ActiveMQMailQueue extends JMSMailQueue implements ActiveMQSupport {
      * Construct a {@link ActiveMQMailQueue} which only use {@link BlobMessage}
      * 
      */
-    public ActiveMQMailQueue(ConnectionFactory connectionFactory, MailQueueItemDecoratorFactory mailQueueItemDecoratorFactory, String queuename, Metric enqueuedMailsMetric, Logger logger) {
-        this(connectionFactory, mailQueueItemDecoratorFactory, queuename, true, enqueuedMailsMetric, logger);
+    public ActiveMQMailQueue(ConnectionFactory connectionFactory, MailQueueItemDecoratorFactory mailQueueItemDecoratorFactory, String queuename, MetricFactory metricFactory, Logger logger) {
+        this(connectionFactory, mailQueueItemDecoratorFactory, queuename, true, metricFactory, logger);
     }
 
     /**
@@ -105,8 +105,8 @@ public class ActiveMQMailQueue extends JMSMailQueue implements ActiveMQSupport {
      * @param useBlob
      * @param logger
      */
-    public ActiveMQMailQueue(ConnectionFactory connectionFactory, MailQueueItemDecoratorFactory mailQueueItemDecoratorFactory, String queuename, boolean useBlob, Metric enqueuedMailsMetric, Logger logger) {
-        super(connectionFactory, mailQueueItemDecoratorFactory, queuename, enqueuedMailsMetric, logger);
+    public ActiveMQMailQueue(ConnectionFactory connectionFactory, MailQueueItemDecoratorFactory mailQueueItemDecoratorFactory, String queuename, boolean useBlob, MetricFactory metricFactory, Logger logger) {
+        super(connectionFactory, mailQueueItemDecoratorFactory, queuename, metricFactory, logger);
         this.useBlob = useBlob;
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/e8b94d17/server/queue/queue-activemq/src/main/java/org/apache/james/queue/activemq/ActiveMQMailQueueFactory.java
----------------------------------------------------------------------
diff --git a/server/queue/queue-activemq/src/main/java/org/apache/james/queue/activemq/ActiveMQMailQueueFactory.java b/server/queue/queue-activemq/src/main/java/org/apache/james/queue/activemq/ActiveMQMailQueueFactory.java
index 9646a29..5653066 100644
--- a/server/queue/queue-activemq/src/main/java/org/apache/james/queue/activemq/ActiveMQMailQueueFactory.java
+++ b/server/queue/queue-activemq/src/main/java/org/apache/james/queue/activemq/ActiveMQMailQueueFactory.java
@@ -50,6 +50,6 @@ public class ActiveMQMailQueueFactory extends JMSMailQueueFactory {
 
     @Override
     protected MailQueue createMailQueue(String name) {
-        return new ActiveMQMailQueue(connectionFactory, mailQueueItemDecoratorFactory, name, useBlob, metricFactory.generate("enqueuedMails:" + name), log);
+        return new ActiveMQMailQueue(connectionFactory, mailQueueItemDecoratorFactory, name, useBlob, metricFactory, log);
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/e8b94d17/server/queue/queue-activemq/src/test/java/org/apache/james/queue/activemq/ActiveMQMailQueueTest.java
----------------------------------------------------------------------
diff --git a/server/queue/queue-activemq/src/test/java/org/apache/james/queue/activemq/ActiveMQMailQueueTest.java b/server/queue/queue-activemq/src/test/java/org/apache/james/queue/activemq/ActiveMQMailQueueTest.java
index 1203c74..3cd6d5d 100644
--- a/server/queue/queue-activemq/src/test/java/org/apache/james/queue/activemq/ActiveMQMailQueueTest.java
+++ b/server/queue/queue-activemq/src/test/java/org/apache/james/queue/activemq/ActiveMQMailQueueTest.java
@@ -18,8 +18,6 @@
  ****************************************************************/
 package org.apache.james.queue.activemq;
 
-import static org.mockito.Mockito.mock;
-
 import java.util.Arrays;
 
 import javax.jms.ConnectionFactory;
@@ -29,7 +27,7 @@ import org.apache.activemq.broker.BrokerService;
 import org.apache.activemq.broker.region.policy.PolicyEntry;
 import org.apache.activemq.broker.region.policy.PolicyMap;
 import org.apache.activemq.plugin.StatisticsBrokerPlugin;
-import org.apache.james.metrics.api.Metric;
+import org.apache.james.metrics.api.NoopMetricFactory;
 import org.apache.james.queue.api.MailQueueItemDecoratorFactory;
 import org.apache.james.queue.jms.AbstractJMSMailQueueTest;
 import org.apache.james.queue.jms.JMSMailQueue;
@@ -79,7 +77,7 @@ public abstract class ActiveMQMailQueueTest extends AbstractJMSMailQueueTest {
     protected JMSMailQueue createQueue(ConnectionFactory factory, MailQueueItemDecoratorFactory mailQueueItemDecoratorFactory, String queueName) {
         Logger log = LoggerFactory.getLogger(ActiveMQMailQueueTest.class);
 
-        return new ActiveMQMailQueue(factory, mailQueueItemDecoratorFactory, queueName, useBlobMessages(), mock(Metric.class), log);
+        return new ActiveMQMailQueue(factory, mailQueueItemDecoratorFactory, queueName, useBlobMessages(), new NoopMetricFactory(), log);
     }
 
     protected boolean useBlobMessages() {

http://git-wip-us.apache.org/repos/asf/james-project/blob/e8b94d17/server/queue/queue-jms/src/main/java/org/apache/james/queue/jms/JMSMailQueue.java
----------------------------------------------------------------------
diff --git a/server/queue/queue-jms/src/main/java/org/apache/james/queue/jms/JMSMailQueue.java b/server/queue/queue-jms/src/main/java/org/apache/james/queue/jms/JMSMailQueue.java
index a14b362..2ebff7b 100644
--- a/server/queue/queue-jms/src/main/java/org/apache/james/queue/jms/JMSMailQueue.java
+++ b/server/queue/queue-jms/src/main/java/org/apache/james/queue/jms/JMSMailQueue.java
@@ -51,6 +51,8 @@ import org.apache.james.core.MailImpl;
 import org.apache.james.core.MimeMessageCopyOnWriteProxy;
 import org.apache.james.lifecycle.api.Disposable;
 import org.apache.james.metrics.api.Metric;
+import org.apache.james.metrics.api.MetricFactory;
+import org.apache.james.metrics.api.TimeMetric;
 import org.apache.james.queue.api.MailPrioritySupport;
 import org.apache.james.queue.api.MailQueue;
 import org.apache.james.queue.api.MailQueueItemDecoratorFactory;
@@ -78,10 +80,11 @@ public class JMSMailQueue implements ManageableMailQueue, JMSSupport, MailPriori
     protected final Connection connection;
     protected final MailQueueItemDecoratorFactory mailQueueItemDecoratorFactory;
     protected final Metric enqueuedMailsMetric;
+    protected final MetricFactory metricFactory;
     protected final Logger logger;
     public final static String FORCE_DELIVERY = "FORCE_DELIVERY";
 
-    public JMSMailQueue(ConnectionFactory connectionFactory, MailQueueItemDecoratorFactory mailQueueItemDecoratorFactory, String queueName, Metric enqueuedMailsMetric, Logger logger) {
+    public JMSMailQueue(ConnectionFactory connectionFactory, MailQueueItemDecoratorFactory mailQueueItemDecoratorFactory, String queueName, MetricFactory metricFactory, Logger logger) {
         try {
             connection = connectionFactory.createConnection();
             connection.start();
@@ -90,7 +93,8 @@ public class JMSMailQueue implements ManageableMailQueue, JMSSupport, MailPriori
         }
         this.mailQueueItemDecoratorFactory = mailQueueItemDecoratorFactory;
         this.queueName = queueName;
-        this.enqueuedMailsMetric = enqueuedMailsMetric;
+        this.metricFactory = metricFactory;
+        this.enqueuedMailsMetric = metricFactory.generate("enqueuedMail:" + queueName);
         this.logger = logger;
     }
 
@@ -113,6 +117,7 @@ public class JMSMailQueue implements ManageableMailQueue, JMSSupport, MailPriori
         MessageConsumer consumer = null;
 
         while (true) {
+            TimeMetric timeMetric = metricFactory.timer("dequeueTime:" + queueName);
             try {
                 session = connection.createSession(true, Session.SESSION_TRANSACTED);
                 Queue queue = session.createQueue(queueName);
@@ -166,6 +171,8 @@ public class JMSMailQueue implements ManageableMailQueue, JMSSupport, MailPriori
                 }
 
                 throw new MailQueueException("Unable to dequeue next message", e);
+            } finally {
+                timeMetric.stopAndPublish();
             }
         }
 
@@ -173,6 +180,7 @@ public class JMSMailQueue implements ManageableMailQueue, JMSSupport, MailPriori
 
     @Override
     public void enQueue(Mail mail, long delay, TimeUnit unit) throws MailQueueException {
+        TimeMetric timeMetric = metricFactory.timer("enqueueMailTime:" + queueName);
         Session session = null;
 
         long mydelay = 0;
@@ -207,13 +215,13 @@ public class JMSMailQueue implements ManageableMailQueue, JMSSupport, MailPriori
             throw new MailQueueException("Unable to enqueue mail " + mail, e);
 
         } finally {
+            timeMetric.stopAndPublish();
             try {
                 if (session != null)
                     session.close();
             } catch (JMSException e) {
                 // ignore here
             }
-
         }
     }
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/e8b94d17/server/queue/queue-jms/src/main/java/org/apache/james/queue/jms/JMSMailQueueFactory.java
----------------------------------------------------------------------
diff --git a/server/queue/queue-jms/src/main/java/org/apache/james/queue/jms/JMSMailQueueFactory.java b/server/queue/queue-jms/src/main/java/org/apache/james/queue/jms/JMSMailQueueFactory.java
index 36770d6..e023de9 100644
--- a/server/queue/queue-jms/src/main/java/org/apache/james/queue/jms/JMSMailQueueFactory.java
+++ b/server/queue/queue-jms/src/main/java/org/apache/james/queue/jms/JMSMailQueueFactory.java
@@ -45,7 +45,7 @@ public class JMSMailQueueFactory extends AbstractMailQueueFactory {
 
     @Override
     protected MailQueue createMailQueue(String name) {
-        return new JMSMailQueue(connectionFactory, mailQueueItemDecoratorFactory, name, metricFactory.generate("enqueuedMail:" + name), log);
+        return new JMSMailQueue(connectionFactory, mailQueueItemDecoratorFactory, name, metricFactory, log);
     }
     
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/e8b94d17/server/queue/queue-jms/src/test/java/org/apache/james/queue/jms/AbstractJMSMailQueueTest.java
----------------------------------------------------------------------
diff --git a/server/queue/queue-jms/src/test/java/org/apache/james/queue/jms/AbstractJMSMailQueueTest.java b/server/queue/queue-jms/src/test/java/org/apache/james/queue/jms/AbstractJMSMailQueueTest.java
index 76bb6c4..3947a58 100644
--- a/server/queue/queue-jms/src/test/java/org/apache/james/queue/jms/AbstractJMSMailQueueTest.java
+++ b/server/queue/queue-jms/src/test/java/org/apache/james/queue/jms/AbstractJMSMailQueueTest.java
@@ -22,7 +22,6 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
 
 import java.io.IOException;
 import java.util.Arrays;
@@ -40,7 +39,7 @@ import javax.mail.internet.MimeMessage;
 
 import org.apache.activemq.ActiveMQConnectionFactory;
 import org.apache.james.core.MailImpl;
-import org.apache.james.metrics.api.Metric;
+import org.apache.james.metrics.api.NoopMetricFactory;
 import org.apache.james.protocols.smtp.MailAddressException;
 import org.apache.james.queue.api.MailQueue.MailQueueItem;
 import org.apache.james.queue.api.MailQueueItemDecoratorFactory;
@@ -72,7 +71,7 @@ public abstract class AbstractJMSMailQueueTest {
     
     protected JMSMailQueue createQueue(ConnectionFactory factory, MailQueueItemDecoratorFactory mailQueueItemDecoratorFactory, String queueName) {
         Logger log = LoggerFactory.getLogger(AbstractJMSMailQueueTest.class);
-        return new JMSMailQueue(factory, mailQueueItemDecoratorFactory, queueName, mock(Metric.class), log);
+        return new JMSMailQueue(factory, mailQueueItemDecoratorFactory, queueName, new NoopMetricFactory(), log);
     }
 
     @Before


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


[08/22] james-project git commit: JAMES-1959 Add integration test for JWT

Posted by bt...@apache.org.
JAMES-1959 Add integration test for JWT


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

Branch: refs/heads/master
Commit: 0b5d95bea7488cc7e96b50e8513ecc85c298a0ee
Parents: 8c9805d
Author: benwa <bt...@linagora.com>
Authored: Thu Mar 9 16:23:39 2017 +0700
Committer: benwa <bt...@linagora.com>
Committed: Wed Mar 15 09:01:53 2017 +0700

----------------------------------------------------------------------
 .../integration/JwtFilterIntegrationTest.java   | 136 +++++++++++++++++++
 .../src/test/resources/jwt_publickey            |   9 ++
 2 files changed, 145 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/0b5d95be/server/protocols/webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/JwtFilterIntegrationTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/JwtFilterIntegrationTest.java b/server/protocols/webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/JwtFilterIntegrationTest.java
new file mode 100644
index 0000000..06fc77c
--- /dev/null
+++ b/server/protocols/webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/JwtFilterIntegrationTest.java
@@ -0,0 +1,136 @@
+/****************************************************************
+ * 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.integration;
+
+import static com.jayway.restassured.RestAssured.given;
+import static com.jayway.restassured.config.EncoderConfig.encoderConfig;
+import static com.jayway.restassured.config.RestAssuredConfig.newConfig;
+import static org.apache.james.webadmin.Constants.SEPARATOR;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Optional;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.james.CassandraJmapTestRule;
+import org.apache.james.GuiceJamesServer;
+import org.apache.james.jwt.JwtConfiguration;
+import org.apache.james.utils.DataProbeImpl;
+import org.apache.james.utils.WebAdminGuiceProbe;
+import org.apache.james.webadmin.authentication.AuthenticationFilter;
+import org.apache.james.webadmin.authentication.JwtFilter;
+import org.apache.james.webadmin.routes.DomainRoutes;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import com.google.common.base.Charsets;
+import com.jayway.restassured.RestAssured;
+import com.jayway.restassured.builder.RequestSpecBuilder;
+import com.jayway.restassured.http.ContentType;
+import com.jayway.restassured.response.Header;
+
+public class JwtFilterIntegrationTest {
+
+    private static final String DOMAIN = "domain";
+    private static final String SPECIFIC_DOMAIN = DomainRoutes.DOMAINS + SEPARATOR + DOMAIN;
+    private static final String VALID_TOKEN_ADMIN_TRUE = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZG1pbkBvcGVuL" +
+        "XBhYXMub3JnIiwiYWRtaW4iOnRydWUsImlhdCI6MTQ4OTAzODQzOH0.rgxCkdWEa-92a4R-72a9Z49k4LRvQDShgci5Y7qWRUP9IGJCK-lMkrHF" +
+        "4H0a6L87BYppxVW701zaZ6dNxRMvHnjLBBWnPsC2B0rkkr2hEL2zfz7sb-iNGV-J4ICx97t8-TfQ5rz3VOX0FwdusPL_rJtmlGEGRivPkR6_aBe1" +
+        "kQnvMlwpqF_3ox58EUqYJk6lK_6rjKEV3Xfre31IMpuQUy6c7TKc95sL2-13cknelTierBEmZ00RzTtv9SHIEfzZTfaUK2Wm0PvnQjmU2nIdEvU" +
+        "EqE-jrM3yYXcQzoO-YTQnEhdl-iqbCfmEpYkl2Bx3eIq7gRxxnr7BPsX6HrCB0w";
+    private static final String VALID_TOKEN_ADMIN_FALSE = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZG1pbkBvcGVu" +
+        "LXBhYXMub3JnIiwiYWRtaW4iOmZhbHNlLCJpYXQiOjE0ODkwNDA4Njd9.reQc3DiVvbQHF08oW1qOUyDJyv3tfzDNk8jhVZequiCdOI9vXnRlOe" +
+        "-yDYktd4WT8MYhqY7MgS-wR0vO9jZFv8ZCgd_MkKCvCO0HmMjP5iQPZ0kqGkgWUH7X123tfR38MfbCVAdPDba-K3MfkogV1xvDhlkPScFr_6MxE" +
+        "xtedOK2JnQZn7t9sUzSrcyjWverm7gZkPptkIVoS8TsEeMMME5vFXe_nqkEG69q3kuBUm_33tbR5oNS0ZGZKlG9r41lHBjyf9J1xN4UYV8n866d" +
+        "a7RPPCzshIWUtO0q9T2umWTnp-6OnOdBCkndrZmRR6pPxsD5YL0_77Wq8KT_5__fGA";
+
+    @Rule
+    public CassandraJmapTestRule cassandraJmapTestRule = CassandraJmapTestRule.defaultTestRule();
+
+    private GuiceJamesServer guiceJamesServer;
+    private DataProbeImpl dataProbe;
+
+    @Before
+    public void setUp() throws Exception {
+        JwtConfiguration jwtConfiguration = new JwtConfiguration(
+            Optional.of(
+                IOUtils.toString(ClassLoader.getSystemResourceAsStream("jwt_publickey"), Charsets.UTF_8)));
+
+        guiceJamesServer = cassandraJmapTestRule.jmapServer()
+            .overrideWith(new WebAdminConfigurationModule(),
+                binder -> binder.bind(AuthenticationFilter.class).to(JwtFilter.class),
+                binder -> binder.bind(JwtConfiguration.class).toInstance(jwtConfiguration));
+        guiceJamesServer.start();
+        dataProbe = guiceJamesServer.getProbe(DataProbeImpl.class);
+
+        RestAssured.requestSpecification = new RequestSpecBuilder()
+            .setContentType(ContentType.JSON)
+            .setAccept(ContentType.JSON)
+            .setConfig(newConfig().encoderConfig(encoderConfig().defaultContentCharset(Charsets.UTF_8)))
+            .setPort(guiceJamesServer.getProbe(WebAdminGuiceProbe.class).getWebAdminPort())
+            .build();
+    }
+
+    @After
+    public void tearDown() {
+        guiceJamesServer.stop();
+    }
+
+    @Test
+    public void jwtAuthenticationShouldWork() throws Exception {
+        given()
+            .header(new Header("Authorization", "Bearer " + VALID_TOKEN_ADMIN_TRUE))
+        .when()
+            .put(SPECIFIC_DOMAIN)
+        .then()
+            .statusCode(204);
+
+        assertThat(dataProbe.listDomains())
+            .contains(DOMAIN);
+    }
+
+    @Test
+    public void jwtShouldRejectNonAdminRequests() throws Exception {
+        given()
+            .header(new Header("Authorization", "Bearer " + VALID_TOKEN_ADMIN_FALSE))
+        .when()
+            .put(SPECIFIC_DOMAIN)
+        .then()
+            .statusCode(401);
+
+        assertThat(dataProbe.listDomains())
+            .doesNotContain(DOMAIN);
+    }
+
+    @Test
+    public void jwtShouldRejectInvalidRequests() throws Exception {
+        given()
+            .header(new Header("Authorization", "Bearer invalid"))
+        .when()
+            .put(SPECIFIC_DOMAIN)
+        .then()
+            .statusCode(401);
+
+        assertThat(dataProbe.listDomains())
+            .doesNotContain(DOMAIN);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/0b5d95be/server/protocols/webadmin-integration-test/src/test/resources/jwt_publickey
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin-integration-test/src/test/resources/jwt_publickey b/server/protocols/webadmin-integration-test/src/test/resources/jwt_publickey
new file mode 100644
index 0000000..53914e0
--- /dev/null
+++ b/server/protocols/webadmin-integration-test/src/test/resources/jwt_publickey
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtlChO/nlVP27MpdkG0Bh
+16XrMRf6M4NeyGa7j5+1UKm42IKUf3lM28oe82MqIIRyvskPc11NuzSor8HmvH8H
+lhDs5DyJtx2qp35AT0zCqfwlaDnlDc/QDlZv1CoRZGpQk1Inyh6SbZwYpxxwh0fi
++d/4RpE3LBVo8wgOaXPylOlHxsDizfkL8QwXItyakBfMO6jWQRrj7/9WDhGf4Hi+
+GQur1tPGZDl9mvCoRHjFrD5M/yypIPlfMGWFVEvV5jClNMLAQ9bYFuOc7H1fEWw6
+U1LZUUbJW9/CH45YXz82CYqkrfbnQxqRb2iVbVjs/sHopHd1NTiCfUtwvcYJiBVj
+kwIDAQAB
+-----END PUBLIC KEY-----


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


[17/22] james-project git commit: JAMES-1958 Adding a log message when WebAdmin configuration file is absent

Posted by bt...@apache.org.
JAMES-1958 Adding a log message when WebAdmin configuration file is absent


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

Branch: refs/heads/master
Commit: 20e362bfcde3c83f4a51feef6bb97427d74d4473
Parents: 9db1633
Author: benwa <bt...@linagora.com>
Authored: Mon Mar 13 17:34:31 2017 +0700
Committer: benwa <bt...@linagora.com>
Committed: Wed Mar 15 09:02:31 2017 +0700

----------------------------------------------------------------------
 .../org/apache/james/modules/server/WebAdminServerModule.java    | 4 ++++
 1 file changed, 4 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/20e362bf/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java b/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
index 431d0d5..0af2cce 100644
--- a/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
+++ b/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
@@ -44,6 +44,8 @@ import org.apache.james.webadmin.routes.DomainRoutes;
 import org.apache.james.webadmin.routes.UserMailboxesRoutes;
 import org.apache.james.webadmin.routes.UserRoutes;
 import org.apache.james.webadmin.utils.JsonTransformer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Throwables;
 import com.google.common.collect.ImmutableList;
@@ -56,6 +58,7 @@ import com.google.inject.multibindings.Multibinder;
 
 public class WebAdminServerModule extends AbstractModule {
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(WebAdminServerModule.class);
     private static final boolean DEFAULT_JWT_DISABLED = false;
     private static final boolean DEFAULT_DISABLED = false;
     private static final String DEFAULT_NO_CORS_ORIGIN = null;
@@ -92,6 +95,7 @@ public class WebAdminServerModule extends AbstractModule {
                 .urlCORSOrigin(configurationFile.getString("cors.origin", DEFAULT_NO_CORS_ORIGIN))
                 .build();
         } catch (FileNotFoundException e) {
+            LOGGER.info("No webadmin.properties file. Disabling WebAdmin interface.");
             return WebAdminConfiguration.builder()
                 .disabled()
                 .build();


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


[14/22] james-project git commit: JAMES-1958 Adding defaults configurations for WebAdmin and Tls

Posted by bt...@apache.org.
JAMES-1958 Adding defaults configurations for WebAdmin and Tls


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

Branch: refs/heads/master
Commit: fd82c99ed86ecbd766cc49a1895640e1691e01da
Parents: 553ba85
Author: benwa <bt...@linagora.com>
Authored: Mon Mar 13 17:48:30 2017 +0700
Committer: benwa <bt...@linagora.com>
Committed: Wed Mar 15 09:02:31 2017 +0700

----------------------------------------------------------------------
 .../apache/james/modules/server/WebAdminServerModule.java   | 9 +++------
 .../java/org/apache/james/webadmin/TlsConfiguration.java    | 4 ++++
 .../org/apache/james/webadmin/WebAdminConfiguration.java    | 8 ++++++++
 .../main/java/org/apache/james/webadmin/WebAdminServer.java | 5 +----
 4 files changed, 16 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/fd82c99e/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java b/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
index 0af2cce..4695bdd 100644
--- a/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
+++ b/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
@@ -19,6 +19,7 @@
 
 package org.apache.james.modules.server;
 
+import static org.apache.james.webadmin.WebAdminConfiguration.DISABLED_CONFIGURATION;
 import static org.apache.james.webadmin.WebAdminServer.NO_CONFIGURATION;
 
 import java.io.FileNotFoundException;
@@ -96,9 +97,7 @@ public class WebAdminServerModule extends AbstractModule {
                 .build();
         } catch (FileNotFoundException e) {
             LOGGER.info("No webadmin.properties file. Disabling WebAdmin interface.");
-            return WebAdminConfiguration.builder()
-                .disabled()
-                .build();
+            return DISABLED_CONFIGURATION;
         }
     }
 
@@ -127,9 +126,7 @@ public class WebAdminServerModule extends AbstractModule {
                     configurationFile.getString("https.trust.password", DEFAULT_NO_TRUST_PASSWORD))
                 .build();
         }
-        return TlsConfiguration.builder()
-            .disabled()
-            .build();
+        return TlsConfiguration.DEFAULT_DISABLE;
     }
 
     @Singleton

http://git-wip-us.apache.org/repos/asf/james-project/blob/fd82c99e/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/TlsConfiguration.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/TlsConfiguration.java b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/TlsConfiguration.java
index 78cc209..81ecb66 100644
--- a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/TlsConfiguration.java
+++ b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/TlsConfiguration.java
@@ -27,6 +27,10 @@ import com.google.common.base.Preconditions;
 
 public class TlsConfiguration {
 
+    public static final TlsConfiguration DEFAULT_DISABLE = TlsConfiguration.builder()
+        .disabled()
+        .build();
+
     public static Builder builder() {
         return new Builder();
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/fd82c99e/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
index 115aaef..c61ae86 100644
--- a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
+++ b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
@@ -31,6 +31,14 @@ public class WebAdminConfiguration {
     public static final boolean DEFAULT_CORS_DISABLED = false;
     public static final String CORS_ALL_ORIGINS = "*";
 
+    public static final WebAdminConfiguration TESTING_CONFIGURATION = WebAdminConfiguration.builder()
+        .enabled()
+        .port(new RandomPort())
+        .build();
+    public static final WebAdminConfiguration DISABLED_CONFIGURATION = WebAdminConfiguration.builder()
+        .disabled()
+        .build();
+
     public static Builder builder() {
         return new Builder();
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/fd82c99e/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
index e2144bf..7c16045 100644
--- a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
+++ b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
@@ -67,10 +67,7 @@ public class WebAdminServer implements Configurable {
 
     @VisibleForTesting
     public WebAdminServer(MetricFactory metricFactory, Routes... routes) throws IOException {
-        this(WebAdminConfiguration.builder()
-            .enabled()
-            .port(new RandomPort())
-            .build(),
+        this(WebAdminConfiguration.TESTING_CONFIGURATION,
             ImmutableSet.copyOf(routes),
             new NoAuthenticationFilter(),
             metricFactory);


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


[05/22] james-project git commit: JAMES-1959 Disable JWT authentication on JPA

Posted by bt...@apache.org.
JAMES-1959 Disable JWT authentication on JPA


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

Branch: refs/heads/master
Commit: 8c9805d4b844280c8462d954ceefb3256337a197
Parents: 3d327f7
Author: benwa <bt...@linagora.com>
Authored: Thu Mar 9 14:53:49 2017 +0700
Committer: benwa <bt...@linagora.com>
Committed: Wed Mar 15 09:01:53 2017 +0700

----------------------------------------------------------------------
 .../org/apache/james/JPAJamesServerMain.java    |  4 ++-
 .../james/modules/server/NoJwtModule.java       | 36 ++++++++++++++++++++
 2 files changed, 39 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/8c9805d4/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 4235822..4514fba 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
@@ -32,6 +32,7 @@ import org.apache.james.modules.protocols.ProtocolHandlerModule;
 import org.apache.james.modules.protocols.SMTPServerModule;
 import org.apache.james.modules.server.ActiveMQQueueModule;
 import org.apache.james.modules.server.JMXServerModule;
+import org.apache.james.modules.server.NoJwtModule;
 import org.apache.james.modules.server.QuotaModule;
 import org.apache.james.modules.server.RawPostDequeueDecoratorModule;
 import org.apache.james.modules.server.WebAdminServerModule;
@@ -57,7 +58,8 @@ public class JPAJamesServerMain {
         new QuotaModule(),
         new ActiveMQQueueModule(),
         new RawPostDequeueDecoratorModule(),
-        new MailboxModule());
+        new MailboxModule(),
+        new NoJwtModule());
 
     public static void main(String[] args) throws Exception {
         GuiceJamesServer server = new GuiceJamesServer()

http://git-wip-us.apache.org/repos/asf/james-project/blob/8c9805d4/server/container/guice/jpa-guice/src/main/java/org/apache/james/modules/server/NoJwtModule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/jpa-guice/src/main/java/org/apache/james/modules/server/NoJwtModule.java b/server/container/guice/jpa-guice/src/main/java/org/apache/james/modules/server/NoJwtModule.java
new file mode 100644
index 0000000..10d3754
--- /dev/null
+++ b/server/container/guice/jpa-guice/src/main/java/org/apache/james/modules/server/NoJwtModule.java
@@ -0,0 +1,36 @@
+/****************************************************************
+ * 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 java.util.Optional;
+
+import org.apache.james.jwt.JwtConfiguration;
+import org.apache.james.webadmin.authentication.AuthenticationFilter;
+import org.apache.james.webadmin.authentication.NoAuthenticationFilter;
+
+import com.google.inject.AbstractModule;
+
+public class NoJwtModule extends AbstractModule {
+
+    @Override
+    protected void configure() {
+        bind(JwtConfiguration.class).toInstance(new JwtConfiguration(Optional.empty()));
+    }
+}


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


[13/22] james-project git commit: JAMES-1958 Port should be optional in WebAdminConfiguration

Posted by bt...@apache.org.
JAMES-1958 Port should be optional in WebAdminConfiguration


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

Branch: refs/heads/master
Commit: 553ba8570195770e3060ba8c343d60d93b8aa7ff
Parents: 20e362b
Author: benwa <bt...@linagora.com>
Authored: Mon Mar 13 17:37:38 2017 +0700
Committer: benwa <bt...@linagora.com>
Committed: Wed Mar 15 09:02:31 2017 +0700

----------------------------------------------------------------------
 .../apache/james/webadmin/WebAdminConfiguration.java    | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/553ba857/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
index 339b213..115aaef 100644
--- a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
+++ b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
@@ -37,7 +37,7 @@ public class WebAdminConfiguration {
 
     public static class Builder {
         private Optional<Boolean> enabled = Optional.empty();
-        private Port port;
+        private Optional<Port> port = Optional.empty();
         private Optional<Boolean> enableCORS = Optional.empty();
         private Optional<TlsConfiguration> httpsConfiguration = Optional.empty();
         private Optional<String> urlCORSOrigin = Optional.empty();
@@ -48,7 +48,7 @@ public class WebAdminConfiguration {
         }
 
         public Builder port(Port port) {
-            this.port = port;
+            this.port = Optional.of(port);
             return this;
         }
 
@@ -84,7 +84,7 @@ public class WebAdminConfiguration {
 
         public WebAdminConfiguration build() {
             Preconditions.checkState(enabled.isPresent(), "You need to explicitly enable or disable WebAdmin server");
-            Preconditions.checkState(!enabled.get() || port != null, "You need to specify a port for WebAdminConfiguration");
+            Preconditions.checkState(!enabled.get() || port.isPresent(), "You need to specify a port for WebAdminConfiguration");
             return new WebAdminConfiguration(enabled.get(),
                 port,
                 httpsConfiguration.orElse(
@@ -97,13 +97,13 @@ public class WebAdminConfiguration {
     }
 
     private final boolean enabled;
-    private final Port port;
+    private final Optional<Port> port;
     private final TlsConfiguration tlsConfiguration;
     private final boolean enableCORS;
     private final String urlCORSOrigin;
 
     @VisibleForTesting
-    WebAdminConfiguration(boolean enabled, Port port, TlsConfiguration tlsConfiguration, boolean enableCORS, String urlCORSOrigin) {
+    WebAdminConfiguration(boolean enabled, Optional<Port> port, TlsConfiguration tlsConfiguration, boolean enableCORS, String urlCORSOrigin) {
         this.enabled = enabled;
         this.port = port;
         this.tlsConfiguration = tlsConfiguration;
@@ -120,7 +120,7 @@ public class WebAdminConfiguration {
     }
 
     public Port getPort() {
-        return port;
+        return port.orElseThrow(() -> new IllegalStateException("No port was specified"));
     }
 
     public TlsConfiguration getTlsConfiguration() {


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


[15/22] james-project git commit: JAMES-1962 Enable basic metric collection on WebAdmin

Posted by bt...@apache.org.
JAMES-1962 Enable basic metric collection on WebAdmin


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

Branch: refs/heads/master
Commit: 3dfb05f3ced89de75e9434c82d22d39a4df7d220
Parents: 1463487
Author: benwa <bt...@linagora.com>
Authored: Fri Mar 10 13:44:05 2017 +0700
Committer: benwa <bt...@linagora.com>
Committed: Wed Mar 15 09:02:31 2017 +0700

----------------------------------------------------------------------
 server/protocols/webadmin/pom.xml               |  9 +++++
 .../apache/james/webadmin/WebAdminServer.java   | 23 +++++++++--
 .../james/webadmin/metric/MetricPostFilter.java | 37 ++++++++++++++++++
 .../james/webadmin/metric/MetricPreFilter.java  | 41 ++++++++++++++++++++
 .../james/webadmin/routes/DomainRoutesTest.java |  5 ++-
 .../routes/UserMailboxesRoutesTest.java         |  5 ++-
 .../james/webadmin/routes/UsersRoutesTest.java  |  5 ++-
 7 files changed, 119 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/3dfb05f3/server/protocols/webadmin/pom.xml
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/pom.xml b/server/protocols/webadmin/pom.xml
index da9d076..3703c7a 100644
--- a/server/protocols/webadmin/pom.xml
+++ b/server/protocols/webadmin/pom.xml
@@ -178,6 +178,15 @@
                     <scope>test</scope>
                 </dependency>
                 <dependency>
+                    <groupId>org.apache.james</groupId>
+                    <artifactId>metrics-api</artifactId>
+                </dependency>
+                <dependency>
+                    <groupId>org.apache.james</groupId>
+                    <artifactId>metrics-logger</artifactId>
+                    <scope>test</scope>
+                </dependency>
+                <dependency>
                     <groupId>com.fasterxml.jackson.core</groupId>
                     <artifactId>jackson-databind</artifactId>
                 </dependency>

http://git-wip-us.apache.org/repos/asf/james-project/blob/3dfb05f3/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
index 9c398b4..e3fb368 100644
--- a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
+++ b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
@@ -28,8 +28,12 @@ import javax.inject.Inject;
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.commons.configuration.HierarchicalConfiguration;
 import org.apache.james.lifecycle.api.Configurable;
+import org.apache.james.metrics.api.MetricFactory;
+import org.apache.james.metrics.api.NoopMetricFactory;
 import org.apache.james.webadmin.authentication.AuthenticationFilter;
 import org.apache.james.webadmin.authentication.NoAuthenticationFilter;
+import org.apache.james.webadmin.metric.MetricPostFilter;
+import org.apache.james.webadmin.metric.MetricPreFilter;
 import org.apache.james.webadmin.routes.CORSRoute;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -37,6 +41,9 @@ import org.slf4j.LoggerFactory;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableSet;
 
+import spark.Filter;
+import spark.Request;
+import spark.Response;
 import spark.Service;
 
 public class WebAdminServer implements Configurable {
@@ -49,24 +56,28 @@ public class WebAdminServer implements Configurable {
     private final Set<Routes> routesList;
     private final Service service;
     private final AuthenticationFilter authenticationFilter;
+    private final MetricFactory metricFactory;
 
     // Spark do not allow to retrieve allocated port when using a random port. Thus we generate the port.
     @Inject
-    private WebAdminServer(WebAdminConfiguration configuration, Set<Routes> routesList, AuthenticationFilter authenticationFilter) {
+    private WebAdminServer(WebAdminConfiguration configuration, Set<Routes> routesList, AuthenticationFilter authenticationFilter,
+                           MetricFactory metricFactory) {
         this.configuration = configuration;
         this.routesList = routesList;
         this.authenticationFilter = authenticationFilter;
+        this.metricFactory = metricFactory;
         this.service = Service.ignite();
     }
 
     @VisibleForTesting
-    public WebAdminServer(Routes... routes) throws IOException {
+    public WebAdminServer(MetricFactory metricFactory, Routes... routes) throws IOException {
         this(WebAdminConfiguration.builder()
             .enabled()
             .port(new RandomPort())
             .build(),
             ImmutableSet.copyOf(routes),
-            new NoAuthenticationFilter());
+            new NoAuthenticationFilter(),
+            metricFactory);
     }
 
     @Override
@@ -75,12 +86,18 @@ public class WebAdminServer implements Configurable {
             service.port(configuration.getPort().toInt());
             configureHTTPS();
             configureCORS();
+            configureMetrics();
             service.before(authenticationFilter);
             routesList.forEach(routes -> routes.define(service));
             LOGGER.info("Web admin server started");
         }
     }
 
+    private void configureMetrics() {
+        service.before(new MetricPreFilter(metricFactory));
+        service.after(new MetricPostFilter());
+    }
+
     private void configureHTTPS() {
         HttpsConfiguration httpsConfiguration = configuration.getHttpsConfiguration();
         if (httpsConfiguration.isEnabled()) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/3dfb05f3/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/metric/MetricPostFilter.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/metric/MetricPostFilter.java b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/metric/MetricPostFilter.java
new file mode 100644
index 0000000..4d9b8b7
--- /dev/null
+++ b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/metric/MetricPostFilter.java
@@ -0,0 +1,37 @@
+/****************************************************************
+ * 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.metric;
+
+import org.apache.james.metrics.api.TimeMetric;
+
+import spark.Filter;
+import spark.Request;
+import spark.Response;
+
+public class MetricPostFilter implements Filter {
+
+    @Override
+    public void handle(Request request, Response response) throws Exception {
+        if (request.attribute(MetricPreFilter.METRICS) instanceof TimeMetric) {
+            TimeMetric timeMetric = request.attribute(MetricPreFilter.METRICS);
+            timeMetric.stopAndPublish();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/3dfb05f3/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/metric/MetricPreFilter.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/metric/MetricPreFilter.java b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/metric/MetricPreFilter.java
new file mode 100644
index 0000000..1ed9d76
--- /dev/null
+++ b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/metric/MetricPreFilter.java
@@ -0,0 +1,41 @@
+/****************************************************************
+ * 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.metric;
+
+import org.apache.james.metrics.api.MetricFactory;
+
+import spark.Filter;
+import spark.Request;
+import spark.Response;
+
+public class MetricPreFilter implements Filter {
+    public static final String METRICS = "metrics";
+    private final MetricFactory metricFactory;
+
+    public MetricPreFilter(MetricFactory metricFactory) {
+        this.metricFactory = metricFactory;
+    }
+
+    @Override
+    public void handle(Request request, Response response) throws Exception {
+        request.attribute(METRICS, metricFactory.timer("webAdmin"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/3dfb05f3/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/routes/DomainRoutesTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/routes/DomainRoutesTest.java b/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/routes/DomainRoutesTest.java
index 3c316b0..1df89d2 100644
--- a/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/routes/DomainRoutesTest.java
+++ b/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/routes/DomainRoutesTest.java
@@ -39,6 +39,7 @@ import org.apache.james.dnsservice.api.DNSService;
 import org.apache.james.domainlist.api.DomainList;
 import org.apache.james.domainlist.api.DomainListException;
 import org.apache.james.domainlist.memory.MemoryDomainList;
+import org.apache.james.metrics.logger.DefaultMetricFactory;
 import org.apache.james.webadmin.WebAdminServer;
 import org.apache.james.webadmin.utils.JsonTransformer;
 import org.junit.After;
@@ -64,7 +65,9 @@ public class DomainRoutesTest {
     private WebAdminServer webAdminServer;
 
     private void createServer(DomainList domainList) throws Exception {
-        webAdminServer = new WebAdminServer(new DomainRoutes(domainList, new JsonTransformer()));
+        webAdminServer = new WebAdminServer(
+            new DefaultMetricFactory(),
+            new DomainRoutes(domainList, new JsonTransformer()));
         webAdminServer.configure(NO_CONFIGURATION);
         webAdminServer.await();
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/3dfb05f3/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java b/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java
index 8c9c2db..3db15b1 100644
--- a/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java
+++ b/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java
@@ -50,6 +50,7 @@ import org.apache.james.mailbox.store.JVMMailboxPathLocker;
 import org.apache.james.mailbox.store.SimpleMailboxMetaData;
 import org.apache.james.mailbox.store.mail.model.DefaultMessageId;
 import org.apache.james.mailbox.store.mail.model.impl.MessageParser;
+import org.apache.james.metrics.logger.DefaultMetricFactory;
 import org.apache.james.user.api.UsersRepository;
 import org.apache.james.webadmin.WebAdminServer;
 import org.apache.james.webadmin.service.UserMailboxesService;
@@ -79,7 +80,9 @@ public class UserMailboxesRoutesTest {
         usersRepository = mock(UsersRepository.class);
         when(usersRepository.contains(USERNAME)).thenReturn(true);
 
-        webAdminServer = new WebAdminServer(new UserMailboxesRoutes(new UserMailboxesService(mailboxManager, usersRepository), new JsonTransformer()));
+        webAdminServer = new WebAdminServer(
+            new DefaultMetricFactory(),
+            new UserMailboxesRoutes(new UserMailboxesService(mailboxManager, usersRepository), new JsonTransformer()));
         webAdminServer.configure(NO_CONFIGURATION);
         webAdminServer.await();
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/3dfb05f3/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/routes/UsersRoutesTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/routes/UsersRoutesTest.java b/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/routes/UsersRoutesTest.java
index eec3fda..684ea9b 100644
--- a/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/routes/UsersRoutesTest.java
+++ b/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/routes/UsersRoutesTest.java
@@ -33,6 +33,7 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 import org.apache.james.domainlist.api.DomainList;
+import org.apache.james.metrics.logger.DefaultMetricFactory;
 import org.apache.james.user.api.UsersRepository;
 import org.apache.james.user.api.UsersRepositoryException;
 import org.apache.james.user.api.model.User;
@@ -60,7 +61,9 @@ public class UsersRoutesTest {
     private WebAdminServer webAdminServer;
 
     private void createServer(UsersRepository usersRepository) throws Exception {
-        webAdminServer = new WebAdminServer(new UserRoutes(new UserService(usersRepository), new JsonTransformer()));
+        webAdminServer = new WebAdminServer(
+            new DefaultMetricFactory(),
+            new UserRoutes(new UserService(usersRepository), new JsonTransformer()));
         webAdminServer.configure(NO_CONFIGURATION);
         webAdminServer.await();
 


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


[16/22] james-project git commit: JAMES-1960 Extract default configuration values in constants

Posted by bt...@apache.org.
JAMES-1960 Extract default configuration values in constants


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

Branch: refs/heads/master
Commit: 642be79f3f8e702db50c63c58add7128075a0aba
Parents: 3dfb05f
Author: benwa <bt...@linagora.com>
Authored: Mon Mar 13 15:24:00 2017 +0700
Committer: benwa <bt...@linagora.com>
Committed: Wed Mar 15 09:02:31 2017 +0700

----------------------------------------------------------------------
 .../modules/server/WebAdminServerModule.java    | 30 +++++++++++---------
 1 file changed, 17 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/642be79f/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java b/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
index 1532471..c100dcb 100644
--- a/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
+++ b/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
@@ -56,7 +56,15 @@ import com.google.inject.multibindings.Multibinder;
 
 public class WebAdminServerModule extends AbstractModule {
 
-    public static final boolean DEFAULT_JWT_DISABLED = false;
+    private static final boolean DEFAULT_JWT_DISABLED = false;
+    private static final boolean DEFAULT_DISABLED = false;
+    private static final String DEFAULT_NO_CORS_ORIGIN = null;
+    private static final boolean DEFAULT_CORS_DISABLED = false;
+    private static final String DEFAULT_NO_KEYSTORE = null;
+    private static final boolean DEFAULT_HTTPS_DISABLED = false;
+    private static final String DEFAULT_NO_PASSWORD = null;
+    private static final String DEFAULT_NO_TRUST_KEYSTORE = null;
+    private static final String DEFAULT_NO_TRUST_PASSWORD = null;
 
     @Override
     protected void configure() {
@@ -77,11 +85,11 @@ public class WebAdminServerModule extends AbstractModule {
         try {
             PropertiesConfiguration configurationFile = propertiesProvider.getConfiguration("webadmin");
             return WebAdminConfiguration.builder()
-                .enable(configurationFile.getBoolean("enabled", false))
+                .enable(configurationFile.getBoolean("enabled", DEFAULT_DISABLED))
                 .port(new FixedPort(configurationFile.getInt("port", WebAdminServer.DEFAULT_PORT)))
                 .https(readHttpsConfiguration(configurationFile))
-                .enableCORS(configurationFile.getBoolean("cors.enable", false))
-                .urlCORSOrigin(configurationFile.getString("cors.origin", null))
+                .enableCORS(configurationFile.getBoolean("cors.enable", DEFAULT_CORS_DISABLED))
+                .urlCORSOrigin(configurationFile.getString("cors.origin", DEFAULT_NO_CORS_ORIGIN))
                 .build();
         } catch (FileNotFoundException e) {
             return WebAdminConfiguration.builder()
@@ -105,14 +113,14 @@ public class WebAdminServerModule extends AbstractModule {
     }
 
     private HttpsConfiguration readHttpsConfiguration(PropertiesConfiguration configurationFile) {
-        boolean enabled = configurationFile.getBoolean("https.enabled", DEFAULT_HTTPS_DISABLED());
+        boolean enabled = configurationFile.getBoolean("https.enabled", DEFAULT_HTTPS_DISABLED);
         if (enabled) {
             return HttpsConfiguration.builder()
                 .enabled()
-                .raw(configurationFile.getString("https.keystore", null),
-                    configurationFile.getString("https.password", null),
-                    configurationFile.getString("https.trust.keystore", null),
-                    configurationFile.getString("https.trust.password", null))
+                .raw(configurationFile.getString("https.keystore", DEFAULT_NO_KEYSTORE),
+                    configurationFile.getString("https.password", DEFAULT_NO_PASSWORD),
+                    configurationFile.getString("https.trust.keystore", DEFAULT_NO_TRUST_KEYSTORE),
+                    configurationFile.getString("https.trust.password", DEFAULT_NO_TRUST_PASSWORD))
                 .build();
         }
         return HttpsConfiguration.builder()
@@ -120,10 +128,6 @@ public class WebAdminServerModule extends AbstractModule {
             .build();
     }
 
-    private boolean DEFAULT_HTTPS_DISABLED() {
-        return false;
-    }
-
     @Singleton
     public static class WebAdminServerModuleConfigurationPerformer implements ConfigurationPerformer {
 


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


[18/22] james-project git commit: JAMES-1958 Improve WebAdminConfiguration and TlsConfiguration

Posted by bt...@apache.org.
JAMES-1958 Improve WebAdminConfiguration and TlsConfiguration


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

Branch: refs/heads/master
Commit: ca04fd6e3d314c042975263874245bed68bb893f
Parents: ef119a4
Author: benwa <bt...@linagora.com>
Authored: Tue Mar 14 15:53:29 2017 +0700
Committer: benwa <bt...@linagora.com>
Committed: Wed Mar 15 09:02:32 2017 +0700

----------------------------------------------------------------------
 .../modules/server/WebAdminServerModule.java    | 12 +++----
 .../apache/james/webadmin/TlsConfiguration.java | 38 +++-----------------
 .../james/webadmin/WebAdminConfiguration.java   | 26 ++++++++------
 .../apache/james/webadmin/WebAdminServer.java   |  4 +--
 .../james/webadmin/TlsConfigurationTest.java    | 19 ++--------
 .../webadmin/WebAdminConfigurationTest.java     | 31 ++++++++++++++--
 6 files changed, 60 insertions(+), 70 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/ca04fd6e/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java b/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
index 4695bdd..9c449a3 100644
--- a/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
+++ b/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
@@ -24,6 +24,7 @@ import static org.apache.james.webadmin.WebAdminServer.NO_CONFIGURATION;
 
 import java.io.FileNotFoundException;
 import java.util.List;
+import java.util.Optional;
 
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.commons.configuration.PropertiesConfiguration;
@@ -91,7 +92,7 @@ public class WebAdminServerModule extends AbstractModule {
             return WebAdminConfiguration.builder()
                 .enable(configurationFile.getBoolean("enabled", DEFAULT_DISABLED))
                 .port(new FixedPort(configurationFile.getInt("port", WebAdminServer.DEFAULT_PORT)))
-                .https(readHttpsConfiguration(configurationFile))
+                .tls(readHttpsConfiguration(configurationFile))
                 .enableCORS(configurationFile.getBoolean("cors.enable", DEFAULT_CORS_DISABLED))
                 .urlCORSOrigin(configurationFile.getString("cors.origin", DEFAULT_NO_CORS_ORIGIN))
                 .build();
@@ -115,18 +116,17 @@ public class WebAdminServerModule extends AbstractModule {
         }
     }
 
-    private TlsConfiguration readHttpsConfiguration(PropertiesConfiguration configurationFile) {
+    private Optional<TlsConfiguration> readHttpsConfiguration(PropertiesConfiguration configurationFile) {
         boolean enabled = configurationFile.getBoolean("https.enabled", DEFAULT_HTTPS_DISABLED);
         if (enabled) {
-            return TlsConfiguration.builder()
-                .enabled()
+            return Optional.of(TlsConfiguration.builder()
                 .raw(configurationFile.getString("https.keystore", DEFAULT_NO_KEYSTORE),
                     configurationFile.getString("https.password", DEFAULT_NO_PASSWORD),
                     configurationFile.getString("https.trust.keystore", DEFAULT_NO_TRUST_KEYSTORE),
                     configurationFile.getString("https.trust.password", DEFAULT_NO_TRUST_PASSWORD))
-                .build();
+                .build());
         }
-        return TlsConfiguration.DEFAULT_DISABLE;
+        return Optional.empty();
     }
 
     @Singleton

http://git-wip-us.apache.org/repos/asf/james-project/blob/ca04fd6e/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/TlsConfiguration.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/TlsConfiguration.java b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/TlsConfiguration.java
index 81ecb66..d549ea3 100644
--- a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/TlsConfiguration.java
+++ b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/TlsConfiguration.java
@@ -20,41 +20,22 @@
 package org.apache.james.webadmin;
 
 import java.util.Objects;
-import java.util.Optional;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
 
 public class TlsConfiguration {
 
-    public static final TlsConfiguration DEFAULT_DISABLE = TlsConfiguration.builder()
-        .disabled()
-        .build();
-
     public static Builder builder() {
         return new Builder();
     }
 
     public static class Builder {
-        private Optional<Boolean> enabled = Optional.empty();
         private String keystoreFilePath;
         private String keystorePassword;
         private String truststoreFilePath;
         private String truststorePassword;
 
-        public Builder enable(boolean isEnabled) {
-            this.enabled = Optional.of(isEnabled);
-            return this;
-        }
-
-        public Builder enabled() {
-            return enable(true);
-        }
-
-        public Builder disabled() {
-            return enable(false);
-        }
-
         public Builder raw(String keystoreFilePath,
                            String keystorePassword,
                            String truststoreFilePath,
@@ -73,17 +54,15 @@ public class TlsConfiguration {
             Preconditions.checkNotNull(keystoreFilePath);
             Preconditions.checkNotNull(keystorePassword);
 
-            this.enabled = Optional.of(true);
             this.keystoreFilePath = keystoreFilePath;
             this.keystorePassword = keystorePassword;
             return this;
         }
 
         public TlsConfiguration build() {
-            Preconditions.checkState(enabled.isPresent(), "You need to specify if https is enabled");
-            Preconditions.checkState(!enabled.get() || hasKeystoreInformation(), "If enabled, you need to provide keystore information");
+            Preconditions.checkState(hasKeystoreInformation(), "If enabled, you need to provide keystore information");
             Preconditions.checkState(optionalHasTrustStoreInformation(), "You need to provide both information about trustStore");
-            return new TlsConfiguration(enabled.get(), keystoreFilePath, keystorePassword, truststoreFilePath, truststorePassword);
+            return new TlsConfiguration(keystoreFilePath, keystorePassword, truststoreFilePath, truststorePassword);
         }
 
         private boolean optionalHasTrustStoreInformation() {
@@ -96,25 +75,19 @@ public class TlsConfiguration {
 
     }
 
-    private final boolean enabled;
     private final String keystoreFilePath;
     private final String keystorePassword;
     private final String truststoreFilePath;
     private final String truststorePassword;
 
     @VisibleForTesting
-    TlsConfiguration(boolean enabled, String keystoreFilePath, String keystorePassword, String truststoreFilePath, String truststorePassword) {
-        this.enabled = enabled;
+    TlsConfiguration(String keystoreFilePath, String keystorePassword, String truststoreFilePath, String truststorePassword) {
         this.keystoreFilePath = keystoreFilePath;
         this.keystorePassword = keystorePassword;
         this.truststoreFilePath = truststoreFilePath;
         this.truststorePassword = truststorePassword;
     }
 
-    public boolean isEnabled() {
-        return enabled;
-    }
-
     public String getKeystoreFilePath() {
         return keystoreFilePath;
     }
@@ -136,8 +109,7 @@ public class TlsConfiguration {
        if (o instanceof TlsConfiguration) {
            TlsConfiguration that = (TlsConfiguration) o;
 
-           return Objects.equals(this.enabled, that.enabled)
-               && Objects.equals(this.keystoreFilePath, that.keystoreFilePath)
+           return Objects.equals(this.keystoreFilePath, that.keystoreFilePath)
                && Objects.equals(this.keystorePassword, that.keystorePassword)
                && Objects.equals(this.truststoreFilePath, that.truststoreFilePath)
                && Objects.equals(this.truststorePassword, that.truststorePassword);
@@ -147,6 +119,6 @@ public class TlsConfiguration {
 
     @Override
     public final int hashCode() {
-        return Objects.hash(enabled, keystoreFilePath, keystorePassword, truststoreFilePath, truststorePassword);
+        return Objects.hash(keystoreFilePath, keystorePassword, truststoreFilePath, truststorePassword);
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/ca04fd6e/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
index c61ae86..4099fdc 100644
--- a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
+++ b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
@@ -47,11 +47,16 @@ public class WebAdminConfiguration {
         private Optional<Boolean> enabled = Optional.empty();
         private Optional<Port> port = Optional.empty();
         private Optional<Boolean> enableCORS = Optional.empty();
-        private Optional<TlsConfiguration> httpsConfiguration = Optional.empty();
+        private Optional<TlsConfiguration> tlsConfiguration = Optional.empty();
         private Optional<String> urlCORSOrigin = Optional.empty();
 
-        public Builder https(TlsConfiguration tlsConfiguration) {
-            this.httpsConfiguration = Optional.of(tlsConfiguration);
+        public Builder tls(TlsConfiguration tlsConfiguration) {
+            this.tlsConfiguration = Optional.of(tlsConfiguration);
+            return this;
+        }
+
+        public Builder tls(Optional<TlsConfiguration> tlsConfiguration) {
+            this.tlsConfiguration = tlsConfiguration;
             return this;
         }
 
@@ -95,10 +100,7 @@ public class WebAdminConfiguration {
             Preconditions.checkState(!enabled.get() || port.isPresent(), "You need to specify a port for WebAdminConfiguration");
             return new WebAdminConfiguration(enabled.get(),
                 port,
-                httpsConfiguration.orElse(
-                    TlsConfiguration.builder()
-                        .disabled()
-                        .build()),
+                tlsConfiguration,
                 enableCORS.orElse(DEFAULT_CORS_DISABLED),
                 urlCORSOrigin.orElse(CORS_ALL_ORIGINS));
         }
@@ -106,12 +108,12 @@ public class WebAdminConfiguration {
 
     private final boolean enabled;
     private final Optional<Port> port;
-    private final TlsConfiguration tlsConfiguration;
+    private final Optional<TlsConfiguration> tlsConfiguration;
     private final boolean enableCORS;
     private final String urlCORSOrigin;
 
     @VisibleForTesting
-    WebAdminConfiguration(boolean enabled, Optional<Port> port, TlsConfiguration tlsConfiguration, boolean enableCORS, String urlCORSOrigin) {
+    WebAdminConfiguration(boolean enabled, Optional<Port> port, Optional<TlsConfiguration> tlsConfiguration, boolean enableCORS, String urlCORSOrigin) {
         this.enabled = enabled;
         this.port = port;
         this.tlsConfiguration = tlsConfiguration;
@@ -132,13 +134,17 @@ public class WebAdminConfiguration {
     }
 
     public TlsConfiguration getTlsConfiguration() {
-        return tlsConfiguration;
+        return tlsConfiguration.orElseThrow(() -> new IllegalStateException("No tls configuration"));
     }
 
     public boolean isEnableCORS() {
         return enableCORS;
     }
 
+    public boolean isTlsEnabled() {
+        return tlsConfiguration.isPresent();
+    }
+
     @Override
     public final boolean equals(Object o) {
         if (o instanceof WebAdminConfiguration) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/ca04fd6e/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
index 7c16045..c5bc5fd 100644
--- a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
+++ b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
@@ -92,8 +92,8 @@ public class WebAdminServer implements Configurable {
     }
 
     private void configureHTTPS() {
-        TlsConfiguration tlsConfiguration = configuration.getTlsConfiguration();
-        if (tlsConfiguration.isEnabled()) {
+        if (configuration.isTlsEnabled()) {
+            TlsConfiguration tlsConfiguration = configuration.getTlsConfiguration();
             service.secure(tlsConfiguration.getKeystoreFilePath(),
                 tlsConfiguration.getKeystorePassword(),
                 tlsConfiguration.getTruststoreFilePath(),

http://git-wip-us.apache.org/repos/asf/james-project/blob/ca04fd6e/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/TlsConfigurationTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/TlsConfigurationTest.java b/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/TlsConfigurationTest.java
index c21ddb7..2d93282 100644
--- a/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/TlsConfigurationTest.java
+++ b/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/TlsConfigurationTest.java
@@ -43,7 +43,7 @@ public class TlsConfigurationTest {
     public void buildShouldThrowWhenEnableWithoutKeystore() {
         expectedException.expect(IllegalStateException.class);
 
-        TlsConfiguration.builder().enabled().build();
+        TlsConfiguration.builder().build();
     }
 
     @Test
@@ -51,7 +51,6 @@ public class TlsConfigurationTest {
         expectedException.expect(NullPointerException.class);
 
         TlsConfiguration.builder()
-            .enabled()
             .selfSigned(null, "abc");
     }
 
@@ -60,37 +59,25 @@ public class TlsConfigurationTest {
         expectedException.expect(NullPointerException.class);
 
         TlsConfiguration.builder()
-            .enabled()
             .selfSigned("abc", null);
     }
 
     @Test
-    public void buildShouldWorkOnDisabledHttps() {
-        assertThat(
-            TlsConfiguration.builder()
-                .disabled()
-                .build())
-            .isEqualTo(new TlsConfiguration(false, null, null, null, null));
-    }
-
-    @Test
     public void buildShouldWorkOnSelfSignedHttps() {
         assertThat(
             TlsConfiguration.builder()
-                .enabled()
                 .selfSigned("abcd", "efgh")
                 .build())
-            .isEqualTo(new TlsConfiguration(true, "abcd", "efgh", null, null));
+            .isEqualTo(new TlsConfiguration("abcd", "efgh", null, null));
     }
 
     @Test
     public void buildShouldWorkOnTrustedHttps() {
         assertThat(
             TlsConfiguration.builder()
-                .enabled()
                 .raw("a", "b", "c", "d")
                 .build())
-            .isEqualTo(new TlsConfiguration(true, "a", "b", "c", "d"));
+            .isEqualTo(new TlsConfiguration("a", "b", "c", "d"));
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/james-project/blob/ca04fd6e/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java b/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java
index dd46f34..1030dcf 100644
--- a/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java
+++ b/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java
@@ -83,14 +83,13 @@ public class WebAdminConfigurationTest {
     @Test
     public void builderShouldAcceptHttps() {
         TlsConfiguration tlsConfiguration = TlsConfiguration.builder()
-            .enable(true)
             .selfSigned("abcd", "efgh")
             .build();
 
         assertThat(
             WebAdminConfiguration.builder()
                 .enabled()
-                .https(tlsConfiguration)
+                .tls(tlsConfiguration)
                 .port(PORT)
                 .build())
             .extracting(WebAdminConfiguration::getTlsConfiguration)
@@ -98,6 +97,33 @@ public class WebAdminConfigurationTest {
     }
 
     @Test
+    public void builderShouldReturnTlsEnableWhenTlsConfiguration() {
+        TlsConfiguration tlsConfiguration = TlsConfiguration.builder()
+            .selfSigned("abcd", "efgh")
+            .build();
+
+        assertThat(
+            WebAdminConfiguration.builder()
+                .enabled()
+                .tls(tlsConfiguration)
+                .port(PORT)
+                .build())
+            .extracting(WebAdminConfiguration::getTlsConfiguration)
+            .containsExactly(tlsConfiguration);
+    }
+
+    @Test
+    public void builderShouldReturnTlsDisableWhenNoTlsConfiguration() {
+        assertThat(
+            WebAdminConfiguration.builder()
+                .enabled()
+                .port(PORT)
+                .build())
+            .extracting(WebAdminConfiguration::isTlsEnabled)
+            .containsExactly(false);
+    }
+
+    @Test
     public void builderShouldCORSEnabled() {
         assertThat(
             WebAdminConfiguration.builder()
@@ -109,7 +135,6 @@ public class WebAdminConfigurationTest {
             .containsExactly(true);
     }
 
-
     @Test
     public void builderShouldAcceptAllOriginsByDefault() {
         assertThat(


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


[03/22] james-project git commit: JAMES-1959 Adding more logs when failed to read keys

Posted by bt...@apache.org.
JAMES-1959 Adding more logs when failed to read keys


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

Branch: refs/heads/master
Commit: 9d99b73afe994300b82fe320823f6107b17e646b
Parents: 0fc16af
Author: benwa <bt...@linagora.com>
Authored: Thu Mar 9 16:22:36 2017 +0700
Committer: benwa <bt...@linagora.com>
Committed: Wed Mar 15 09:01:52 2017 +0700

----------------------------------------------------------------------
 .../main/java/org/apache/james/jmap/crypto/PublicKeyReader.java    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/9d99b73a/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/PublicKeyReader.java
----------------------------------------------------------------------
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/PublicKeyReader.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/PublicKeyReader.java
index 25f2ed8..b695c26 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/PublicKeyReader.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/crypto/PublicKeyReader.java
@@ -35,7 +35,6 @@ public class PublicKeyReader {
     private static final Logger LOGGER = LoggerFactory.getLogger(PublicKeyReader.class);
 
     Optional<PublicKey> fromPEM(Optional<String> pemKey) {
-
         return pemKey
                 .map(k -> new PEMParser(new PemReader(new StringReader(k))))
                 .flatMap(this::publicKeyFrom);
@@ -47,6 +46,7 @@ public class PublicKeyReader {
             if (readPEM instanceof SubjectPublicKeyInfo) {
                 return Optional.of(new JcaPEMKeyConverter().getPublicKey((SubjectPublicKeyInfo) readPEM));
             }
+            LOGGER.warn("Key is not an instance of SubjectPublicKeyInfo but of " + readPEM);
             return Optional.empty();
         } catch (IOException e) {
             LOGGER.warn("Error when reading the PEM file", e);


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


[11/22] james-project git commit: JAMES-1960 Allow CORS request on WebAdmin (configuration defined)

Posted by bt...@apache.org.
JAMES-1960 Allow CORS request on WebAdmin (configuration defined)


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

Branch: refs/heads/master
Commit: 1463487763dc70f801922067a1d5e7b0f933bd6f
Parents: 0b5d95b
Author: benwa <bt...@linagora.com>
Authored: Thu Mar 9 14:40:56 2017 +0700
Committer: benwa <bt...@linagora.com>
Committed: Wed Mar 15 09:02:26 2017 +0700

----------------------------------------------------------------------
 .../destination/conf/webadmin.properties        |  6 +-
 .../destination/conf/webadmin.properties        |  6 +-
 .../modules/server/WebAdminServerModule.java    |  2 +
 .../org/apache/james/webadmin/CORSFilter.java   | 40 +++++++++++
 .../james/webadmin/WebAdminConfiguration.java   | 49 ++++++++++++--
 .../apache/james/webadmin/WebAdminServer.java   | 30 ++++++---
 .../webadmin/authentication/JwtFilter.java      | 15 +++--
 .../apache/james/webadmin/routes/CORSRoute.java | 42 ++++++++++++
 .../webadmin/WebAdminConfigurationTest.java     | 70 +++++++++++++++++++-
 9 files changed, 236 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/14634877/dockerfiles/run/guice/cassandra-ldap/destination/conf/webadmin.properties
----------------------------------------------------------------------
diff --git a/dockerfiles/run/guice/cassandra-ldap/destination/conf/webadmin.properties b/dockerfiles/run/guice/cassandra-ldap/destination/conf/webadmin.properties
index a9aced0..38e2ba0 100644
--- a/dockerfiles/run/guice/cassandra-ldap/destination/conf/webadmin.properties
+++ b/dockerfiles/run/guice/cassandra-ldap/destination/conf/webadmin.properties
@@ -33,4 +33,8 @@ https.enabled=false
 #https.trust.password
 
 # Defaults to false
-#jwt.enabled=true
\ No newline at end of file
+#jwt.enabled=true
+
+# Defaults to false
+#cors.enable=true
+#cors.origin
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/14634877/dockerfiles/run/guice/cassandra/destination/conf/webadmin.properties
----------------------------------------------------------------------
diff --git a/dockerfiles/run/guice/cassandra/destination/conf/webadmin.properties b/dockerfiles/run/guice/cassandra/destination/conf/webadmin.properties
index a9aced0..38e2ba0 100644
--- a/dockerfiles/run/guice/cassandra/destination/conf/webadmin.properties
+++ b/dockerfiles/run/guice/cassandra/destination/conf/webadmin.properties
@@ -33,4 +33,8 @@ https.enabled=false
 #https.trust.password
 
 # Defaults to false
-#jwt.enabled=true
\ No newline at end of file
+#jwt.enabled=true
+
+# Defaults to false
+#cors.enable=true
+#cors.origin
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/14634877/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java b/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
index 68e1b43..1532471 100644
--- a/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
+++ b/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
@@ -80,6 +80,8 @@ public class WebAdminServerModule extends AbstractModule {
                 .enable(configurationFile.getBoolean("enabled", false))
                 .port(new FixedPort(configurationFile.getInt("port", WebAdminServer.DEFAULT_PORT)))
                 .https(readHttpsConfiguration(configurationFile))
+                .enableCORS(configurationFile.getBoolean("cors.enable", false))
+                .urlCORSOrigin(configurationFile.getString("cors.origin", null))
                 .build();
         } catch (FileNotFoundException e) {
             return WebAdminConfiguration.builder()

http://git-wip-us.apache.org/repos/asf/james-project/blob/14634877/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/CORSFilter.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/CORSFilter.java b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/CORSFilter.java
new file mode 100644
index 0000000..c4cfb29
--- /dev/null
+++ b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/CORSFilter.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.webadmin;
+
+import spark.Filter;
+import spark.Request;
+import spark.Response;
+
+
+public class CORSFilter implements Filter {
+    private final String urlCORSOrigin;
+
+    public CORSFilter(String urlCORSOrigin) {
+        this.urlCORSOrigin = urlCORSOrigin;
+    }
+
+    @Override
+    public void handle(Request request, Response response) throws Exception {
+            response.header("Access-Control-Allow-Origin", urlCORSOrigin);
+            response.header("Access-Control-Request-Method", "DELETE, GET, POST, PUT");
+            response.header("Access-Control-Allow-Headers", "Content-Type, Authorization, Accept");
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/14634877/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
index 8cb022a..c87589b 100644
--- a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
+++ b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
@@ -28,6 +28,9 @@ import com.google.common.base.Preconditions;
 
 public class WebAdminConfiguration {
 
+    public static final boolean DEFAULT_CORS_DISABLED = false;
+    public static final String CORS_ALL_ORIGINS = "*";
+
     public static Builder builder() {
         return new Builder();
     }
@@ -35,7 +38,9 @@ public class WebAdminConfiguration {
     public static class Builder {
         private Optional<Boolean> enabled = Optional.empty();
         private Port port;
+        private Optional<Boolean> enableCORS = Optional.empty();
         private Optional<HttpsConfiguration> httpsConfiguration = Optional.empty();
+        private Optional<String> urlCORSOrigin = Optional.empty();
 
         public Builder https(HttpsConfiguration httpsConfiguration) {
             this.httpsConfiguration = Optional.of(httpsConfiguration);
@@ -51,7 +56,6 @@ public class WebAdminConfiguration {
             this.enabled = Optional.of(isEnabled);
             return this;
         }
-
         public Builder enabled() {
             return enable(true);
         }
@@ -60,6 +64,24 @@ public class WebAdminConfiguration {
             return enable(false);
         }
 
+        public Builder urlCORSOrigin(String origin) {
+            this.urlCORSOrigin = Optional.ofNullable(origin);
+            return this;
+        }
+
+        public Builder enableCORS(boolean isEnabled) {
+            this.enableCORS = Optional.of(isEnabled);
+            return this;
+        }
+
+        public Builder CORSenabled() {
+            return enableCORS(true);
+        }
+
+        public Builder CORSdisabled() {
+            return enableCORS(false);
+        }
+
         public WebAdminConfiguration build() {
             Preconditions.checkState(enabled.isPresent(), "You need to explicitly enable or disable WebAdmin server");
             Preconditions.checkState(!enabled.get() || port != null, "You need to specify a port for WebAdminConfiguration");
@@ -68,25 +90,35 @@ public class WebAdminConfiguration {
                 httpsConfiguration.orElse(
                     HttpsConfiguration.builder()
                         .disabled()
-                        .build()));
+                        .build()),
+                enableCORS.orElse(DEFAULT_CORS_DISABLED),
+                urlCORSOrigin.orElse(CORS_ALL_ORIGINS));
         }
     }
 
     private final boolean enabled;
     private final Port port;
     private final HttpsConfiguration httpsConfiguration;
+    private final boolean enableCORS;
+    private final String urlCORSOrigin;
 
     @VisibleForTesting
-    WebAdminConfiguration(boolean enabled, Port port, HttpsConfiguration httpsConfiguration) {
+    WebAdminConfiguration(boolean enabled, Port port, HttpsConfiguration httpsConfiguration, boolean enableCORS, String urlCORSOrigin) {
         this.enabled = enabled;
         this.port = port;
         this.httpsConfiguration = httpsConfiguration;
+        this.enableCORS = enableCORS;
+        this.urlCORSOrigin = urlCORSOrigin;
     }
 
     public boolean isEnabled() {
         return enabled;
     }
 
+    public String getUrlCORSOrigin() {
+        return urlCORSOrigin;
+    }
+
     public Port getPort() {
         return port;
     }
@@ -95,19 +127,26 @@ public class WebAdminConfiguration {
         return httpsConfiguration;
     }
 
+    public boolean isEnableCORS() {
+        return enableCORS;
+    }
+
     @Override
     public final boolean equals(Object o) {
         if (o instanceof WebAdminConfiguration) {
             WebAdminConfiguration that = (WebAdminConfiguration) o;
 
             return Objects.equals(this.enabled, that.enabled)
-                && Objects.equals(this.port, that.port);
+                && Objects.equals(this.port, that.port)
+                && Objects.equals(this.httpsConfiguration, that.httpsConfiguration)
+                && Objects.equals(this.enableCORS, that.enableCORS)
+                && Objects.equals(this.urlCORSOrigin, that.urlCORSOrigin);
         }
         return false;
     }
 
     @Override
     public final int hashCode() {
-        return Objects.hash(enabled, port);
+        return Objects.hash(enabled, port, httpsConfiguration, enableCORS, urlCORSOrigin);
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/14634877/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
index 7457219..9c398b4 100644
--- a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
+++ b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
@@ -30,6 +30,7 @@ import org.apache.commons.configuration.HierarchicalConfiguration;
 import org.apache.james.lifecycle.api.Configurable;
 import org.apache.james.webadmin.authentication.AuthenticationFilter;
 import org.apache.james.webadmin.authentication.NoAuthenticationFilter;
+import org.apache.james.webadmin.routes.CORSRoute;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -72,20 +73,33 @@ public class WebAdminServer implements Configurable {
     public void configure(HierarchicalConfiguration config) throws ConfigurationException {
         if (configuration.isEnabled()) {
             service.port(configuration.getPort().toInt());
-            HttpsConfiguration httpsConfiguration = configuration.getHttpsConfiguration();
-            if (httpsConfiguration.isEnabled()) {
-                service.secure(httpsConfiguration.getKeystoreFilePath(),
-                    httpsConfiguration.getKeystorePassword(),
-                    httpsConfiguration.getTruststoreFilePath(),
-                    httpsConfiguration.getTruststorePassword());
-                LOGGER.info("Web admin set up to use HTTPS");
-            }
+            configureHTTPS();
+            configureCORS();
             service.before(authenticationFilter);
             routesList.forEach(routes -> routes.define(service));
             LOGGER.info("Web admin server started");
         }
     }
 
+    private void configureHTTPS() {
+        HttpsConfiguration httpsConfiguration = configuration.getHttpsConfiguration();
+        if (httpsConfiguration.isEnabled()) {
+            service.secure(httpsConfiguration.getKeystoreFilePath(),
+                httpsConfiguration.getKeystorePassword(),
+                httpsConfiguration.getTruststoreFilePath(),
+                httpsConfiguration.getTruststorePassword());
+            LOGGER.info("Web admin set up to use HTTPS");
+        }
+    }
+
+    private void configureCORS() {
+        if (configuration.isEnabled()) {
+            service.before(new CORSFilter(configuration.getUrlCORSOrigin()));
+            new CORSRoute().define(service);
+            LOGGER.info("Web admin set up to enable CORS from " + configuration.getUrlCORSOrigin());
+        }
+    }
+
     @PreDestroy
     public void destroy() {
         if (configuration.isEnabled()) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/14634877/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/authentication/JwtFilter.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/authentication/JwtFilter.java b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/authentication/JwtFilter.java
index 991f412..4832d6f 100644
--- a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/authentication/JwtFilter.java
+++ b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/authentication/JwtFilter.java
@@ -33,6 +33,7 @@ import spark.Response;
 public class JwtFilter implements AuthenticationFilter {
     public static final String AUTHORIZATION_HEADER_PREFIX = "Bearer ";
     public static final String AUTHORIZATION_HEADER_NAME = "Authorization";
+    public static final String OPTIONS = "OPTIONS";
 
     private final JwtTokenVerifier jwtTokenVerifier;
 
@@ -43,13 +44,15 @@ public class JwtFilter implements AuthenticationFilter {
 
     @Override
     public void handle(Request request, Response response) throws Exception {
-        Optional<String> bearer = Optional.ofNullable(request.headers(AUTHORIZATION_HEADER_NAME))
-            .filter(value -> value.startsWith(AUTHORIZATION_HEADER_PREFIX))
-            .map(value -> value.substring(AUTHORIZATION_HEADER_PREFIX.length()));
+        if (request.requestMethod() != OPTIONS) {
+            Optional<String> bearer = Optional.ofNullable(request.headers(AUTHORIZATION_HEADER_NAME))
+                .filter(value -> value.startsWith(AUTHORIZATION_HEADER_PREFIX))
+                .map(value -> value.substring(AUTHORIZATION_HEADER_PREFIX.length()));
 
-        checkHeaderPresent(bearer);
-        checkValidSignature(bearer);
-        checkIsAdmin(bearer);
+            checkHeaderPresent(bearer);
+            checkValidSignature(bearer);
+            checkIsAdmin(bearer);
+        }
     }
 
     private void checkHeaderPresent(Optional<String> bearer) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/14634877/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/routes/CORSRoute.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/routes/CORSRoute.java b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/routes/CORSRoute.java
new file mode 100644
index 0000000..39e9bd7
--- /dev/null
+++ b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/routes/CORSRoute.java
@@ -0,0 +1,42 @@
+/****************************************************************
+ * 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 org.apache.james.webadmin.Routes;
+
+import spark.Service;
+
+public class CORSRoute implements Routes {
+
+    @Override
+    public void define(Service service) {
+        service.options("/*", (request, response) -> {
+            String accessControlRequestHeaders = request.headers("Access-Control-Request-Headers");
+            if (accessControlRequestHeaders != null) {
+                response.header("Access-Control-Allow-Headers", accessControlRequestHeaders);
+            }
+            String accessControlRequestMethod = request.headers("Access-Control-Request-Method");
+            if (accessControlRequestMethod != null) {
+                response.header("Access-Control-Allow-Methods", accessControlRequestMethod);
+            }
+            return "";
+        });
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/14634877/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java b/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java
index d20100c..4606e94 100644
--- a/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java
+++ b/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java
@@ -46,7 +46,11 @@ public class WebAdminConfigurationTest {
         assertThat(WebAdminConfiguration.builder()
             .disabled()
             .build())
-            .isEqualTo(new WebAdminConfiguration(false, null, HttpsConfiguration.builder().disabled().build()));
+            .isEqualTo(new WebAdminConfiguration(false,
+                null,
+                HttpsConfiguration.builder().disabled().build(),
+                false,
+                "*"));
     }
 
     @Test
@@ -63,7 +67,12 @@ public class WebAdminConfigurationTest {
                 .enabled()
                 .port(PORT)
                 .build())
-            .isEqualTo(new WebAdminConfiguration(true, PORT, HttpsConfiguration.builder().disabled().build()));
+            .isEqualTo(new WebAdminConfiguration(
+                true,
+                PORT,
+                HttpsConfiguration.builder().disabled().build(),
+                false,
+                "*"));
     }
 
     @Test
@@ -79,7 +88,62 @@ public class WebAdminConfigurationTest {
                 .https(httpsConfiguration)
                 .port(PORT)
                 .build())
-            .isEqualTo(new WebAdminConfiguration(true, PORT, httpsConfiguration));
+            .isEqualTo(new WebAdminConfiguration(
+                true,
+                PORT,
+                httpsConfiguration,
+                false,
+                "*"));
+    }
+
+    @Test
+    public void builderShouldCORSEnabled() {
+        assertThat(
+            WebAdminConfiguration.builder()
+                .enabled()
+                .port(PORT)
+                .CORSenabled()
+                .build())
+            .isEqualTo(new WebAdminConfiguration(
+                true,
+                PORT,
+                HttpsConfiguration.builder().disabled().build(),
+                true,
+                "*"));
+    }
+
+    @Test
+    public void builderShouldCORSDisabled() {
+        assertThat(
+            WebAdminConfiguration.builder()
+                .enabled()
+                .port(PORT)
+                .CORSdisabled()
+                .build())
+            .isEqualTo(new WebAdminConfiguration(
+                true,
+                PORT,
+                HttpsConfiguration.builder().disabled().build(),
+                false,
+                "*"));
+    }
+
+    @Test
+    public void builderShouldCORSWithOrigin() {
+        String origin = "linagora.com";
+        assertThat(
+            WebAdminConfiguration.builder()
+                .enabled()
+                .port(PORT)
+                .CORSenabled()
+                .urlCORSOrigin(origin)
+                .build())
+            .isEqualTo(new WebAdminConfiguration(
+                true,
+                PORT,
+                HttpsConfiguration.builder().disabled().build(),
+                true,
+                origin));
     }
 
     @Test


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


[12/22] james-project git commit: JAMES-1958 Rename HttpsConfiguration to TlsConfiguration

Posted by bt...@apache.org.
JAMES-1958 Rename HttpsConfiguration to TlsConfiguration


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

Branch: refs/heads/master
Commit: 9db1633a54787945706da2a4b3edd746f4757f74
Parents: 642be79
Author: benwa <bt...@linagora.com>
Authored: Mon Mar 13 17:31:26 2017 +0700
Committer: benwa <bt...@linagora.com>
Committed: Wed Mar 15 09:02:31 2017 +0700

----------------------------------------------------------------------
 .../modules/server/WebAdminServerModule.java    |   8 +-
 .../james/webadmin/HttpsConfiguration.java      | 148 -------------------
 .../apache/james/webadmin/TlsConfiguration.java | 148 +++++++++++++++++++
 .../james/webadmin/WebAdminConfiguration.java   |  22 +--
 .../apache/james/webadmin/WebAdminServer.java   |  16 +-
 .../james/webadmin/HttpsConfigurationTest.java  | 101 -------------
 .../james/webadmin/TlsConfigurationTest.java    | 101 +++++++++++++
 .../webadmin/WebAdminConfigurationTest.java     |  16 +-
 8 files changed, 278 insertions(+), 282 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/9db1633a/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java b/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
index c100dcb..431d0d5 100644
--- a/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
+++ b/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
@@ -33,7 +33,7 @@ import org.apache.james.utils.GuiceProbe;
 import org.apache.james.utils.PropertiesProvider;
 import org.apache.james.utils.WebAdminGuiceProbe;
 import org.apache.james.webadmin.FixedPort;
-import org.apache.james.webadmin.HttpsConfiguration;
+import org.apache.james.webadmin.TlsConfiguration;
 import org.apache.james.webadmin.Routes;
 import org.apache.james.webadmin.WebAdminConfiguration;
 import org.apache.james.webadmin.WebAdminServer;
@@ -112,10 +112,10 @@ public class WebAdminServerModule extends AbstractModule {
         }
     }
 
-    private HttpsConfiguration readHttpsConfiguration(PropertiesConfiguration configurationFile) {
+    private TlsConfiguration readHttpsConfiguration(PropertiesConfiguration configurationFile) {
         boolean enabled = configurationFile.getBoolean("https.enabled", DEFAULT_HTTPS_DISABLED);
         if (enabled) {
-            return HttpsConfiguration.builder()
+            return TlsConfiguration.builder()
                 .enabled()
                 .raw(configurationFile.getString("https.keystore", DEFAULT_NO_KEYSTORE),
                     configurationFile.getString("https.password", DEFAULT_NO_PASSWORD),
@@ -123,7 +123,7 @@ public class WebAdminServerModule extends AbstractModule {
                     configurationFile.getString("https.trust.password", DEFAULT_NO_TRUST_PASSWORD))
                 .build();
         }
-        return HttpsConfiguration.builder()
+        return TlsConfiguration.builder()
             .disabled()
             .build();
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/9db1633a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/HttpsConfiguration.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/HttpsConfiguration.java b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/HttpsConfiguration.java
deleted file mode 100644
index 3c6a49e..0000000
--- a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/HttpsConfiguration.java
+++ /dev/null
@@ -1,148 +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.webadmin;
-
-import java.util.Objects;
-import java.util.Optional;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-
-public class HttpsConfiguration {
-
-    public static Builder builder() {
-        return new Builder();
-    }
-
-    public static class Builder {
-        private Optional<Boolean> enabled = Optional.empty();
-        private String keystoreFilePath;
-        private String keystorePassword;
-        private String truststoreFilePath;
-        private String truststorePassword;
-
-        public Builder enable(boolean isEnabled) {
-            this.enabled = Optional.of(isEnabled);
-            return this;
-        }
-
-        public Builder enabled() {
-            return enable(true);
-        }
-
-        public Builder disabled() {
-            return enable(false);
-        }
-
-        public Builder raw(String keystoreFilePath,
-                           String keystorePassword,
-                           String truststoreFilePath,
-                           String truststorePassword){
-            Preconditions.checkNotNull(keystoreFilePath);
-            Preconditions.checkNotNull(keystorePassword);
-
-            this.keystoreFilePath = keystoreFilePath;
-            this.keystorePassword = keystorePassword;
-            this.truststoreFilePath = truststoreFilePath;
-            this.truststorePassword = truststorePassword;
-            return this;
-        }
-
-        public Builder selfSigned(String keystoreFilePath, String keystorePassword){
-            Preconditions.checkNotNull(keystoreFilePath);
-            Preconditions.checkNotNull(keystorePassword);
-
-            this.enabled = Optional.of(true);
-            this.keystoreFilePath = keystoreFilePath;
-            this.keystorePassword = keystorePassword;
-            return this;
-        }
-
-        public HttpsConfiguration build() {
-            Preconditions.checkState(enabled.isPresent(), "You need to specify if https is enabled");
-            Preconditions.checkState(!enabled.get() || hasKeystoreInformation(), "If enabled, you need to provide keystore information");
-            Preconditions.checkState(optionalHasTrustStoreInformation(), "You need to provide both information about trustStore");
-            return new HttpsConfiguration(enabled.get(), keystoreFilePath, keystorePassword, truststoreFilePath, truststorePassword);
-        }
-
-        private boolean optionalHasTrustStoreInformation() {
-            return (truststoreFilePath == null) == (truststorePassword == null);
-        }
-
-        private boolean hasKeystoreInformation() {
-            return keystorePassword != null && keystoreFilePath != null;
-        }
-
-    }
-
-    private final boolean enabled;
-    private final String keystoreFilePath;
-    private final String keystorePassword;
-    private final String truststoreFilePath;
-    private final String truststorePassword;
-
-    @VisibleForTesting
-    HttpsConfiguration(boolean enabled, String keystoreFilePath, String keystorePassword, String truststoreFilePath, String truststorePassword) {
-        this.enabled = enabled;
-        this.keystoreFilePath = keystoreFilePath;
-        this.keystorePassword = keystorePassword;
-        this.truststoreFilePath = truststoreFilePath;
-        this.truststorePassword = truststorePassword;
-    }
-
-    public boolean isEnabled() {
-        return enabled;
-    }
-
-    public String getKeystoreFilePath() {
-        return keystoreFilePath;
-    }
-
-    public String getKeystorePassword() {
-        return keystorePassword;
-    }
-
-    public String getTruststoreFilePath() {
-        return truststoreFilePath;
-    }
-
-    public String getTruststorePassword() {
-        return truststorePassword;
-    }
-
-    @Override
-    public final boolean equals(Object o) {
-       if (o instanceof HttpsConfiguration) {
-           HttpsConfiguration that = (HttpsConfiguration) o;
-
-           return Objects.equals(this.enabled, that.enabled)
-               && Objects.equals(this.keystoreFilePath, that.keystoreFilePath)
-               && Objects.equals(this.keystorePassword, that.keystorePassword)
-               && Objects.equals(this.truststoreFilePath, that.truststoreFilePath)
-               && Objects.equals(this.truststorePassword, that.truststorePassword);
-       }
-       return false;
-    }
-
-    @Override
-    public final int hashCode() {
-        return Objects.hash(enabled, keystoreFilePath, keystorePassword, truststoreFilePath, truststorePassword);
-    }
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/9db1633a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/TlsConfiguration.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/TlsConfiguration.java b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/TlsConfiguration.java
new file mode 100644
index 0000000..78cc209
--- /dev/null
+++ b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/TlsConfiguration.java
@@ -0,0 +1,148 @@
+/****************************************************************
+ * 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;
+
+import java.util.Objects;
+import java.util.Optional;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+
+public class TlsConfiguration {
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    public static class Builder {
+        private Optional<Boolean> enabled = Optional.empty();
+        private String keystoreFilePath;
+        private String keystorePassword;
+        private String truststoreFilePath;
+        private String truststorePassword;
+
+        public Builder enable(boolean isEnabled) {
+            this.enabled = Optional.of(isEnabled);
+            return this;
+        }
+
+        public Builder enabled() {
+            return enable(true);
+        }
+
+        public Builder disabled() {
+            return enable(false);
+        }
+
+        public Builder raw(String keystoreFilePath,
+                           String keystorePassword,
+                           String truststoreFilePath,
+                           String truststorePassword){
+            Preconditions.checkNotNull(keystoreFilePath);
+            Preconditions.checkNotNull(keystorePassword);
+
+            this.keystoreFilePath = keystoreFilePath;
+            this.keystorePassword = keystorePassword;
+            this.truststoreFilePath = truststoreFilePath;
+            this.truststorePassword = truststorePassword;
+            return this;
+        }
+
+        public Builder selfSigned(String keystoreFilePath, String keystorePassword){
+            Preconditions.checkNotNull(keystoreFilePath);
+            Preconditions.checkNotNull(keystorePassword);
+
+            this.enabled = Optional.of(true);
+            this.keystoreFilePath = keystoreFilePath;
+            this.keystorePassword = keystorePassword;
+            return this;
+        }
+
+        public TlsConfiguration build() {
+            Preconditions.checkState(enabled.isPresent(), "You need to specify if https is enabled");
+            Preconditions.checkState(!enabled.get() || hasKeystoreInformation(), "If enabled, you need to provide keystore information");
+            Preconditions.checkState(optionalHasTrustStoreInformation(), "You need to provide both information about trustStore");
+            return new TlsConfiguration(enabled.get(), keystoreFilePath, keystorePassword, truststoreFilePath, truststorePassword);
+        }
+
+        private boolean optionalHasTrustStoreInformation() {
+            return (truststoreFilePath == null) == (truststorePassword == null);
+        }
+
+        private boolean hasKeystoreInformation() {
+            return keystorePassword != null && keystoreFilePath != null;
+        }
+
+    }
+
+    private final boolean enabled;
+    private final String keystoreFilePath;
+    private final String keystorePassword;
+    private final String truststoreFilePath;
+    private final String truststorePassword;
+
+    @VisibleForTesting
+    TlsConfiguration(boolean enabled, String keystoreFilePath, String keystorePassword, String truststoreFilePath, String truststorePassword) {
+        this.enabled = enabled;
+        this.keystoreFilePath = keystoreFilePath;
+        this.keystorePassword = keystorePassword;
+        this.truststoreFilePath = truststoreFilePath;
+        this.truststorePassword = truststorePassword;
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public String getKeystoreFilePath() {
+        return keystoreFilePath;
+    }
+
+    public String getKeystorePassword() {
+        return keystorePassword;
+    }
+
+    public String getTruststoreFilePath() {
+        return truststoreFilePath;
+    }
+
+    public String getTruststorePassword() {
+        return truststorePassword;
+    }
+
+    @Override
+    public final boolean equals(Object o) {
+       if (o instanceof TlsConfiguration) {
+           TlsConfiguration that = (TlsConfiguration) o;
+
+           return Objects.equals(this.enabled, that.enabled)
+               && Objects.equals(this.keystoreFilePath, that.keystoreFilePath)
+               && Objects.equals(this.keystorePassword, that.keystorePassword)
+               && Objects.equals(this.truststoreFilePath, that.truststoreFilePath)
+               && Objects.equals(this.truststorePassword, that.truststorePassword);
+       }
+       return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(enabled, keystoreFilePath, keystorePassword, truststoreFilePath, truststorePassword);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/9db1633a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
index c87589b..339b213 100644
--- a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
+++ b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
@@ -39,11 +39,11 @@ public class WebAdminConfiguration {
         private Optional<Boolean> enabled = Optional.empty();
         private Port port;
         private Optional<Boolean> enableCORS = Optional.empty();
-        private Optional<HttpsConfiguration> httpsConfiguration = Optional.empty();
+        private Optional<TlsConfiguration> httpsConfiguration = Optional.empty();
         private Optional<String> urlCORSOrigin = Optional.empty();
 
-        public Builder https(HttpsConfiguration httpsConfiguration) {
-            this.httpsConfiguration = Optional.of(httpsConfiguration);
+        public Builder https(TlsConfiguration tlsConfiguration) {
+            this.httpsConfiguration = Optional.of(tlsConfiguration);
             return this;
         }
 
@@ -88,7 +88,7 @@ public class WebAdminConfiguration {
             return new WebAdminConfiguration(enabled.get(),
                 port,
                 httpsConfiguration.orElse(
-                    HttpsConfiguration.builder()
+                    TlsConfiguration.builder()
                         .disabled()
                         .build()),
                 enableCORS.orElse(DEFAULT_CORS_DISABLED),
@@ -98,15 +98,15 @@ public class WebAdminConfiguration {
 
     private final boolean enabled;
     private final Port port;
-    private final HttpsConfiguration httpsConfiguration;
+    private final TlsConfiguration tlsConfiguration;
     private final boolean enableCORS;
     private final String urlCORSOrigin;
 
     @VisibleForTesting
-    WebAdminConfiguration(boolean enabled, Port port, HttpsConfiguration httpsConfiguration, boolean enableCORS, String urlCORSOrigin) {
+    WebAdminConfiguration(boolean enabled, Port port, TlsConfiguration tlsConfiguration, boolean enableCORS, String urlCORSOrigin) {
         this.enabled = enabled;
         this.port = port;
-        this.httpsConfiguration = httpsConfiguration;
+        this.tlsConfiguration = tlsConfiguration;
         this.enableCORS = enableCORS;
         this.urlCORSOrigin = urlCORSOrigin;
     }
@@ -123,8 +123,8 @@ public class WebAdminConfiguration {
         return port;
     }
 
-    public HttpsConfiguration getHttpsConfiguration() {
-        return httpsConfiguration;
+    public TlsConfiguration getTlsConfiguration() {
+        return tlsConfiguration;
     }
 
     public boolean isEnableCORS() {
@@ -138,7 +138,7 @@ public class WebAdminConfiguration {
 
             return Objects.equals(this.enabled, that.enabled)
                 && Objects.equals(this.port, that.port)
-                && Objects.equals(this.httpsConfiguration, that.httpsConfiguration)
+                && Objects.equals(this.tlsConfiguration, that.tlsConfiguration)
                 && Objects.equals(this.enableCORS, that.enableCORS)
                 && Objects.equals(this.urlCORSOrigin, that.urlCORSOrigin);
         }
@@ -147,6 +147,6 @@ public class WebAdminConfiguration {
 
     @Override
     public final int hashCode() {
-        return Objects.hash(enabled, port, httpsConfiguration, enableCORS, urlCORSOrigin);
+        return Objects.hash(enabled, port, tlsConfiguration, enableCORS, urlCORSOrigin);
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/9db1633a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
index e3fb368..e2144bf 100644
--- a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
+++ b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
@@ -29,7 +29,6 @@ import org.apache.commons.configuration.ConfigurationException;
 import org.apache.commons.configuration.HierarchicalConfiguration;
 import org.apache.james.lifecycle.api.Configurable;
 import org.apache.james.metrics.api.MetricFactory;
-import org.apache.james.metrics.api.NoopMetricFactory;
 import org.apache.james.webadmin.authentication.AuthenticationFilter;
 import org.apache.james.webadmin.authentication.NoAuthenticationFilter;
 import org.apache.james.webadmin.metric.MetricPostFilter;
@@ -41,9 +40,6 @@ import org.slf4j.LoggerFactory;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableSet;
 
-import spark.Filter;
-import spark.Request;
-import spark.Response;
 import spark.Service;
 
 public class WebAdminServer implements Configurable {
@@ -99,12 +95,12 @@ public class WebAdminServer implements Configurable {
     }
 
     private void configureHTTPS() {
-        HttpsConfiguration httpsConfiguration = configuration.getHttpsConfiguration();
-        if (httpsConfiguration.isEnabled()) {
-            service.secure(httpsConfiguration.getKeystoreFilePath(),
-                httpsConfiguration.getKeystorePassword(),
-                httpsConfiguration.getTruststoreFilePath(),
-                httpsConfiguration.getTruststorePassword());
+        TlsConfiguration tlsConfiguration = configuration.getTlsConfiguration();
+        if (tlsConfiguration.isEnabled()) {
+            service.secure(tlsConfiguration.getKeystoreFilePath(),
+                tlsConfiguration.getKeystorePassword(),
+                tlsConfiguration.getTruststoreFilePath(),
+                tlsConfiguration.getTruststorePassword());
             LOGGER.info("Web admin set up to use HTTPS");
         }
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/9db1633a/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/HttpsConfigurationTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/HttpsConfigurationTest.java b/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/HttpsConfigurationTest.java
deleted file mode 100644
index 0d69cbe..0000000
--- a/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/HttpsConfigurationTest.java
+++ /dev/null
@@ -1,101 +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.webadmin;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-import nl.jqno.equalsverifier.EqualsVerifier;
-
-public class HttpsConfigurationTest {
-
-    @Rule
-    public ExpectedException expectedException = ExpectedException.none();
-
-    @Test
-    public void buildShouldThrowWhenNotEnabled() {
-        expectedException.expect(IllegalStateException.class);
-
-        HttpsConfiguration.builder().build();
-    }
-
-    @Test
-    public void buildShouldThrowWhenEnableWithoutKeystore() {
-        expectedException.expect(IllegalStateException.class);
-
-        HttpsConfiguration.builder().enabled().build();
-    }
-
-    @Test
-    public void selfSignedShouldThrowOnNullKeyStorePath() {
-        expectedException.expect(NullPointerException.class);
-
-        HttpsConfiguration.builder()
-            .enabled()
-            .selfSigned(null, "abc");
-    }
-
-    @Test
-    public void selfSignedShouldThrowOnNullKeyStorePassword() {
-        expectedException.expect(NullPointerException.class);
-
-        HttpsConfiguration.builder()
-            .enabled()
-            .selfSigned("abc", null);
-    }
-
-    @Test
-    public void buildShouldWorkOnDisabledHttps() {
-        assertThat(
-            HttpsConfiguration.builder()
-                .disabled()
-                .build())
-            .isEqualTo(new HttpsConfiguration(false, null, null, null, null));
-    }
-
-    @Test
-    public void buildShouldWorkOnSelfSignedHttps() {
-        assertThat(
-            HttpsConfiguration.builder()
-                .enabled()
-                .selfSigned("abcd", "efgh")
-                .build())
-            .isEqualTo(new HttpsConfiguration(true, "abcd", "efgh", null, null));
-    }
-
-    @Test
-    public void buildShouldWorkOnTrustedHttps() {
-        assertThat(
-            HttpsConfiguration.builder()
-                .enabled()
-                .raw("a", "b", "c", "d")
-                .build())
-            .isEqualTo(new HttpsConfiguration(true, "a", "b", "c", "d"));
-    }
-
-    @Test
-    public void shouldRespectBeanContract() {
-        EqualsVerifier.forClass(HttpsConfiguration.class).verify();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/9db1633a/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/TlsConfigurationTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/TlsConfigurationTest.java b/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/TlsConfigurationTest.java
new file mode 100644
index 0000000..c21ddb7
--- /dev/null
+++ b/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/TlsConfigurationTest.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.webadmin;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+
+public class TlsConfigurationTest {
+
+    @Rule
+    public ExpectedException expectedException = ExpectedException.none();
+
+    @Test
+    public void buildShouldThrowWhenNotEnabled() {
+        expectedException.expect(IllegalStateException.class);
+
+        TlsConfiguration.builder().build();
+    }
+
+    @Test
+    public void buildShouldThrowWhenEnableWithoutKeystore() {
+        expectedException.expect(IllegalStateException.class);
+
+        TlsConfiguration.builder().enabled().build();
+    }
+
+    @Test
+    public void selfSignedShouldThrowOnNullKeyStorePath() {
+        expectedException.expect(NullPointerException.class);
+
+        TlsConfiguration.builder()
+            .enabled()
+            .selfSigned(null, "abc");
+    }
+
+    @Test
+    public void selfSignedShouldThrowOnNullKeyStorePassword() {
+        expectedException.expect(NullPointerException.class);
+
+        TlsConfiguration.builder()
+            .enabled()
+            .selfSigned("abc", null);
+    }
+
+    @Test
+    public void buildShouldWorkOnDisabledHttps() {
+        assertThat(
+            TlsConfiguration.builder()
+                .disabled()
+                .build())
+            .isEqualTo(new TlsConfiguration(false, null, null, null, null));
+    }
+
+    @Test
+    public void buildShouldWorkOnSelfSignedHttps() {
+        assertThat(
+            TlsConfiguration.builder()
+                .enabled()
+                .selfSigned("abcd", "efgh")
+                .build())
+            .isEqualTo(new TlsConfiguration(true, "abcd", "efgh", null, null));
+    }
+
+    @Test
+    public void buildShouldWorkOnTrustedHttps() {
+        assertThat(
+            TlsConfiguration.builder()
+                .enabled()
+                .raw("a", "b", "c", "d")
+                .build())
+            .isEqualTo(new TlsConfiguration(true, "a", "b", "c", "d"));
+    }
+
+    @Test
+    public void shouldRespectBeanContract() {
+        EqualsVerifier.forClass(TlsConfiguration.class).verify();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/9db1633a/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java b/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java
index 4606e94..48df15e 100644
--- a/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java
+++ b/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java
@@ -48,7 +48,7 @@ public class WebAdminConfigurationTest {
             .build())
             .isEqualTo(new WebAdminConfiguration(false,
                 null,
-                HttpsConfiguration.builder().disabled().build(),
+                TlsConfiguration.builder().disabled().build(),
                 false,
                 "*"));
     }
@@ -70,14 +70,14 @@ public class WebAdminConfigurationTest {
             .isEqualTo(new WebAdminConfiguration(
                 true,
                 PORT,
-                HttpsConfiguration.builder().disabled().build(),
+                TlsConfiguration.builder().disabled().build(),
                 false,
                 "*"));
     }
 
     @Test
     public void builderShouldAcceptHttps() {
-        HttpsConfiguration httpsConfiguration = HttpsConfiguration.builder()
+        TlsConfiguration tlsConfiguration = TlsConfiguration.builder()
             .enable(true)
             .selfSigned("abcd", "efgh")
             .build();
@@ -85,13 +85,13 @@ public class WebAdminConfigurationTest {
         assertThat(
             WebAdminConfiguration.builder()
                 .enabled()
-                .https(httpsConfiguration)
+                .https(tlsConfiguration)
                 .port(PORT)
                 .build())
             .isEqualTo(new WebAdminConfiguration(
                 true,
                 PORT,
-                httpsConfiguration,
+                tlsConfiguration,
                 false,
                 "*"));
     }
@@ -107,7 +107,7 @@ public class WebAdminConfigurationTest {
             .isEqualTo(new WebAdminConfiguration(
                 true,
                 PORT,
-                HttpsConfiguration.builder().disabled().build(),
+                TlsConfiguration.builder().disabled().build(),
                 true,
                 "*"));
     }
@@ -123,7 +123,7 @@ public class WebAdminConfigurationTest {
             .isEqualTo(new WebAdminConfiguration(
                 true,
                 PORT,
-                HttpsConfiguration.builder().disabled().build(),
+                TlsConfiguration.builder().disabled().build(),
                 false,
                 "*"));
     }
@@ -141,7 +141,7 @@ public class WebAdminConfigurationTest {
             .isEqualTo(new WebAdminConfiguration(
                 true,
                 PORT,
-                HttpsConfiguration.builder().disabled().build(),
+                TlsConfiguration.builder().disabled().build(),
                 true,
                 origin));
     }


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


[06/22] james-project git commit: JAMES-1959 Implement a Jwt authentication filter for webAdmin

Posted by bt...@apache.org.
JAMES-1959 Implement a Jwt authentication filter for webAdmin


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

Branch: refs/heads/master
Commit: 3d327f720772a841844cb2f1033830c13d8e63ac
Parents: f1a087f
Author: benwa <bt...@linagora.com>
Authored: Wed Mar 8 17:54:58 2017 +0700
Committer: benwa <bt...@linagora.com>
Committed: Wed Mar 15 09:01:53 2017 +0700

----------------------------------------------------------------------
 .../destination/conf/webadmin.properties        |   5 +-
 .../destination/conf/webadmin.properties        |   5 +-
 .../modules/server/WebAdminServerModule.java    |  20 +++
 .../org/apache/james/jwt/JwtTokenVerifier.java  |  33 ++++-
 .../apache/james/jwt/JwtTokenVerifierTest.java  |  63 +++++++---
 server/protocols/webadmin/pom.xml               |   4 +
 .../apache/james/webadmin/WebAdminServer.java   |  10 +-
 .../authentication/AuthenticationFilter.java    |  25 ++++
 .../webadmin/authentication/JwtFilter.java      |  73 +++++++++++
 .../authentication/NoAuthenticationFilter.java  |  31 +++++
 .../webadmin/authentication/JwtFilterTest.java  | 124 +++++++++++++++++++
 11 files changed, 364 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/3d327f72/dockerfiles/run/guice/cassandra-ldap/destination/conf/webadmin.properties
----------------------------------------------------------------------
diff --git a/dockerfiles/run/guice/cassandra-ldap/destination/conf/webadmin.properties b/dockerfiles/run/guice/cassandra-ldap/destination/conf/webadmin.properties
index 3a1e755..a9aced0 100644
--- a/dockerfiles/run/guice/cassandra-ldap/destination/conf/webadmin.properties
+++ b/dockerfiles/run/guice/cassandra-ldap/destination/conf/webadmin.properties
@@ -30,4 +30,7 @@ https.enabled=false
 
 # Optional when enabling HTTPS (self signed)
 #https.trust.keystore
-#https.trust.password
\ No newline at end of file
+#https.trust.password
+
+# Defaults to false
+#jwt.enabled=true
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/3d327f72/dockerfiles/run/guice/cassandra/destination/conf/webadmin.properties
----------------------------------------------------------------------
diff --git a/dockerfiles/run/guice/cassandra/destination/conf/webadmin.properties b/dockerfiles/run/guice/cassandra/destination/conf/webadmin.properties
index 3a1e755..a9aced0 100644
--- a/dockerfiles/run/guice/cassandra/destination/conf/webadmin.properties
+++ b/dockerfiles/run/guice/cassandra/destination/conf/webadmin.properties
@@ -30,4 +30,7 @@ https.enabled=false
 
 # Optional when enabling HTTPS (self signed)
 #https.trust.keystore
-#https.trust.password
\ No newline at end of file
+#https.trust.password
+
+# Defaults to false
+#jwt.enabled=true
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/3d327f72/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java b/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
index 29c6223..68e1b43 100644
--- a/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
+++ b/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
@@ -26,6 +26,7 @@ import java.util.List;
 
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.commons.configuration.PropertiesConfiguration;
+import org.apache.james.jwt.JwtTokenVerifier;
 import org.apache.james.lifecycle.api.Configurable;
 import org.apache.james.utils.ConfigurationPerformer;
 import org.apache.james.utils.GuiceProbe;
@@ -36,6 +37,9 @@ import org.apache.james.webadmin.HttpsConfiguration;
 import org.apache.james.webadmin.Routes;
 import org.apache.james.webadmin.WebAdminConfiguration;
 import org.apache.james.webadmin.WebAdminServer;
+import org.apache.james.webadmin.authentication.AuthenticationFilter;
+import org.apache.james.webadmin.authentication.JwtFilter;
+import org.apache.james.webadmin.authentication.NoAuthenticationFilter;
 import org.apache.james.webadmin.routes.DomainRoutes;
 import org.apache.james.webadmin.routes.UserMailboxesRoutes;
 import org.apache.james.webadmin.routes.UserRoutes;
@@ -52,6 +56,8 @@ import com.google.inject.multibindings.Multibinder;
 
 public class WebAdminServerModule extends AbstractModule {
 
+    public static final boolean DEFAULT_JWT_DISABLED = false;
+
     @Override
     protected void configure() {
         bind(JsonTransformer.class).in(Scopes.SINGLETON);
@@ -82,6 +88,20 @@ public class WebAdminServerModule extends AbstractModule {
         }
     }
 
+    @Provides
+    public AuthenticationFilter providesAuthenticationFilter(PropertiesProvider propertiesProvider,
+                                                             JwtTokenVerifier jwtTokenVerifier) throws Exception {
+        try {
+            PropertiesConfiguration configurationFile = propertiesProvider.getConfiguration("webadmin");
+            if (configurationFile.getBoolean("jwt.enabled", DEFAULT_JWT_DISABLED)) {
+                return new JwtFilter(jwtTokenVerifier);
+            }
+            return new NoAuthenticationFilter();
+        } catch (FileNotFoundException e) {
+            return new NoAuthenticationFilter();
+        }
+    }
+
     private HttpsConfiguration readHttpsConfiguration(PropertiesConfiguration configurationFile) {
         boolean enabled = configurationFile.getBoolean("https.enabled", DEFAULT_HTTPS_DISABLED());
         if (enabled) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/3d327f72/server/protocols/jwt/src/main/java/org/apache/james/jwt/JwtTokenVerifier.java
----------------------------------------------------------------------
diff --git a/server/protocols/jwt/src/main/java/org/apache/james/jwt/JwtTokenVerifier.java b/server/protocols/jwt/src/main/java/org/apache/james/jwt/JwtTokenVerifier.java
index 661302f..cffc5fb 100644
--- a/server/protocols/jwt/src/main/java/org/apache/james/jwt/JwtTokenVerifier.java
+++ b/server/protocols/jwt/src/main/java/org/apache/james/jwt/JwtTokenVerifier.java
@@ -20,6 +20,9 @@ package org.apache.james.jwt;
 
 import javax.inject.Inject;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Strings;
 
@@ -31,6 +34,7 @@ import io.jsonwebtoken.MalformedJwtException;
 
 public class JwtTokenVerifier {
 
+    private static Logger LOGGER = LoggerFactory.getLogger(JwtTokenVerifier.class);
     private final PublicKeyProvider pubKeyProvider;
 
     @Inject
@@ -39,12 +43,17 @@ public class JwtTokenVerifier {
         this.pubKeyProvider = pubKeyProvider;
     }
 
-    public boolean verify(String token) throws JwtException {
-        String subject = extractLogin(token);
-        if (Strings.isNullOrEmpty(subject)) {
-            throw new MalformedJwtException("'subject' field in token is mandatory");
+    public boolean verify(String token) {
+        try {
+            String subject = extractLogin(token);
+            if (Strings.isNullOrEmpty(subject)) {
+                throw new MalformedJwtException("'subject' field in token is mandatory");
+            }
+            return true;
+        } catch (JwtException e) {
+            LOGGER.info("Failed Jwt verification");
+            return false;
         }
-        return true;
     }
 
     public String extractLogin(String token) throws JwtException {
@@ -54,6 +63,20 @@ public class JwtTokenVerifier {
                 .getSubject();
     }
 
+    public boolean hasAttribute(String attributeName, Object expectedValue, String token) {
+        try {
+            Jwts
+                .parser()
+                .require(attributeName, expectedValue)
+                .setSigningKey(pubKeyProvider.get())
+                .parseClaimsJws(token);
+            return true;
+        } catch (JwtException e) {
+            LOGGER.info("Jwt validation failed for claim " + attributeName + " to " + expectedValue, e);
+            return false;
+        }
+    }
+
     private Jws<Claims> parseToken(String token) throws JwtException {
         return Jwts
                 .parser()

http://git-wip-us.apache.org/repos/asf/james-project/blob/3d327f72/server/protocols/jwt/src/test/java/org/apache/james/jwt/JwtTokenVerifierTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/jwt/src/test/java/org/apache/james/jwt/JwtTokenVerifierTest.java b/server/protocols/jwt/src/test/java/org/apache/james/jwt/JwtTokenVerifierTest.java
index ac5cc94..698b28d 100644
--- a/server/protocols/jwt/src/test/java/org/apache/james/jwt/JwtTokenVerifierTest.java
+++ b/server/protocols/jwt/src/test/java/org/apache/james/jwt/JwtTokenVerifierTest.java
@@ -19,7 +19,6 @@
 package org.apache.james.jwt;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 import java.security.Security;
 import java.util.Optional;
@@ -27,10 +26,9 @@ import java.util.Optional;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.junit.Before;
 import org.junit.BeforeClass;
+import org.junit.Rule;
 import org.junit.Test;
-
-import io.jsonwebtoken.MalformedJwtException;
-import io.jsonwebtoken.SignatureException;
+import org.junit.rules.ExpectedException;
 
 public class JwtTokenVerifierTest {
 
@@ -44,14 +42,27 @@ public class JwtTokenVerifierTest {
             "kwIDAQAB\n" +
             "-----END PUBLIC KEY-----";
     
-    private static final String VALID_TOKEN = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0.T04BTk" +
+    private static final String VALID_TOKEN_WITHOUT_ADMIN = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0.T04BTk" +
             "LXkJj24coSZkK13RfG25lpvmSl2MJ7N10KpBk9_-95EGYZdog-BDAn3PJzqVw52z-Bwjh4VOj1-j7cURu0cT4jXehhUrlCxS4n7QHZD" +
             "N_bsEYGu7KzjWTpTsUiHe-rN7izXVFxDGG1TGwlmBCBnPW-EFCf9ylUsJi0r2BKNdaaPRfMIrHptH1zJBkkUziWpBN1RNLjmvlAUf49" +
             "t1Tbv21ZqYM5Ht2vrhJWczFbuC-TD-8zJkXhjTmA1GVgomIX5dx1cH-dZX1wANNmshUJGHgepWlPU-5VIYxPEhb219RMLJIELMY2qN" +
             "OR8Q31ydinyqzXvCSzVJOf6T60-w";
 
+    private static final String VALID_TOKEN_ADMIN_TRUE = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZG1pbkBvcGVuL" +
+        "XBhYXMub3JnIiwiYWRtaW4iOnRydWUsImlhdCI6MTQ4OTAzODQzOH0.rgxCkdWEa-92a4R-72a9Z49k4LRvQDShgci5Y7qWRUP9IGJCK-lMkrHF" +
+        "4H0a6L87BYppxVW701zaZ6dNxRMvHnjLBBWnPsC2B0rkkr2hEL2zfz7sb-iNGV-J4ICx97t8-TfQ5rz3VOX0FwdusPL_rJtmlGEGRivPkR6_aBe1" +
+        "kQnvMlwpqF_3ox58EUqYJk6lK_6rjKEV3Xfre31IMpuQUy6c7TKc95sL2-13cknelTierBEmZ00RzTtv9SHIEfzZTfaUK2Wm0PvnQjmU2nIdEvU" +
+        "EqE-jrM3yYXcQzoO-YTQnEhdl-iqbCfmEpYkl2Bx3eIq7gRxxnr7BPsX6HrCB0w";
+    private static final String VALID_TOKEN_ADMIN_FALSE = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZG1pbkBvcGVu" +
+        "LXBhYXMub3JnIiwiYWRtaW4iOmZhbHNlLCJpYXQiOjE0ODkwNDA4Njd9.reQc3DiVvbQHF08oW1qOUyDJyv3tfzDNk8jhVZequiCdOI9vXnRlOe" +
+        "-yDYktd4WT8MYhqY7MgS-wR0vO9jZFv8ZCgd_MkKCvCO0HmMjP5iQPZ0kqGkgWUH7X123tfR38MfbCVAdPDba-K3MfkogV1xvDhlkPScFr_6MxE" +
+        "xtedOK2JnQZn7t9sUzSrcyjWverm7gZkPptkIVoS8TsEeMMME5vFXe_nqkEG69q3kuBUm_33tbR5oNS0ZGZKlG9r41lHBjyf9J1xN4UYV8n866d" +
+        "a7RPPCzshIWUtO0q9T2umWTnp-6OnOdBCkndrZmRR6pPxsD5YL0_77Wq8KT_5__fGA";
     private JwtTokenVerifier sut;
 
+    @Rule
+    public ExpectedException expectedException = ExpectedException.none();
+
     @BeforeClass
     public static void init() {
         Security.addProvider(new BouncyCastleProvider());
@@ -64,56 +75,68 @@ public class JwtTokenVerifierTest {
     }
 
     private JwtConfiguration getJWTConfiguration() {
-
         return new JwtConfiguration(Optional.of(PUBLIC_PEM_KEY));
     }
 
     @Test
     public void shouldReturnTrueOnValidSignature() {
-
-        assertThat(sut.verify(VALID_TOKEN)).isTrue();
+        assertThat(sut.verify(VALID_TOKEN_WITHOUT_ADMIN)).isTrue();
     }
 
     @Test
-    public void shouldThrowOnMismatchingSigningKey() {
+    public void shouldReturnFalseOnMismatchingSigningKey() {
         String invalidToken = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0.Pd6t82" +
                 "tPL3EZdkeYxw_DV2KimE1U2FvuLHmfR_mimJ5US3JFU4J2Gd94O7rwpSTGN1B9h-_lsTebo4ua4xHsTtmczZ9xa8a_kWKaSkqFjNFa" +
                 "Fp6zcoD6ivCu03SlRqsQzSRHXo6TKbnqOt9D6Y2rNa3C4igSwoS0jUE4BgpXbc0";
 
-        assertThatThrownBy(() -> sut.verify(invalidToken))
-            .isInstanceOf(SignatureException.class);
+        assertThat(sut.verify(invalidToken)).isFalse();
     }
 
     @Test
-    public void verifyShouldThrowWhenSubjectIsNull() {
+    public void verifyShouldReturnFalseWhenSubjectIsNull() {
         String tokenWithNullSubject = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOm51bGwsIm5hbWUiOiJKb2huIERvZSJ9.EB" +
                 "_1grWDy_kFelXs3AQeiP13ay4eG_134dWB9XPRSeWsuPs8Mz2UY-VHDxLGD-fAqv-xKXr4QFEnS7iZkdpe0tPLNSwIjqeqkC6KqQln" +
                 "oC1okqWVWBDOcf7Acp1Jzp_cFTUhL5LkHvZDsyCdq5T9OOVVkzO4A9RrzIUsTrYPtRCBuYJ3ggR33cKpw191PulPGNH70rZqpUfDXe" +
                 "VPY3q15vWzZH9O9IJzB2KdHRMPxl2luRjzDbh4DLp56NhZuLX_2a9UAlmbV8MQX4Z_04ybhAYrcBfxR3MgJyr0jlxSibqSbXrkXuo-" +
                 "PyybfZCIhK_qXUlO5OS6sO7AQhKZO9p0MQ";
 
-        assertThatThrownBy(() -> sut.verify(tokenWithNullSubject))
-            .isInstanceOf(MalformedJwtException.class)
-            .hasMessage("'subject' field in token is mandatory");
+        assertThat(sut.verify(tokenWithNullSubject)).isFalse();
     }
     
     @Test
-    public void verifyShouldThrowWhenEmptySubject() {
+    public void verifyShouldReturnFalseWhenEmptySubject() {
         String tokenWithEmptySubject = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIiLCJuYW1lIjoiSm9obiBEb2UifQ.UdY" +
                 "s2PPzFCegUYspoDCnlJR_bJm8_z1InOv4v3tq8SJETQUarOXlhb_n6y6ujVvmJiSx9dI24Hc3Czi3RGUOXbnBDj1WPfd0aVSiUSqZr" +
                 "MCHBt5vjCYqAseDaP3w4aiiFb6EV3tteJFeBLZx8XlKPYxlzRLLUADDyDSQvrFBBPxfsvCETZovKdo9ofIN64o-yx23ss63yE6oIOd" +
                 "zJZ1Id40KSR2d7l3kIQJPLKUWJDnro5RAh4DOGOWNSq0JSbMhk7Zn3cXIBUpv3R8p79tui1UQpzwHMC0e6OSuWEDNQHtq-Cz85u8GG" +
                 "sUSbogmgObA_BimNtUq_Q1p0SGtIYBXmQ";
 
-        assertThatThrownBy(() -> sut.verify(tokenWithEmptySubject))
-            .isInstanceOf(MalformedJwtException.class)
-            .hasMessage("'subject' field in token is mandatory");
+
+        assertThat(sut.verify(tokenWithEmptySubject)).isFalse();
     }
 
     @Test
     public void shouldReturnUserLoginFromValidToken() {
+        assertThat(sut.extractLogin(VALID_TOKEN_WITHOUT_ADMIN)).isEqualTo("1234567890");
+    }
+
+    @Test
+    public void hasAttributeShouldReturnTrueIfClaimValid() throws Exception {
+        boolean authorized = sut.hasAttribute("admin", true, VALID_TOKEN_ADMIN_TRUE);
+
+        assertThat(authorized).isTrue();
+    }
+
+    @Test
+    public void extractLoginShouldWorkWithAdminClaim() {
+        assertThat(sut.extractLogin(VALID_TOKEN_ADMIN_TRUE)).isEqualTo("admin@open-paas.org");
+    }
+
+    @Test
+    public void hasAttributeShouldThrowIfClaimInvalid() throws Exception {
+        boolean authorized = sut.hasAttribute("admin", true, VALID_TOKEN_ADMIN_FALSE);
 
-        assertThat(sut.extractLogin(VALID_TOKEN)).isEqualTo("1234567890");
+        assertThat(authorized).isFalse();
     }
 
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/3d327f72/server/protocols/webadmin/pom.xml
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/pom.xml b/server/protocols/webadmin/pom.xml
index 8ae6689..da9d076 100644
--- a/server/protocols/webadmin/pom.xml
+++ b/server/protocols/webadmin/pom.xml
@@ -166,6 +166,10 @@
                 </dependency>
                 <dependency>
                     <groupId>org.apache.james</groupId>
+                    <artifactId>james-server-jwt</artifactId>
+                </dependency>
+                <dependency>
+                    <groupId>org.apache.james</groupId>
                     <artifactId>james-server-data-api</artifactId>
                 </dependency>
                 <dependency>

http://git-wip-us.apache.org/repos/asf/james-project/blob/3d327f72/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
index c1e1cad..7457219 100644
--- a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
+++ b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
@@ -28,6 +28,8 @@ import javax.inject.Inject;
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.commons.configuration.HierarchicalConfiguration;
 import org.apache.james.lifecycle.api.Configurable;
+import org.apache.james.webadmin.authentication.AuthenticationFilter;
+import org.apache.james.webadmin.authentication.NoAuthenticationFilter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -45,12 +47,14 @@ public class WebAdminServer implements Configurable {
     private final WebAdminConfiguration configuration;
     private final Set<Routes> routesList;
     private final Service service;
+    private final AuthenticationFilter authenticationFilter;
 
     // Spark do not allow to retrieve allocated port when using a random port. Thus we generate the port.
     @Inject
-    private WebAdminServer(WebAdminConfiguration configuration, Set<Routes> routesList) {
+    private WebAdminServer(WebAdminConfiguration configuration, Set<Routes> routesList, AuthenticationFilter authenticationFilter) {
         this.configuration = configuration;
         this.routesList = routesList;
+        this.authenticationFilter = authenticationFilter;
         this.service = Service.ignite();
     }
 
@@ -60,7 +64,8 @@ public class WebAdminServer implements Configurable {
             .enabled()
             .port(new RandomPort())
             .build(),
-            ImmutableSet.copyOf(routes));
+            ImmutableSet.copyOf(routes),
+            new NoAuthenticationFilter());
     }
 
     @Override
@@ -75,6 +80,7 @@ public class WebAdminServer implements Configurable {
                     httpsConfiguration.getTruststorePassword());
                 LOGGER.info("Web admin set up to use HTTPS");
             }
+            service.before(authenticationFilter);
             routesList.forEach(routes -> routes.define(service));
             LOGGER.info("Web admin server started");
         }

http://git-wip-us.apache.org/repos/asf/james-project/blob/3d327f72/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/authentication/AuthenticationFilter.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/authentication/AuthenticationFilter.java b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/authentication/AuthenticationFilter.java
new file mode 100644
index 0000000..f73b818
--- /dev/null
+++ b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/authentication/AuthenticationFilter.java
@@ -0,0 +1,25 @@
+/****************************************************************
+ * 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.authentication;
+
+import spark.Filter;
+
+public interface AuthenticationFilter extends Filter {
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/3d327f72/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/authentication/JwtFilter.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/authentication/JwtFilter.java b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/authentication/JwtFilter.java
new file mode 100644
index 0000000..991f412
--- /dev/null
+++ b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/authentication/JwtFilter.java
@@ -0,0 +1,73 @@
+/****************************************************************
+ * 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.authentication;
+
+import static spark.Spark.halt;
+
+import java.util.Optional;
+
+import javax.inject.Inject;
+
+import org.apache.james.jwt.JwtTokenVerifier;
+
+import spark.Request;
+import spark.Response;
+
+public class JwtFilter implements AuthenticationFilter {
+    public static final String AUTHORIZATION_HEADER_PREFIX = "Bearer ";
+    public static final String AUTHORIZATION_HEADER_NAME = "Authorization";
+
+    private final JwtTokenVerifier jwtTokenVerifier;
+
+    @Inject
+    public JwtFilter(JwtTokenVerifier jwtTokenVerifier) {
+        this.jwtTokenVerifier = jwtTokenVerifier;
+    }
+
+    @Override
+    public void handle(Request request, Response response) throws Exception {
+        Optional<String> bearer = Optional.ofNullable(request.headers(AUTHORIZATION_HEADER_NAME))
+            .filter(value -> value.startsWith(AUTHORIZATION_HEADER_PREFIX))
+            .map(value -> value.substring(AUTHORIZATION_HEADER_PREFIX.length()));
+
+        checkHeaderPresent(bearer);
+        checkValidSignature(bearer);
+        checkIsAdmin(bearer);
+    }
+
+    private void checkHeaderPresent(Optional<String> bearer) {
+        if (!bearer.isPresent()) {
+            halt(401, "No Bearer header.");
+        }
+    }
+
+    private void checkValidSignature(Optional<String> bearer) {
+        if (!jwtTokenVerifier.verify(bearer.get())) {
+            halt(401, "Invalid Bearer header.");
+        }
+    }
+
+    private void checkIsAdmin(Optional<String> bearer) {
+        if (!jwtTokenVerifier.hasAttribute("admin", true, bearer.get())) {
+            halt(401, "Non authorized user.");
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/3d327f72/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/authentication/NoAuthenticationFilter.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/authentication/NoAuthenticationFilter.java b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/authentication/NoAuthenticationFilter.java
new file mode 100644
index 0000000..45a2f5b
--- /dev/null
+++ b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/authentication/NoAuthenticationFilter.java
@@ -0,0 +1,31 @@
+/****************************************************************
+ * 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.authentication;
+
+import spark.Request;
+import spark.Response;
+
+public class NoAuthenticationFilter implements AuthenticationFilter {
+
+    @Override
+    public void handle(Request request, Response response) throws Exception {
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/3d327f72/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/authentication/JwtFilterTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/authentication/JwtFilterTest.java b/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/authentication/JwtFilterTest.java
new file mode 100644
index 0000000..6512ddb
--- /dev/null
+++ b/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/authentication/JwtFilterTest.java
@@ -0,0 +1,124 @@
+/****************************************************************
+ * 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.authentication;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.apache.james.jwt.JwtTokenVerifier;
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import com.google.common.collect.ImmutableSet;
+
+import spark.HaltException;
+import spark.Request;
+import spark.Response;
+
+public class JwtFilterTest {
+
+    public static final Matcher<HaltException> STATUS_CODE_MATCHER_401 = new BaseMatcher<HaltException>() {
+        @Override
+        public boolean matches(Object o) {
+            if (o instanceof HaltException) {
+                HaltException haltException = (HaltException) o;
+                return haltException.statusCode() == 401;
+            }
+            return false;
+        }
+
+        @Override
+        public void describeTo(Description description) {}
+    };
+
+    private JwtTokenVerifier jwtTokenVerifier;
+    private JwtFilter jwtFilter;
+
+    @Rule
+    public ExpectedException expectedException = ExpectedException.none();
+
+    @Before
+    public void setUp() {
+        jwtTokenVerifier = mock(JwtTokenVerifier.class);
+        jwtFilter = new JwtFilter(jwtTokenVerifier);
+    }
+
+    @Test
+    public void handleShouldRejectRequestWithHeaders() throws Exception {
+        Request request = mock(Request.class);
+        when(request.headers()).thenReturn(ImmutableSet.of());
+
+        expectedException.expect(HaltException.class);
+        expectedException.expect(STATUS_CODE_MATCHER_401);
+
+        jwtFilter.handle(request, mock(Response.class));
+    }
+
+    @Test
+    public void handleShouldRejectRequestWithBearersHeaders() throws Exception {
+        Request request = mock(Request.class);
+        when(request.headers(JwtFilter.AUTHORIZATION_HEADER_NAME)).thenReturn("Invalid value");
+
+        expectedException.expect(HaltException.class);
+        expectedException.expect(STATUS_CODE_MATCHER_401);
+
+        jwtFilter.handle(request, mock(Response.class));
+    }
+
+    @Test
+    public void handleShouldRejectRequestWithInvalidBearerHeaders() throws Exception {
+        Request request = mock(Request.class);
+        when(request.headers(JwtFilter.AUTHORIZATION_HEADER_NAME)).thenReturn("Bearer value");
+        when(jwtTokenVerifier.verify("value")).thenReturn(false);
+
+        expectedException.expect(HaltException.class);
+        expectedException.expect(STATUS_CODE_MATCHER_401);
+
+        jwtFilter.handle(request, mock(Response.class));
+    }
+
+    @Test
+    public void handleShouldRejectRequestWithoutAdminClaim() throws Exception {
+        Request request = mock(Request.class);
+        when(request.headers(JwtFilter.AUTHORIZATION_HEADER_NAME)).thenReturn("Bearer value");
+        when(jwtTokenVerifier.verify("value")).thenReturn(true);
+        when(jwtTokenVerifier.hasAttribute("admin", true, "value")).thenReturn(false);
+
+        expectedException.expect(HaltException.class);
+        expectedException.expect(STATUS_CODE_MATCHER_401);
+
+        jwtFilter.handle(request, mock(Response.class));
+    }
+
+    @Test
+    public void handleShouldAcceptValidJwt() throws Exception {
+        Request request = mock(Request.class);
+        when(request.headers(JwtFilter.AUTHORIZATION_HEADER_NAME)).thenReturn("Bearer value");
+        when(jwtTokenVerifier.verify("value")).thenReturn(true);
+        when(jwtTokenVerifier.hasAttribute("admin", true, "value")).thenReturn(true);
+
+        jwtFilter.handle(request, mock(Response.class));
+    }
+}


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


[10/22] james-project git commit: JAMES-1958 Enable HTTPS through configuration

Posted by bt...@apache.org.
JAMES-1958 Enable HTTPS through configuration


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

Branch: refs/heads/master
Commit: 3ac2368bf86ad6c607b6a31dc5eddf7ff160a197
Parents: ef84ed7
Author: benwa <bt...@linagora.com>
Authored: Wed Mar 8 16:26:19 2017 +0700
Committer: benwa <bt...@linagora.com>
Committed: Wed Mar 15 09:01:53 2017 +0700

----------------------------------------------------------------------
 .../destination/conf/webadmin.properties        | 13 +++++++++++-
 .../destination/conf/webadmin.properties        | 13 +++++++++++-
 .../modules/server/WebAdminServerModule.java    | 22 ++++++++++++++++++++
 .../apache/james/webadmin/WebAdminServer.java   |  8 +++++++
 4 files changed, 54 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/3ac2368b/dockerfiles/run/guice/cassandra-ldap/destination/conf/webadmin.properties
----------------------------------------------------------------------
diff --git a/dockerfiles/run/guice/cassandra-ldap/destination/conf/webadmin.properties b/dockerfiles/run/guice/cassandra-ldap/destination/conf/webadmin.properties
index 70a6cb9..3a1e755 100644
--- a/dockerfiles/run/guice/cassandra-ldap/destination/conf/webadmin.properties
+++ b/dockerfiles/run/guice/cassandra-ldap/destination/conf/webadmin.properties
@@ -19,4 +19,15 @@
 #  DO NOT USE IT AS SUCH AND ADAPT IT TO YOUR NEEDS
 
 enabled=true
-port=8000
\ No newline at end of file
+port=8000
+
+# Defaults to false
+https.enabled=false
+
+# Compulsory when enabling HTTPS
+#https.keystore=/path/to/keystore
+#https.password=password
+
+# Optional when enabling HTTPS (self signed)
+#https.trust.keystore
+#https.trust.password
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/3ac2368b/dockerfiles/run/guice/cassandra/destination/conf/webadmin.properties
----------------------------------------------------------------------
diff --git a/dockerfiles/run/guice/cassandra/destination/conf/webadmin.properties b/dockerfiles/run/guice/cassandra/destination/conf/webadmin.properties
index 70a6cb9..3a1e755 100644
--- a/dockerfiles/run/guice/cassandra/destination/conf/webadmin.properties
+++ b/dockerfiles/run/guice/cassandra/destination/conf/webadmin.properties
@@ -19,4 +19,15 @@
 #  DO NOT USE IT AS SUCH AND ADAPT IT TO YOUR NEEDS
 
 enabled=true
-port=8000
\ No newline at end of file
+port=8000
+
+# Defaults to false
+https.enabled=false
+
+# Compulsory when enabling HTTPS
+#https.keystore=/path/to/keystore
+#https.password=password
+
+# Optional when enabling HTTPS (self signed)
+#https.trust.keystore
+#https.trust.password
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/3ac2368b/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
----------------------------------------------------------------------
diff --git a/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java b/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
index 8495797..29c6223 100644
--- a/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
+++ b/server/container/guice/protocols/webadmin/src/main/java/org/apache/james/modules/server/WebAdminServerModule.java
@@ -32,6 +32,7 @@ import org.apache.james.utils.GuiceProbe;
 import org.apache.james.utils.PropertiesProvider;
 import org.apache.james.utils.WebAdminGuiceProbe;
 import org.apache.james.webadmin.FixedPort;
+import org.apache.james.webadmin.HttpsConfiguration;
 import org.apache.james.webadmin.Routes;
 import org.apache.james.webadmin.WebAdminConfiguration;
 import org.apache.james.webadmin.WebAdminServer;
@@ -72,6 +73,7 @@ public class WebAdminServerModule extends AbstractModule {
             return WebAdminConfiguration.builder()
                 .enable(configurationFile.getBoolean("enabled", false))
                 .port(new FixedPort(configurationFile.getInt("port", WebAdminServer.DEFAULT_PORT)))
+                .https(readHttpsConfiguration(configurationFile))
                 .build();
         } catch (FileNotFoundException e) {
             return WebAdminConfiguration.builder()
@@ -80,6 +82,26 @@ public class WebAdminServerModule extends AbstractModule {
         }
     }
 
+    private HttpsConfiguration readHttpsConfiguration(PropertiesConfiguration configurationFile) {
+        boolean enabled = configurationFile.getBoolean("https.enabled", DEFAULT_HTTPS_DISABLED());
+        if (enabled) {
+            return HttpsConfiguration.builder()
+                .enabled()
+                .raw(configurationFile.getString("https.keystore", null),
+                    configurationFile.getString("https.password", null),
+                    configurationFile.getString("https.trust.keystore", null),
+                    configurationFile.getString("https.trust.password", null))
+                .build();
+        }
+        return HttpsConfiguration.builder()
+            .disabled()
+            .build();
+    }
+
+    private boolean DEFAULT_HTTPS_DISABLED() {
+        return false;
+    }
+
     @Singleton
     public static class WebAdminServerModuleConfigurationPerformer implements ConfigurationPerformer {
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/3ac2368b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
index c70f318..c1e1cad 100644
--- a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
+++ b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminServer.java
@@ -67,6 +67,14 @@ public class WebAdminServer implements Configurable {
     public void configure(HierarchicalConfiguration config) throws ConfigurationException {
         if (configuration.isEnabled()) {
             service.port(configuration.getPort().toInt());
+            HttpsConfiguration httpsConfiguration = configuration.getHttpsConfiguration();
+            if (httpsConfiguration.isEnabled()) {
+                service.secure(httpsConfiguration.getKeystoreFilePath(),
+                    httpsConfiguration.getKeystorePassword(),
+                    httpsConfiguration.getTruststoreFilePath(),
+                    httpsConfiguration.getTruststorePassword());
+                LOGGER.info("Web admin set up to use HTTPS");
+            }
             routesList.forEach(routes -> routes.define(service));
             LOGGER.info("Web admin server started");
         }


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


[07/22] james-project git commit: JAMES-1958 Add a HttpsConfiguration

Posted by bt...@apache.org.
JAMES-1958 Add a HttpsConfiguration


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

Branch: refs/heads/master
Commit: ef84ed711275c5d7ecdab05fc2e54e5955381ca3
Parents: da41f83
Author: benwa <bt...@linagora.com>
Authored: Wed Mar 8 15:14:15 2017 +0700
Committer: benwa <bt...@linagora.com>
Committed: Wed Mar 15 09:01:53 2017 +0700

----------------------------------------------------------------------
 .../james/webadmin/HttpsConfiguration.java      | 148 +++++++++++++++++++
 .../james/webadmin/WebAdminConfiguration.java   |  21 ++-
 .../james/webadmin/HttpsConfigurationTest.java  | 101 +++++++++++++
 .../webadmin/WebAdminConfigurationTest.java     |  20 ++-
 4 files changed, 286 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/ef84ed71/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/HttpsConfiguration.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/HttpsConfiguration.java b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/HttpsConfiguration.java
new file mode 100644
index 0000000..3c6a49e
--- /dev/null
+++ b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/HttpsConfiguration.java
@@ -0,0 +1,148 @@
+/****************************************************************
+ * 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;
+
+import java.util.Objects;
+import java.util.Optional;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+
+public class HttpsConfiguration {
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    public static class Builder {
+        private Optional<Boolean> enabled = Optional.empty();
+        private String keystoreFilePath;
+        private String keystorePassword;
+        private String truststoreFilePath;
+        private String truststorePassword;
+
+        public Builder enable(boolean isEnabled) {
+            this.enabled = Optional.of(isEnabled);
+            return this;
+        }
+
+        public Builder enabled() {
+            return enable(true);
+        }
+
+        public Builder disabled() {
+            return enable(false);
+        }
+
+        public Builder raw(String keystoreFilePath,
+                           String keystorePassword,
+                           String truststoreFilePath,
+                           String truststorePassword){
+            Preconditions.checkNotNull(keystoreFilePath);
+            Preconditions.checkNotNull(keystorePassword);
+
+            this.keystoreFilePath = keystoreFilePath;
+            this.keystorePassword = keystorePassword;
+            this.truststoreFilePath = truststoreFilePath;
+            this.truststorePassword = truststorePassword;
+            return this;
+        }
+
+        public Builder selfSigned(String keystoreFilePath, String keystorePassword){
+            Preconditions.checkNotNull(keystoreFilePath);
+            Preconditions.checkNotNull(keystorePassword);
+
+            this.enabled = Optional.of(true);
+            this.keystoreFilePath = keystoreFilePath;
+            this.keystorePassword = keystorePassword;
+            return this;
+        }
+
+        public HttpsConfiguration build() {
+            Preconditions.checkState(enabled.isPresent(), "You need to specify if https is enabled");
+            Preconditions.checkState(!enabled.get() || hasKeystoreInformation(), "If enabled, you need to provide keystore information");
+            Preconditions.checkState(optionalHasTrustStoreInformation(), "You need to provide both information about trustStore");
+            return new HttpsConfiguration(enabled.get(), keystoreFilePath, keystorePassword, truststoreFilePath, truststorePassword);
+        }
+
+        private boolean optionalHasTrustStoreInformation() {
+            return (truststoreFilePath == null) == (truststorePassword == null);
+        }
+
+        private boolean hasKeystoreInformation() {
+            return keystorePassword != null && keystoreFilePath != null;
+        }
+
+    }
+
+    private final boolean enabled;
+    private final String keystoreFilePath;
+    private final String keystorePassword;
+    private final String truststoreFilePath;
+    private final String truststorePassword;
+
+    @VisibleForTesting
+    HttpsConfiguration(boolean enabled, String keystoreFilePath, String keystorePassword, String truststoreFilePath, String truststorePassword) {
+        this.enabled = enabled;
+        this.keystoreFilePath = keystoreFilePath;
+        this.keystorePassword = keystorePassword;
+        this.truststoreFilePath = truststoreFilePath;
+        this.truststorePassword = truststorePassword;
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public String getKeystoreFilePath() {
+        return keystoreFilePath;
+    }
+
+    public String getKeystorePassword() {
+        return keystorePassword;
+    }
+
+    public String getTruststoreFilePath() {
+        return truststoreFilePath;
+    }
+
+    public String getTruststorePassword() {
+        return truststorePassword;
+    }
+
+    @Override
+    public final boolean equals(Object o) {
+       if (o instanceof HttpsConfiguration) {
+           HttpsConfiguration that = (HttpsConfiguration) o;
+
+           return Objects.equals(this.enabled, that.enabled)
+               && Objects.equals(this.keystoreFilePath, that.keystoreFilePath)
+               && Objects.equals(this.keystorePassword, that.keystorePassword)
+               && Objects.equals(this.truststoreFilePath, that.truststoreFilePath)
+               && Objects.equals(this.truststorePassword, that.truststorePassword);
+       }
+       return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(enabled, keystoreFilePath, keystorePassword, truststoreFilePath, truststorePassword);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/ef84ed71/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
index b21749c..8cb022a 100644
--- a/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
+++ b/server/protocols/webadmin/src/main/java/org/apache/james/webadmin/WebAdminConfiguration.java
@@ -35,6 +35,12 @@ public class WebAdminConfiguration {
     public static class Builder {
         private Optional<Boolean> enabled = Optional.empty();
         private Port port;
+        private Optional<HttpsConfiguration> httpsConfiguration = Optional.empty();
+
+        public Builder https(HttpsConfiguration httpsConfiguration) {
+            this.httpsConfiguration = Optional.of(httpsConfiguration);
+            return this;
+        }
 
         public Builder port(Port port) {
             this.port = port;
@@ -57,17 +63,24 @@ public class WebAdminConfiguration {
         public WebAdminConfiguration build() {
             Preconditions.checkState(enabled.isPresent(), "You need to explicitly enable or disable WebAdmin server");
             Preconditions.checkState(!enabled.get() || port != null, "You need to specify a port for WebAdminConfiguration");
-            return new WebAdminConfiguration(enabled.get(), port);
+            return new WebAdminConfiguration(enabled.get(),
+                port,
+                httpsConfiguration.orElse(
+                    HttpsConfiguration.builder()
+                        .disabled()
+                        .build()));
         }
     }
 
     private final boolean enabled;
     private final Port port;
+    private final HttpsConfiguration httpsConfiguration;
 
     @VisibleForTesting
-    WebAdminConfiguration(boolean enabled, Port port) {
+    WebAdminConfiguration(boolean enabled, Port port, HttpsConfiguration httpsConfiguration) {
         this.enabled = enabled;
         this.port = port;
+        this.httpsConfiguration = httpsConfiguration;
     }
 
     public boolean isEnabled() {
@@ -78,6 +91,10 @@ public class WebAdminConfiguration {
         return port;
     }
 
+    public HttpsConfiguration getHttpsConfiguration() {
+        return httpsConfiguration;
+    }
+
     @Override
     public final boolean equals(Object o) {
         if (o instanceof WebAdminConfiguration) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/ef84ed71/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/HttpsConfigurationTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/HttpsConfigurationTest.java b/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/HttpsConfigurationTest.java
new file mode 100644
index 0000000..0d69cbe
--- /dev/null
+++ b/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/HttpsConfigurationTest.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.webadmin;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+
+public class HttpsConfigurationTest {
+
+    @Rule
+    public ExpectedException expectedException = ExpectedException.none();
+
+    @Test
+    public void buildShouldThrowWhenNotEnabled() {
+        expectedException.expect(IllegalStateException.class);
+
+        HttpsConfiguration.builder().build();
+    }
+
+    @Test
+    public void buildShouldThrowWhenEnableWithoutKeystore() {
+        expectedException.expect(IllegalStateException.class);
+
+        HttpsConfiguration.builder().enabled().build();
+    }
+
+    @Test
+    public void selfSignedShouldThrowOnNullKeyStorePath() {
+        expectedException.expect(NullPointerException.class);
+
+        HttpsConfiguration.builder()
+            .enabled()
+            .selfSigned(null, "abc");
+    }
+
+    @Test
+    public void selfSignedShouldThrowOnNullKeyStorePassword() {
+        expectedException.expect(NullPointerException.class);
+
+        HttpsConfiguration.builder()
+            .enabled()
+            .selfSigned("abc", null);
+    }
+
+    @Test
+    public void buildShouldWorkOnDisabledHttps() {
+        assertThat(
+            HttpsConfiguration.builder()
+                .disabled()
+                .build())
+            .isEqualTo(new HttpsConfiguration(false, null, null, null, null));
+    }
+
+    @Test
+    public void buildShouldWorkOnSelfSignedHttps() {
+        assertThat(
+            HttpsConfiguration.builder()
+                .enabled()
+                .selfSigned("abcd", "efgh")
+                .build())
+            .isEqualTo(new HttpsConfiguration(true, "abcd", "efgh", null, null));
+    }
+
+    @Test
+    public void buildShouldWorkOnTrustedHttps() {
+        assertThat(
+            HttpsConfiguration.builder()
+                .enabled()
+                .raw("a", "b", "c", "d")
+                .build())
+            .isEqualTo(new HttpsConfiguration(true, "a", "b", "c", "d"));
+    }
+
+    @Test
+    public void shouldRespectBeanContract() {
+        EqualsVerifier.forClass(HttpsConfiguration.class).verify();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/ef84ed71/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java
----------------------------------------------------------------------
diff --git a/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java b/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java
index 01f3c2a..d20100c 100644
--- a/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java
+++ b/server/protocols/webadmin/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java
@@ -46,7 +46,7 @@ public class WebAdminConfigurationTest {
         assertThat(WebAdminConfiguration.builder()
             .disabled()
             .build())
-            .isEqualTo(new WebAdminConfiguration(false, null));
+            .isEqualTo(new WebAdminConfiguration(false, null, HttpsConfiguration.builder().disabled().build()));
     }
 
     @Test
@@ -63,7 +63,23 @@ public class WebAdminConfigurationTest {
                 .enabled()
                 .port(PORT)
                 .build())
-            .isEqualTo(new WebAdminConfiguration(true, PORT));
+            .isEqualTo(new WebAdminConfiguration(true, PORT, HttpsConfiguration.builder().disabled().build()));
+    }
+
+    @Test
+    public void builderShouldAcceptHttps() {
+        HttpsConfiguration httpsConfiguration = HttpsConfiguration.builder()
+            .enable(true)
+            .selfSigned("abcd", "efgh")
+            .build();
+
+        assertThat(
+            WebAdminConfiguration.builder()
+                .enabled()
+                .https(httpsConfiguration)
+                .port(PORT)
+                .build())
+            .isEqualTo(new WebAdminConfiguration(true, PORT, httpsConfiguration));
     }
 
     @Test


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


[22/22] james-project git commit: JAMES-1950 Move TimeMetric inside the JamesSpoolerWorker service

Posted by bt...@apache.org.
JAMES-1950 Move TimeMetric inside the JamesSpoolerWorker service

Measuring time out of the worker service don't make sense. Even if we loose time for the DeQueue time.


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

Branch: refs/heads/master
Commit: a00d5e4fd18da4866606ff41fefe10e9d5336943
Parents: 33b74fb
Author: benwa <bt...@linagora.com>
Authored: Wed Mar 15 10:38:58 2017 +0700
Committer: benwa <bt...@linagora.com>
Committed: Wed Mar 15 16:57:31 2017 +0700

----------------------------------------------------------------------
 .../org/apache/james/mailetcontainer/impl/JamesMailSpooler.java | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/a00d5e4f/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/JamesMailSpooler.java
----------------------------------------------------------------------
diff --git a/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/JamesMailSpooler.java b/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/JamesMailSpooler.java
index 2875a00..896a7db 100644
--- a/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/JamesMailSpooler.java
+++ b/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/JamesMailSpooler.java
@@ -155,13 +155,13 @@ public class JamesMailSpooler implements Runnable, Disposable, Configurable, Log
         while (active.get()) {
 
             final MailQueueItem queueItem;
-            TimeMetric timeMetric = metricFactory.timer(SPOOL_PROCESSING);
             try {
                 queueItem = queue.deQueue();
                 workerService.execute(new Runnable() {
 
                     @Override
                     public void run() {
+                        TimeMetric timeMetric = metricFactory.timer(SPOOL_PROCESSING);
                         try {
                             numActive.incrementAndGet();
 
@@ -195,6 +195,7 @@ public class JamesMailSpooler implements Runnable, Disposable, Configurable, Log
                         } finally {
                             processingActive.decrementAndGet();
                             numActive.decrementAndGet();
+                            timeMetric.stopAndPublish();
                         }
 
                     }
@@ -206,8 +207,6 @@ public class JamesMailSpooler implements Runnable, Disposable, Configurable, Log
                 }
             } catch (InterruptedException interrupted) {
                 //MailSpooler is stopping
-            } finally {
-                timeMetric.stopAndPublish();
             }
         }
         logger.info("Stop {} : {}", getClass().getName(), Thread.currentThread().getName());


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