You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by bt...@apache.org on 2020/08/11 09:39:18 UTC

[james-project] 01/10: JAMES-3316 Configure session hardcoded prefixes

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

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

commit 989365f58ac6eaa72a98b35d76350ef247070da7
Author: duc91 <vd...@linagora.com>
AuthorDate: Tue Jul 28 17:36:38 2020 +0700

    JAMES-3316 Configure session hardcoded prefixes
---
 .../james/jmap/rfc8621/RFC8621MethodsModule.java   | 23 +++++++++
 .../src/test/resources/jmap.properties             |  2 +
 .../rfc8621/contract/SessionRoutesContract.scala   | 30 ++++++++---
 .../src/test/resources/jmap.properties             |  2 +
 .../org/apache/james/jmap/http/SessionRoutes.scala |  2 +-
 .../apache/james/jmap/http/SessionSupplier.scala   | 18 +++----
 .../jmap/model/JmapRfc8621Configuration.scala      | 43 ++++++++++++++++
 .../apache/james/jmap/http/SessionRoutesTest.scala | 16 +++---
 .../james/jmap/http/SessionSupplierTest.scala      |  5 +-
 .../scala/org/apache/james/jmap/json/Fixture.scala |  2 +-
 .../jmap/model/JmapRfc8621ConfigurationTest.scala  | 59 ++++++++++++++++++++++
 11 files changed, 172 insertions(+), 30 deletions(-)

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 4c856da..3012858 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
@@ -20,6 +20,12 @@
 package org.apache.james.jmap.rfc8621;
 
 
+import static org.apache.james.jmap.model.JmapRfc8621Configuration.LOCALHOST_CONFIGURATION;
+
+import java.io.FileNotFoundException;
+
+import org.apache.commons.configuration2.Configuration;
+import org.apache.commons.configuration2.ex.ConfigurationException;
 import org.apache.james.jmap.JMAPRoutesHandler;
 import org.apache.james.jmap.Version;
 import org.apache.james.jmap.http.Authenticator;
@@ -31,8 +37,12 @@ import org.apache.james.jmap.jwt.JWTAuthenticationStrategy;
 import org.apache.james.jmap.method.CoreEchoMethod;
 import org.apache.james.jmap.method.MailboxGetMethod;
 import org.apache.james.jmap.method.Method;
+import org.apache.james.jmap.model.JmapRfc8621Configuration;
 import org.apache.james.jmap.routes.JMAPApiRoutes;
 import org.apache.james.metrics.api.MetricFactory;
+import org.apache.james.utils.PropertiesProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.Provides;
@@ -43,6 +53,7 @@ import com.google.inject.multibindings.ProvidesIntoSet;
 import com.google.inject.name.Named;
 
 public class RFC8621MethodsModule extends AbstractModule {
+    private static final Logger LOGGER = LoggerFactory.getLogger(RFC8621MethodsModule.class);
 
     @Override
     protected void configure() {
@@ -69,4 +80,16 @@ public class RFC8621MethodsModule extends AbstractModule {
             basicAuthenticationStrategy,
             jwtAuthenticationStrategy);
     }
+
+    @Provides
+    @Singleton
+    JmapRfc8621Configuration provideConfiguration(PropertiesProvider propertiesProvider) throws ConfigurationException {
+        try {
+            Configuration configuration = propertiesProvider.getConfiguration("jmap");
+            return JmapRfc8621Configuration.from(configuration);
+        } catch (FileNotFoundException e) {
+            LOGGER.warn("Could not find JMAP configuration file [jmap.properties]. JMAP server will be enabled with default value.");
+            return LOCALHOST_CONFIGURATION();
+        }
+    }
 }
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/resources/jmap.properties b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/resources/jmap.properties
new file mode 100644
index 0000000..a0da434
--- /dev/null
+++ b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/resources/jmap.properties
@@ -0,0 +1,2 @@
+# Configuration urlPrefix for JMAP routes.
+url.prefix=http://domain.com
\ No newline at end of file
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/SessionRoutesContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/SessionRoutesContract.scala
index 274d660..02415ef 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/SessionRoutesContract.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/SessionRoutesContract.scala
@@ -18,21 +18,28 @@
  * ***************************************************************/
 package org.apache.james.jmap.rfc8621.contract
 
