diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/HomeServerConnectionConfig.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/HomeServerConnectionConfig.kt index e1c5171bfc..be29a880e5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/HomeServerConnectionConfig.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/HomeServerConnectionConfig.kt @@ -30,8 +30,13 @@ import okhttp3.TlsVersion * You should use the [Builder] to create one. */ @JsonClass(generateAdapter = true) -data class HomeServerConnectionConfig( +data class HomeServerConnectionConfig constructor( + // This is the homeserver URL entered by the user val homeServerUri: Uri, + // This is the homeserver base URL for the client-server API. Default to homeServerUri, + // but can be updated with data from .Well-Known before login, and/or with the data + // included in the login response + val homeServerUriBase: Uri = homeServerUri, val identityServerUri: Uri? = null, val antiVirusServerUri: Uri? = null, val allowedFingerprints: List = emptyList(), @@ -47,7 +52,6 @@ data class HomeServerConnectionConfig( * This builder should be use to create a [HomeServerConnectionConfig] instance. */ class Builder { - private lateinit var homeServerUri: Uri private var identityServerUri: Uri? = null private var antiVirusServerUri: Uri? = null @@ -234,16 +238,16 @@ data class HomeServerConnectionConfig( */ fun build(): HomeServerConnectionConfig { return HomeServerConnectionConfig( - homeServerUri, - identityServerUri, - antiVirusServerUri, - allowedFingerprints, - shouldPin, - tlsVersions, - tlsCipherSuites, - shouldAcceptTlsExtensions, - allowHttpExtension, - forceUsageTlsVersions + homeServerUri = homeServerUri, + identityServerUri = identityServerUri, + antiVirusServerUri = antiVirusServerUri, + allowedFingerprints = allowedFingerprints, + shouldPin = shouldPin, + tlsVersions = tlsVersions, + tlsCipherSuites = tlsCipherSuites, + shouldAcceptTlsExtensions = shouldAcceptTlsExtensions, + allowHttpExtension = allowHttpExtension, + forceUsageTlsVersions = forceUsageTlsVersions ) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/SessionParams.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/SessionParams.kt index b2a57c7f5c..b490ac877e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/SessionParams.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/SessionParams.kt @@ -51,13 +51,18 @@ data class SessionParams( val deviceId = credentials.deviceId /** - * The current homeserver Url. It can be different that the homeserver url entered - * during login phase, because a redirection may have occurred + * The homeserver Url entered by the user during the login phase. */ val homeServerUrl = homeServerConnectionConfig.homeServerUri.toString() /** - * The current homeserver host + * The current homeserver Url for client-server API. It can be different that the homeserver url entered + * during login phase, because a redirection may have occurred + */ + val homeServerUrlBase = homeServerConnectionConfig.homeServerUriBase.toString() + + /** + * The current homeserver host, using what has been entered by the user during login phase */ val homeServerHost = homeServerConnectionConfig.homeServerUri.host 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 7077453aae..b86964837b 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 @@ -124,7 +124,7 @@ internal class DefaultAuthenticationService @Inject constructor( private fun getHomeServerUrlBase(): String? { return pendingSessionData ?.homeServerConnectionConfig - ?.homeServerUri + ?.homeServerUriBase ?.toString() ?.trim { it == '/' } } @@ -147,7 +147,7 @@ internal class DefaultAuthenticationService @Inject constructor( // The homeserver exists and up to date, keep the config // Homeserver url may have been changed, if it was a Riot url val alteredHomeServerConnectionConfig = homeServerConnectionConfig.copy( - homeServerUri = Uri.parse(it.homeServerUrl) + homeServerUriBase = Uri.parse(it.homeServerUrl) ) pendingSessionData = PendingSessionData(alteredHomeServerConnectionConfig) @@ -156,7 +156,7 @@ internal class DefaultAuthenticationService @Inject constructor( }, { if (it is UnrecognizedCertificateException) { - throw Failure.UnrecognizedCertificateFailure(homeServerConnectionConfig.homeServerUri.toString(), it.fingerprint) + throw Failure.UnrecognizedCertificateFailure(homeServerConnectionConfig.homeServerUriBase.toString(), it.fingerprint) } else { throw it } @@ -175,7 +175,7 @@ internal class DefaultAuthenticationService @Inject constructor( } .map { versions -> // Ok, it seems that the homeserver url is valid - getLoginFlowResult(authAPI, versions, homeServerConnectionConfig.homeServerUri.toString()) + getLoginFlowResult(authAPI, versions, homeServerConnectionConfig.homeServerUriBase.toString()) } .fold( { @@ -196,7 +196,7 @@ internal class DefaultAuthenticationService @Inject constructor( private suspend fun getRiotDomainLoginFlowInternal(homeServerConnectionConfig: HomeServerConnectionConfig): LoginFlowResult { val authAPI = buildAuthAPI(homeServerConnectionConfig) - val domain = homeServerConnectionConfig.homeServerUri.host + val domain = homeServerConnectionConfig.homeServerUriBase.host ?: return getRiotLoginFlowInternal(homeServerConnectionConfig) // Ok, try to get the config.domain.json file of a RiotWeb client @@ -257,7 +257,7 @@ internal class DefaultAuthenticationService @Inject constructor( if (defaultHomeServerUrl?.isNotEmpty() == true) { // Ok, good sign, we got a default hs url val newHomeServerConnectionConfig = homeServerConnectionConfig.copy( - homeServerUri = Uri.parse(defaultHomeServerUrl) + homeServerUriBase = Uri.parse(defaultHomeServerUrl) ) val newAuthAPI = buildAuthAPI(newHomeServerConnectionConfig) @@ -274,7 +274,7 @@ internal class DefaultAuthenticationService @Inject constructor( } private suspend fun getWellknownLoginFlowInternal(homeServerConnectionConfig: HomeServerConnectionConfig): LoginFlowResult { - val domain = homeServerConnectionConfig.homeServerUri.host + val domain = homeServerConnectionConfig.homeServerUriBase.host ?: throw Failure.OtherServerError("", HttpsURLConnection.HTTP_NOT_FOUND /* 404 */) val wellknownResult = getWellknownTask.execute(GetWellknownTask.Params(domain, homeServerConnectionConfig)) @@ -282,7 +282,7 @@ internal class DefaultAuthenticationService @Inject constructor( return when (wellknownResult) { is WellknownResult.Prompt -> { val newHomeServerConnectionConfig = homeServerConnectionConfig.copy( - homeServerUri = Uri.parse(wellknownResult.homeServerUrl), + homeServerUriBase = Uri.parse(wellknownResult.homeServerUrl), identityServerUri = wellknownResult.identityServerUrl?.let { Uri.parse(it) } ) @@ -397,7 +397,7 @@ internal class DefaultAuthenticationService @Inject constructor( } private fun buildAuthAPI(homeServerConnectionConfig: HomeServerConnectionConfig): AuthAPI { - val retrofit = retrofitFactory.create(buildClient(homeServerConnectionConfig), homeServerConnectionConfig.homeServerUri.toString()) + val retrofit = retrofitFactory.create(buildClient(homeServerConnectionConfig), homeServerConnectionConfig.homeServerUriBase.toString()) return retrofit.create(AuthAPI::class.java) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/IsValidClientServerApiTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/IsValidClientServerApiTask.kt index 867cf46b8d..bc3d887000 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/IsValidClientServerApiTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/IsValidClientServerApiTask.kt @@ -42,7 +42,7 @@ internal class DefaultIsValidClientServerApiTask @Inject constructor( override suspend fun execute(params: IsValidClientServerApiTask.Params): Boolean { val client = buildClient(params.homeServerConnectionConfig) - val homeServerUrl = params.homeServerConnectionConfig.homeServerUri.toString() + val homeServerUrl = params.homeServerConnectionConfig.homeServerUriBase.toString() val authAPI = retrofitFactory.create(client, homeServerUrl) .create(AuthAPI::class.java) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/SessionCreator.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/SessionCreator.kt index 7c4a0c38ec..51ecc68d62 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/SessionCreator.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/SessionCreator.kt @@ -56,7 +56,7 @@ internal class DefaultSessionCreator @Inject constructor( tryOrNull { isValidClientServerApiTask.execute( IsValidClientServerApiTask.Params( - homeServerConnectionConfig.copy(homeServerUri = it) + homeServerConnectionConfig.copy(homeServerUriBase = it) ) ) .also { Timber.d("Overriding homeserver url: $it") } @@ -66,7 +66,7 @@ internal class DefaultSessionCreator @Inject constructor( val sessionParams = SessionParams( credentials = credentials, homeServerConnectionConfig = homeServerConnectionConfig.copy( - homeServerUri = overriddenUrl ?: homeServerConnectionConfig.homeServerUri, + homeServerUriBase = overriddenUrl ?: homeServerConnectionConfig.homeServerUriBase, identityServerUri = credentials.discoveryInformation?.identityServer?.baseURL // remove trailing "/" ?.trim { it == '/' } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/AuthRealmMigration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/AuthRealmMigration.kt index bb2667228b..c2104690b3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/AuthRealmMigration.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/AuthRealmMigration.kt @@ -16,17 +16,19 @@ package org.matrix.android.sdk.internal.auth.db -import org.matrix.android.sdk.api.auth.data.Credentials -import org.matrix.android.sdk.api.auth.data.sessionId -import org.matrix.android.sdk.internal.di.MoshiProvider +import android.net.Uri import io.realm.DynamicRealm import io.realm.RealmMigration +import org.matrix.android.sdk.api.auth.data.Credentials +import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig +import org.matrix.android.sdk.api.auth.data.sessionId +import org.matrix.android.sdk.internal.di.MoshiProvider import timber.log.Timber internal object AuthRealmMigration : RealmMigration { // Current schema version - const val SCHEMA_VERSION = 3L + const val SCHEMA_VERSION = 4L override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) { Timber.d("Migrating Auth Realm from $oldVersion to $newVersion") @@ -34,6 +36,7 @@ internal object AuthRealmMigration : RealmMigration { if (oldVersion <= 0) migrateTo1(realm) if (oldVersion <= 1) migrateTo2(realm) if (oldVersion <= 2) migrateTo3(realm) + if (oldVersion <= 3) migrateTo4(realm) } private fun migrateTo1(realm: DynamicRealm) { @@ -81,4 +84,34 @@ internal object AuthRealmMigration : RealmMigration { } ?.addPrimaryKey(SessionParamsEntityFields.SESSION_ID) } + + private fun migrateTo4(realm: DynamicRealm) { + Timber.d("Step 3 -> 4") + Timber.d("Update SessionParamsEntity to add HomeServerConnectionConfig.homeServerUriBase value") + + val adapter = MoshiProvider.providesMoshi() + .adapter(HomeServerConnectionConfig::class.java) + + realm.schema.get("SessionParamsEntity") + ?.transform { + val homeserverConnectionConfigJson = it.getString(SessionParamsEntityFields.HOME_SERVER_CONNECTION_CONFIG_JSON) + + val homeserverConnectionConfig = adapter + .fromJson(homeserverConnectionConfigJson) + + val homeserverUrl = homeserverConnectionConfig?.homeServerUri?.toString() + // Special case for matrix.org. Old session may use "https://matrix.org", newer one may use + // "https://matrix-client.matrix.org". So fix that here + val alteredHomeserverConnectionConfig = + if (homeserverUrl == "https://matrix.org" || homeserverUrl == "https://matrix-client.matrix.org") { + homeserverConnectionConfig.copy( + homeServerUri = Uri.parse("https://matrix.org"), + homeServerUriBase = Uri.parse("https://matrix-client.matrix.org") + ) + } else { + homeserverConnectionConfig + } + it.set(SessionParamsEntityFields.HOME_SERVER_CONNECTION_CONFIG_JSON, adapter.toJson(alteredHomeserverConnectionConfig)) + } + } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/DirectLoginTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/DirectLoginTask.kt index 77bbb8096f..3888633723 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/DirectLoginTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/DirectLoginTask.kt @@ -50,7 +50,7 @@ internal class DefaultDirectLoginTask @Inject constructor( override suspend fun execute(params: DirectLoginTask.Params): Session { val client = buildClient(params.homeServerConnectionConfig) - val homeServerUrl = params.homeServerConnectionConfig.homeServerUri.toString() + val homeServerUrl = params.homeServerConnectionConfig.homeServerUriBase.toString() val authAPI = retrofitFactory.create(client, homeServerUrl) .create(AuthAPI::class.java) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/CertUtil.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/CertUtil.kt index 9d7263f56a..976751446b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/CertUtil.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/CertUtil.kt @@ -253,7 +253,7 @@ internal object CertUtil { val list = ArrayList() list.add(builder.build()) // TODO: we should display a warning if user enter an http url - if (hsConfig.allowHttpExtension || hsConfig.homeServerUri.toString().startsWith("http://")) { + if (hsConfig.allowHttpExtension || hsConfig.homeServerUriBase.toString().startsWith("http://")) { list.add(ConnectionSpec.CLEARTEXT) } return list diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt index 1cf99bbbd7..c2bd1e24ed 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt @@ -313,7 +313,7 @@ internal class DefaultSession @Inject constructor( override fun getUiaSsoFallbackUrl(authenticationSessionId: String): String { val hsBas = sessionParams.homeServerConnectionConfig - .homeServerUri + .homeServerUriBase .toString() .trim { it == '/' } return buildString { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionModule.kt index e6da21315b..cb29cb4819 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionModule.kt @@ -261,7 +261,7 @@ internal abstract class SessionModule { sessionParams: SessionParams, retrofitFactory: RetrofitFactory): Retrofit { return retrofitFactory - .create(okHttpClient, sessionParams.homeServerConnectionConfig.homeServerUri.toString()) + .create(okHttpClient, sessionParams.homeServerConnectionConfig.homeServerUriBase.toString()) } @JvmStatic diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/DefaultContentUrlResolver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/DefaultContentUrlResolver.kt index f765056496..e4efdaa254 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/DefaultContentUrlResolver.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/DefaultContentUrlResolver.kt @@ -26,7 +26,7 @@ private const val MATRIX_CONTENT_URI_SCHEME = "mxc://" internal class DefaultContentUrlResolver @Inject constructor(homeServerConnectionConfig: HomeServerConnectionConfig) : ContentUrlResolver { - private val baseUrl = homeServerConnectionConfig.homeServerUri.toString().ensureTrailingSlash() + private val baseUrl = homeServerConnectionConfig.homeServerUriBase.toString().ensureTrailingSlash() override val uploadUrl = baseUrl + NetworkConstants.URI_API_MEDIA_PREFIX_PATH_R0 + "upload" diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/HomeServerAvailabilityChecker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/HomeServerAvailabilityChecker.kt index 2d53699917..1d7ce587f9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/HomeServerAvailabilityChecker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/HomeServerAvailabilityChecker.kt @@ -26,8 +26,8 @@ import java.net.Socket internal class HomeServerAvailabilityChecker(val sessionParams: SessionParams) { fun check(): Boolean { - val host = sessionParams.homeServerConnectionConfig.homeServerUri.host ?: return false - val port = sessionParams.homeServerConnectionConfig.homeServerUri.port.takeIf { it != -1 } ?: 80 + val host = sessionParams.homeServerConnectionConfig.homeServerUriBase.host ?: return false + val port = sessionParams.homeServerConnectionConfig.homeServerUriBase.port.takeIf { it != -1 } ?: 80 val timeout = 30_000 try { Socket().use { socket -> diff --git a/vector/src/main/java/im/vector/app/core/dialogs/UnrecognizedCertificateDialog.kt b/vector/src/main/java/im/vector/app/core/dialogs/UnrecognizedCertificateDialog.kt index ca92e6aa75..c1efc72ba7 100644 --- a/vector/src/main/java/im/vector/app/core/dialogs/UnrecognizedCertificateDialog.kt +++ b/vector/src/main/java/im/vector/app/core/dialogs/UnrecognizedCertificateDialog.kt @@ -50,7 +50,7 @@ class UnrecognizedCertificateDialog @Inject constructor( val userId = activeSessionHolder.getSafeActiveSession()?.myUserId val hsConfig = activeSessionHolder.getSafeActiveSession()?.sessionParams?.homeServerConnectionConfig ?: return - internalShow(activity, unrecognizedFingerprint, true, callback, userId, hsConfig.homeServerUri.toString(), hsConfig.allowedFingerprints.isNotEmpty()) + internalShow(activity, unrecognizedFingerprint, true, callback, userId, hsConfig.homeServerUriBase.toString(), hsConfig.allowedFingerprints.isNotEmpty()) } /** diff --git a/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt b/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt index c9b571dca1..440220882a 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt @@ -591,7 +591,7 @@ class LoginViewModel @AssistedInject constructor( homeServerConnectionConfig: HomeServerConnectionConfig?) { val alteredHomeServerConnectionConfig = homeServerConnectionConfig ?.copy( - homeServerUri = Uri.parse(wellKnownPrompt.homeServerUrl), + homeServerUriBase = Uri.parse(wellKnownPrompt.homeServerUrl), identityServerUri = wellKnownPrompt.identityServerUrl?.let { Uri.parse(it) } ) ?: HomeServerConnectionConfig( @@ -772,7 +772,7 @@ class LoginViewModel @AssistedInject constructor( data ?: return@launch // Valid Homeserver, add it to the history. - // Note: we add what the user has input, data.homeServerUrl can be different + // Note: we add what the user has input, data.homeServerUrlBase can be different rememberHomeServer(homeServerConnectionConfig.homeServerUri.toString()) val loginMode = when { diff --git a/vector/src/main/java/im/vector/app/features/login2/LoginViewModel2.kt b/vector/src/main/java/im/vector/app/features/login2/LoginViewModel2.kt index 110e4f7fe4..d0da12e6ed 100644 --- a/vector/src/main/java/im/vector/app/features/login2/LoginViewModel2.kt +++ b/vector/src/main/java/im/vector/app/features/login2/LoginViewModel2.kt @@ -612,7 +612,7 @@ class LoginViewModel2 @AssistedInject constructor( homeServerConnectionConfig: HomeServerConnectionConfig?) { val alteredHomeServerConnectionConfig = homeServerConnectionConfig ?.copy( - homeServerUri = Uri.parse(wellKnownPrompt.homeServerUrl), + homeServerUriBase = Uri.parse(wellKnownPrompt.homeServerUrl), identityServerUri = wellKnownPrompt.identityServerUrl?.let { Uri.parse(it) } ) ?: HomeServerConnectionConfig( @@ -752,7 +752,7 @@ class LoginViewModel2 @AssistedInject constructor( } ?: return@launch // Valid Homeserver, add it to the history. - // Note: we add what the user has input, data.homeServerUrl can be different + // Note: we add what the user has input, data.homeServerUrlBase can be different rememberHomeServer(homeServerConnectionConfig.homeServerUri.toString()) val loginMode = when {