diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/auth/data/Versions.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/auth/data/Versions.kt index c4186c6ec5..e17209b316 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/auth/data/Versions.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/auth/data/Versions.kt @@ -18,6 +18,7 @@ package im.vector.matrix.android.api.auth.data import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import im.vector.matrix.android.internal.auth.version.HomeServerVersion /** * Model for https://matrix.org/docs/spec/client_server/latest#get-matrix-client-versions @@ -47,13 +48,13 @@ data class Versions( ) // MatrixClientServerAPIVersion -private const val r0_0_1 = "r0.0.1" -private const val r0_1_0 = "r0.1.0" -private const val r0_2_0 = "r0.2.0" -private const val r0_3_0 = "r0.3.0" -private const val r0_4_0 = "r0.4.0" -private const val r0_5_0 = "r0.5.0" -private const val r0_6_0 = "r0.6.0" +private val r0_0_1 = HomeServerVersion.parse("r0.0.1")!! +private val r0_1_0 = HomeServerVersion.parse("r0.1.0")!! +private val r0_2_0 = HomeServerVersion.parse("r0.2.0")!! +private val r0_3_0 = HomeServerVersion.parse("r0.3.0")!! +private val r0_4_0 = HomeServerVersion.parse("r0.4.0")!! +private val r0_5_0 = HomeServerVersion.parse("r0.5.0")!! +private val r0_6_0 = HomeServerVersion.parse("r0.6.0")!! // MatrixVersionsFeature private const val FEATURE_LAZY_LOAD_MEMBERS = "m.lazy_load_members" @@ -83,7 +84,7 @@ fun Versions.isLoginAndRegistrationSupportedBySdk(): Boolean { * @return true if the server support the lazy loading of room members */ private fun Versions.supportLazyLoadMembers(): Boolean { - return supportedVersions?.contains(r0_5_0) == true + return getMaxVersion() >= r0_5_0 || unstableFeatures?.get(FEATURE_LAZY_LOAD_MEMBERS) == true } @@ -92,7 +93,7 @@ private fun Versions.supportLazyLoadMembers(): Boolean { * adding a 3pid or resetting password. */ private fun Versions.doesServerRequireIdentityServerParam(): Boolean { - if (supportedVersions?.contains(r0_6_0) == true) return false + if (getMaxVersion() >= r0_6_0) return false return unstableFeatures?.get(FEATURE_REQUIRE_IDENTITY_SERVER) ?: true } @@ -101,11 +102,18 @@ private fun Versions.doesServerRequireIdentityServerParam(): Boolean { * Some homeservers may trigger errors if they are not prepared for the new parameter. */ private fun Versions.doesServerAcceptIdentityAccessToken(): Boolean { - return supportedVersions?.contains(r0_6_0) == true + return getMaxVersion() >= r0_6_0 || unstableFeatures?.get(FEATURE_ID_ACCESS_TOKEN) ?: false } private fun Versions.doesServerSeparatesAddAndBind(): Boolean { - return supportedVersions?.contains(r0_6_0) == true + return getMaxVersion() >= r0_6_0 || unstableFeatures?.get(FEATURE_SEPARATE_ADD_AND_BIND) ?: false } + +private fun Versions.getMaxVersion(): HomeServerVersion { + return supportedVersions + ?.mapNotNull { HomeServerVersion.parse(it) } + ?.max() + ?: r0_0_1 +} diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/version/HomeServerVersion.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/version/HomeServerVersion.kt new file mode 100644 index 0000000000..0ea230774e --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/version/HomeServerVersion.kt @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020 New Vector Ltd + * + * Licensed 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 im.vector.matrix.android.internal.auth.version + +/** + * Values will take the form "rX.Y.Z". + * Ref: https://matrix.org/docs/spec/client_server/latest#get-matrix-client-versions + */ +internal data class HomeServerVersion( + val major: Int, + val minor: Int, + val patch: Int +) : Comparable { + override fun compareTo(other: HomeServerVersion): Int { + return when { + major > other.major -> 1 + major < other.major -> -1 + minor > other.minor -> 1 + minor < other.minor -> -1 + patch > other.patch -> 1 + patch < other.patch -> -1 + else -> 0 + } + } + + companion object { + internal val pattern = Regex("""r(\d+)\.(\d+)\.(\d+)""") + + internal fun parse(value: String): HomeServerVersion? { + val result = pattern.matchEntire(value) ?: return null + return HomeServerVersion( + major = result.groupValues[1].toInt(), + minor = result.groupValues[2].toInt(), + patch = result.groupValues[3].toInt() + ) + } + } +} diff --git a/matrix-sdk-android/src/test/java/im/vector/matrix/android/api/auth/data/VersionsKtTest.kt b/matrix-sdk-android/src/test/java/im/vector/matrix/android/api/auth/data/VersionsKtTest.kt new file mode 100644 index 0000000000..b129c019b5 --- /dev/null +++ b/matrix-sdk-android/src/test/java/im/vector/matrix/android/api/auth/data/VersionsKtTest.kt @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2020 New Vector Ltd + * + * Licensed 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 im.vector.matrix.android.api.auth.data + +import org.amshove.kluent.shouldBe +import org.junit.Test + +class VersionsKtTest { + + @Test + fun isSupportedBySdkTooLow() { + Versions(supportedVersions = listOf("r0.4.0")).isSupportedBySdk() shouldBe false + Versions(supportedVersions = listOf("r0.4.1")).isSupportedBySdk() shouldBe false + } + + @Test + fun isSupportedBySdkUnstable() { + Versions(supportedVersions = listOf("r0.4.0"), unstableFeatures = mapOf("m.lazy_load_members" to true)).isSupportedBySdk() shouldBe true + } + + @Test + fun isSupportedBySdkOk() { + Versions(supportedVersions = listOf("r0.5.0")).isSupportedBySdk() shouldBe true + Versions(supportedVersions = listOf("r0.5.1")).isSupportedBySdk() shouldBe true + } + + // Was not working + @Test + fun isSupportedBySdkLater() { + Versions(supportedVersions = listOf("r0.6.0")).isSupportedBySdk() shouldBe true + Versions(supportedVersions = listOf("r0.6.1")).isSupportedBySdk() shouldBe true + } + + // Cover cases of issue #1442 + @Test + fun isSupportedBySdk1442() { + Versions(supportedVersions = listOf("r0.5.0", "r0.6.0")).isSupportedBySdk() shouldBe true + Versions(supportedVersions = listOf("r0.5.0", "r0.6.1")).isSupportedBySdk() shouldBe true + Versions(supportedVersions = listOf("r0.6.0")).isSupportedBySdk() shouldBe true + } +}