+import java.nio.charset.StandardCharsets
+
 import io.netty.handler.codec.http.HttpHeaderNames.ACCEPT
 import io.restassured.RestAssured._
+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.JSON
 import net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson
 import org.apache.http.HttpStatus.SC_OK
 import org.apache.james.GuiceJamesServer
+import org.apache.james.jmap.draft.JmapGuiceProbe
 import org.apache.james.jmap.http.UserCredential
 import org.apache.james.jmap.rfc8621.contract.Fixture._
-import org.apache.james.jmap.rfc8621.contract.SessionRoutesContract.expected_session_object
+import org.apache.james.jmap.rfc8621.contract.SessionRoutesContract.{EXPECTED_BASE_PATH, expected_session_object}
 import org.apache.james.jmap.rfc8621.contract.tags.CategoryTags
 import org.apache.james.utils.DataProbeImpl
 import org.junit.jupiter.api.{BeforeEach, Tag, Test}
 
 object SessionRoutesContract {
-  private val expected_session_object = """{
+  private val expected_session_object: String = """{
                          |  "capabilities" : {
                          |    "urn:ietf:params:jmap:core" : {
                          |      "maxSizeUpload" : 10000000,
@@ -91,12 +98,13 @@ object SessionRoutesContract {
                          |    "urn:apache:james:params:jmap:mail:shares": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6"
                          |  },
                          |  "username" : "bob@domain.tld",
-                         |  "apiUrl" : "http://this-url-is-hardcoded.org/jmap",
-                         |  "downloadUrl" : "http://this-url-is-hardcoded.org/download",
-                         |  "uploadUrl" : "http://this-url-is-hardcoded.org/upload",
-                         |  "eventSourceUrl" : "http://this-url-is-hardcoded.org/eventSource",
+                         |  "apiUrl" : "http://domain.com/jmap",
+                         |  "downloadUrl" : "http://domain.com/download",
+                         |  "uploadUrl" : "http://domain.com/upload",
+                         |  "eventSourceUrl" : "http://domain.com/eventSource",
                          |  "state" : "000001"
                          |}""".stripMargin
+  private val EXPECTED_BASE_PATH: String = "/jmap"
 }
 
 trait SessionRoutesContract {
@@ -109,7 +117,15 @@ trait SessionRoutesContract {
       .addUser(BOB.asString, BOB_PASSWORD)
       .addUser(ANDRE.asString, ANDRE_PASSWORD)
 
-    requestSpecification = baseRequestSpecBuilder(server)
+    val jmapGuiceProbe: JmapGuiceProbe = server.getProbe(classOf[JmapGuiceProbe])
+    requestSpecification = new RequestSpecBuilder()
+    .setContentType(ContentType.JSON)
+    .setAccept(ContentType.JSON)
+    .setConfig(newConfig.encoderConfig(encoderConfig.defaultContentCharset(StandardCharsets.UTF_8)))
+    .setPort(jmapGuiceProbe
+      .getJmapPort
+      .getValue)
+    .setBasePath(EXPECTED_BASE_PATH)
         .setAuth(authScheme(UserCredential(BOB, BOB_PASSWORD)))
       .build
   }
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/resources/jmap.properties b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/resources/jmap.properties
new file mode 100644
index 0000000..a0da434
--- /dev/null
+++ b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/resources/jmap.properties
@@ -0,0 +1,2 @@
+# Configuration urlPrefix for JMAP routes.
+url.prefix=http://domain.com
\ No newline at end of file
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/http/SessionRoutes.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/http/SessionRoutes.scala
index 047e8da..557282f 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/http/SessionRoutes.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/http/SessionRoutes.scala
@@ -48,7 +48,7 @@ object SessionRoutes {
 
 class SessionRoutes @Inject() (@Named(InjectionKeys.RFC_8621) val authenticator: Authenticator,
                     val serializer: Serializer,
-                    val sessionSupplier: SessionSupplier = new SessionSupplier()) extends JMAPRoutes {
+                    val sessionSupplier: SessionSupplier) extends JMAPRoutes {
 
   private val generateSession: JMAPRoute.Action =
     (request, response) => SMono.fromPublisher(authenticator.authenticate(request))
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/http/SessionSupplier.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/http/SessionSupplier.scala
index 191480a..40fc252 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/http/SessionSupplier.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/http/SessionSupplier.scala
@@ -19,19 +19,13 @@
 
 package org.apache.james.jmap.http
 
-import java.net.URL
-
+import javax.inject.Inject
 import org.apache.james.core.Username
-import org.apache.james.jmap.http.SessionSupplier.HARD_CODED_URL_PREFIX
 import org.apache.james.jmap.model.CapabilityIdentifier.CapabilityIdentifier
 import org.apache.james.jmap.model._
 import reactor.core.scala.publisher.SMono
 
-object SessionSupplier {
-  private val HARD_CODED_URL_PREFIX = "http://this-url-is-hardcoded.org"
-}
-
-class SessionSupplier {
+class SessionSupplier @Inject() (val configuration: JmapRfc8621Configuration){
   def generate(username: Username): SMono[Session] = {
     accounts(username)
       .map(account => Session(
@@ -39,10 +33,10 @@ class SessionSupplier {
         List(account),
         primaryAccounts(account.accountId),
         username,
-        apiUrl = new URL(s"$HARD_CODED_URL_PREFIX/jmap"),
-        downloadUrl = new URL(s"$HARD_CODED_URL_PREFIX/download"),
-        uploadUrl = new URL(s"$HARD_CODED_URL_PREFIX/upload"),
-        eventSourceUrl = new URL(s"$HARD_CODED_URL_PREFIX/eventSource")))
+        apiUrl = configuration.apiUrl,
+        downloadUrl = configuration.downloadUrl,
+        uploadUrl = configuration.uploadUrl,
+        eventSourceUrl = configuration.eventSourceUrl))
   }
 
   private def accounts(username: Username): SMono[Account] = SMono.defer(() =>
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/model/JmapRfc8621Configuration.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/model/JmapRfc8621Configuration.scala
new file mode 100644
index 0000000..dbd5654
--- /dev/null
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/model/JmapRfc8621Configuration.scala
@@ -0,0 +1,43 @@
+/****************************************************************
+ * 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.model
+
+import java.net.URL
+
+import eu.timepit.refined.api.Refined
+import org.apache.commons.configuration2.Configuration
+
+object JmapRfc8621Configuration {
+  val LOCALHOST_URL_PREFIX: String = "http://localhost"
+  private def from(urlPrefixString: String): JmapRfc8621Configuration = JmapRfc8621Configuration(urlPrefixString)
+  var LOCALHOST_CONFIGURATION: JmapRfc8621Configuration = from(LOCALHOST_URL_PREFIX)
+  val URL_PREFIX_PROPERTIES: String = "url.prefix"
+
+  def from(configuration: Configuration): JmapRfc8621Configuration =
+    JmapRfc8621Configuration(Option(configuration.getString(URL_PREFIX_PROPERTIES)).getOrElse(LOCALHOST_URL_PREFIX))
+}
+
+case class JmapRfc8621Configuration(urlPrefixString: String) {
+  val urlPrefix: URL = new URL(urlPrefixString)
+  val apiUrl: URL = new URL(s"$urlPrefixString/jmap")
+  val downloadUrl: URL = new URL(s"$urlPrefixString/download")
+  val uploadUrl: URL = new URL(s"$urlPrefixString/upload")
+  val eventSourceUrl: URL = new URL(s"$urlPrefixString/eventSource")
+}
diff --git a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/http/SessionRoutesTest.scala b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/http/SessionRoutesTest.scala
index d1f4a77..f2fbb07 100644
--- a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/http/SessionRoutesTest.scala
+++ b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/http/SessionRoutesTest.scala
@@ -27,11 +27,13 @@ import io.restassured.builder.RequestSpecBuilder
 import io.restassured.config.EncoderConfig.encoderConfig
 import io.restassured.config.RestAssuredConfig.newConfig
 import io.restassured.http.ContentType
+import net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson
 import org.apache.http.HttpStatus
 import org.apache.james.core.Username
 import org.apache.james.jmap._
 import org.apache.james.jmap.http.SessionRoutesTest.{BOB, TEST_CONFIGURATION}
 import org.apache.james.jmap.json.Serializer
+import org.apache.james.jmap.model.JmapRfc8621Configuration
 import org.apache.james.mailbox.MailboxSession
 import org.apache.james.mailbox.model.TestId
 import org.mockito.ArgumentMatchers.any
@@ -65,7 +67,7 @@ class SessionRoutesTest extends AnyFlatSpec with BeforeAndAfter with Matchers {
 
     val sessionRoutes = new SessionRoutes(
       serializer = new Serializer(new TestId.Factory),
-      sessionSupplier = new SessionSupplier(),
+      sessionSupplier = new SessionSupplier(JmapRfc8621Configuration.LOCALHOST_CONFIGURATION),
       authenticator = mockedAuthFilter)
     jmapServer = new JMAPServer(
       TEST_CONFIGURATION,
@@ -100,7 +102,7 @@ class SessionRoutesTest extends AnyFlatSpec with BeforeAndAfter with Matchers {
       .thenReturn
         .getBody
         .asString()
-    val expectedJson = """{
+    val expectedJson = s"""{
                          |  "capabilities" : {
                          |    "urn:ietf:params:jmap:core" : {
                          |      "maxSizeUpload" : 10000000,
@@ -159,13 +161,13 @@ class SessionRoutesTest extends AnyFlatSpec with BeforeAndAfter with Matchers {
                          |    "urn:apache:james:params:jmap:mail:shares": "0fe275bf13ff761407c17f64b1dfae2f4b3186feea223d7267b79f873a105401"
                          |  },
                          |  "username" : "bob@james.org",
-                         |  "apiUrl" : "http://this-url-is-hardcoded.org/jmap",
-                         |  "downloadUrl" : "http://this-url-is-hardcoded.org/download",
-                         |  "uploadUrl" : "http://this-url-is-hardcoded.org/upload",
-                         |  "eventSourceUrl" : "http://this-url-is-hardcoded.org/eventSource",
+                         |  "apiUrl" : "${JmapRfc8621Configuration.LOCALHOST_URL_PREFIX}/jmap",
+                         |  "downloadUrl" : "${JmapRfc8621Configuration.LOCALHOST_URL_PREFIX}/download",
+                         |  "uploadUrl" : "${JmapRfc8621Configuration.LOCALHOST_URL_PREFIX}/upload",
+                         |  "eventSourceUrl" : "${JmapRfc8621Configuration.LOCALHOST_URL_PREFIX}/eventSource",
                          |  "state" : "000001"
                          |}""".stripMargin
 
-    Json.parse(sessionJson) should equal(Json.parse(expectedJson))
+    assertThatJson(sessionJson).isEqualTo(expectedJson)
   }
 }
diff --git a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/http/SessionSupplierTest.scala b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/http/SessionSupplierTest.scala
index 11bd415..71f00d0 100644
--- a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/http/SessionSupplierTest.scala
+++ b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/http/SessionSupplierTest.scala
@@ -21,6 +21,7 @@ package org.apache.james.jmap.http
 
 import org.apache.james.core.Username
 import org.apache.james.jmap.http.SessionSupplierTest.USERNAME
+import org.apache.james.jmap.model.JmapRfc8621Configuration
 import org.scalatest.matchers.should.Matchers
 import org.scalatest.wordspec.AnyWordSpec
 
@@ -32,11 +33,11 @@ class SessionSupplierTest extends AnyWordSpec with Matchers {
 
   "generate" should {
     "return correct username" in {
-      new SessionSupplier().generate(USERNAME).block().username should equal(USERNAME)
+      new SessionSupplier(JmapRfc8621Configuration.LOCALHOST_CONFIGURATION).generate(USERNAME).block().username should equal(USERNAME)
     }
 
     "return correct account" which {
-      val accounts = new SessionSupplier().generate(USERNAME).block().accounts
+      val accounts = new SessionSupplier(JmapRfc8621Configuration.LOCALHOST_CONFIGURATION).generate(USERNAME).block().accounts
 
       "has size" in {
         accounts should have size 1
diff --git a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/json/Fixture.scala b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/json/Fixture.scala
index c1c1d79..e249535 100644
--- a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/json/Fixture.scala
+++ b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/json/Fixture.scala
@@ -24,7 +24,7 @@ import org.apache.james.jmap.model.CapabilityIdentifier.CapabilityIdentifier
 import org.apache.james.jmap.model.Id.Id
 import org.apache.james.jmap.model.Invocation.{Arguments, MethodCallId, MethodName}
 import org.apache.james.jmap.model.{ClientId, CreatedIds, Invocation, ResponseObject, ServerId}
-import play.api.libs.json.{JsValue, Json}
+import play.api.libs.json.Json
 
 object Fixture {
   val id: Id = "aHR0cHM6Ly93d3cuYmFzZTY0ZW5jb2RlLm9yZy8"
diff --git a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/model/JmapRfc8621ConfigurationTest.scala b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/model/JmapRfc8621ConfigurationTest.scala
new file mode 100644
index 0000000..16af554
--- /dev/null
+++ b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/model/JmapRfc8621ConfigurationTest.scala
@@ -0,0 +1,59 @@
+/****************************************************************
+ * 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.model
+
+import java.net.URL
+
+import org.apache.commons.configuration2.{Configuration, PropertiesConfiguration}
+import org.apache.james.jmap.model.JmapRfc8621Configuration.URL_PREFIX_PROPERTIES
+import org.apache.james.jmap.model.JmapRfc8621ConfigurationTest.{emptyConfiguration, providedConfiguration}
+import org.scalatest.matchers.must.Matchers
+import org.scalatest.wordspec.AnyWordSpec
+
+object JmapRfc8621ConfigurationTest {
+  val emptyConfiguration: Configuration = new PropertiesConfiguration()
+  def providedConfiguration(): Configuration = {
+    val configuration: Configuration = new PropertiesConfiguration()
+    configuration.addProperty(URL_PREFIX_PROPERTIES, "http://random-domain.com")
+    configuration
+  }
+}
+
+class JmapRfc8621ConfigurationTest extends AnyWordSpec with Matchers {
+  "JmapRfc8621ConfigurationTest" should {
+    "succeed to configuration urlPrefix when provided" in {
+      val jmapRfc8621Configuration: JmapRfc8621Configuration = JmapRfc8621Configuration.from(providedConfiguration())
+
+      jmapRfc8621Configuration.apiUrl must be(new URL("http://random-domain.com/jmap"))
+      jmapRfc8621Configuration.downloadUrl must be(new URL("http://random-domain.com/download"))
+      jmapRfc8621Configuration.uploadUrl must be(new URL("http://random-domain.com/upload"))
+      jmapRfc8621Configuration.eventSourceUrl must be(new URL("http://random-domain.com/eventSource"))
+    }
+
+    "load default config for urlPrefix when no configuration provided" in {
+      val jmapRfc8621Configuration: JmapRfc8621Configuration = JmapRfc8621Configuration.from(emptyConfiguration)
+
+      jmapRfc8621Configuration.apiUrl must be(new URL("http://localhost/jmap"))
+      jmapRfc8621Configuration.downloadUrl must be(new URL("http://localhost/download"))
+      jmapRfc8621Configuration.uploadUrl must be(new URL("http://localhost/upload"))
+      jmapRfc8621Configuration.eventSourceUrl must be(new URL("http://localhost/eventSource"))
+    }
+  }
+}


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