From b14d8d8b1cad11c0786127567f457642c4ccd667 Mon Sep 17 00:00:00 2001 From: Benoit TELLIER Date: Wed, 11 Sep 2024 21:22:08 +0200 Subject: [PATCH] JAMES-3950 Remove disabled capabilities from session --- .../contract/DisabledCapabilityContract.scala | 99 +++++++++++++++++++ .../james/jmap/routes/SessionSupplier.scala | 9 +- .../james/jmap/routes/SessionRoutesTest.scala | 2 +- .../jmap/routes/SessionSupplierTest.scala | 4 +- 4 files changed, 107 insertions(+), 7 deletions(-) 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/DisabledCapabilityContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/DisabledCapabilityContract.scala index f18a2546232..355552b82ea 100644 --- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/DisabledCapabilityContract.scala +++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/DisabledCapabilityContract.scala @@ -29,6 +29,7 @@ import org.apache.james.jmap.core.ResponseObject.SESSION_STATE import org.apache.james.jmap.core.{CapabilityIdentifier, JmapRfc8621Configuration} 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.utils.DataProbeImpl import org.junit.jupiter.api.{BeforeEach, Test} @@ -36,6 +37,88 @@ object DisabledCapabilityContract { val configuration: JmapRfc8621Configuration = JmapRfc8621Configuration(urlPrefixString = "http://127.0.0.1", websocketPrefixString = "ws://127.0.0.1", disabledCapabilities = Set(CapabilityIdentifier.JMAP_MAIL)) + val expected_session_object: String = + """{ + | "capabilities" : { + | "urn:ietf:params:jmap:submission": { + | "maxDelayedSend": 0, + | "submissionExtensions": {} + | }, + | "urn:ietf:params:jmap:core" : { + | "maxSizeUpload" : 31457280, + | "maxConcurrentUpload" : 4, + | "maxSizeRequest" : 10000000, + | "maxConcurrentRequests" : 4, + | "maxCallsInRequest" : 16, + | "maxObjectsInGet" : 500, + | "maxObjectsInSet" : 500, + | "collationAlgorithms" : [ "i;unicode-casemap" ] + | }, + | "urn:ietf:params:jmap:websocket": { + | "supportsPush": true, + | "url": "ws://127.0.0.1/jmap/ws" + | }, + | "urn:apache:james:params:jmap:mail:quota": {}, + | "urn:ietf:params:jmap:quota": {}, + | "urn:apache:james:params:jmap:mail:identity:sortorder": {}, + | "urn:apache:james:params:jmap:delegation": {}, + | "urn:apache:james:params:jmap:mail:shares": {}, + | "urn:ietf:params:jmap:vacationresponse":{}, + | "urn:ietf:params:jmap:mdn":{} + | }, + | "accounts" : { + | "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6" : { + | "name" : "bob@domain.tld", + | "isPersonal" : true, + | "isReadOnly" : false, + | "accountCapabilities" : { + | "urn:ietf:params:jmap:submission": { + | "maxDelayedSend": 0, + | "submissionExtensions": {} + | }, + | "urn:ietf:params:jmap:websocket": { + | "supportsPush": true, + | "url": "ws://127.0.0.1/jmap/ws" + | }, + | "urn:ietf:params:jmap:core" : { + | "maxSizeUpload" : 31457280, + | "maxConcurrentUpload" : 4, + | "maxSizeRequest" : 10000000, + | "maxConcurrentRequests" : 4, + | "maxCallsInRequest" : 16, + | "maxObjectsInGet" : 500, + | "maxObjectsInSet" : 500, + | "collationAlgorithms" : [ "i;unicode-casemap" ] + | }, + | "urn:apache:james:params:jmap:mail:quota": {}, + | "urn:ietf:params:jmap:quota": {}, + | "urn:apache:james:params:jmap:mail:identity:sortorder": {}, + | "urn:apache:james:params:jmap:delegation": {}, + | "urn:apache:james:params:jmap:mail:shares": {}, + | "urn:ietf:params:jmap:vacationresponse":{}, + | "urn:ietf:params:jmap:mdn":{} + | } + | } + | }, + | "primaryAccounts" : { + | "urn:ietf:params:jmap:submission": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", + | "urn:ietf:params:jmap:websocket": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", + | "urn:ietf:params:jmap:core" : "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", + | "urn:apache:james:params:jmap:mail:quota": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", + | "urn:ietf:params:jmap:quota": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", + | "urn:apache:james:params:jmap:mail:identity:sortorder": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", + | "urn:apache:james:params:jmap:delegation": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", + | "urn:apache:james:params:jmap:mail:shares": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", + | "urn:ietf:params:jmap:vacationresponse": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", + | "urn:ietf:params:jmap:mdn": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6" + | }, + | "username" : "bob@domain.tld", + | "apiUrl" : "http://127.0.0.1/jmap", + | "downloadUrl" : "http://127.0.0.1/download/{accountId}/{blobId}?type={type}&name={name}", + | "uploadUrl" : "http://127.0.0.1/upload/{accountId}", + | "eventSourceUrl" : "http://127.0.0.1/eventSource?types={types}&closeAfter={closeafter}&ping={ping}", + | "state" : "2c9f1b12-b35a-43e6-9af2-0106fb53a943" + |}""".stripMargin } trait DisabledCapabilityContract { @@ -92,4 +175,20 @@ trait DisabledCapabilityContract { | "c1"]] |}""".stripMargin) } + + @Test + def getShouldReturnCorrectSession(): Unit = { + val sessionJson: String = `given`() + .when() + .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) + .get("/session") + .`then` + .statusCode(SC_OK) + .contentType(JSON) + .extract() + .body() + .asString() + + assertThatJson(sessionJson).isEqualTo(DisabledCapabilityContract.expected_session_object) + } } diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/routes/SessionSupplier.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/routes/SessionSupplier.scala index 7827265e3ac..ea7e101dc47 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/routes/SessionSupplier.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/routes/SessionSupplier.scala @@ -25,14 +25,14 @@ import cats.instances.list._ import jakarta.inject.Inject import org.apache.james.core.Username import org.apache.james.jmap.core.CapabilityIdentifier.CapabilityIdentifier -import org.apache.james.jmap.core.{Account, AccountId, Capabilities, Capability, CapabilityFactory, IsPersonal, IsReadOnly, Session, URL, UrlPrefixes} +import org.apache.james.jmap.core.{Account, AccountId, Capabilities, Capability, CapabilityFactory, IsPersonal, IsReadOnly, JmapRfc8621Configuration, Session, URL, UrlPrefixes} import scala.jdk.CollectionConverters._ -class SessionSupplier(capabilityFactories: Set[CapabilityFactory]) { +class SessionSupplier(capabilityFactories: Set[CapabilityFactory], configuration: JmapRfc8621Configuration) { @Inject - def this(defaultCapabilities: java.util.Set[CapabilityFactory]) = { - this(defaultCapabilities.asScala.toSet) + def this(defaultCapabilities: java.util.Set[CapabilityFactory], configuration: JmapRfc8621Configuration) = { + this(defaultCapabilities.asScala.toSet, configuration) } def validate(username: Username, accountId: AccountId): Boolean = AccountId.from(username) @@ -44,6 +44,7 @@ class SessionSupplier(capabilityFactories: Set[CapabilityFactory]) { val urlEndpointResolver: JmapUrlEndpointResolver = new JmapUrlEndpointResolver(urlPrefixes) val capabilities: Set[Capability] = capabilityFactories .map(cf => cf.create(urlPrefixes)) + .filter(capability => !configuration.disabledCapabilities.contains(capability.identifier())) for { account <- accounts(username, capabilities) 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 3cb88e41244..3c29c40f03b 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 @@ -71,7 +71,7 @@ class SessionRoutesTest extends AnyFlatSpec with BeforeAndAfter with Matchers { .thenReturn(Mono.empty()) val sessionRoutes = new SessionRoutes( - sessionSupplier = new SessionSupplier(DefaultCapabilities.supported(JmapRfc8621Configuration.LOCALHOST_CONFIGURATION)), + sessionSupplier = new SessionSupplier(DefaultCapabilities.supported(JmapRfc8621Configuration.LOCALHOST_CONFIGURATION), JmapRfc8621Configuration.LOCALHOST_CONFIGURATION), delegationStore = mockDelegationStore, authenticator = mockedAuthFilter, jmapRfc8621Configuration = JmapRfc8621Configuration.LOCALHOST_CONFIGURATION) diff --git a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/routes/SessionSupplierTest.scala b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/routes/SessionSupplierTest.scala index 3338b1d2867..2df5cb91222 100644 --- a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/routes/SessionSupplierTest.scala +++ b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/routes/SessionSupplierTest.scala @@ -33,12 +33,12 @@ class SessionSupplierTest extends AnyWordSpec with Matchers { "generate" should { "return correct username" in { - new SessionSupplier(DefaultCapabilities.supported(JmapRfc8621Configuration.LOCALHOST_CONFIGURATION)) + new SessionSupplier(DefaultCapabilities.supported(JmapRfc8621Configuration.LOCALHOST_CONFIGURATION), JmapRfc8621Configuration.LOCALHOST_CONFIGURATION) .generate(USERNAME, Set(), JmapRfc8621Configuration.LOCALHOST_CONFIGURATION.urlPrefixes()).toOption.get.username should equal(USERNAME) } "return correct account" which { - val accounts = new SessionSupplier(DefaultCapabilities.supported(JmapRfc8621Configuration.LOCALHOST_CONFIGURATION)) + val accounts = new SessionSupplier(DefaultCapabilities.supported(JmapRfc8621Configuration.LOCALHOST_CONFIGURATION), JmapRfc8621Configuration.LOCALHOST_CONFIGURATION) .generate(USERNAME, Set(), JmapRfc8621Configuration.LOCALHOST_CONFIGURATION.urlPrefixes()).toOption.get.accounts "has size" in {