This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit bce3fb8b3f56e6900f007ef9f745049d49854071
Author: quanth <hqt...@linagora.com>
AuthorDate: Mon Nov 23 13:57:28 2020 +0700

    JAMES 3400 Add Jwt Option
---
 .../java/org/apache/james/cli/WebAdminCli.java     |  24 +++
 .../org/apache/james/cli/domain/DomainCommand.java |   5 +
 .../james/cli/domain/DomainCreateCommand.java      |   4 +-
 .../james/cli/domain/DomainDeleteCommand.java      |   4 +-
 .../james/cli/domain/DomainExistCommand.java       |   4 +-
 .../apache/james/cli/domain/DomainListCommand.java |   6 +-
 .../org/apache/james/cli/user/UserCommand.java     |   5 +
 .../apache/james/cli/user/UserCreateCommand.java   |   6 +-
 .../apache/james/cli/user/UserDeleteCommand.java   |   4 +-
 .../apache/james/cli/user/UserExistCommand.java    |   4 +-
 .../org/apache/james/cli/user/UserListCommand.java |   6 +-
 .../james/httpclient/FeignClientFactory.java       |  79 +++++++++
 .../UserCommand.java => httpclient/JwtToken.java}  |  46 ++----
 .../java/org/apache/james/cli/JwtOptionTest.java   | 178 +++++++++++++++++++++
 .../src/test/resources/valid_token_admin_false.jwt |   5 +
 .../src/test/resources/valid_token_admin_true.jwt  |   5 +
 16 files changed, 324 insertions(+), 61 deletions(-)

diff --git 
a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/WebAdminCli.java
 
b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/WebAdminCli.java
index 7efdebd..71d20bb 100644
--- 
a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/WebAdminCli.java
+++ 
b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/WebAdminCli.java
@@ -20,11 +20,17 @@
 package org.apache.james.cli;
 
 import java.io.PrintStream;
+import java.util.Optional;
 import java.util.concurrent.Callable;
 
 import org.apache.james.cli.domain.DomainCommand;
 import org.apache.james.cli.user.UserCommand;
+import org.apache.james.httpclient.FeignClientFactory;
+import org.apache.james.httpclient.JwtToken;
 
+import feign.Feign;
+import feign.jackson.JacksonDecoder;
+import feign.jackson.JacksonEncoder;
 import picocli.CommandLine;
 
 @CommandLine.Command(
@@ -41,6 +47,16 @@ public class WebAdminCli implements Callable<Integer> {
         defaultValue = "http://127.0.0.1:8000";)
     String jamesUrl;
 
+    public @CommandLine.Option(
+        names = "--jwt-token",
+        description = "Authentication Token")
+    String jwt;
+
+    public @CommandLine.Option(
+        names = "--jwt-from-file",
+        description = "Authentication Token from a file")
+    String jwtFilePath;
+
     @Override
     public Integer call() {
         return CLI_FINISHED_SUCCEED;
@@ -66,4 +82,12 @@ public class WebAdminCli implements Callable<Integer> {
         return execute(out, err, args);
     }
 
+    public Feign.Builder feignClientFactory(PrintStream err) {
+        return new FeignClientFactory(new JwtToken(Optional.ofNullable(jwt),
+            Optional.ofNullable(jwtFilePath), err))
+            .builder()
+            .decoder(new JacksonDecoder())
+            .encoder(new JacksonEncoder());
+    }
+
 }
\ No newline at end of file
diff --git 
a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/domain/DomainCommand.java
 
b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/domain/DomainCommand.java
index 209fb95..ec38083 100644
--- 
a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/domain/DomainCommand.java
+++ 
b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/domain/DomainCommand.java
@@ -23,6 +23,7 @@ import java.io.PrintStream;
 import java.util.concurrent.Callable;
 
 import org.apache.james.cli.WebAdminCli;
+import org.apache.james.httpclient.DomainClient;
 
 import picocli.CommandLine;
 
@@ -52,4 +53,8 @@ public class DomainCommand implements Callable<Integer> {
         return WebAdminCli.CLI_FINISHED_SUCCEED;
     }
 
+    public DomainClient fullyQualifiedURL(String partOfUrl) {
+        return webAdminCli.feignClientFactory(err).target(DomainClient.class, 
webAdminCli.jamesUrl + partOfUrl);
+    }
+
 }
