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 rc...@apache.org on 2020/06/05 03:25:57 UTC

[james-project] branch master updated (5e5c80f -> 9239b2f)

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

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


    from 5e5c80f  [ADR] Enforce monotic ADR id increment
     new ceb6a95  JAMES-3200 Fix qcontent rule in MDN parser
     new e22e7c6  JAMES-3200 Fix obsQp rule in MDN parser
     new 84c3b34  JAMES-3198: Add detail message when error throw, add assert  in test
     new c396527  JAMES-3093 Add JWT Authentication, integration test for JMAP RFC 8621
     new 9239b2f  JAMES-3093 Organize AuthenticationContract and implementations

The 5 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../java/org/apache/james/mdn/MDNReportParser.java |  21 +-
 .../james/jmap/draft/DraftMethodsModule.java       |   2 +-
 .../james/jmap/rfc8621/RFC8621MethodsModule.java   |  10 +-
 .../apache/james/jmap/http/AuthenticatorTest.java  |   2 +-
 .../jmap/http/JWTAuthenticationStrategyTest.java   |   3 +-
 ...est.java => DistributedAuthenticationTest.java} |   3 +-
 .../distributed/DistributedEchoMethodTest.java     |   1 -
 .../rfc8621/contract/AuthenticationContract.scala  | 285 +++++++++++++--------
 .../james/jmap/rfc8621/contract/Fixture.scala      |  43 +++-
 .../rfc8621/memory/MemoryAuthenticationTest.java   |   2 +-
 server/protocols/jmap-rfc-8621/pom.xml             |   4 +
 server/protocols/jmap/pom.xml                      |  14 +-
 .../MailboxSessionCreationException.java           |   2 +-
 .../james/jmap/jwt}/JWTAuthenticationStrategy.java |  10 +-
 .../james/webadmin/routes/UserMailboxesRoutes.java |  14 +-
 .../webadmin/service/UserMailboxesService.java     |   2 +-
 .../webadmin/routes/UserMailboxesRoutesTest.java   | 277 ++++++++++----------
 17 files changed, 428 insertions(+), 267 deletions(-)
 rename server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/{DistributedBasicAuthenticationTest.java => DistributedAuthenticationTest.java} (95%)
 rename server/protocols/{jmap-draft/src/main/java/org/apache/james/jmap/draft => jmap/src/main/java/org/apache/james/jmap}/exceptions/MailboxSessionCreationException.java (96%)
 rename server/protocols/{jmap-draft/src/main/java/org/apache/james/jmap/http => jmap/src/main/java/org/apache/james/jmap/jwt}/JWTAuthenticationStrategy.java (88%)


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


[james-project] 03/05: JAMES-3198: Add detail message when error throw, add assert in test

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 84c3b34b7fada5061e168aed0c0d0d13314a324c
Author: duc91 <du...@gmail.com>
AuthorDate: Mon Jun 1 11:30:05 2020 +0700

    JAMES-3198: Add detail message when error throw, add assert  in test
---
 .../james/webadmin/routes/UserMailboxesRoutes.java |  14 +-
 .../webadmin/service/UserMailboxesService.java     |   2 +-
 .../webadmin/routes/UserMailboxesRoutesTest.java   | 277 +++++++++++----------
 3 files changed, 150 insertions(+), 143 deletions(-)

diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserMailboxesRoutes.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserMailboxesRoutes.java
index a18747d..781f6ed 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserMailboxesRoutes.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserMailboxesRoutes.java
@@ -150,7 +150,7 @@ public class UserMailboxesRoutes implements Routes {
                 LOGGER.info("Invalid get on user mailboxes", e);
                 throw ErrorResponder.builder()
                     .statusCode(HttpStatus.NOT_FOUND_404)
-                    .type(ErrorType.INVALID_ARGUMENT)
+                    .type(ErrorType.NOT_FOUND)
                     .message("Invalid get on user mailboxes")
                     .cause(e)
                     .haltError();
@@ -206,7 +206,7 @@ public class UserMailboxesRoutes implements Routes {
                 LOGGER.info("Invalid delete on user mailbox", e);
                 throw ErrorResponder.builder()
                     .statusCode(HttpStatus.NOT_FOUND_404)
-                    .type(ErrorType.INVALID_ARGUMENT)
+                    .type(ErrorType.NOT_FOUND)
                     .message("Invalid delete on user mailboxes")
                     .cause(e)
                     .haltError();
@@ -250,7 +250,7 @@ public class UserMailboxesRoutes implements Routes {
                 LOGGER.info("Invalid delete on user mailboxes", e);
                 throw ErrorResponder.builder()
                     .statusCode(HttpStatus.NOT_FOUND_404)
-                    .type(ErrorType.INVALID_ARGUMENT)
+                    .type(ErrorType.NOT_FOUND)
                     .message("Invalid delete on user mailboxes")
                     .cause(e)
                     .haltError();
@@ -280,15 +280,15 @@ public class UserMailboxesRoutes implements Routes {
                 } else {
                     throw ErrorResponder.builder()
                         .statusCode(HttpStatus.NOT_FOUND_404)
-                        .type(ErrorType.INVALID_ARGUMENT)
-                        .message("Invalid get on user mailboxes")
+                        .type(ErrorType.NOT_FOUND)
+                        .message("Mailbox does not exist")
                         .haltError();
                 }
             } catch (IllegalStateException e) {
                 LOGGER.info("Invalid get on user mailbox", e);
                 throw ErrorResponder.builder()
                     .statusCode(HttpStatus.NOT_FOUND_404)
-                    .type(ErrorType.INVALID_ARGUMENT)
+                    .type(ErrorType.NOT_FOUND)
                     .message("Invalid get on user mailboxes")
                     .cause(e)
                     .haltError();
@@ -327,7 +327,7 @@ public class UserMailboxesRoutes implements Routes {
                 LOGGER.info("Invalid put on user mailbox", e);
                 throw ErrorResponder.builder()
                     .statusCode(HttpStatus.NOT_FOUND_404)
-                    .type(ErrorType.INVALID_ARGUMENT)
+                    .type(ErrorType.NOT_FOUND)
                     .message("Invalid get on user mailboxes")
                     .cause(e)
                     .haltError();
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/UserMailboxesService.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/UserMailboxesService.java
index 8f4e8e7..8f78beb 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/UserMailboxesService.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/service/UserMailboxesService.java
@@ -121,7 +121,7 @@ public class UserMailboxesService {
     }
 
     private void usernamePreconditions(Username username) throws UsersRepositoryException {
-        Preconditions.checkState(usersRepository.contains(username));
+        Preconditions.checkState(usersRepository.contains(username), "User does not exist");
     }
 
     private Stream<MailboxMetaData> listUserMailboxes(MailboxSession mailboxSession) throws MailboxException {
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java
index 35f8374..6d0e299 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java
@@ -22,9 +22,15 @@ package org.apache.james.webadmin.routes;
 import static io.restassured.RestAssured.given;
 import static io.restassured.RestAssured.when;
 import static io.restassured.RestAssured.with;
+import static io.restassured.http.ContentType.JSON;
 import static org.apache.james.webadmin.Constants.SEPARATOR;
 import static org.apache.james.webadmin.routes.UserMailboxesRoutes.USERS_BASE;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.eclipse.jetty.http.HttpStatus.BAD_REQUEST_400;
+import static org.eclipse.jetty.http.HttpStatus.INTERNAL_SERVER_ERROR_500;
+import static org.eclipse.jetty.http.HttpStatus.NOT_FOUND_404;
+import static org.eclipse.jetty.http.HttpStatus.NO_CONTENT_204;
+import static org.eclipse.jetty.http.HttpStatus.OK_200;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.Matchers.notNullValue;
 import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
@@ -66,12 +72,10 @@ import org.apache.james.user.api.UsersRepository;
 import org.apache.james.webadmin.WebAdminServer;
 import org.apache.james.webadmin.WebAdminUtils;
 import org.apache.james.webadmin.service.UserMailboxesService;
-import org.apache.james.webadmin.utils.ErrorResponder;
 import org.apache.james.webadmin.utils.JsonTransformer;
 import org.apache.mailbox.tools.indexer.ReIndexerImpl;
 import org.apache.mailbox.tools.indexer.ReIndexerPerformer;
 import org.apache.mailbox.tools.indexer.UserReindexingTask;
-import org.eclipse.jetty.http.HttpStatus;
 import org.hamcrest.Matchers;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
@@ -84,7 +88,6 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 
 import io.restassured.RestAssured;
-import io.restassured.http.ContentType;
 import reactor.core.publisher.Mono;
 
 class UserMailboxesRoutesTest {
@@ -93,7 +96,8 @@ class UserMailboxesRoutesTest {
     private static final String MAILBOX_NAME_WITH_DOTS = "my..MailboxName";
     private static final String INVALID_MAILBOX_NAME = "myMailboxName#";
     private static final MailboxPath INBOX = MailboxPath.inbox(USERNAME);
-
+    private static final String ERROR_TYPE_NOTFOUND = "notFound";
+    
     private WebAdminServer webAdminServer;
     private UsersRepository usersRepository;
     private ListeningMessageSearchIndex searchIndex;
@@ -151,16 +155,16 @@ class UserMailboxesRoutesTest {
             Map<String, Object> errors = when()
                 .get()
             .then()
-                .statusCode(HttpStatus.NOT_FOUND_404)
-                .contentType(ContentType.JSON)
+                .statusCode(NOT_FOUND_404)
+                .contentType(JSON)
                 .extract()
                 .body()
                 .jsonPath()
                 .getMap(".");
 
             assertThat(errors)
-                .containsEntry("statusCode", HttpStatus.NOT_FOUND_404)
-                .containsEntry("type", "InvalidArgument")
+                .containsEntry("statusCode", NOT_FOUND_404)
+                .containsEntry("type", ERROR_TYPE_NOTFOUND)
                 .containsEntry("message", "Invalid get on user mailboxes");
         }
 
@@ -171,17 +175,18 @@ class UserMailboxesRoutesTest {
             Map<String, Object> errors = when()
                 .get(MAILBOX_NAME)
             .then()
-                .statusCode(HttpStatus.NOT_FOUND_404)
-                .contentType(ContentType.JSON)
+                .statusCode(NOT_FOUND_404)
+                .contentType(JSON)
                 .extract()
                 .body()
                 .jsonPath()
                 .getMap(".");
 
             assertThat(errors)
-                .containsEntry("statusCode", HttpStatus.NOT_FOUND_404)
-                .containsEntry("type", "InvalidArgument")
-                .containsEntry("message", "Invalid get on user mailboxes");
+                .containsEntry("statusCode", NOT_FOUND_404)
+                .containsEntry("type", ERROR_TYPE_NOTFOUND)
+                .containsEntry("message", "Invalid get on user mailboxes")
+                .containsEntry("details", "User does not exist");
         }
 
         @Test
@@ -191,17 +196,18 @@ class UserMailboxesRoutesTest {
             Map<String, Object> errors = when()
                 .put(MAILBOX_NAME)
             .then()
-                .statusCode(HttpStatus.NOT_FOUND_404)
-                .contentType(ContentType.JSON)
+                .statusCode(NOT_FOUND_404)
+                .contentType(JSON)
                 .extract()
                 .body()
                 .jsonPath()
                 .getMap(".");
 
             assertThat(errors)
-                .containsEntry("statusCode", HttpStatus.NOT_FOUND_404)
-                .containsEntry("type", "InvalidArgument")
-                .containsEntry("message", "Invalid get on user mailboxes");
+                .containsEntry("statusCode", NOT_FOUND_404)
+                .containsEntry("type", ERROR_TYPE_NOTFOUND)
+                .containsEntry("message", "Invalid get on user mailboxes")
+                .containsEntry("details", "User does not exist");
         }
 
         @Test
@@ -209,15 +215,15 @@ class UserMailboxesRoutesTest {
             Map<String, Object> errors = when()
                 .put(MAILBOX_NAME_WITH_DOTS)
             .then()
-                .statusCode(HttpStatus.BAD_REQUEST_400)
-                .contentType(ContentType.JSON)
+                .statusCode(BAD_REQUEST_400)
+                .contentType(JSON)
                 .extract()
                 .body()
                 .jsonPath()
                 .getMap(".");
 
             assertThat(errors)
-                .containsEntry("statusCode", HttpStatus.BAD_REQUEST_400)
+                .containsEntry("statusCode", BAD_REQUEST_400)
                 .containsEntry("type", "InvalidArgument")
                 .containsEntry("message", "Attempt to create an invalid mailbox")
                 .containsEntry("details", "'#private:username:my..MailboxName' has an empty part within its mailbox name considering . as a delimiter");
@@ -228,15 +234,15 @@ class UserMailboxesRoutesTest {
             Map<String, Object> errors = when()
                 .put(".startWithDot")
             .then()
-                .statusCode(HttpStatus.BAD_REQUEST_400)
-                .contentType(ContentType.JSON)
+                .statusCode(BAD_REQUEST_400)
+                .contentType(JSON)
                 .extract()
                 .body()
                 .jsonPath()
                 .getMap(".");
 
             assertThat(errors)
-                .containsEntry("statusCode", HttpStatus.BAD_REQUEST_400)
+                .containsEntry("statusCode", BAD_REQUEST_400)
                 .containsEntry("type", "InvalidArgument")
                 .containsEntry("message", "Attempt to create an invalid mailbox")
                 .containsEntry("details", "'#private:username:.startWithDot' has an empty part within its mailbox name considering . as a delimiter");
@@ -247,15 +253,15 @@ class UserMailboxesRoutesTest {
             Map<String, Object> errors = when()
                 .put("endWithDot.")
             .then()
-                .statusCode(HttpStatus.BAD_REQUEST_400)
-                .contentType(ContentType.JSON)
+                .statusCode(BAD_REQUEST_400)
+                .contentType(JSON)
                 .extract()
                 .body()
                 .jsonPath()
                 .getMap(".");
 
             assertThat(errors)
-                .containsEntry("statusCode", HttpStatus.BAD_REQUEST_400)
+                .containsEntry("statusCode", BAD_REQUEST_400)
                 .containsEntry("type", "InvalidArgument")
                 .containsEntry("message", "Attempt to create an invalid mailbox")
                 .containsEntry("details", "'#private:username:endWithDot.' has an empty part within its mailbox name considering . as a delimiter");
@@ -268,15 +274,15 @@ class UserMailboxesRoutesTest {
             Map<String, Object> errors = when()
                 .put(INVALID_MAILBOX_NAME)
             .then()
-                .statusCode(HttpStatus.BAD_REQUEST_400)
-                .contentType(ContentType.JSON)
+                .statusCode(BAD_REQUEST_400)
+                .contentType(JSON)
                 .extract()
                 .body()
                 .jsonPath()
                 .getMap(".");
 
             assertThat(errors)
-                .containsEntry("statusCode", HttpStatus.BAD_REQUEST_400)
+                .containsEntry("statusCode", BAD_REQUEST_400)
                 .containsEntry("type", "InvalidArgument")
                 .containsEntry("message", "Attempt to create an invalid mailbox")
                 .containsEntry("details", "#private:username:myMailboxName# contains one of the forbidden characters %*&#");
@@ -289,17 +295,18 @@ class UserMailboxesRoutesTest {
             Map<String, Object> errors = when()
                 .put(MAILBOX_NAME)
             .then()
-                .statusCode(HttpStatus.NOT_FOUND_404)
-                .contentType(ContentType.JSON)
+                .statusCode(NOT_FOUND_404)
+                .contentType(JSON)
                 .extract()
                 .body()
                 .jsonPath()
                 .getMap(".");
 
             assertThat(errors)
-                .containsEntry("statusCode", HttpStatus.NOT_FOUND_404)
-                .containsEntry("type", "InvalidArgument")
-                .containsEntry("message", "Invalid get on user mailboxes");
+                .containsEntry("statusCode", NOT_FOUND_404)
+                .containsEntry("type", ERROR_TYPE_NOTFOUND)
+                .containsEntry("message", "Invalid get on user mailboxes")
+                .containsEntry("details", "User does not exist");
         }
 
         @Test
@@ -307,15 +314,15 @@ class UserMailboxesRoutesTest {
             Map<String, Object> errors = when()
                 .get(MAILBOX_NAME + "*")
             .then()
-                .statusCode(HttpStatus.BAD_REQUEST_400)
-                .contentType(ContentType.JSON)
+                .statusCode(BAD_REQUEST_400)
+                .contentType(JSON)
                 .extract()
                 .body()
                 .jsonPath()
                 .getMap(".");
 
             assertThat(errors)
-                .containsEntry("statusCode", HttpStatus.BAD_REQUEST_400)
+                .containsEntry("statusCode", BAD_REQUEST_400)
                 .containsEntry("type", "InvalidArgument")
                 .containsEntry("message", "Attempt to test existence of an invalid mailbox")
                 .containsEntry("details", "#private:username:myMailboxName* contains one of the forbidden characters %*&#");
@@ -326,15 +333,15 @@ class UserMailboxesRoutesTest {
             Map<String, Object> errors = when()
                 .put(MAILBOX_NAME + "*")
             .then()
-                .statusCode(HttpStatus.BAD_REQUEST_400)
-                .contentType(ContentType.JSON)
+                .statusCode(BAD_REQUEST_400)
+                .contentType(JSON)
                 .extract()
                 .body()
                 .jsonPath()
                 .getMap(".");
 
             assertThat(errors)
-                .containsEntry("statusCode", HttpStatus.BAD_REQUEST_400)
+                .containsEntry("statusCode", BAD_REQUEST_400)
                 .containsEntry("type", "InvalidArgument")
                 .containsEntry("message", "Attempt to create an invalid mailbox");
         }
@@ -344,15 +351,15 @@ class UserMailboxesRoutesTest {
             Map<String, Object> errors = when()
                 .put(MAILBOX_NAME + "*")
             .then()
-                .statusCode(HttpStatus.BAD_REQUEST_400)
-                .contentType(ContentType.JSON)
+                .statusCode(BAD_REQUEST_400)
+                .contentType(JSON)
                 .extract()
                 .body()
                 .jsonPath()
                 .getMap(".");
 
             assertThat(errors)
-                .containsEntry("statusCode", HttpStatus.BAD_REQUEST_400)
+                .containsEntry("statusCode", BAD_REQUEST_400)
                 .containsEntry("type", "InvalidArgument")
                 .containsEntry("message", "Attempt to create an invalid mailbox");
         }
@@ -362,15 +369,15 @@ class UserMailboxesRoutesTest {
             Map<String, Object> errors = when()
                 .get(MAILBOX_NAME + "%")
             .then()
-                .statusCode(HttpStatus.BAD_REQUEST_400)
-                .contentType(ContentType.JSON)
+                .statusCode(BAD_REQUEST_400)
+                .contentType(JSON)
                 .extract()
                 .body()
                 .jsonPath()
                 .getMap(".");
 
             assertThat(errors)
-                .containsEntry("statusCode", HttpStatus.BAD_REQUEST_400)
+                .containsEntry("statusCode", BAD_REQUEST_400)
                 .containsEntry("type", "InvalidArgument")
                 .containsEntry("message", "Attempt to test existence of an invalid mailbox")
                 .containsEntry("details", "#private:username:myMailboxName% contains one of the forbidden characters %*&#");
@@ -381,15 +388,15 @@ class UserMailboxesRoutesTest {
             Map<String, Object> errors = when()
                 .put(MAILBOX_NAME + "%")
             .then()
-                .statusCode(HttpStatus.BAD_REQUEST_400)
-                .contentType(ContentType.JSON)
+                .statusCode(BAD_REQUEST_400)
+                .contentType(JSON)
                 .extract()
                 .body()
                 .jsonPath()
                 .getMap(".");
 
             assertThat(errors)
-                .containsEntry("statusCode", HttpStatus.BAD_REQUEST_400)
+                .containsEntry("statusCode", BAD_REQUEST_400)
                 .containsEntry("type", "InvalidArgument")
                 .containsEntry("message", "Attempt to create an invalid mailbox");
         }
@@ -399,15 +406,15 @@ class UserMailboxesRoutesTest {
             Map<String, Object> errors = when()
                 .put(MAILBOX_NAME + "%")
             .then()
-                .statusCode(HttpStatus.BAD_REQUEST_400)
-                .contentType(ContentType.JSON)
+                .statusCode(BAD_REQUEST_400)
+                .contentType(JSON)
                 .extract()
                 .body()
                 .jsonPath()
                 .getMap(".");
 
             assertThat(errors)
-                .containsEntry("statusCode", HttpStatus.BAD_REQUEST_400)
+                .containsEntry("statusCode", BAD_REQUEST_400)
                 .containsEntry("type", "InvalidArgument")
                 .containsEntry("message", "Attempt to create an invalid mailbox");
         }
@@ -417,15 +424,15 @@ class UserMailboxesRoutesTest {
             Map<String, Object> errors = when()
                 .get(MAILBOX_NAME + "#")
             .then()
-                .statusCode(HttpStatus.BAD_REQUEST_400)
-                .contentType(ContentType.JSON)
+                .statusCode(BAD_REQUEST_400)
+                .contentType(JSON)
                 .extract()
                 .body()
                 .jsonPath()
                 .getMap(".");
 
             assertThat(errors)
-                .containsEntry("statusCode", HttpStatus.BAD_REQUEST_400)
+                .containsEntry("statusCode", BAD_REQUEST_400)
                 .containsEntry("type", "InvalidArgument")
                 .containsEntry("message", "Attempt to test existence of an invalid mailbox")
                 .containsEntry("details", "#private:username:myMailboxName# contains one of the forbidden characters %*&#");
@@ -436,15 +443,15 @@ class UserMailboxesRoutesTest {
             Map<String, Object> errors = when()
                 .put(MAILBOX_NAME + "#")
             .then()
-                .statusCode(HttpStatus.BAD_REQUEST_400)
-                .contentType(ContentType.JSON)
+                .statusCode(BAD_REQUEST_400)
+                .contentType(JSON)
                 .extract()
                 .body()
                 .jsonPath()
                 .getMap(".");
 
             assertThat(errors)
-                .containsEntry("statusCode", HttpStatus.BAD_REQUEST_400)
+                .containsEntry("statusCode", BAD_REQUEST_400)
                 .containsEntry("type", "InvalidArgument")
                 .containsEntry("message", "Attempt to create an invalid mailbox");
         }
@@ -454,15 +461,15 @@ class UserMailboxesRoutesTest {
             Map<String, Object> errors = when()
                 .put(MAILBOX_NAME + "#")
             .then()
-                .statusCode(HttpStatus.BAD_REQUEST_400)
-                .contentType(ContentType.JSON)
+                .statusCode(BAD_REQUEST_400)
+                .contentType(JSON)
                 .extract()
                 .body()
                 .jsonPath()
                 .getMap(".");
 
             assertThat(errors)
-                .containsEntry("statusCode", HttpStatus.BAD_REQUEST_400)
+                .containsEntry("statusCode", BAD_REQUEST_400)
                 .containsEntry("type", "InvalidArgument")
                 .containsEntry("message", "Attempt to create an invalid mailbox");
         }
@@ -472,15 +479,15 @@ class UserMailboxesRoutesTest {
             Map<String, Object> errors = when()
                 .get(MAILBOX_NAME + "&")
             .then()
-                .statusCode(HttpStatus.BAD_REQUEST_400)
-                .contentType(ContentType.JSON)
+                .statusCode(BAD_REQUEST_400)
+                .contentType(JSON)
                 .extract()
                 .body()
                 .jsonPath()
                 .getMap(".");
 
             assertThat(errors)
-                .containsEntry("statusCode", HttpStatus.BAD_REQUEST_400)
+                .containsEntry("statusCode", BAD_REQUEST_400)
                 .containsEntry("type", "InvalidArgument")
                 .containsEntry("message", "Attempt to test existence of an invalid mailbox")
                 .containsEntry("details", "#private:username:myMailboxName& contains one of the forbidden characters %*&#");
@@ -491,15 +498,15 @@ class UserMailboxesRoutesTest {
             Map<String, Object> errors = when()
                 .put(MAILBOX_NAME + "&")
             .then()
-                .statusCode(HttpStatus.BAD_REQUEST_400)
-                .contentType(ContentType.JSON)
+                .statusCode(BAD_REQUEST_400)
+                .contentType(JSON)
                 .extract()
                 .body()
                 .jsonPath()
                 .getMap(".");
 
             assertThat(errors)
-                .containsEntry("statusCode", HttpStatus.BAD_REQUEST_400)
+                .containsEntry("statusCode", BAD_REQUEST_400)
                 .containsEntry("type", "InvalidArgument")
                 .containsEntry("message", "Attempt to create an invalid mailbox");
         }
@@ -509,15 +516,15 @@ class UserMailboxesRoutesTest {
             Map<String, Object> errors = when()
                 .put(MAILBOX_NAME + "&")
             .then()
-                .statusCode(HttpStatus.BAD_REQUEST_400)
-                .contentType(ContentType.JSON)
+                .statusCode(BAD_REQUEST_400)
+                .contentType(JSON)
                 .extract()
                 .body()
                 .jsonPath()
                 .getMap(".");
 
             assertThat(errors)
-                .containsEntry("statusCode", HttpStatus.BAD_REQUEST_400)
+                .containsEntry("statusCode", BAD_REQUEST_400)
                 .containsEntry("type", "InvalidArgument")
                 .containsEntry("message", "Attempt to create an invalid mailbox");
         }
@@ -529,16 +536,16 @@ class UserMailboxesRoutesTest {
             Map<String, Object> errors = when()
                 .delete()
             .then()
-                .statusCode(HttpStatus.NOT_FOUND_404)
-                .contentType(ContentType.JSON)
+                .statusCode(NOT_FOUND_404)
+                .contentType(JSON)
                 .extract()
                 .body()
                 .jsonPath()
                 .getMap(".");
 
             assertThat(errors)
-                .containsEntry("statusCode", HttpStatus.NOT_FOUND_404)
-                .containsEntry("type", "InvalidArgument")
+                .containsEntry("statusCode", NOT_FOUND_404)
+                .containsEntry("type", ERROR_TYPE_NOTFOUND)
                 .containsEntry("message", "Invalid delete on user mailboxes");
         }
 
@@ -548,8 +555,8 @@ class UserMailboxesRoutesTest {
                 when()
                     .get()
                 .then()
-                    .statusCode(HttpStatus.OK_200)
-                    .contentType(ContentType.JSON)
+                    .statusCode(OK_200)
+                    .contentType(JSON)
                     .extract()
                     .body()
                     .jsonPath()
@@ -563,7 +570,7 @@ class UserMailboxesRoutesTest {
             when()
                 .put()
             .then()
-                .statusCode(HttpStatus.NOT_FOUND_404);
+                .statusCode(NOT_FOUND_404);
         }
 
         @Test
@@ -571,7 +578,7 @@ class UserMailboxesRoutesTest {
             when()
                 .put(SEPARATOR)
             .then()
-                .statusCode(HttpStatus.NOT_FOUND_404);
+                .statusCode(NOT_FOUND_404);
         }
 
         @Test
@@ -579,7 +586,7 @@ class UserMailboxesRoutesTest {
             when()
                 .put(MAILBOX_NAME)
             .then()
-                .statusCode(HttpStatus.NO_CONTENT_204);
+                .statusCode(NO_CONTENT_204);
         }
 
         @Test
@@ -590,7 +597,7 @@ class UserMailboxesRoutesTest {
             when()
                 .put(MAILBOX_NAME)
             .then()
-                .statusCode(HttpStatus.NO_CONTENT_204);
+                .statusCode(NO_CONTENT_204);
         }
 
         @Test
@@ -601,7 +608,7 @@ class UserMailboxesRoutesTest {
             when()
                 .get()
             .then()
-                .statusCode(HttpStatus.OK_200)
+                .statusCode(OK_200)
                 .body(".", hasSize(1))
                 .body("[0].mailboxName", is("myMailboxName"))
                 .body("[0].mailboxId", is("1"));
@@ -612,17 +619,17 @@ class UserMailboxesRoutesTest {
             Map<String, Object> errors = when()
                 .get(MAILBOX_NAME)
             .then()
-                .statusCode(HttpStatus.NOT_FOUND_404)
-                .contentType(ContentType.JSON)
+                .statusCode(NOT_FOUND_404)
+                .contentType(JSON)
                 .extract()
                 .body()
                 .jsonPath()
                 .getMap(".");
 
             assertThat(errors)
-                .containsEntry("statusCode", HttpStatus.NOT_FOUND_404)
-                .containsEntry("type", "InvalidArgument")
-                .containsEntry("message", "Invalid get on user mailboxes");
+                .containsEntry("statusCode", NOT_FOUND_404)
+                .containsEntry("type", ERROR_TYPE_NOTFOUND)
+                .containsEntry("message", "Mailbox does not exist");
         }
 
         @Test
@@ -633,7 +640,7 @@ class UserMailboxesRoutesTest {
             when()
                 .get(MAILBOX_NAME)
             .then()
-                .statusCode(HttpStatus.NO_CONTENT_204);
+                .statusCode(NO_CONTENT_204);
         }
 
         @Test
@@ -641,7 +648,7 @@ class UserMailboxesRoutesTest {
             when()
                 .delete(MAILBOX_NAME)
             .then()
-                .statusCode(HttpStatus.NO_CONTENT_204);
+                .statusCode(NO_CONTENT_204);
         }
 
         @Test
@@ -652,7 +659,7 @@ class UserMailboxesRoutesTest {
             when()
                 .delete(MAILBOX_NAME)
             .then()
-                .statusCode(HttpStatus.NO_CONTENT_204);
+                .statusCode(NO_CONTENT_204);
         }
 
         @Test
@@ -666,17 +673,17 @@ class UserMailboxesRoutesTest {
             Map<String, Object> errors = when()
                 .get(MAILBOX_NAME)
             .then()
-                .statusCode(HttpStatus.NOT_FOUND_404)
-                .contentType(ContentType.JSON)
+                .statusCode(NOT_FOUND_404)
+                .contentType(JSON)
                 .extract()
                 .body()
                 .jsonPath()
                 .getMap(".");
 
             assertThat(errors)
-                .containsEntry("statusCode", HttpStatus.NOT_FOUND_404)
-                .containsEntry("type", "InvalidArgument")
-                .containsEntry("message", "Invalid get on user mailboxes");
+                .containsEntry("statusCode", NOT_FOUND_404)
+                .containsEntry("type", ERROR_TYPE_NOTFOUND)
+                .containsEntry("message", "Mailbox does not exist");
         }
 
         @Test
@@ -684,7 +691,7 @@ class UserMailboxesRoutesTest {
             when()
                 .delete()
             .then()
-                .statusCode(HttpStatus.NO_CONTENT_204);
+                .statusCode(NO_CONTENT_204);
         }
 
         @Test
@@ -695,7 +702,7 @@ class UserMailboxesRoutesTest {
             when()
                 .delete()
                 .then()
-                .statusCode(HttpStatus.NO_CONTENT_204);
+                .statusCode(NO_CONTENT_204);
         }
 
         @Test
@@ -713,8 +720,8 @@ class UserMailboxesRoutesTest {
                 when()
                     .get()
                 .then()
-                    .statusCode(HttpStatus.OK_200)
-                    .contentType(ContentType.JSON)
+                    .statusCode(OK_200)
+                    .contentType(JSON)
                     .extract()
                     .body()
                     .jsonPath()
@@ -734,7 +741,7 @@ class UserMailboxesRoutesTest {
             when()
                 .delete(MAILBOX_NAME)
             .then()
-                .statusCode(HttpStatus.NO_CONTENT_204);
+                .statusCode(NO_CONTENT_204);
         }
 
         @Test
@@ -752,8 +759,8 @@ class UserMailboxesRoutesTest {
                 when()
                     .get()
                 .then()
-                    .statusCode(HttpStatus.OK_200)
-                    .contentType(ContentType.JSON)
+                    .statusCode(OK_200)
+                    .contentType(JSON)
                     .extract()
                     .body()
                     .jsonPath()
@@ -778,8 +785,8 @@ class UserMailboxesRoutesTest {
                 when()
                     .get()
                 .then()
-                    .statusCode(HttpStatus.OK_200)
-                    .contentType(ContentType.JSON)
+                    .statusCode(OK_200)
+                    .contentType(JSON)
                     .extract()
                     .body()
                     .jsonPath()
@@ -804,7 +811,7 @@ class UserMailboxesRoutesTest {
             when()
                 .delete(MAILBOX_NAME + ".child")
             .then()
-                .statusCode(HttpStatus.NO_CONTENT_204);
+                .statusCode(NO_CONTENT_204);
         }
 
         @Test
@@ -822,8 +829,8 @@ class UserMailboxesRoutesTest {
                 when()
                     .get()
                 .then()
-                    .statusCode(HttpStatus.OK_200)
-                    .contentType(ContentType.JSON)
+                    .statusCode(OK_200)
+                    .contentType(JSON)
                     .extract()
                     .body()
                     .jsonPath()
@@ -857,7 +864,7 @@ class UserMailboxesRoutesTest {
             when()
                 .put(MAILBOX_NAME)
             .then()
-                .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500);
+                .statusCode(INTERNAL_SERVER_ERROR_500);
         }
 
         @Test
@@ -867,7 +874,7 @@ class UserMailboxesRoutesTest {
             when()
                 .put(MAILBOX_NAME)
             .then()
-                .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500);
+                .statusCode(INTERNAL_SERVER_ERROR_500);
         }
 
         @Test
@@ -877,7 +884,7 @@ class UserMailboxesRoutesTest {
             when()
                 .put(MAILBOX_NAME)
             .then()
-                .statusCode(HttpStatus.NO_CONTENT_204);
+                .statusCode(NO_CONTENT_204);
         }
 
         @Test
@@ -893,7 +900,7 @@ class UserMailboxesRoutesTest {
             when()
                 .delete(MAILBOX_NAME)
             .then()
-                .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500);
+                .statusCode(INTERNAL_SERVER_ERROR_500);
         }
 
         @Test
@@ -903,7 +910,7 @@ class UserMailboxesRoutesTest {
             when()
                 .delete(MAILBOX_NAME)
             .then()
-                .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500);
+                .statusCode(INTERNAL_SERVER_ERROR_500);
         }
 
         @Test
@@ -918,7 +925,7 @@ class UserMailboxesRoutesTest {
             when()
                 .delete(MAILBOX_NAME)
             .then()
-                .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500);
+                .statusCode(INTERNAL_SERVER_ERROR_500);
         }
 
         @Test
@@ -928,7 +935,7 @@ class UserMailboxesRoutesTest {
             when()
                 .delete(MAILBOX_NAME)
             .then()
-                .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500);
+                .statusCode(INTERNAL_SERVER_ERROR_500);
         }
 
         @Test
@@ -938,7 +945,7 @@ class UserMailboxesRoutesTest {
             when()
                 .delete(MAILBOX_NAME)
             .then()
-                .statusCode(HttpStatus.NO_CONTENT_204);
+                .statusCode(NO_CONTENT_204);
         }
 
         @Test
@@ -948,7 +955,7 @@ class UserMailboxesRoutesTest {
             when()
                 .delete()
             .then()
-                .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500);
+                .statusCode(INTERNAL_SERVER_ERROR_500);
         }
 
         @Test
@@ -958,7 +965,7 @@ class UserMailboxesRoutesTest {
             when()
                 .delete()
             .then()
-                .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500);
+                .statusCode(INTERNAL_SERVER_ERROR_500);
         }
 
 
@@ -974,7 +981,7 @@ class UserMailboxesRoutesTest {
             when()
                 .delete()
             .then()
-                .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500);
+                .statusCode(INTERNAL_SERVER_ERROR_500);
         }
 
         @Test
@@ -988,7 +995,7 @@ class UserMailboxesRoutesTest {
             when()
                 .delete()
             .then()
-                .statusCode(HttpStatus.NO_CONTENT_204);
+                .statusCode(NO_CONTENT_204);
         }
 
         @Test
@@ -1002,7 +1009,7 @@ class UserMailboxesRoutesTest {
             when()
                 .delete()
             .then()
-                .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500);
+                .statusCode(INTERNAL_SERVER_ERROR_500);
         }
 
         @Test
@@ -1012,7 +1019,7 @@ class UserMailboxesRoutesTest {
             when()
                 .get(MAILBOX_NAME)
             .then()
-                .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500);
+                .statusCode(INTERNAL_SERVER_ERROR_500);
         }
 
         @Test
@@ -1022,7 +1029,7 @@ class UserMailboxesRoutesTest {
             when()
                 .get(MAILBOX_NAME)
             .then()
-                .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500);
+                .statusCode(INTERNAL_SERVER_ERROR_500);
         }
 
         @Test
@@ -1032,7 +1039,7 @@ class UserMailboxesRoutesTest {
             when()
                 .get()
             .then()
-                .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500);
+                .statusCode(INTERNAL_SERVER_ERROR_500);
         }
 
         @Test
@@ -1042,7 +1049,7 @@ class UserMailboxesRoutesTest {
             when()
                 .get()
             .then()
-                .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500);
+                .statusCode(INTERNAL_SERVER_ERROR_500);
         }
 
         @Test
@@ -1052,7 +1059,7 @@ class UserMailboxesRoutesTest {
             when()
                 .get()
             .then()
-                .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500);
+                .statusCode(INTERNAL_SERVER_ERROR_500);
         }
 
         @Test
@@ -1062,7 +1069,7 @@ class UserMailboxesRoutesTest {
             when()
                 .get(MAILBOX_NAME)
             .then()
-                .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500);
+                .statusCode(INTERNAL_SERVER_ERROR_500);
         }
 
         @Test
@@ -1072,7 +1079,7 @@ class UserMailboxesRoutesTest {
             when()
                 .put(MAILBOX_NAME)
             .then()
-                .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500);
+                .statusCode(INTERNAL_SERVER_ERROR_500);
         }
 
         @Test
@@ -1082,7 +1089,7 @@ class UserMailboxesRoutesTest {
             when()
                 .delete(MAILBOX_NAME)
             .then()
-                .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500);
+                .statusCode(INTERNAL_SERVER_ERROR_500);
         }
 
         @Test
@@ -1092,7 +1099,7 @@ class UserMailboxesRoutesTest {
             when()
                 .delete()
             .then()
-                .statusCode(HttpStatus.INTERNAL_SERVER_ERROR_500);
+                .statusCode(INTERNAL_SERVER_ERROR_500);
         }
 
     }
@@ -1115,9 +1122,9 @@ class UserMailboxesRoutesTest {
                 when()
                     .post()
                 .then()
-                    .statusCode(HttpStatus.BAD_REQUEST_400)
+                    .statusCode(BAD_REQUEST_400)
                     .body("statusCode", Matchers.is(400))
-                    .body("type", Matchers.is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
+                    .body("type", Matchers.is("InvalidArgument"))
                     .body("message", Matchers.is("Invalid arguments supplied in the user request"))
                     .body("details", Matchers.is("'task' query parameter is compulsory. Supported values are [reIndex]"));
             }
@@ -1129,9 +1136,9 @@ class UserMailboxesRoutesTest {
                 .when()
                     .post()
                 .then()
-                    .statusCode(HttpStatus.BAD_REQUEST_400)
+                    .statusCode(BAD_REQUEST_400)
                     .body("statusCode", Matchers.is(400))
-                    .body("type", Matchers.is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
+                    .body("type", Matchers.is("InvalidArgument"))
                     .body("message", Matchers.is("Invalid arguments supplied in the user request"))
                     .body("details", Matchers.is("Invalid value supplied for query parameter 'task': bad. Supported values are [reIndex]"));
             }
@@ -1148,9 +1155,9 @@ class UserMailboxesRoutesTest {
                 .when()
                     .post()
                 .then()
-                    .statusCode(HttpStatus.BAD_REQUEST_400)
+                    .statusCode(BAD_REQUEST_400)
                     .body("statusCode", Matchers.is(400))
-                    .body("type", Matchers.is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType()))
+                    .body("type", Matchers.is("InvalidArgument"))
                     .body("message", Matchers.is("Invalid arguments supplied in the user request"))
                     .body("details", Matchers.is("The username should not contain multiple domain delimiter."));
             }


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


[james-project] 05/05: JAMES-3093 Organize AuthenticationContract and implementations

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 9239b2f838b11978082fa2807fbb07db4952d913
Author: duc91 <du...@gmail.com>
AuthorDate: Fri May 29 14:20:55 2020 +0700

    JAMES-3093 Organize AuthenticationContract and implementations
---
 ...est.java => DistributedAuthenticationTest.java} |   4 +-
 .../DistributedBasicAuthenticationTest.java        |  51 -----
 .../rfc8621/contract/AuthenticationContract.scala  | 232 +++++++++++++++++++++
 .../contract/BasicAuthenticationContract.scala     | 123 -----------
 .../james/jmap/rfc8621/contract/Fixture.scala      |   8 +
 .../contract/JWTAuthenticationContract.scala       | 107 ----------
 .../rfc8621/memory/MemoryAuthenticationTest.java   |   4 +-
 server/protocols/jmap/pom.xml                      |   4 -
 8 files changed, 244 insertions(+), 289 deletions(-)

diff --git a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedJWTAuthenticationTest.java b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedAuthenticationTest.java
similarity index 94%
rename from server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedJWTAuthenticationTest.java
rename to server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedAuthenticationTest.java
index 0a8787b..8ab8ee8 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedJWTAuthenticationTest.java
+++ b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedAuthenticationTest.java
@@ -25,14 +25,14 @@ import org.apache.james.CassandraRabbitMQJamesServerMain;
 import org.apache.james.DockerElasticSearchExtension;
 import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
-import org.apache.james.jmap.rfc8621.contract.JWTAuthenticationContract;
+import org.apache.james.jmap.rfc8621.contract.AuthenticationContract;
 import org.apache.james.modules.AwsS3BlobStoreExtension;
 import org.apache.james.modules.RabbitMQExtension;
 import org.apache.james.modules.TestJMAPServerModule;
 import org.apache.james.modules.blobstore.BlobStoreConfiguration;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
-public class DistributedJWTAuthenticationTest implements JWTAuthenticationContract {
+class DistributedAuthenticationTest implements AuthenticationContract {
     @RegisterExtension
     static JamesServerExtension testExtension = new JamesServerBuilder<CassandraRabbitMQJamesConfiguration>(tmpDir ->
         CassandraRabbitMQJamesConfiguration.builder()
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedBasicAuthenticationTest.java b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedBasicAuthenticationTest.java
deleted file mode 100644
index d4f2151..0000000
--- a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedBasicAuthenticationTest.java
+++ /dev/null
@@ -1,51 +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.rfc8621.distributed;
-
-import org.apache.james.CassandraExtension;
-import org.apache.james.CassandraRabbitMQJamesConfiguration;
-import org.apache.james.CassandraRabbitMQJamesServerMain;
-import org.apache.james.DockerElasticSearchExtension;
-import org.apache.james.GuiceJamesServer;
-import org.apache.james.JamesServerBuilder;
-import org.apache.james.JamesServerExtension;
-import org.apache.james.jmap.rfc8621.contract.BasicAuthenticationContract;
-import org.apache.james.modules.AwsS3BlobStoreExtension;
-import org.apache.james.modules.RabbitMQExtension;
-import org.apache.james.modules.TestJMAPServerModule;
-import org.apache.james.modules.blobstore.BlobStoreConfiguration;
-import org.junit.jupiter.api.extension.RegisterExtension;
-
-public class DistributedBasicAuthenticationTest implements BasicAuthenticationContract {
-    @RegisterExtension
-    static JamesServerExtension testExtension = new JamesServerBuilder<CassandraRabbitMQJamesConfiguration>(tmpDir ->
-        CassandraRabbitMQJamesConfiguration.builder()
-            .workingDirectory(tmpDir)
-            .configurationFromClasspath()
-            .blobStore(BlobStoreConfiguration.objectStorage().disableCache())
-            .build())
-        .extension(new DockerElasticSearchExtension())
-        .extension(new CassandraExtension())
-        .extension(new RabbitMQExtension())
-        .extension(new AwsS3BlobStoreExtension())
-        .server(configuration -> CassandraRabbitMQJamesServerMain.createServer(configuration)
-            .overrideWith(new TestJMAPServerModule()))
-        .build();
-}
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/AuthenticationContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/AuthenticationContract.scala
new file mode 100644
index 0000000..6d2b766
--- /dev/null
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/AuthenticationContract.scala
@@ -0,0 +1,232 @@
+/****************************************************************
+ * 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.rfc8621.contract
+
+import io.netty.handler.codec.http.HttpHeaderNames.ACCEPT
+import io.restassured.RestAssured.{`given`, requestSpecification}
+import io.restassured.authentication.NoAuthScheme
+import io.restassured.http.Header
+import org.apache.http.HttpStatus.{SC_OK, SC_UNAUTHORIZED}
+import org.apache.james.GuiceJamesServer
+import org.apache.james.jmap.rfc8621.contract.Fixture.{ACCEPT_RFC8621_VERSION_HEADER, ALICE, ALICE_PASSWORD, AUTHORIZATION_HEADER, BOB, BOB_BASIC_AUTH_HEADER, BOB_PASSWORD, DOMAIN, DOMAIN_WITH_SPACE, ECHO_REQUEST_OBJECT, INVALID_JWT_TOKEN, UNKNOWN_USER_TOKEN, USER_TOKEN, getHeadersWith, toBase64, _}
+import org.apache.james.jmap.rfc8621.contract.tags.CategoryTags
+import org.apache.james.utils.DataProbeImpl
+import org.junit.jupiter.api.{BeforeEach, Nested, Tag, Test}
+
+
+trait AuthenticationContract {
+  @BeforeEach
+  def setup(server: GuiceJamesServer): Unit = {
+    server.getProbe(classOf[DataProbeImpl])
+      .fluent
+      .addDomain(DOMAIN.asString)
+      .addDomain(_2_DOT_DOMAIN.asString)
+      .addUser(USER.asString, USER_PASSWORD)
+      .addUser(ALICE.asString, ALICE_PASSWORD)
+      .addUser(BOB.asString, BOB_PASSWORD)
+
+    requestSpecification = baseRequestSpecBuilder(server)
+        .setAuth(new NoAuthScheme)
+      .build
+  }
+
+  @Nested
+  class BothAuthenticationMechanisms {
+    @Tag(CategoryTags.BASIC_FEATURE)
+    @Test
+    def shouldRespond200WhenBasicAuthValidAndJWTInvalid(): Unit = {
+      `given`
+        .headers(getHeadersWith(BOB_BASIC_AUTH_HEADER))
+        .header(new Header(AUTHORIZATION_HEADER, s"Bearer $UNKNOWN_USER_TOKEN"))
+        .body(ECHO_REQUEST_OBJECT)
+      .when
+        .post
+      .`then`
+        .statusCode(SC_OK)
+    }
+
+    @Tag(CategoryTags.BASIC_FEATURE)
+    @Test
+    def shouldRespond200WhenJWTAuthValidAndBasicAuthInvalid(): Unit = {
+      `given`
+        .headers(getHeadersWith(new Header(AUTHORIZATION_HEADER, s"Basic ${toBase64(s"this-thing-wrong")}")))
+        .header(new Header(AUTHORIZATION_HEADER, s"Bearer $USER_TOKEN"))
+        .body(ECHO_REQUEST_OBJECT)
+      .when
+        .post
+      .`then`
+        .statusCode(SC_OK)
+    }
+
+    @Tag(CategoryTags.BASIC_FEATURE)
+    @Test
+    def shouldRespond200WhenBothAuthenticationValid(): Unit = {
+      `given`
+        .headers(getHeadersWith(BOB_BASIC_AUTH_HEADER))
+        .header(new Header(AUTHORIZATION_HEADER, s"Bearer $USER_TOKEN"))
+        .body(ECHO_REQUEST_OBJECT)
+      .when
+        .post
+      .`then`
+        .statusCode(SC_OK)
+    }
+
+    @Tag(CategoryTags.BASIC_FEATURE)
+    @Test
+    def shouldRespond401WhenNoneAuthenticationValid(): Unit = {
+      `given`
+        .headers(getHeadersWith(new Header(AUTHORIZATION_HEADER, s"Basic ${toBase64(s"this-one-wrong")}")))
+        .header(new Header(AUTHORIZATION_HEADER, s"Bearer $UNKNOWN_USER_TOKEN"))
+        .body(ECHO_REQUEST_OBJECT)
+      .when
+        .post
+      .`then`
+        .statusCode(SC_UNAUTHORIZED)
+    }
+  }
+
+  @Nested
+  class BasicAuth {
+    @Test
+    def postShouldRespond401WhenNoAuthorizationHeader(): Unit = {
+      given()
+        .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+        .body(ECHO_REQUEST_OBJECT)
+      .when
+        .post
+      .`then`
+        .statusCode(SC_UNAUTHORIZED)
+    }
+
+    @Test
+    @Tag(CategoryTags.BASIC_FEATURE)
+    def postShouldRespond200WhenHasCredentials(): Unit = {
+      `given`
+        .headers(getHeadersWith(BOB_BASIC_AUTH_HEADER))
+        .body(ECHO_REQUEST_OBJECT)
+      .when
+        .post
+      .`then`
+        .statusCode(SC_OK)
+    }
+
+    @Test
+    def postShouldRespond401WhenCredentialsWithInvalidUser(): Unit = {
+      val authHeader: Header = new Header(AUTHORIZATION_HEADER, s"Basic ${toBase64(s"${BOB.getLocalPart}@@$DOMAIN:$BOB_PASSWORD")}")
+      `given`
+        .headers(getHeadersWith(authHeader))
+        .body(ECHO_REQUEST_OBJECT)
+      .when
+        .post
+      .`then`
+        .statusCode(SC_UNAUTHORIZED)
+    }
+
+    @Test
+    def postShouldRespond200WhenCredentialsWith2DotDomain(): Unit = {
+      val authHeader: Header = new Header(AUTHORIZATION_HEADER, s"Basic ${toBase64(s"${ALICE.asString}:$ALICE_PASSWORD")}")
+      `given`
+        .headers(getHeadersWith(authHeader))
+        .body(ECHO_REQUEST_OBJECT)
+      .when
+        .post
+      .`then`
+        .statusCode(SC_OK)
+    }
+
+    @Test
+    def postShouldRespond401WhenCredentialsWithSpaceDomain(): Unit = {
+      val authHeader: Header = new Header(AUTHORIZATION_HEADER, s"Basic ${toBase64(s"${BOB.getLocalPart}@$DOMAIN_WITH_SPACE:$BOB_PASSWORD")}")
+      `given`
+        .headers(getHeadersWith(authHeader))
+        .body(ECHO_REQUEST_OBJECT)
+      .when
+        .post
+      .`then`
+        .statusCode(SC_UNAUTHORIZED)
+    }
+
+    @Test
+    def postShouldRespond401WhenUserNotFound(): Unit = {
+      val authHeader: Header = new Header(AUTHORIZATION_HEADER, s"Basic ${toBase64(s"usernotfound@$DOMAIN:$BOB_PASSWORD")}")
+      `given`
+        .headers(getHeadersWith(authHeader))
+        .body(ECHO_REQUEST_OBJECT)
+      .when
+        .post
+      .`then`
+        .statusCode(SC_UNAUTHORIZED)
+    }
+
+    @Test
+    @Tag(CategoryTags.BASIC_FEATURE)
+    def postShouldRespond401WhenWrongPassword(): Unit = {
+      val authHeader: Header = new Header(AUTHORIZATION_HEADER, s"Basic ${toBase64(s"${BOB.asString}:WRONG_PASSWORD")}")
+      `given`
+        .headers(getHeadersWith(authHeader))
+        .body(ECHO_REQUEST_OBJECT)
+      .when
+        .post
+      .`then`
+        .statusCode(SC_UNAUTHORIZED)
+    }
+  }
+
+  @Nested
+  class JWTAuth {
+    @Tag(CategoryTags.BASIC_FEATURE)
+    @Test
+    def postShouldReturn200WhenValidJwtAuthorizationHeader(): Unit = {
+      `given`
+        .headers(getHeadersWith(new Header(AUTHORIZATION_HEADER, s"Bearer $USER_TOKEN")))
+        .body(ECHO_REQUEST_OBJECT)
+      .when
+        .post
+      .`then`
+        .statusCode(SC_OK)
+    }
+
+    @Test
+    @Tag(CategoryTags.BASIC_FEATURE)
+    def postShouldReturn401WhenValidUnknownUserJwtAuthorizationHeader(): Unit = {
+      val authHeader: Header = new Header(AUTHORIZATION_HEADER, s"Bearer $UNKNOWN_USER_TOKEN")
+      `given`
+        .headers(getHeadersWith(authHeader))
+        .body(ECHO_REQUEST_OBJECT)
+      .when
+        .post
+      .`then`
+        .statusCode(SC_UNAUTHORIZED)
+    }
+
+    @Test
+    @Tag(CategoryTags.BASIC_FEATURE)
+    def postShouldReturn401WhenInvalidJwtAuthorizationHeader(): Unit = {
+      `given`
+        .headers(getHeadersWith(new Header(AUTHORIZATION_HEADER, s"Bearer $INVALID_JWT_TOKEN")))
+        .body(ECHO_REQUEST_OBJECT)
+      .when
+        .post
+      .`then`
+        .statusCode(SC_UNAUTHORIZED)
+    }
+  }
+}
+
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/BasicAuthenticationContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/BasicAuthenticationContract.scala
deleted file mode 100644
index f257bbf..0000000
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/BasicAuthenticationContract.scala
+++ /dev/null
@@ -1,123 +0,0 @@
-package org.apache.james.jmap.rfc8621.contract
-
-import java.nio.charset.StandardCharsets.UTF_8
-import java.util.Base64
-
-import io.netty.handler.codec.http.HttpHeaderNames.ACCEPT
-import io.restassured.RestAssured.{`given`, requestSpecification}
-import io.restassured.authentication.NoAuthScheme
-import io.restassured.http.Header
-import org.apache.http.HttpStatus.{SC_OK, SC_UNAUTHORIZED}
-import org.apache.james.GuiceJamesServer
-import org.apache.james.jmap.rfc8621.contract.BasicAuthenticationContract._
-import org.apache.james.jmap.rfc8621.contract.Fixture._
-import org.apache.james.jmap.rfc8621.contract.tags.CategoryTags
-import org.apache.james.utils.DataProbeImpl
-import org.junit.jupiter.api.{BeforeEach, Tag, Test}
-
-object BasicAuthenticationContract {
-  private def toBase64(stringValue: String): String = {
-    Base64.getEncoder.encodeToString(stringValue.getBytes(UTF_8))
-  }
-}
-
-trait BasicAuthenticationContract {
-  @BeforeEach
-  def setUp(server: GuiceJamesServer): Unit = {
-    server.getProbe(classOf[DataProbeImpl])
-      .fluent()
-      .addDomain(DOMAIN.asString())
-      .addUser(BOB.asString(), BOB_PASSWORD)
-      .addDomain(_2_DOT_DOMAIN.asString())
-      .addUser(ALICE.asString(), ALICE_PASSWORD)
-
-    requestSpecification = baseRequestSpecBuilder(server)
-      .setAuth(new NoAuthScheme())
-      .build
-  }
-
-  @Test
-  def postShouldRespondUnauthorizedWhenNoAuthorizationHeader(): Unit = {
-    given()
-      .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
-      .body(ECHO_REQUEST_OBJECT)
-    .when()
-      .post()
-    .then
-      .statusCode(SC_UNAUTHORIZED)
-  }
-
-  @Test
-  @Tag(CategoryTags.BASIC_FEATURE)
-  def postShouldRespond200WhenHasCredentials(): Unit = {
-    val authHeader: Header = new Header(AUTHORIZATION_HEADER, s"Basic ${toBase64(s"${BOB.asString}:$BOB_PASSWORD")}")
-    `given`()
-      .headers(getHeadersWith(authHeader))
-      .body(ECHO_REQUEST_OBJECT)
-    .when()
-      .post()
-    .then
-      .statusCode(SC_OK)
-  }
-
-  @Test
-  def postShouldRespond401WhenCredentialsWithInvalidUser(): Unit = {
-    val authHeader: Header = new Header(AUTHORIZATION_HEADER, s"Basic ${toBase64(s"${BOB.getLocalPart}@@$DOMAIN:$BOB_PASSWORD")}")
-    `given`()
-      .headers(getHeadersWith(authHeader))
-      .body(ECHO_REQUEST_OBJECT)
-    .when()
-      .post()
-    .then
-      .statusCode(SC_UNAUTHORIZED)
-  }
-
-  @Test
-  def postShouldRespondOKWhenCredentialsWith2DotDomain(): Unit = {
-    val authHeader: Header = new Header(AUTHORIZATION_HEADER, s"Basic ${toBase64(s"${ALICE.asString}:$ALICE_PASSWORD")}")
-    `given`()
-      .headers(getHeadersWith(authHeader))
-      .body(ECHO_REQUEST_OBJECT)
-    .when()
-      .post()
-    .then
-      .statusCode(SC_OK)
-  }
-
-  @Test
-  def postShouldRespond401WhenCredentialsWithSpaceDomain(): Unit = {
-    val authHeader: Header = new Header(AUTHORIZATION_HEADER, s"Basic ${toBase64(s"${BOB.getLocalPart}@$DOMAIN_WITH_SPACE:$BOB_PASSWORD")}")
-    `given`()
-      .headers(getHeadersWith(authHeader))
-      .body(ECHO_REQUEST_OBJECT)
-    .when()
-      .post()
-    .then
-      .statusCode(SC_UNAUTHORIZED)
-  }
-
-  @Test
-  def postShouldRespond401WhenUserNotFound(): Unit = {
-    val authHeader: Header = new Header(AUTHORIZATION_HEADER, s"Basic ${toBase64(s"usernotfound@$DOMAIN:$BOB_PASSWORD")}")
-    `given`()
-      .headers(getHeadersWith(authHeader))
-      .body(ECHO_REQUEST_OBJECT)
-    .when()
-      .post()
-    .then
-      .statusCode(SC_UNAUTHORIZED)
-  }
-
-  @Test
-  @Tag(CategoryTags.BASIC_FEATURE)
-  def postShouldRespond401WhenWrongPassword(): Unit = {
-    val authHeader: Header = new Header(AUTHORIZATION_HEADER, s"Basic ${toBase64(s"${BOB.asString}:WRONG_PASSWORD")}")
-    `given`()
-      .headers(getHeadersWith(authHeader))
-      .body(ECHO_REQUEST_OBJECT)
-    .when()
-      .post()
-    .then
-      .statusCode(SC_UNAUTHORIZED)
-  }
-}
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/Fixture.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/Fixture.scala
index be44b77..7d22579 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/Fixture.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/Fixture.scala
@@ -20,6 +20,8 @@
 package org.apache.james.jmap.rfc8621.contract
 
 import java.nio.charset.StandardCharsets
+import java.nio.charset.StandardCharsets.UTF_8
+import java.util.Base64
 
 import io.netty.handler.codec.http.HttpHeaderNames.ACCEPT
 import io.restassured.authentication.PreemptiveBasicAuthScheme
@@ -51,6 +53,10 @@ object Fixture {
     authScheme
   }
 
+  def toBase64(stringValue: String): String = {
+    Base64.getEncoder.encodeToString(stringValue.getBytes(UTF_8))
+  }
+
   def getHeadersWith(authHeader: Header): Headers = {
     new Headers(
       new Header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER),
@@ -67,6 +73,8 @@ object Fixture {
   val BOB_PASSWORD: String = "bobpassword"
   val ALICE_PASSWORD: String = "alicepassword"
 
+  val BOB_BASIC_AUTH_HEADER: Header = new Header(AUTHORIZATION_HEADER, s"Basic ${toBase64(s"${BOB.asString}:$BOB_PASSWORD")}")
+
   val ECHO_REQUEST_OBJECT: String =
     """{
       |  "using": [
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/JWTAuthenticationContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/JWTAuthenticationContract.scala
deleted file mode 100644
index 5fbad90..0000000
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/JWTAuthenticationContract.scala
+++ /dev/null
@@ -1,107 +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.rfc8621.contract
-
-import io.restassured.RestAssured.{`given`, requestSpecification}
-import io.restassured.authentication.NoAuthScheme
-import io.restassured.http.Header
-import org.apache.http.HttpStatus._
-import org.apache.james.GuiceJamesServer
-import org.apache.james.core.Username
-import org.apache.james.jmap.rfc8621.contract.Fixture._
-import org.apache.james.jmap.rfc8621.contract.JWTAuthenticationContract._
-import org.apache.james.jmap.rfc8621.contract.tags.CategoryTags
-import org.apache.james.utils.DataProbeImpl
-import org.junit.jupiter.api.{BeforeEach, Tag, Test}
-
-object JWTAuthenticationContract {
-  private val USER_TOKEN: String =
-    "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyQGRvbWFpbi50bGQifQ.U-dUPv6OU6KO5N7CooHUfMkCd" +
-      "FJHx2F3H4fm7Q79g1BPfBSkifPj5xyVlZ0JwEGXypC4zBw9ay3l4DxzX7D_6p1Hx_ihXsoLx1Ca-WUo44x-XRSpPfgxiZjHCJkGBLMV3RZlA" +
-      "jip-d18mxkcX3JGplX_sCQkFisduAOAHuKSUg9wI6VBgUQi_0B35FYv6tP_bD6eFtvaAUN9QyXXh8UQjEp8CO12lRz6enfLx_V6BG_fEMkee" +
-      "6vRqdEqx_F9OF3eWTe1giMp_JhQ7_l1OXXtbd4TndVvTeuVy4irPbsRc-M8x_-qTDpFp6saRRsyOcFspxPp5n3yIhEK7B3UZiseXw"
-
-  private val UNKNOWN_USER_TOKEN: String =
-    "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0.T04BTk" +
-      "LXkJj24coSZkK13RfG25lpvmSl2MJ7N10KpBk9_-95EGYZdog-BDAn3PJzqVw52z-Bwjh4VOj1-j7cURu0cT4jXehhUrlCxS4n7QHZD" +
-      "N_bsEYGu7KzjWTpTsUiHe-rN7izXVFxDGG1TGwlmBCBnPW-EFCf9ylUsJi0r2BKNdaaPRfMIrHptH1zJBkkUziWpBN1RNLjmvlAUf49" +
-      "t1Tbv21ZqYM5Ht2vrhJWczFbuC-TD-8zJkXhjTmA1GVgomIX5dx1cH-dZX1wANNmshUJGHgepWlPU-5VIYxPEhb219RMLJIELMY2qN" +
-      "OR8Q31ydinyqzXvCSzVJOf6T60-w"
-
-  private val INVALID_JWT_TOKEN: String =
-    "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZG1pbkBvcGVu" +
-      "thispartiscompletelywrong.reQc3DiVvbQHF08oW1qOUyDJyv3tfzDNk8jhVZequiCdOI9vXnRlOe" +
-      "-yDYktd4WT8MYhqY7MgS-wR0vO9jZFv8ZCgd_MkKCvCO0HmMjP5iQPZ0kqGkgWUH7X123tfR38MfbCVAdPDba-K3MfkogV1xvDhlkPScFr_6MxE" +
-      "xtedOK2JnQZn7t9sUzSrcyjWverm7gZkPptkIVoS8TsEeMMME5vFXe_nqkEG69q3kuBUm_33tbR5oNS0ZGZKlG9r41lHBjyf9J1xN4UYV8n866d" +
-      "a7RPPCzshIWUtO0q9T2umWTnp-6OnOdBCkndrZmRR6pPxsD5YL0_77Wq8KT_5__fGA"
-
-  private val USER: Username = Username.fromLocalPartWithDomain("user", DOMAIN)
-  private val USER_PASSWORD: String = "user"
-}
-
-trait JWTAuthenticationContract {
-  @BeforeEach
-  def setUp(server: GuiceJamesServer): Unit = {
-    server.getProbe(classOf[DataProbeImpl])
-      .fluent()
-      .addDomain(DOMAIN.asString())
-      .addUser(USER.asString(), USER_PASSWORD)
-
-    requestSpecification = baseRequestSpecBuilder(server)
-      .setAuth(new NoAuthScheme)
-      .build
-  }
-
-  @Tag(CategoryTags.BASIC_FEATURE)
-  @Test
-  def getMustReturnEndpointsWhenValidJwtAuthorizationHeader(): Unit = {
-    `given`
-      .headers(getHeadersWith(new Header(AUTHORIZATION_HEADER, s"Bearer $USER_TOKEN")))
-      .body(ECHO_REQUEST_OBJECT)
-    .when
-      .post()
-    .`then`
-      .statusCode(SC_OK)
-  }
-
-  @Test
-  @Tag(CategoryTags.BASIC_FEATURE)
-  def getMustReturnOKWhenValidUnknownUserJwtAuthorizationHeader(): Unit = {
-    val authHeader: Header = new Header(AUTHORIZATION_HEADER, s"Bearer $UNKNOWN_USER_TOKEN")
-    `given`()
-      .headers(getHeadersWith(authHeader))
-      .body(ECHO_REQUEST_OBJECT)
-    .when()
-      .post()
-    .then
-      .statusCode(SC_UNAUTHORIZED)
-  }
-
-  @Test
-  @Tag(CategoryTags.BASIC_FEATURE)
-  def getMustReturnBadCredentialsWhenInvalidJwtAuthorizationHeader(): Unit = {
-    `given`
-      .headers(getHeadersWith(new Header(AUTHORIZATION_HEADER, s"Bearer $INVALID_JWT_TOKEN")))
-      .body(ECHO_REQUEST_OBJECT)
-    .when
-      .post()
-    .`then`
-      .statusCode(SC_UNAUTHORIZED)
-  }
-}
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryAuthenticationTest.java b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryAuthenticationTest.java
index 5fd5b42..74163fd 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryAuthenticationTest.java
+++ b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryAuthenticationTest.java
@@ -24,11 +24,11 @@ import static org.apache.james.MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_
 import org.apache.james.GuiceJamesServer;
 import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
-import org.apache.james.jmap.rfc8621.contract.BasicAuthenticationContract;
+import org.apache.james.jmap.rfc8621.contract.AuthenticationContract;
 import org.apache.james.modules.TestJMAPServerModule;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
-public class MemoryAuthenticationTest implements BasicAuthenticationContract {
+class MemoryAuthenticationTest implements AuthenticationContract {
     @RegisterExtension
     static JamesServerExtension testExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
         .server(configuration -> GuiceJamesServer.forConfiguration(configuration)
diff --git a/server/protocols/jmap/pom.xml b/server/protocols/jmap/pom.xml
index 37cc3db..33e0e04 100644
--- a/server/protocols/jmap/pom.xml
+++ b/server/protocols/jmap/pom.xml
@@ -81,10 +81,6 @@
             <artifactId>javax.annotation-api</artifactId>
         </dependency>
         <dependency>
-            <groupId>javax.annotation</groupId>
-            <artifactId>javax.annotation-api</artifactId>
-        </dependency>
-        <dependency>
             <groupId>org.apache.httpcomponents</groupId>
             <artifactId>httpcore</artifactId>
             <version>4.4.13</version>


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


[james-project] 02/05: JAMES-3200 Fix obsQp rule in MDN parser

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit e22e7c6c2679e95be5c62475772cba3ad9d79722
Author: Raphael Ouazana <ra...@linagora.com>
AuthorDate: Wed Jun 3 16:28:53 2020 +0200

    JAMES-3200 Fix obsQp rule in MDN parser
---
 mdn/src/main/java/org/apache/james/mdn/MDNReportParser.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mdn/src/main/java/org/apache/james/mdn/MDNReportParser.java b/mdn/src/main/java/org/apache/james/mdn/MDNReportParser.java
index 0a6c1f1..8db2e95 100644
--- a/mdn/src/main/java/org/apache/james/mdn/MDNReportParser.java
+++ b/mdn/src/main/java/org/apache/james/mdn/MDNReportParser.java
@@ -190,7 +190,7 @@ public class MDNReportParser {
             return Sequence(
                 "\\",
                 FirstOf(
-                    Ch((char)0xd0),
+                    Ch((char)0),
                     obsCtext(),
                     lf(),
                     cr()));


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


[james-project] 01/05: JAMES-3200 Fix qcontent rule in MDN parser

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit ceb6a95132ad4a4cdb7e3973a75f990ab7d8aeae
Author: Raphael Ouazana <ra...@linagora.com>
AuthorDate: Wed Jun 3 16:20:49 2020 +0200

    JAMES-3200 Fix qcontent rule in MDN parser
---
 .../java/org/apache/james/mdn/MDNReportParser.java    | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/mdn/src/main/java/org/apache/james/mdn/MDNReportParser.java b/mdn/src/main/java/org/apache/james/mdn/MDNReportParser.java
index a1dc416..0a6c1f1 100644
--- a/mdn/src/main/java/org/apache/james/mdn/MDNReportParser.java
+++ b/mdn/src/main/java/org/apache/james/mdn/MDNReportParser.java
@@ -260,9 +260,26 @@ public class MDNReportParser {
             return Ch((char)0x22);
         }
 
+        //   obs-qtext       =   obs-NO-WS-CTL
+        Rule obsQtext() {
+            return obsNoWsCtl();
+        }
+
+        /*   qtext           =   %d33 /             ; Printable US-ASCII
+                                 %d35-91 /          ;  characters not including
+                                 %d93-126 /         ;  "\" or the quote character
+                                 obs-qtext  */
+        Rule qtext() {
+            return FirstOf(
+                (char)33,
+                CharRange((char)35, (char)91),
+                CharRange((char)93, (char)126),
+                obsQtext());
+        }
+
         //   qcontent        =   qtext / quoted-pair
         Rule qcontent() {
-            return FirstOf(qcontent(), quotedPair());
+            return FirstOf(qtext(), quotedPair());
         }
 
         //   domain          =   dot-atom / domain-literal / obs-domain


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


[james-project] 04/05: JAMES-3093 Add JWT Authentication, integration test for JMAP RFC 8621

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit c3965277428a9ffdef6bdf997163a66290d7a139
Author: duc91 <du...@gmail.com>
AuthorDate: Fri May 22 11:51:44 2020 +0700

    JAMES-3093 Add JWT Authentication, integration test for JMAP RFC 8621
---
 .../james/jmap/draft/DraftMethodsModule.java       |   2 +-
 .../james/jmap/rfc8621/RFC8621MethodsModule.java   |  10 +-
 .../apache/james/jmap/http/AuthenticatorTest.java  |   2 +-
 .../jmap/http/JWTAuthenticationStrategyTest.java   |   3 +-
 .../DistributedBasicAuthenticationTest.java        |   4 +-
 .../distributed/DistributedEchoMethodTest.java     |   1 -
 ....java => DistributedJWTAuthenticationTest.java} |   6 +-
 ...act.scala => BasicAuthenticationContract.scala} |  46 ++-------
 .../james/jmap/rfc8621/contract/Fixture.scala      |  35 ++++++-
 .../contract/JWTAuthenticationContract.scala       | 107 +++++++++++++++++++++
 .../rfc8621/memory/MemoryAuthenticationTest.java   |   4 +-
 server/protocols/jmap-rfc-8621/pom.xml             |   4 +
 server/protocols/jmap/pom.xml                      |  18 +++-
 .../MailboxSessionCreationException.java           |   2 +-
 .../james/jmap/jwt}/JWTAuthenticationStrategy.java |  10 +-
 15 files changed, 192 insertions(+), 62 deletions(-)

diff --git a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/DraftMethodsModule.java b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/DraftMethodsModule.java
index 72488fd..d95d95c 100644
--- a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/DraftMethodsModule.java
+++ b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/DraftMethodsModule.java
@@ -46,8 +46,8 @@ import org.apache.james.jmap.draft.methods.SetVacationResponseMethod;
 import org.apache.james.jmap.http.AccessTokenAuthenticationStrategy;
 import org.apache.james.jmap.http.Authenticator;
 import org.apache.james.jmap.http.InjectionKeys;
-import org.apache.james.jmap.http.JWTAuthenticationStrategy;
 import org.apache.james.jmap.http.QueryParameterAccessTokenAuthenticationStrategy;
+import org.apache.james.jmap.jwt.JWTAuthenticationStrategy;
 import org.apache.james.metrics.api.MetricFactory;
 
 import com.google.inject.AbstractModule;
diff --git a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/rfc8621/RFC8621MethodsModule.java b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/rfc8621/RFC8621MethodsModule.java
index adffa45..f085137 100644
--- a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/rfc8621/RFC8621MethodsModule.java
+++ b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/rfc8621/RFC8621MethodsModule.java
@@ -26,6 +26,7 @@ import org.apache.james.jmap.http.Authenticator;
 import org.apache.james.jmap.http.BasicAuthenticationStrategy;
 import org.apache.james.jmap.http.rfc8621.InjectionKeys;
 import org.apache.james.jmap.json.Serializer;
+import org.apache.james.jmap.jwt.JWTAuthenticationStrategy;
 import org.apache.james.jmap.method.CoreEcho;
 import org.apache.james.jmap.method.Method;
 import org.apache.james.jmap.routes.JMAPApiRoutes;
@@ -57,7 +58,12 @@ public class RFC8621MethodsModule extends AbstractModule {
     @Provides
     @Singleton
     @Named(InjectionKeys.RFC_8621)
-    Authenticator provideAuthenticator(MetricFactory metricFactory, BasicAuthenticationStrategy basicAuthenticationStrategy) {
-        return Authenticator.of(metricFactory, basicAuthenticationStrategy);
+    Authenticator provideAuthenticator(MetricFactory metricFactory,
+                                       BasicAuthenticationStrategy basicAuthenticationStrategy,
+                                       JWTAuthenticationStrategy jwtAuthenticationStrategy) {
+        return Authenticator.of(
+            metricFactory,
+            basicAuthenticationStrategy,
+            jwtAuthenticationStrategy);
     }
 }
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/http/AuthenticatorTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/http/AuthenticatorTest.java
index 59c3816..f009783 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/http/AuthenticatorTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/http/AuthenticatorTest.java
@@ -30,7 +30,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
 import org.apache.james.core.Username;
 import org.apache.james.jmap.api.access.AccessToken;
 import org.apache.james.jmap.api.access.AccessTokenRepository;
-import org.apache.james.jmap.draft.exceptions.MailboxSessionCreationException;
+import org.apache.james.jmap.exceptions.MailboxSessionCreationException;
 import org.apache.james.jmap.exceptions.UnauthorizedException;
 import org.apache.james.jmap.memory.access.MemoryAccessTokenRepository;
 import org.apache.james.mailbox.MailboxSession;
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/http/JWTAuthenticationStrategyTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/http/JWTAuthenticationStrategyTest.java
index 49d5144..ac5169d 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/http/JWTAuthenticationStrategyTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/http/JWTAuthenticationStrategyTest.java
@@ -26,7 +26,8 @@ import static org.mockito.Mockito.when;
 
 import org.apache.james.core.Username;
 import org.apache.james.domainlist.api.DomainList;
-import org.apache.james.jmap.draft.exceptions.MailboxSessionCreationException;
+import org.apache.james.jmap.exceptions.MailboxSessionCreationException;
+import org.apache.james.jmap.jwt.JWTAuthenticationStrategy;
 import org.apache.james.jwt.JwtTokenVerifier;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.MailboxSession;
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedBasicAuthenticationTest.java b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedBasicAuthenticationTest.java
index 1d7932b..d4f2151 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedBasicAuthenticationTest.java
+++ b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedBasicAuthenticationTest.java
@@ -26,14 +26,14 @@ import org.apache.james.DockerElasticSearchExtension;
 import org.apache.james.GuiceJamesServer;
 import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
-import org.apache.james.jmap.rfc8621.contract.AuthenticationContract;
+import org.apache.james.jmap.rfc8621.contract.BasicAuthenticationContract;
 import org.apache.james.modules.AwsS3BlobStoreExtension;
 import org.apache.james.modules.RabbitMQExtension;
 import org.apache.james.modules.TestJMAPServerModule;
 import org.apache.james.modules.blobstore.BlobStoreConfiguration;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
-public class DistributedBasicAuthenticationTest implements AuthenticationContract {
+public class DistributedBasicAuthenticationTest implements BasicAuthenticationContract {
     @RegisterExtension
     static JamesServerExtension testExtension = new JamesServerBuilder<CassandraRabbitMQJamesConfiguration>(tmpDir ->
         CassandraRabbitMQJamesConfiguration.builder()
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedEchoMethodTest.java b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedEchoMethodTest.java
index c55787b..1e504db 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedEchoMethodTest.java
+++ b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedEchoMethodTest.java
@@ -23,7 +23,6 @@ import org.apache.james.CassandraExtension;
 import org.apache.james.CassandraRabbitMQJamesConfiguration;
 import org.apache.james.CassandraRabbitMQJamesServerMain;
 import org.apache.james.DockerElasticSearchExtension;
-import org.apache.james.GuiceJamesServer;
 import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
 import org.apache.james.jmap.rfc8621.contract.EchoMethodContract;
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedEchoMethodTest.java b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedJWTAuthenticationTest.java
similarity index 93%
copy from server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedEchoMethodTest.java
copy to server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedJWTAuthenticationTest.java
index c55787b..0a8787b 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedEchoMethodTest.java
+++ b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/distributed/DistributedJWTAuthenticationTest.java
@@ -23,18 +23,16 @@ import org.apache.james.CassandraExtension;
 import org.apache.james.CassandraRabbitMQJamesConfiguration;
 import org.apache.james.CassandraRabbitMQJamesServerMain;
 import org.apache.james.DockerElasticSearchExtension;
-import org.apache.james.GuiceJamesServer;
 import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
-import org.apache.james.jmap.rfc8621.contract.EchoMethodContract;
+import org.apache.james.jmap.rfc8621.contract.JWTAuthenticationContract;
 import org.apache.james.modules.AwsS3BlobStoreExtension;
 import org.apache.james.modules.RabbitMQExtension;
 import org.apache.james.modules.TestJMAPServerModule;
 import org.apache.james.modules.blobstore.BlobStoreConfiguration;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
-public class DistributedEchoMethodTest implements EchoMethodContract {
-
+public class DistributedJWTAuthenticationTest implements JWTAuthenticationContract {
     @RegisterExtension
     static JamesServerExtension testExtension = new JamesServerBuilder<CassandraRabbitMQJamesConfiguration>(tmpDir ->
         CassandraRabbitMQJamesConfiguration.builder()
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/AuthenticationContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/BasicAuthenticationContract.scala
similarity index 68%
rename from server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/AuthenticationContract.scala
rename to server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/BasicAuthenticationContract.scala
index 6716c1a..f257bbf 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/AuthenticationContract.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/BasicAuthenticationContract.scala
@@ -1,44 +1,27 @@
-/****************************************************************
- * 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.rfc8621.contract
 
 import java.nio.charset.StandardCharsets.UTF_8
 import java.util.Base64
 
 import io.netty.handler.codec.http.HttpHeaderNames.ACCEPT
-import io.restassured.RestAssured._
+import io.restassured.RestAssured.{`given`, requestSpecification}
 import io.restassured.authentication.NoAuthScheme
-import io.restassured.http.{Header, Headers}
+import io.restassured.http.Header
 import org.apache.http.HttpStatus.{SC_OK, SC_UNAUTHORIZED}
 import org.apache.james.GuiceJamesServer
-import org.apache.james.jmap.rfc8621.contract.AuthenticationContract._
+import org.apache.james.jmap.rfc8621.contract.BasicAuthenticationContract._
 import org.apache.james.jmap.rfc8621.contract.Fixture._
 import org.apache.james.jmap.rfc8621.contract.tags.CategoryTags
 import org.apache.james.utils.DataProbeImpl
 import org.junit.jupiter.api.{BeforeEach, Tag, Test}
 
-object AuthenticationContract {
-  private val AUTHORIZATION_HEADER: String = "Authorization"
+object BasicAuthenticationContract {
+  private def toBase64(stringValue: String): String = {
+    Base64.getEncoder.encodeToString(stringValue.getBytes(UTF_8))
+  }
 }
 
-trait AuthenticationContract {
+trait BasicAuthenticationContract {
   @BeforeEach
   def setUp(server: GuiceJamesServer): Unit = {
     server.getProbe(classOf[DataProbeImpl])
@@ -55,7 +38,7 @@ trait AuthenticationContract {
 
   @Test
   def postShouldRespondUnauthorizedWhenNoAuthorizationHeader(): Unit = {
-    `given`()
+    given()
       .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
       .body(ECHO_REQUEST_OBJECT)
     .when()
@@ -137,15 +120,4 @@ trait AuthenticationContract {
     .then
       .statusCode(SC_UNAUTHORIZED)
   }
-
-  private def getHeadersWith(authHeader: Header): Headers = {
-    new Headers(
-      new Header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER),
-      authHeader
-    )
-  }
-
-  private def toBase64(stringValue: String): String = {
-    Base64.getEncoder.encodeToString(stringValue.getBytes(UTF_8))
-  }
 }
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/Fixture.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/Fixture.scala
index 56be582..be44b77 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/Fixture.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/Fixture.scala
@@ -21,11 +21,12 @@ package org.apache.james.jmap.rfc8621.contract
 
 import java.nio.charset.StandardCharsets
 
+import io.netty.handler.codec.http.HttpHeaderNames.ACCEPT
 import io.restassured.authentication.PreemptiveBasicAuthScheme
 import io.restassured.builder.RequestSpecBuilder
 import io.restassured.config.EncoderConfig.encoderConfig
 import io.restassured.config.RestAssuredConfig.newConfig
-import io.restassured.http.ContentType
+import io.restassured.http.{ContentType, Header, Headers}
 import org.apache.james.GuiceJamesServer
 import org.apache.james.core.{Domain, Username}
 import org.apache.james.jmap.JMAPUrls.JMAP
@@ -50,6 +51,14 @@ object Fixture {
     authScheme
   }
 
+  def getHeadersWith(authHeader: Header): Headers = {
+    new Headers(
+      new Header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER),
+      authHeader
+    )
+  }
+
+  val AUTHORIZATION_HEADER: String = "Authorization"
   val DOMAIN: Domain = Domain.of("domain.tld")
   val DOMAIN_WITH_SPACE: Domain = Domain.of("dom ain.tld")
   val _2_DOT_DOMAIN: Domain = Domain.of("do.main.tld")
@@ -91,4 +100,28 @@ object Fixture {
       |}""".stripMargin
 
   val ACCEPT_RFC8621_VERSION_HEADER: String = "application/json; jmapVersion=rfc-8621"
+
+  val USER: Username = Username.fromLocalPartWithDomain("user", DOMAIN)
+  val USER_PASSWORD: String = "user"
+
+  // These tokens copied from class JwtTokenVerifierTest
+  val USER_TOKEN: String =
+    "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyQGRvbWFpbi50bGQifQ.U-dUPv6OU6KO5N7CooHUfMkCd" +
+      "FJHx2F3H4fm7Q79g1BPfBSkifPj5xyVlZ0JwEGXypC4zBw9ay3l4DxzX7D_6p1Hx_ihXsoLx1Ca-WUo44x-XRSpPfgxiZjHCJkGBLMV3RZlA" +
+      "jip-d18mxkcX3JGplX_sCQkFisduAOAHuKSUg9wI6VBgUQi_0B35FYv6tP_bD6eFtvaAUN9QyXXh8UQjEp8CO12lRz6enfLx_V6BG_fEMkee" +
+      "6vRqdEqx_F9OF3eWTe1giMp_JhQ7_l1OXXtbd4TndVvTeuVy4irPbsRc-M8x_-qTDpFp6saRRsyOcFspxPp5n3yIhEK7B3UZiseXw"
+
+  val UNKNOWN_USER_TOKEN: String =
+    "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0.T04BTk" +
+      "LXkJj24coSZkK13RfG25lpvmSl2MJ7N10KpBk9_-95EGYZdog-BDAn3PJzqVw52z-Bwjh4VOj1-j7cURu0cT4jXehhUrlCxS4n7QHZD" +
+      "N_bsEYGu7KzjWTpTsUiHe-rN7izXVFxDGG1TGwlmBCBnPW-EFCf9ylUsJi0r2BKNdaaPRfMIrHptH1zJBkkUziWpBN1RNLjmvlAUf49" +
+      "t1Tbv21ZqYM5Ht2vrhJWczFbuC-TD-8zJkXhjTmA1GVgomIX5dx1cH-dZX1wANNmshUJGHgepWlPU-5VIYxPEhb219RMLJIELMY2qN" +
+      "OR8Q31ydinyqzXvCSzVJOf6T60-w"
+
+  val INVALID_JWT_TOKEN: String =
+    "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZG1pbkBvcGVu" +
+      "thispartiscompletelywrong.reQc3DiVvbQHF08oW1qOUyDJyv3tfzDNk8jhVZequiCdOI9vXnRlOe" +
+      "-yDYktd4WT8MYhqY7MgS-wR0vO9jZFv8ZCgd_MkKCvCO0HmMjP5iQPZ0kqGkgWUH7X123tfR38MfbCVAdPDba-K3MfkogV1xvDhlkPScFr_6MxE" +
+      "xtedOK2JnQZn7t9sUzSrcyjWverm7gZkPptkIVoS8TsEeMMME5vFXe_nqkEG69q3kuBUm_33tbR5oNS0ZGZKlG9r41lHBjyf9J1xN4UYV8n866d" +
+      "a7RPPCzshIWUtO0q9T2umWTnp-6OnOdBCkndrZmRR6pPxsD5YL0_77Wq8KT_5__fGA"
 }
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/JWTAuthenticationContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/JWTAuthenticationContract.scala
new file mode 100644
index 0000000..5fbad90
--- /dev/null
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/JWTAuthenticationContract.scala
@@ -0,0 +1,107 @@
+/****************************************************************
+ * 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.rfc8621.contract
+
+import io.restassured.RestAssured.{`given`, requestSpecification}
+import io.restassured.authentication.NoAuthScheme
+import io.restassured.http.Header
+import org.apache.http.HttpStatus._
+import org.apache.james.GuiceJamesServer
+import org.apache.james.core.Username
+import org.apache.james.jmap.rfc8621.contract.Fixture._
+import org.apache.james.jmap.rfc8621.contract.JWTAuthenticationContract._
+import org.apache.james.jmap.rfc8621.contract.tags.CategoryTags
+import org.apache.james.utils.DataProbeImpl
+import org.junit.jupiter.api.{BeforeEach, Tag, Test}
+
+object JWTAuthenticationContract {
+  private val USER_TOKEN: String =
+    "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyQGRvbWFpbi50bGQifQ.U-dUPv6OU6KO5N7CooHUfMkCd" +
+      "FJHx2F3H4fm7Q79g1BPfBSkifPj5xyVlZ0JwEGXypC4zBw9ay3l4DxzX7D_6p1Hx_ihXsoLx1Ca-WUo44x-XRSpPfgxiZjHCJkGBLMV3RZlA" +
+      "jip-d18mxkcX3JGplX_sCQkFisduAOAHuKSUg9wI6VBgUQi_0B35FYv6tP_bD6eFtvaAUN9QyXXh8UQjEp8CO12lRz6enfLx_V6BG_fEMkee" +
+      "6vRqdEqx_F9OF3eWTe1giMp_JhQ7_l1OXXtbd4TndVvTeuVy4irPbsRc-M8x_-qTDpFp6saRRsyOcFspxPp5n3yIhEK7B3UZiseXw"
+
+  private val UNKNOWN_USER_TOKEN: String =
+    "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0.T04BTk" +
+      "LXkJj24coSZkK13RfG25lpvmSl2MJ7N10KpBk9_-95EGYZdog-BDAn3PJzqVw52z-Bwjh4VOj1-j7cURu0cT4jXehhUrlCxS4n7QHZD" +
+      "N_bsEYGu7KzjWTpTsUiHe-rN7izXVFxDGG1TGwlmBCBnPW-EFCf9ylUsJi0r2BKNdaaPRfMIrHptH1zJBkkUziWpBN1RNLjmvlAUf49" +
+      "t1Tbv21ZqYM5Ht2vrhJWczFbuC-TD-8zJkXhjTmA1GVgomIX5dx1cH-dZX1wANNmshUJGHgepWlPU-5VIYxPEhb219RMLJIELMY2qN" +
+      "OR8Q31ydinyqzXvCSzVJOf6T60-w"
+
+  private val INVALID_JWT_TOKEN: String =
+    "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZG1pbkBvcGVu" +
+      "thispartiscompletelywrong.reQc3DiVvbQHF08oW1qOUyDJyv3tfzDNk8jhVZequiCdOI9vXnRlOe" +
+      "-yDYktd4WT8MYhqY7MgS-wR0vO9jZFv8ZCgd_MkKCvCO0HmMjP5iQPZ0kqGkgWUH7X123tfR38MfbCVAdPDba-K3MfkogV1xvDhlkPScFr_6MxE" +
+      "xtedOK2JnQZn7t9sUzSrcyjWverm7gZkPptkIVoS8TsEeMMME5vFXe_nqkEG69q3kuBUm_33tbR5oNS0ZGZKlG9r41lHBjyf9J1xN4UYV8n866d" +
+      "a7RPPCzshIWUtO0q9T2umWTnp-6OnOdBCkndrZmRR6pPxsD5YL0_77Wq8KT_5__fGA"
+
+  private val USER: Username = Username.fromLocalPartWithDomain("user", DOMAIN)
+  private val USER_PASSWORD: String = "user"
+}
+
+trait JWTAuthenticationContract {
+  @BeforeEach
+  def setUp(server: GuiceJamesServer): Unit = {
+    server.getProbe(classOf[DataProbeImpl])
+      .fluent()
+      .addDomain(DOMAIN.asString())
+      .addUser(USER.asString(), USER_PASSWORD)
+
+    requestSpecification = baseRequestSpecBuilder(server)
+      .setAuth(new NoAuthScheme)
+      .build
+  }
+
+  @Tag(CategoryTags.BASIC_FEATURE)
+  @Test
+  def getMustReturnEndpointsWhenValidJwtAuthorizationHeader(): Unit = {
+    `given`
+      .headers(getHeadersWith(new Header(AUTHORIZATION_HEADER, s"Bearer $USER_TOKEN")))
+      .body(ECHO_REQUEST_OBJECT)
+    .when
+      .post()
+    .`then`
+      .statusCode(SC_OK)
+  }
+
+  @Test
+  @Tag(CategoryTags.BASIC_FEATURE)
+  def getMustReturnOKWhenValidUnknownUserJwtAuthorizationHeader(): Unit = {
+    val authHeader: Header = new Header(AUTHORIZATION_HEADER, s"Bearer $UNKNOWN_USER_TOKEN")
+    `given`()
+      .headers(getHeadersWith(authHeader))
+      .body(ECHO_REQUEST_OBJECT)
+    .when()
+      .post()
+    .then
+      .statusCode(SC_UNAUTHORIZED)
+  }
+
+  @Test
+  @Tag(CategoryTags.BASIC_FEATURE)
+  def getMustReturnBadCredentialsWhenInvalidJwtAuthorizationHeader(): Unit = {
+    `given`
+      .headers(getHeadersWith(new Header(AUTHORIZATION_HEADER, s"Bearer $INVALID_JWT_TOKEN")))
+      .body(ECHO_REQUEST_OBJECT)
+    .when
+      .post()
+    .`then`
+      .statusCode(SC_UNAUTHORIZED)
+  }
+}
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryAuthenticationTest.java b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryAuthenticationTest.java
index c99bf0f..5fd5b42 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryAuthenticationTest.java
+++ b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryAuthenticationTest.java
@@ -24,11 +24,11 @@ import static org.apache.james.MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_
 import org.apache.james.GuiceJamesServer;
 import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
-import org.apache.james.jmap.rfc8621.contract.AuthenticationContract;
+import org.apache.james.jmap.rfc8621.contract.BasicAuthenticationContract;
 import org.apache.james.modules.TestJMAPServerModule;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
-public class MemoryAuthenticationTest implements AuthenticationContract {
+public class MemoryAuthenticationTest implements BasicAuthenticationContract {
     @RegisterExtension
     static JamesServerExtension testExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
         .server(configuration -> GuiceJamesServer.forConfiguration(configuration)
diff --git a/server/protocols/jmap-rfc-8621/pom.xml b/server/protocols/jmap-rfc-8621/pom.xml
index feccb0c..0cf4eae 100644
--- a/server/protocols/jmap-rfc-8621/pom.xml
+++ b/server/protocols/jmap-rfc-8621/pom.xml
@@ -73,6 +73,10 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>james-server-jwt</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>metrics-tests</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/server/protocols/jmap/pom.xml b/server/protocols/jmap/pom.xml
index a052b80..37cc3db 100644
--- a/server/protocols/jmap/pom.xml
+++ b/server/protocols/jmap/pom.xml
@@ -32,11 +32,19 @@
     <dependencies>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>james-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>apache-james-mailbox-api</artifactId>
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
-            <artifactId>james-core</artifactId>
+            <artifactId>james-server-data-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>james-server-jwt</artifactId>
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
@@ -73,15 +81,15 @@
             <artifactId>javax.annotation-api</artifactId>
         </dependency>
         <dependency>
+            <groupId>javax.annotation</groupId>
+            <artifactId>javax.annotation-api</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.apache.httpcomponents</groupId>
             <artifactId>httpcore</artifactId>
             <version>4.4.13</version>
         </dependency>
         <dependency>
-            <groupId>javax.annotation</groupId>
-            <artifactId>javax.annotation-api</artifactId>
-        </dependency>
-        <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>jcl-over-slf4j</artifactId>
             <scope>test</scope>
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/exceptions/MailboxSessionCreationException.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/MailboxSessionCreationException.java
similarity index 96%
rename from server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/exceptions/MailboxSessionCreationException.java
rename to server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/MailboxSessionCreationException.java
index 8865c15..a1971c2 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/exceptions/MailboxSessionCreationException.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/exceptions/MailboxSessionCreationException.java
@@ -17,7 +17,7 @@
  * under the License.                                           *
  ****************************************************************/
 
-package org.apache.james.jmap.draft.exceptions;
+package org.apache.james.jmap.exceptions;
 
 public class MailboxSessionCreationException extends RuntimeException {
 
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/JWTAuthenticationStrategy.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/jwt/JWTAuthenticationStrategy.java
similarity index 88%
rename from server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/JWTAuthenticationStrategy.java
rename to server/protocols/jmap/src/main/java/org/apache/james/jmap/jwt/JWTAuthenticationStrategy.java
index 6f4a275..41566a7 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/http/JWTAuthenticationStrategy.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/jwt/JWTAuthenticationStrategy.java
@@ -16,14 +16,15 @@
  * specific language governing permissions and limitations      *
  * under the License.                                           *
  ****************************************************************/
-package org.apache.james.jmap.http;
+package org.apache.james.jmap.jwt;
 
 import java.util.stream.Stream;
 
 import javax.inject.Inject;
 
 import org.apache.james.core.Username;
-import org.apache.james.jmap.draft.exceptions.MailboxSessionCreationException;
+import org.apache.james.jmap.exceptions.MailboxSessionCreationException;
+import org.apache.james.jmap.http.AuthenticationStrategy;
 import org.apache.james.jwt.JwtTokenVerifier;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.MailboxSession;
@@ -37,14 +38,15 @@ import reactor.netty.http.server.HttpServerRequest;
 
 public class JWTAuthenticationStrategy implements AuthenticationStrategy {
 
-    @VisibleForTesting static final String AUTHORIZATION_HEADER_PREFIX = "Bearer ";
+    @VisibleForTesting
+    public static final String AUTHORIZATION_HEADER_PREFIX = "Bearer ";
     private final JwtTokenVerifier tokenManager;
     private final MailboxManager mailboxManager;
     private final UsersRepository usersRepository;
 
     @Inject
     @VisibleForTesting
-    JWTAuthenticationStrategy(JwtTokenVerifier tokenManager, MailboxManager mailboxManager, UsersRepository usersRepository) {
+    public JWTAuthenticationStrategy(JwtTokenVerifier tokenManager, MailboxManager mailboxManager, UsersRepository usersRepository) {
         this.tokenManager = tokenManager;
         this.mailboxManager = mailboxManager;
         this.usersRepository = usersRepository;


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