From c11c28b406d8b81377776ad2e997afec643800a8 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 17 Aug 2020 19:27:13 +0200 Subject: [PATCH 1/4] #1682: parse "default_server_config" --- .../auth/DefaultAuthenticationService.kt | 7 +++-- .../sdk/internal/auth/data/RiotConfig.kt | 28 +++++++++++++++++-- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt index 1294855b6e..385fdcbf9b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt @@ -176,10 +176,11 @@ internal class DefaultAuthenticationService @Inject constructor( } } .map { riotConfig -> - if (riotConfig.defaultHomeServerUrl?.isNotBlank() == true) { + val defaultHomeServerUrl = riotConfig.getPreferredHomeServerUrl() + if (defaultHomeServerUrl?.isNotEmpty() == true) { // Ok, good sign, we got a default hs url val newHomeServerConnectionConfig = homeServerConnectionConfig.copy( - homeServerUri = Uri.parse(riotConfig.defaultHomeServerUrl) + homeServerUri = Uri.parse(defaultHomeServerUrl) ) val newAuthAPI = buildAuthAPI(newHomeServerConnectionConfig) @@ -188,7 +189,7 @@ internal class DefaultAuthenticationService @Inject constructor( apiCall = newAuthAPI.versions() } - getLoginFlowResult(newAuthAPI, versions, riotConfig.defaultHomeServerUrl) + getLoginFlowResult(newAuthAPI, versions, defaultHomeServerUrl) } else { // Config exists, but there is no default homeserver url (ex: https://riot.im/app) throw Failure.OtherServerError("", HttpsURLConnection.HTTP_NOT_FOUND /* 404 */) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/RiotConfig.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/RiotConfig.kt index 42db315262..1c1c5c0c29 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/RiotConfig.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/RiotConfig.kt @@ -22,8 +22,30 @@ import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) data class RiotConfig( - // There are plenty of other elements in the file config.json of a RiotWeb client, but for the moment only one is interesting - // Ex: "brand", "branding", etc. + /** + * This is now deprecated, but still used first, rather than value from "default_server_config" + */ @Json(name = "default_hs_url") - val defaultHomeServerUrl: String? + val defaultHomeServerUrl: String?, + + @Json(name = "default_server_config") + val defaultServerConfig: RiotConfigDefaultServerConfig? +) { + fun getPreferredHomeServerUrl(): String? { + return defaultHomeServerUrl + ?.takeIf { it.isNotEmpty() } + ?: defaultServerConfig?.homeServer?.baseURL + } +} + +@JsonClass(generateAdapter = true) +data class RiotConfigDefaultServerConfig( + @Json(name = "m.homeserver") + val homeServer: RiotConfigBaseConfig? = null +) + +@JsonClass(generateAdapter = true) +data class RiotConfigBaseConfig( + @Json(name = "base_url") + val baseURL: String? = null ) From 112f77c4e06af6da6ce925094c08855cdc6ac381 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 17 Aug 2020 19:39:29 +0200 Subject: [PATCH 2/4] #1682: try to fetch config.domain.json --- .../android/sdk/internal/auth/AuthAPI.kt | 5 ++ .../auth/DefaultAuthenticationService.kt | 82 +++++++++++++------ 2 files changed, 63 insertions(+), 24 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/AuthAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/AuthAPI.kt index 00eb7e8599..d0c02b6027 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/AuthAPI.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/AuthAPI.kt @@ -42,6 +42,11 @@ import retrofit2.http.Url * The login REST API. */ internal interface AuthAPI { + /** + * Get a Riot config file, using the name including the domain + */ + @GET("config.{domain}.json") + fun getRiotConfigDomain(@Path("domain") domain: String): Call /** * Get a Riot config file diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt index 385fdcbf9b..02c48dab07 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt @@ -19,6 +19,9 @@ package org.matrix.android.sdk.internal.auth import android.net.Uri import dagger.Lazy +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.OkHttpClient import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.auth.AuthenticationService import org.matrix.android.sdk.api.auth.data.Credentials @@ -50,12 +53,8 @@ import org.matrix.android.sdk.internal.task.TaskExecutor import org.matrix.android.sdk.internal.task.configureWith import org.matrix.android.sdk.internal.task.launchToCallback import org.matrix.android.sdk.internal.util.MatrixCoroutineDispatchers -import org.matrix.android.sdk.internal.util.exhaustive import org.matrix.android.sdk.internal.util.toCancelable import org.matrix.android.sdk.internal.wellknown.GetWellknownTask -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import okhttp3.OkHttpClient import javax.inject.Inject import javax.net.ssl.HttpsURLConnection @@ -157,7 +156,7 @@ internal class DefaultAuthenticationService @Inject constructor( if (it is Failure.OtherServerError && it.httpCode == HttpsURLConnection.HTTP_NOT_FOUND /* 404 */) { // It's maybe a Riot url? - getRiotLoginFlowInternal(homeServerConnectionConfig) + getRiotDomainLoginFlowInternal(homeServerConnectionConfig) } else { throw it } @@ -166,6 +165,37 @@ internal class DefaultAuthenticationService @Inject constructor( } } + private suspend fun getRiotDomainLoginFlowInternal(homeServerConnectionConfig: HomeServerConnectionConfig): LoginFlowResult { + val authAPI = buildAuthAPI(homeServerConnectionConfig) + + val domain = homeServerConnectionConfig.homeServerUri.host + ?: return getRiotLoginFlowInternal(homeServerConnectionConfig) + + // Ok, try to get the config.domain.json file of a RiotWeb client + return runCatching { + executeRequest(null) { + apiCall = authAPI.getRiotConfigDomain(domain) + } + } + .map { riotConfig -> + onRiotConfigRetrieved(homeServerConnectionConfig, riotConfig) + } + .fold( + { + it + }, + { + if (it is Failure.OtherServerError + && it.httpCode == HttpsURLConnection.HTTP_NOT_FOUND /* 404 */) { + // Try with config.json + getRiotLoginFlowInternal(homeServerConnectionConfig) + } else { + throw it + } + } + ) + } + private suspend fun getRiotLoginFlowInternal(homeServerConnectionConfig: HomeServerConnectionConfig): LoginFlowResult { val authAPI = buildAuthAPI(homeServerConnectionConfig) @@ -176,24 +206,7 @@ internal class DefaultAuthenticationService @Inject constructor( } } .map { riotConfig -> - val defaultHomeServerUrl = riotConfig.getPreferredHomeServerUrl() - if (defaultHomeServerUrl?.isNotEmpty() == true) { - // Ok, good sign, we got a default hs url - val newHomeServerConnectionConfig = homeServerConnectionConfig.copy( - homeServerUri = Uri.parse(defaultHomeServerUrl) - ) - - val newAuthAPI = buildAuthAPI(newHomeServerConnectionConfig) - - val versions = executeRequest(null) { - apiCall = newAuthAPI.versions() - } - - getLoginFlowResult(newAuthAPI, versions, defaultHomeServerUrl) - } else { - // Config exists, but there is no default homeserver url (ex: https://riot.im/app) - throw Failure.OtherServerError("", HttpsURLConnection.HTTP_NOT_FOUND /* 404 */) - } + onRiotConfigRetrieved(homeServerConnectionConfig, riotConfig) } .fold( { @@ -211,6 +224,27 @@ internal class DefaultAuthenticationService @Inject constructor( ) } + private suspend fun onRiotConfigRetrieved(homeServerConnectionConfig: HomeServerConnectionConfig, riotConfig: RiotConfig): LoginFlowResult { + val defaultHomeServerUrl = riotConfig.getPreferredHomeServerUrl() + if (defaultHomeServerUrl?.isNotEmpty() == true) { + // Ok, good sign, we got a default hs url + val newHomeServerConnectionConfig = homeServerConnectionConfig.copy( + homeServerUri = Uri.parse(defaultHomeServerUrl) + ) + + val newAuthAPI = buildAuthAPI(newHomeServerConnectionConfig) + + val versions = executeRequest(null) { + apiCall = newAuthAPI.versions() + } + + return getLoginFlowResult(newAuthAPI, versions, defaultHomeServerUrl) + } else { + // Config exists, but there is no default homeserver url (ex: https://riot.im/app) + throw Failure.OtherServerError("", HttpsURLConnection.HTTP_NOT_FOUND /* 404 */) + } + } + private suspend fun getWellknownLoginFlowInternal(homeServerConnectionConfig: HomeServerConnectionConfig): LoginFlowResult { val domain = homeServerConnectionConfig.homeServerUri.host ?: throw Failure.OtherServerError("", HttpsURLConnection.HTTP_NOT_FOUND /* 404 */) @@ -235,7 +269,7 @@ internal class DefaultAuthenticationService @Inject constructor( getLoginFlowResult(newAuthAPI, versions, wellknownResult.homeServerUrl) } else -> throw Failure.OtherServerError("", HttpsURLConnection.HTTP_NOT_FOUND /* 404 */) - }.exhaustive + } } private suspend fun getLoginFlowResult(authAPI: AuthAPI, versions: Versions, homeServerUrl: String): LoginFlowResult { From f012e23fa90f72202fa2fc23f4592c76a423378f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 17 Aug 2020 19:42:21 +0200 Subject: [PATCH 3/4] #1682: changelog --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index a49507b516..1f309875a6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,6 +9,7 @@ Improvements 🙌: - Give user the possibility to prevent accidental call (#1869) - Display device information (name, id and key) in Cryptography setting screen (#1784) - Ensure users do not accidentally ignore other users (#1890) + - Support new config.json format and config.domain.json files (#1682) Bugfix 🐛: - Fix invisible toolbar (Status.im theme) (#1746) From bde77784b9926c4ff27991de286992d794c5bdc7 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 17 Aug 2020 19:46:44 +0200 Subject: [PATCH 4/4] Add `internal` --- .../org/matrix/android/sdk/internal/auth/data/RiotConfig.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/RiotConfig.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/RiotConfig.kt index 1c1c5c0c29..9fb8963812 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/RiotConfig.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/RiotConfig.kt @@ -21,7 +21,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) -data class RiotConfig( +internal data class RiotConfig( /** * This is now deprecated, but still used first, rather than value from "default_server_config" */ @@ -39,13 +39,13 @@ data class RiotConfig( } @JsonClass(generateAdapter = true) -data class RiotConfigDefaultServerConfig( +internal data class RiotConfigDefaultServerConfig( @Json(name = "m.homeserver") val homeServer: RiotConfigBaseConfig? = null ) @JsonClass(generateAdapter = true) -data class RiotConfigBaseConfig( +internal data class RiotConfigBaseConfig( @Json(name = "base_url") val baseURL: String? = null )