\ No newline at end of file
diff --git 
a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/domain/DomainCreateCommand.java
 
b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/domain/DomainCreateCommand.java
index 5b75b00..af0b074 100644
--- 
a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/domain/DomainCreateCommand.java
+++ 
b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/domain/DomainCreateCommand.java
@@ -24,7 +24,6 @@ import java.util.concurrent.Callable;
 import org.apache.james.cli.WebAdminCli;
 import org.apache.james.httpclient.DomainClient;
 
-import feign.Feign;
 import feign.Response;
 import picocli.CommandLine;
 
@@ -43,8 +42,7 @@ public class DomainCreateCommand implements Callable<Integer> 
{
     @Override
     public Integer call() {
         try {
-            DomainClient domainClient = Feign.builder()
-                .target(DomainClient.class, domainCommand.webAdminCli.jamesUrl 
+ "/domains");
+            DomainClient domainClient = 
domainCommand.fullyQualifiedURL("/domains");
             Response rs = domainClient.createADomain(domainName);
             if (rs.status() == CREATED_CODE) {
                 return WebAdminCli.CLI_FINISHED_SUCCEED;
diff --git 
a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/domain/DomainDeleteCommand.java
 
b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/domain/DomainDeleteCommand.java
index 11853fd..af2115e 100644
--- 
a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/domain/DomainDeleteCommand.java
+++ 
b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/domain/DomainDeleteCommand.java
@@ -24,7 +24,6 @@ import java.util.concurrent.Callable;
 import org.apache.james.cli.WebAdminCli;
 import org.apache.james.httpclient.DomainClient;
 
-import feign.Feign;
 import feign.Response;
 import picocli.CommandLine;
 
@@ -43,8 +42,7 @@ public class DomainDeleteCommand implements Callable<Integer> 
{
     @Override
     public Integer call() {
         try {
-            DomainClient domainClient = Feign.builder()
-                .target(DomainClient.class, domainCommand.webAdminCli.jamesUrl 
+ "/domains");
+            DomainClient domainClient = 
domainCommand.fullyQualifiedURL("/domains");
             Response rs = domainClient.deleteADomain(domainName);
             if (rs.status() == DELETED_CODE) {
                 return WebAdminCli.CLI_FINISHED_SUCCEED;
diff --git 
a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/domain/DomainExistCommand.java
 
b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/domain/DomainExistCommand.java
index be39c31..094c16b 100644
--- 
a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/domain/DomainExistCommand.java
+++ 
b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/domain/DomainExistCommand.java
@@ -24,7 +24,6 @@ import java.util.concurrent.Callable;
 import org.apache.james.cli.WebAdminCli;
 import org.apache.james.httpclient.DomainClient;
 
-import feign.Feign;
 import feign.Response;
 import picocli.CommandLine;
 
@@ -44,8 +43,7 @@ public class DomainExistCommand implements Callable<Integer> {
     @Override
     public Integer call() {
         try {
-            DomainClient domainClient = Feign.builder()
-                .target(DomainClient.class, domainCommand.webAdminCli.jamesUrl 
+ "/domains");
+            DomainClient domainClient = 
domainCommand.fullyQualifiedURL("/domains");
             Response rs = domainClient.doesExist(domainName);
             if (rs.status() == EXISTED_CODE) {
                 domainCommand.out.println(domainName + " exists");
diff --git 
a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/domain/DomainListCommand.java
 
b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/domain/DomainListCommand.java
index ef4ab43..e8d00fd 100644
--- 
a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/domain/DomainListCommand.java
+++ 
b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/domain/DomainListCommand.java
@@ -24,8 +24,6 @@ import java.util.concurrent.Callable;
 import org.apache.james.cli.WebAdminCli;
 import org.apache.james.httpclient.DomainClient;
 
-import feign.Feign;
-import feign.jackson.JacksonDecoder;
 import picocli.CommandLine;
 
 @CommandLine.Command(
@@ -38,9 +36,7 @@ public class DomainListCommand implements Callable<Integer> {
     @Override
     public Integer call() {
         try {
-            DomainClient domainClient = Feign.builder()
-                    .decoder(new JacksonDecoder())
-                    .target(DomainClient.class, 
domainCommand.webAdminCli.jamesUrl + "/domains");
+            DomainClient domainClient = 
domainCommand.fullyQualifiedURL("/domains");
             domainClient.getDomainList().forEach(domainCommand.out::println);
             return WebAdminCli.CLI_FINISHED_SUCCEED;
         } catch (Exception e) {
diff --git 
a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/user/UserCommand.java
 
b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/user/UserCommand.java
index 6e27b3d..7d75f55 100644
--- 
a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/user/UserCommand.java
+++ 
b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/user/UserCommand.java
@@ -23,6 +23,7 @@ import java.io.PrintStream;
 import java.util.concurrent.Callable;
 
 import org.apache.james.cli.WebAdminCli;
+import org.apache.james.httpclient.UserClient;
 
 import picocli.CommandLine;
 
@@ -52,4 +53,8 @@ public class UserCommand implements Callable<Integer> {
         return WebAdminCli.CLI_FINISHED_SUCCEED;
     }
 
+    public UserClient fullyQualifiedURL(String partOfUrl) {
+        return webAdminCli.feignClientFactory(err).target(UserClient.class, 
webAdminCli.jamesUrl + partOfUrl);
+    }
+
 }
\ No newline at end of file
diff --git 
a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/user/UserCreateCommand.java
 
b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/user/UserCreateCommand.java
index 7c0cd52..f694ed3 100644
--- 
a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/user/UserCreateCommand.java
+++ 
b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/user/UserCreateCommand.java
@@ -25,9 +25,7 @@ import org.apache.james.cli.WebAdminCli;
 import org.apache.james.httpclient.UserClient;
 import org.apache.james.httpclient.model.UserPassword;
 
-import feign.Feign;
 import feign.Response;
-import feign.jackson.JacksonEncoder;
 import picocli.CommandLine;
 
 @CommandLine.Command(
@@ -49,9 +47,7 @@ public class UserCreateCommand implements Callable<Integer> {
     @Override
     public Integer call() {
         try {
-            UserClient userClient = Feign.builder()
-                .encoder(new JacksonEncoder())
-                .target(UserClient.class, userCommand.webAdminCli.jamesUrl + 
"/users");
+            UserClient userClient = userCommand.fullyQualifiedURL("/users");
             Response rs = userClient.createAUser(userName, new 
UserPassword(new String(password)));
             if (rs.status() == CREATED_CODE) {
                 userCommand.out.println("The user was created successfully");
diff --git 
a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/user/UserDeleteCommand.java
 
b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/user/UserDeleteCommand.java
index b5adab1..2578c01 100644
--- 
a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/user/UserDeleteCommand.java
+++ 
b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/user/UserDeleteCommand.java
@@ -24,7 +24,6 @@ import java.util.concurrent.Callable;
 import org.apache.james.cli.WebAdminCli;
 import org.apache.james.httpclient.UserClient;
 
-import feign.Feign;
 import feign.Response;
 import picocli.CommandLine;
 
@@ -42,8 +41,7 @@ public class UserDeleteCommand implements Callable<Integer> {
     @Override
     public Integer call() {
         try {
-            UserClient userClient = Feign.builder()
-                .target(UserClient.class, userCommand.webAdminCli.jamesUrl + 
"/users");
+            UserClient userClient = userCommand.fullyQualifiedURL("/users");
             Response rs = userClient.deleteAUser(userName);
             if (rs.status() == DELETED_CODE) {
                 return WebAdminCli.CLI_FINISHED_SUCCEED;
diff --git 
a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/user/UserExistCommand.java
 
b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/user/UserExistCommand.java
index 5d4b391..e7eb91f 100644
--- 
a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/user/UserExistCommand.java
+++ 
b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/user/UserExistCommand.java
@@ -24,7 +24,6 @@ import java.util.concurrent.Callable;
 import org.apache.james.cli.WebAdminCli;
 import org.apache.james.httpclient.UserClient;
 
-import feign.Feign;
 import feign.Response;
 import picocli.CommandLine;
 
@@ -44,8 +43,7 @@ public class UserExistCommand implements Callable<Integer> {
     @Override
     public Integer call() {
         try {
-            UserClient userClient = Feign.builder()
-                .target(UserClient.class, userCommand.webAdminCli.jamesUrl + 
"/users");
+            UserClient userClient = userCommand.fullyQualifiedURL("/users");
             Response rs = userClient.doesExist(userName);
             if (rs.status() == EXISTED_CODE) {
                 userCommand.out.println(userName + " exists");
diff --git 
a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/user/UserListCommand.java
 
b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/user/UserListCommand.java
index 9e2b0d7..3ad46e1 100644
--- 
a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/user/UserListCommand.java
+++ 
b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/user/UserListCommand.java
@@ -24,8 +24,6 @@ import java.util.concurrent.Callable;
 import org.apache.james.cli.WebAdminCli;
 import org.apache.james.httpclient.UserClient;
 
-import feign.Feign;
-import feign.jackson.JacksonDecoder;
 import picocli.CommandLine;
 
 @CommandLine.Command(
@@ -38,9 +36,7 @@ public class UserListCommand implements Callable<Integer> {
     @Override
     public Integer call() {
         try {
-            UserClient userClient = Feign.builder()
-                .decoder(new JacksonDecoder())
-                .target(UserClient.class, userCommand.webAdminCli.jamesUrl + 
"/users");
+            UserClient userClient = userCommand.fullyQualifiedURL("/users");
             userClient.getUserNameList().forEach(userName -> 
userCommand.out.println(userName.getUserName()));
             return WebAdminCli.CLI_FINISHED_SUCCEED;
         } catch (Exception e) {
diff --git 
a/server/protocols/webadmin-cli/src/main/java/org/apache/james/httpclient/FeignClientFactory.java
 
b/server/protocols/webadmin-cli/src/main/java/org/apache/james/httpclient/FeignClientFactory.java
new file mode 100644
index 0000000..9a80b26
--- /dev/null
+++ 
b/server/protocols/webadmin-cli/src/main/java/org/apache/james/httpclient/FeignClientFactory.java
@@ -0,0 +1,79 @@
+/******************************************************************
+ * 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.httpclient;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.Scanner;
+
+import feign.Feign;
+
+public class FeignClientFactory {
+
+    private final JwtToken jwtToken;
+
+    public FeignClientFactory(JwtToken jwtToken) {
+        this.jwtToken = jwtToken;
+    }
+
+    public Feign.Builder builder() {
+        return jwtOptionsHandler();
+    }
+
+    private Feign.Builder jwtOptionsHandler() {
+        return jwtToken.jwtTokenString
+            .map(tokenString -> jwtToken.jwtFilePath
+                .map(tokenFile -> jwtTokenAndJwtFileAreBothPresentHandler())
+                
.orElse(jwtTokenIsPresentAndJwtFromFileIsNotPresentHandler(tokenString)))
+            .orElse(jwtToken.jwtFilePath
+                .map(this::jwtTokenIsNotPresentAndJwtFromFileIsPresentHandler)
+                .orElse(jwtTokenAndJwtFromFileAreNotPresentHandler()));
+    }
+
+    private Feign.Builder jwtTokenAndJwtFileAreBothPresentHandler() {
+        jwtToken.err.println("Cannot specify both --jwt-from-file and 
--jwt-token options.");
+        return Feign.builder();
+    }
+
+    private Feign.Builder 
jwtTokenIsPresentAndJwtFromFileIsNotPresentHandler(String tokenString) {
+        return Feign.builder()
+            .requestInterceptor(requestTemplate -> 
requestTemplate.header("Authorization", "Bearer " + tokenString));
+    }
+
+    private Feign.Builder 
jwtTokenIsNotPresentAndJwtFromFileIsPresentHandler(String tokenFile) {
+        File myObj = new File(tokenFile);
+        try (Scanner myReader = new Scanner(myObj)) {
+            StringBuilder data = new StringBuilder();
+            while (myReader.hasNextLine()) {
+                data.append(myReader.nextLine());
+            }
+            return Feign.builder()
+                .requestInterceptor(requestTemplate -> 
requestTemplate.header("Authorization", "Bearer " + data.toString()));
+        } catch (FileNotFoundException e) {
+            e.printStackTrace(jwtToken.err);
+            return Feign.builder();
+        }
+    }
+
+    private Feign.Builder jwtTokenAndJwtFromFileAreNotPresentHandler() {
+        return Feign.builder();
+    }
+
+}
diff --git 
a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/user/UserCommand.java
 
b/server/protocols/webadmin-cli/src/main/java/org/apache/james/httpclient/JwtToken.java
similarity index 61%
copy from 
server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/user/UserCommand.java
copy to 
server/protocols/webadmin-cli/src/main/java/org/apache/james/httpclient/JwtToken.java
index 6e27b3d..ad23364 100644
--- 
a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/user/UserCommand.java
+++ 
b/server/protocols/webadmin-cli/src/main/java/org/apache/james/httpclient/JwtToken.java
@@ -17,39 +17,23 @@
  * under the License.                                             *
  ******************************************************************/
 
-package org.apache.james.cli.user;
+package org.apache.james.httpclient;
 
 import java.io.PrintStream;
-import java.util.concurrent.Callable;
-
-import org.apache.james.cli.WebAdminCli;
-
-import picocli.CommandLine;
-
-@CommandLine.Command(
-    name = "user",
-    description = "Manage Users",
-    subcommands = {
-        UserListCommand.class,
-        UserCreateCommand.class,
-        UserDeleteCommand.class,
-        UserExistCommand.class
-    })
-public class UserCommand implements Callable<Integer> {
-
-    protected final WebAdminCli webAdminCli;
-    protected final PrintStream out;
-    protected final PrintStream err;
-
-    public UserCommand(PrintStream out, WebAdminCli webAdminCli, PrintStream 
err) {
-        this.out = out;
-        this.webAdminCli = webAdminCli;
-        this.err = err;
-    }
+import java.util.Optional;
+
+public class JwtToken {
+
+    final Optional<String> jwtTokenString;
 
-    @Override
-    public Integer call() {
-        return WebAdminCli.CLI_FINISHED_SUCCEED;
+    final Optional<String> jwtFilePath;
+
+    PrintStream err;
+
+    public JwtToken(Optional<String> jwtTokenString, Optional<String> 
jwtFilePath, PrintStream err) {
+        this.jwtTokenString = jwtTokenString;
+        this.jwtFilePath = jwtFilePath;
+        this.err = err;
     }
 
-}
\ No newline at end of file
+}
diff --git 
a/server/protocols/webadmin-cli/src/test/java/org/apache/james/cli/JwtOptionTest.java
 
b/server/protocols/webadmin-cli/src/test/java/org/apache/james/cli/JwtOptionTest.java
new file mode 100644
index 0000000..65841d2
--- /dev/null
+++ 
b/server/protocols/webadmin-cli/src/test/java/org/apache/james/cli/JwtOptionTest.java
@@ -0,0 +1,178 @@
+/******************************************************************
+ * 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.cli;
+
+import static 
org.apache.james.MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_MODULE;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.Optional;
+
+import org.apache.james.GuiceJamesServer;
+import org.apache.james.JamesServerBuilder;
+import org.apache.james.JamesServerExtension;
+import org.apache.james.jwt.JwtConfiguration;
+import org.apache.james.jwt.JwtTokenVerifier;
+import org.apache.james.util.ClassLoaderUtils;
+import org.apache.james.util.Port;
+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.integration.WebadminIntegrationTestModule;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import com.google.inject.name.Names;
+
+public class JwtOptionTest {
+
+    @RegisterExtension
+    static JamesServerExtension jamesServerExtension = new 
JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
+        .server(configuration -> 
GuiceJamesServer.forConfiguration(configuration)
+            .combineWith(IN_MEMORY_SERVER_AGGREGATE_MODULE)
+            .overrideWith(new WebadminIntegrationTestModule())
+            .overrideWith(binder -> 
binder.bind(AuthenticationFilter.class).to(JwtFilter.class))
+            .overrideWith(binder -> binder.bind(JwtTokenVerifier.Factory.class)
+                .annotatedWith(Names.named("webadmin"))
+                .toInstance(() -> 
JwtTokenVerifier.create(jwtConfiguration()))))
+        .build();
+
+    protected static JwtConfiguration jwtConfiguration() {
+        return new JwtConfiguration(
+            
Optional.of(ClassLoaderUtils.getSystemResourceAsString("jwt_publickey")));
+    }
+
+    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 static final String PATH_OF_VALID_TOKEN_ADMIN_TRUE_FILE = 
"src/test/resources/valid_token_admin_true.jwt";
+    private static final String PATH_OF_VALID_TOKEN_ADMIN_FALSE_FILE = 
"src/test/resources/valid_token_admin_false.jwt";
+    private static final String PATH_OF_INVALID_JWT_FILE = 
"src/test/resources/keystore";
+
+    private final ByteArrayOutputStream outputStreamCaptor = new 
ByteArrayOutputStream();
+    private final ByteArrayOutputStream errorStreamCaptor = new 
ByteArrayOutputStream();
+
+    private DataProbeImpl dataProbe;
+
+    @Test
+    void 
jwtTokenWithAdminTrueAndNonPresentJwtFileShouldPassAuthentication(GuiceJamesServer
 server) throws Exception {
+        Port port = 
server.getProbe(WebAdminGuiceProbe.class).getWebAdminPort();
+        dataProbe = server.getProbe(DataProbeImpl.class);
+
+        int exitCode = WebAdminCli.executeFluent(new 
PrintStream(outputStreamCaptor), new PrintStream(errorStreamCaptor),
+            "--url", "http://127.0.0.1:"; + port.getValue(), "--jwt-token", 
VALID_TOKEN_ADMIN_TRUE, "domain", "create", "linagora.com");
+
+        assertThat(exitCode).isEqualTo(0);
+        assertThat(dataProbe.listDomains()).contains("linagora.com");
+    }
+
+    @Test
+    void 
jwtTokenWithAdminFalseAndNonPresentJwtFileShouldRejectRequests(GuiceJamesServer 
server) {
+        Port port = 
server.getProbe(WebAdminGuiceProbe.class).getWebAdminPort();
+        dataProbe = server.getProbe(DataProbeImpl.class);
+
+        int exitCode = WebAdminCli.executeFluent(new 
PrintStream(outputStreamCaptor), new PrintStream(errorStreamCaptor),
+            "--url", "http://127.0.0.1:"; + port.getValue(), "--jwt-token", 
VALID_TOKEN_ADMIN_FALSE, "domain", "create", "linagora.com");
+
+        assertThat(exitCode).isEqualTo(1);
+    }
+
+    @Test
+    void 
jwtFromFileWithAdminTrueAndNonPresentJwtTokenShouldPassAuthentication(GuiceJamesServer
 server) throws Exception {
+        Port port = 
server.getProbe(WebAdminGuiceProbe.class).getWebAdminPort();
+        dataProbe = server.getProbe(DataProbeImpl.class);
+
+        int exitCode = WebAdminCli.executeFluent(new 
PrintStream(outputStreamCaptor), new PrintStream(errorStreamCaptor),
+            "--url", "http://127.0.0.1:"; + port.getValue(), "--jwt-from-file", 
PATH_OF_VALID_TOKEN_ADMIN_TRUE_FILE, "domain", "create", "linagora.com");
+
+        assertThat(exitCode).isEqualTo(0);
+        assertThat(dataProbe.listDomains()).contains("linagora.com");
+    }
+
+    @Test
+    void 
jwtFromFileWithAdminFalseAndNonPresentJwtTokenShouldRejectRequests(GuiceJamesServer
 server) {
+        Port port = 
server.getProbe(WebAdminGuiceProbe.class).getWebAdminPort();
+        dataProbe = server.getProbe(DataProbeImpl.class);
+
+        int exitCode = WebAdminCli.executeFluent(new 
PrintStream(outputStreamCaptor), new PrintStream(errorStreamCaptor),
+            "--url", "http://127.0.0.1:"; + port.getValue(), "--jwt-from-file", 
PATH_OF_VALID_TOKEN_ADMIN_FALSE_FILE, "domain", "create", "linagora.com");
+
+        assertThat(exitCode).isEqualTo(1);
+    }
+
+    @Test
+    void 
jwtFromFileWithNonExistingFileShouldThrowFileNotFoundException(GuiceJamesServer 
server) {
+        Port port = 
server.getProbe(WebAdminGuiceProbe.class).getWebAdminPort();
+        dataProbe = server.getProbe(DataProbeImpl.class);
+
+        int exitCode = WebAdminCli.executeFluent(new 
PrintStream(outputStreamCaptor), new PrintStream(errorStreamCaptor),
+            "--url", "http://127.0.0.1:"; + port.getValue(), "--jwt-from-file", 
"", "domain", "create", "linagora.com");
+
+        assertThat(exitCode).isEqualTo(1);
+        
assertThat(errorStreamCaptor.toString()).contains("FileNotFoundException");
+    }
+
+    @Test
+    void jwtFromFileWithInvalidFileShouldRejectRequests(GuiceJamesServer 
server) {
+        Port port = 
server.getProbe(WebAdminGuiceProbe.class).getWebAdminPort();
+        dataProbe = server.getProbe(DataProbeImpl.class);
+
+        int exitCode = WebAdminCli.executeFluent(new 
PrintStream(outputStreamCaptor), new PrintStream(errorStreamCaptor),
+            "--url", "http://127.0.0.1:"; + port.getValue(), "--jwt-from-file", 
PATH_OF_INVALID_JWT_FILE, "domain", "create", "linagora.com");
+
+        assertThat(exitCode).isEqualTo(1);
+    }
+
+    @Test
+    void 
jwtTokenAndJwtFileAreBothPresentShouldFailAuthentication(GuiceJamesServer 
server) {
+        Port port = 
server.getProbe(WebAdminGuiceProbe.class).getWebAdminPort();
+        dataProbe = server.getProbe(DataProbeImpl.class);
+
+        int exitCode = WebAdminCli.executeFluent(new 
PrintStream(outputStreamCaptor), new PrintStream(errorStreamCaptor),
+            "--url", "http://127.0.0.1:"; + port.getValue(), "--jwt-from-file", 
PATH_OF_VALID_TOKEN_ADMIN_TRUE_FILE,
+            "--jwt-token", VALID_TOKEN_ADMIN_TRUE, "domain", "list");
+
+        assertThat(exitCode).isEqualTo(1);
+        assertThat(errorStreamCaptor.toString()).contains("Cannot specify both 
--jwt-from-file and --jwt-token options.");
+    }
+
+    @Test
+    void jwtTokenAndJwtFileAreNotPresentShouldRejectRequests(GuiceJamesServer 
server) {
+        Port port = 
server.getProbe(WebAdminGuiceProbe.class).getWebAdminPort();
+        dataProbe = server.getProbe(DataProbeImpl.class);
+
+        int exitCode = WebAdminCli.executeFluent(new 
PrintStream(outputStreamCaptor), new PrintStream(errorStreamCaptor),
+            "--url", "http://127.0.0.1:"; + port.getValue(), "domain", 
"create", "linagora.com");
+
+        assertThat(exitCode).isEqualTo(1);
+    }
+
+}
diff --git 
a/server/protocols/webadmin-cli/src/test/resources/valid_token_admin_false.jwt 
b/server/protocols/webadmin-cli/src/test/resources/valid_token_admin_false.jwt
new file mode 100644
index 0000000..2e1befa
--- /dev/null
+++ 
b/server/protocols/webadmin-cli/src/test/resources/valid_token_admin_false.jwt
@@ -0,0 +1,5 @@
+eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZG1pbkBvcGVu
+LXBhYXMub3JnIiwiYWRtaW4iOmZhbHNlLCJpYXQiOjE0ODkwNDA4Njd9.reQc3DiVvbQHF08oW1qOUyDJyv3tfzDNk8jhVZequiCdOI9vXnRlOe
+-yDYktd4WT8MYhqY7MgS-wR0vO9jZFv8ZCgd_MkKCvCO0HmMjP5iQPZ0kqGkgWUH7X123tfR38MfbCVAdPDba-K3MfkogV1xvDhlkPScFr_6MxE
+xtedOK2JnQZn7t9sUzSrcyjWverm7gZkPptkIVoS8TsEeMMME5vFXe_nqkEG69q3kuBUm_33tbR5oNS0ZGZKlG9r41lHBjyf9J1xN4UYV8n866d
+a7RPPCzshIWUtO0q9T2umWTnp-6OnOdBCkndrZmRR6pPxsD5YL0_77Wq8KT_5__fGA
\ No newline at end of file
diff --git 
a/server/protocols/webadmin-cli/src/test/resources/valid_token_admin_true.jwt 
b/server/protocols/webadmin-cli/src/test/resources/valid_token_admin_true.jwt
new file mode 100644
index 0000000..71a623e
--- /dev/null
+++ 
b/server/protocols/webadmin-cli/src/test/resources/valid_token_admin_true.jwt
@@ -0,0 +1,5 @@
+eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZG1pbkBvcGVuL
+XBhYXMub3JnIiwiYWRtaW4iOnRydWUsImlhdCI6MTQ4OTAzODQzOH0.rgxCkdWEa-92a4R-72a9Z49k4LRvQDShgci5Y7qWRUP9IGJCK-lMkrHF
+4H0a6L87BYppxVW701zaZ6dNxRMvHnjLBBWnPsC2B0rkkr2hEL2zfz7sb-iNGV-J4ICx97t8-TfQ5rz3VOX0FwdusPL_rJtmlGEGRivPkR6_aBe1
+kQnvMlwpqF_3ox58EUqYJk6lK_6rjKEV3Xfre31IMpuQUy6c7TKc95sL2-13cknelTierBEmZ00RzTtv9SHIEfzZTfaUK2Wm0PvnQjmU2nIdEvU
+EqE-jrM3yYXcQzoO-YTQnEhdl-iqbCfmEpYkl2Bx3eIq7gRxxnr7BPsX6HrCB0w
\ No newline at end of file


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

Reply via email to