You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by bt...@apache.org on 2020/11/23 08:20:04 UTC
[james-project] 05/19: JAMES-2884 Configure default JMAP version
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 f6594105783b424157b7c761d0fa022c97402055
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Sat Nov 21 08:02:43 2020 +0700
JAMES-2884 Configure default JMAP version
---
.../servers/pages/distributed/configure/jmap.adoc | 6 ++++++
.../org/apache/james/jmap/draft/JMAPModule.java | 4 +++-
.../james/jmap/routes/JMAPApiRoutesTest.scala | 4 ++--
.../james/jmap/routes/SessionRoutesTest.scala | 2 +-
.../org/apache/james/jmap/JMAPConfiguration.java | 24 +++++++++++++++++++---
.../main/java/org/apache/james/jmap/Version.java | 4 ++++
.../java/org/apache/james/jmap/VersionParser.java | 9 ++++++--
.../apache/james/jmap/JMAPConfigurationTest.java | 6 +++---
.../java/org/apache/james/jmap/JMAPServerTest.java | 12 +++++------
.../org/apache/james/jmap/VersionParserTest.java | 2 +-
src/site/xdoc/server/config-jmap.xml | 6 ++++++
11 files changed, 60 insertions(+), 19 deletions(-)
diff --git a/docs/modules/servers/pages/distributed/configure/jmap.adoc b/docs/modules/servers/pages/distributed/configure/jmap.adoc
index 5ab56a9..6650de7 100644
--- a/docs/modules/servers/pages/distributed/configure/jmap.adoc
+++ b/docs/modules/servers/pages/distributed/configure/jmap.adoc
@@ -42,6 +42,12 @@ This should not be the same keystore than the ones used by TLS based protocols.
| Should simple Email/query be resolved against a Cassandra projection, or should we resolve them against ElasticSearch?
This enables a higher resilience, but the projection needs to be correctly populated.
+| jmap.version.default
+| Optional string. Defaults to draft. Allowed values: draft, rfc-8621.
+| Which version of the JMAP protocol should be served when none supplied in the Accept header.
+Defaults to draft for legacy reasons (avoid breaking changes) but setting the value to
+rfc-8621 allow compatibility with other third party apps.
+
|===
== Wire tapping
diff --git a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JMAPModule.java b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JMAPModule.java
index 91cf4bf..49613ca 100644
--- a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JMAPModule.java
+++ b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JMAPModule.java
@@ -133,13 +133,15 @@ public class JMAPModule extends AbstractModule {
@Provides
@Singleton
- JMAPConfiguration provideConfiguration(PropertiesProvider propertiesProvider) throws ConfigurationException, IOException {
+ JMAPConfiguration provideConfiguration(PropertiesProvider propertiesProvider) throws ConfigurationException {
try {
Configuration configuration = propertiesProvider.getConfiguration("jmap");
return JMAPConfiguration.builder()
.enabled(configuration.getBoolean("enabled", true))
.port(Port.of(configuration.getInt("jmap.port", DEFAULT_JMAP_PORT)))
.enableEmailQueryView(Optional.ofNullable(configuration.getBoolean("view.email.query.enabled", null)))
+ .defaultVersion(Optional.ofNullable(configuration.getString("jmap.version.default", null))
+ .map(Version::of))
.build();
} catch (FileNotFoundException e) {
LOGGER.warn("Could not find JMAP configuration file. JMAP server will not be enabled.");
diff --git a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/routes/JMAPApiRoutesTest.scala b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/routes/JMAPApiRoutesTest.scala
index 8521824..eb64f27 100644
--- a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/routes/JMAPApiRoutesTest.scala
+++ b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/routes/JMAPApiRoutesTest.scala
@@ -255,7 +255,7 @@ class JMAPApiRoutesTest extends AnyFlatSpec with BeforeAndAfter with Matchers {
var jmapServer: JMAPServer = _
before {
- val versionParser: VersionParser = new VersionParser(SUPPORTED_VERSIONS)
+ val versionParser: VersionParser = new VersionParser(SUPPORTED_VERSIONS, JMAPConfiguration.DEFAULT)
jmapServer = new JMAPServer(TEST_CONFIGURATION, ROUTES_HANDLER, versionParser)
jmapServer.start()
@@ -446,7 +446,7 @@ class JMAPApiRoutesTest extends AnyFlatSpec with BeforeAndAfter with Matchers {
val apiRoute: JMAPApiRoutes = new JMAPApiRoutes(AUTHENTICATOR, userProvisionner, mailboxesProvisioner, methods)
val routesHandler: ImmutableSet[JMAPRoutesHandler] = ImmutableSet.of(new JMAPRoutesHandler(Version.RFC8621, apiRoute))
- val versionParser: VersionParser = new VersionParser(SUPPORTED_VERSIONS)
+ val versionParser: VersionParser = new VersionParser(SUPPORTED_VERSIONS, JMAPConfiguration.DEFAULT)
jmapServer = new JMAPServer(TEST_CONFIGURATION, routesHandler, versionParser)
jmapServer.start()
diff --git a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/routes/SessionRoutesTest.scala b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/routes/SessionRoutesTest.scala
index 6cab55a..7a27623 100644
--- a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/routes/SessionRoutesTest.scala
+++ b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/routes/SessionRoutesTest.scala
@@ -70,7 +70,7 @@ class SessionRoutesTest extends AnyFlatSpec with BeforeAndAfter with Matchers {
jmapServer = new JMAPServer(
TEST_CONFIGURATION,
Set(new JMAPRoutesHandler(Version.RFC8621, sessionRoutes)).asJava,
- new VersionParser(Set(Version.RFC8621).asJava))
+ new VersionParser(Set(Version.RFC8621, Version.DRAFT).asJava, JMAPConfiguration.DEFAULT))
jmapServer.start()
RestAssured.requestSpecification = new RequestSpecBuilder()
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPConfiguration.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPConfiguration.java
index 5b7c729..0eaeb3f 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPConfiguration.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPConfiguration.java
@@ -35,6 +35,7 @@ public class JMAPConfiguration {
private Optional<Boolean> enabled = Optional.empty();
private Optional<Boolean> emailQueryViewEnabled = Optional.empty();
private Optional<Port> port = Optional.empty();
+ private Optional<Version> defaultVersion = Optional.empty();
private Builder() {
@@ -75,6 +76,15 @@ public class JMAPConfiguration {
return this;
}
+ public Builder defaultVersion(Version defaultVersion) {
+ return defaultVersion(Optional.of(defaultVersion));
+ }
+
+ public Builder defaultVersion(Optional<Version> defaultVersion) {
+ this.defaultVersion = defaultVersion;
+ return this;
+ }
+
public Builder randomPort() {
this.port = Optional.empty();
return this;
@@ -82,20 +92,24 @@ public class JMAPConfiguration {
public JMAPConfiguration build() {
Preconditions.checkState(enabled.isPresent(), "You should specify if JMAP server should be started");
- return new JMAPConfiguration(enabled.get(), port, emailQueryViewEnabled.orElse(false));
+ return new JMAPConfiguration(enabled.get(), port, emailQueryViewEnabled.orElse(false),
+ defaultVersion.orElse(Version.DRAFT));
}
-
}
+ public static JMAPConfiguration DEFAULT = JMAPConfiguration.builder().enable().build();
+
private final boolean enabled;
private final Optional<Port> port;
private final boolean emailQueryViewEnabled;
+ private final Version defaultVersion;
@VisibleForTesting
- JMAPConfiguration(boolean enabled, Optional<Port> port, boolean emailQueryViewEnabled) {
+ JMAPConfiguration(boolean enabled, Optional<Port> port, boolean emailQueryViewEnabled, Version defaultVersion) {
this.enabled = enabled;
this.port = port;
this.emailQueryViewEnabled = emailQueryViewEnabled;
+ this.defaultVersion = defaultVersion;
}
public boolean isEnabled() {
@@ -109,4 +123,8 @@ public class JMAPConfiguration {
public boolean isEmailQueryViewEnabled() {
return emailQueryViewEnabled;
}
+
+ public Version getDefaultVersion() {
+ return defaultVersion;
+ }
}
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/Version.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/Version.java
index 7fe2ef5..5437789 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/Version.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/Version.java
@@ -25,6 +25,10 @@ public class Version {
public static final Version DRAFT = new Version("draft");
public static final Version RFC8621 = new Version("rfc-8621");
+ public static Version of(String value) {
+ return new Version(value);
+ }
+
private final String version;
Version(String version) {
diff --git a/server/protocols/jmap/src/main/java/org/apache/james/jmap/VersionParser.java b/server/protocols/jmap/src/main/java/org/apache/james/jmap/VersionParser.java
index 0368679..1e9c8ac 100644
--- a/server/protocols/jmap/src/main/java/org/apache/james/jmap/VersionParser.java
+++ b/server/protocols/jmap/src/main/java/org/apache/james/jmap/VersionParser.java
@@ -39,9 +39,14 @@ public class VersionParser {
private static final String JMAP_VERSION_HEADER = "jmapVersion";
private final Set<Version> supportedVersions;
+ private final JMAPConfiguration jmapConfiguration;
@Inject
- public VersionParser(Set<Version> supportedVersions) {
+ public VersionParser(Set<Version> supportedVersions, JMAPConfiguration jmapConfiguration) {
+ this.jmapConfiguration = jmapConfiguration;
+ Preconditions.checkArgument(supportedVersions.contains(jmapConfiguration.getDefaultVersion()),
+ jmapConfiguration + " is not a supported JMAP version");
+
this.supportedVersions = supportedVersions;
}
@@ -61,7 +66,7 @@ public class VersionParser {
.map(NameValuePair::getValue)
.map(this::parse)
.findFirst()
- .orElse(Version.DRAFT);
+ .orElse(jmapConfiguration.getDefaultVersion());
}
private Stream<NameValuePair> asVersion(HttpServerRequest request) {
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/JMAPConfigurationTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/JMAPConfigurationTest.java
index 011f774..af5e159 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/JMAPConfigurationTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/JMAPConfigurationTest.java
@@ -41,7 +41,7 @@ class JMAPConfigurationTest {
@Test
void buildShouldWorkWhenRandomPort() {
- JMAPConfiguration expectedJMAPConfiguration = new JMAPConfiguration(ENABLED, Optional.empty(), ENABLED);
+ JMAPConfiguration expectedJMAPConfiguration = new JMAPConfiguration(ENABLED, Optional.empty(), ENABLED, Version.DRAFT);
JMAPConfiguration jmapConfiguration = JMAPConfiguration.builder()
.enable()
@@ -53,7 +53,7 @@ class JMAPConfigurationTest {
@Test
void buildShouldWorkWhenFixedPort() {
- JMAPConfiguration expectedJMAPConfiguration = new JMAPConfiguration(ENABLED, Optional.of(Port.of(80)), ENABLED);
+ JMAPConfiguration expectedJMAPConfiguration = new JMAPConfiguration(ENABLED, Optional.of(Port.of(80)), ENABLED, Version.DRAFT);
JMAPConfiguration jmapConfiguration = JMAPConfiguration.builder()
.enable()
@@ -66,7 +66,7 @@ class JMAPConfigurationTest {
@Test
void buildShouldWorkWhenDisabled() {
- JMAPConfiguration expectedJMAPConfiguration = new JMAPConfiguration(DISABLED, Optional.empty(), DISABLED);
+ JMAPConfiguration expectedJMAPConfiguration = new JMAPConfiguration(DISABLED, Optional.empty(), DISABLED, Version.DRAFT);
JMAPConfiguration jmapConfiguration = JMAPConfiguration.builder()
.disable()
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/JMAPServerTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/JMAPServerTest.java
index 6fd242b..207e12a 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/JMAPServerTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/JMAPServerTest.java
@@ -88,7 +88,7 @@ class JMAPServerTest {
@Test
void serverShouldAnswerWhenStarted() {
- VersionParser versionParser = new VersionParser(SUPPORTED_VERSIONS);
+ VersionParser versionParser = new VersionParser(SUPPORTED_VERSIONS, JMAPConfiguration.DEFAULT);
JMAPServer jmapServer = new JMAPServer(TEST_CONFIGURATION, NO_ROUTES_HANDLERS, versionParser);
jmapServer.start();
@@ -107,7 +107,7 @@ class JMAPServerTest {
@Test
void startShouldNotThrowWhenConfigurationDisabled() {
- VersionParser versionParser = new VersionParser(SUPPORTED_VERSIONS);
+ VersionParser versionParser = new VersionParser(SUPPORTED_VERSIONS, JMAPConfiguration.DEFAULT);
JMAPServer jmapServer = new JMAPServer(DISABLED_CONFIGURATION, NO_ROUTES_HANDLERS, versionParser);
assertThatCode(jmapServer::start).doesNotThrowAnyException();
@@ -115,7 +115,7 @@ class JMAPServerTest {
@Test
void stopShouldNotThrowWhenConfigurationDisabled() {
- VersionParser versionParser = new VersionParser(SUPPORTED_VERSIONS);
+ VersionParser versionParser = new VersionParser(SUPPORTED_VERSIONS, JMAPConfiguration.DEFAULT);
JMAPServer jmapServer = new JMAPServer(DISABLED_CONFIGURATION, NO_ROUTES_HANDLERS, versionParser);
jmapServer.start();
@@ -124,7 +124,7 @@ class JMAPServerTest {
@Test
void getPortShouldThrowWhenServerIsNotStarted() {
- VersionParser versionParser = new VersionParser(SUPPORTED_VERSIONS);
+ VersionParser versionParser = new VersionParser(SUPPORTED_VERSIONS, JMAPConfiguration.DEFAULT);
JMAPServer jmapServer = new JMAPServer(TEST_CONFIGURATION, NO_ROUTES_HANDLERS, versionParser);
assertThatThrownBy(jmapServer::getPort)
@@ -133,7 +133,7 @@ class JMAPServerTest {
@Test
void getPortShouldThrowWhenDisabledConfiguration() {
- VersionParser versionParser = new VersionParser(SUPPORTED_VERSIONS);
+ VersionParser versionParser = new VersionParser(SUPPORTED_VERSIONS, JMAPConfiguration.DEFAULT);
JMAPServer jmapServer = new JMAPServer(DISABLED_CONFIGURATION, NO_ROUTES_HANDLERS, versionParser);
jmapServer.start();
@@ -147,7 +147,7 @@ class JMAPServerTest {
@BeforeEach
void setUp() {
- VersionParser versionParser = new VersionParser(SUPPORTED_VERSIONS);
+ VersionParser versionParser = new VersionParser(SUPPORTED_VERSIONS, JMAPConfiguration.DEFAULT);
server = new JMAPServer(TEST_CONFIGURATION, FAKE_ROUTES_HANDLERS, versionParser);
server.start();
diff --git a/server/protocols/jmap/src/test/java/org/apache/james/jmap/VersionParserTest.java b/server/protocols/jmap/src/test/java/org/apache/james/jmap/VersionParserTest.java
index 17e1882..5709620 100644
--- a/server/protocols/jmap/src/test/java/org/apache/james/jmap/VersionParserTest.java
+++ b/server/protocols/jmap/src/test/java/org/apache/james/jmap/VersionParserTest.java
@@ -37,7 +37,7 @@ class VersionParserTest {
@BeforeEach
void setUp() {
- versionParser = new VersionParser(SUPPORTED_VERSIONS);
+ versionParser = new VersionParser(SUPPORTED_VERSIONS, JMAPConfiguration.DEFAULT);
}
@Test
diff --git a/src/site/xdoc/server/config-jmap.xml b/src/site/xdoc/server/config-jmap.xml
index ef03111..77c5326 100644
--- a/src/site/xdoc/server/config-jmap.xml
+++ b/src/site/xdoc/server/config-jmap.xml
@@ -69,6 +69,12 @@
<dd>Optional boolean. Defaults to false.</dd>
<dd>Should simple Email/query be resolved against a Cassandra projection, or should we resolve them against ElasticSearch?
This enables a higher resilience, but the projection needs to be correctly populated.</dd>
+
+ <dt><strong>jmap.version.default</strong></dt>
+ <dd>Optional string. Defaults to draft. Allowed values: draft, rfc-8621.</dd>
+ <dd>Which version of the JMAP protocol should be served when none supplied in the Accept header.
+ Defaults to draft for legacy reasons (avoid breaking changes) but setting the value to
+ rfc-8621 allow compatibility with other third party apps.</dd>
</dl>
</subsection>
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org