Merge pull request #3585 from vector-im/feature/bma/wellknown

Improve wellknown usage
This commit is contained in:
Benoit Marty 2021-07-05 21:36:16 +02:00 committed by GitHub
commit ca45cdd5c7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
52 changed files with 330 additions and 200 deletions

View file

@ -38,6 +38,7 @@
<w>unpublish</w>
<w>unwedging</w>
<w>vctr</w>
<w>wellknown</w>
</words>
</dictionary>
</component>

1
changelog.d/2843.bugfix Normal file
View file

@ -0,0 +1 @@
Perform .well-known request first, even if the entered URL is a valid homeserver base url

1
changelog.d/3572.misc Normal file
View file

@ -0,0 +1 @@
RawService.getWellknown() now takes a domain instead of a matrixId as parameter

View file

@ -16,6 +16,8 @@
package org.matrix.android.sdk.api
import org.matrix.android.sdk.BuildConfig
/**
* This class contains pattern to match the different Matrix ids
*/
@ -154,7 +156,7 @@ object MatrixPatterns {
* Orders which are not strings, or do not consist solely of ascii characters in the range \x20 (space) to \x7E (~),
* or consist of more than 50 characters, are forbidden and the field should be ignored if received.
*/
fun isValidOrderString(order: String?) : Boolean {
fun isValidOrderString(order: String?): Boolean {
return order != null && order.length < 50 && order matches ORDER_STRING_REGEX
}
@ -163,4 +165,17 @@ object MatrixPatterns {
"[^a-z0-9._%#@=+-]".toRegex().replace(it, "")
}
}
/**
* Return the domain form a userId
* Examples:
* - "@alice:domain.org".getDomain() will return "domain.org"
* - "@bob:domain.org:3455".getDomain() will return "domain.org:3455"
*/
fun String.getDomain(): String {
if (BuildConfig.DEBUG) {
assert(isUserId(this))
}
return substringAfter(":")
}
}

View file

@ -18,11 +18,11 @@ package org.matrix.android.sdk.api.auth.data
import android.net.Uri
import com.squareup.moshi.JsonClass
import okhttp3.CipherSuite
import okhttp3.TlsVersion
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig.Builder
import org.matrix.android.sdk.internal.network.ssl.Fingerprint
import org.matrix.android.sdk.internal.util.ensureTrailingSlash
import okhttp3.CipherSuite
import okhttp3.TlsVersion
/**
* This data class holds how to connect to a specific Homeserver.
@ -31,7 +31,12 @@ import okhttp3.TlsVersion
*/
@JsonClass(generateAdapter = true)
data class HomeServerConnectionConfig(
// 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<Fingerprint> = 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
)
}
}

View file

@ -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

View file

@ -22,11 +22,6 @@ import org.matrix.android.sdk.api.auth.data.WellKnown
* Ref: https://matrix.org/docs/spec/client_server/latest#well-known-uri
*/
sealed class WellknownResult {
/**
* The provided matrixId is no valid. Unable to extract a domain name.
*/
object InvalidMatrixId : WellknownResult()
/**
* Retrieve the specific piece of information from the user in a way which fits within the existing client user experience,
* if the client is inclined to do so. Failure can take place instead if no good user experience for this is possible at this point.

View file

@ -0,0 +1,21 @@
/*
* Copyright (c) 2021 The Matrix.org Foundation C.I.C.
*
* 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 org.matrix.android.sdk.api.failure
sealed class MatrixIdFailure : Failure.FeatureFailure() {
object InvalidMatrixId : MatrixIdFailure()
}

View file

@ -29,8 +29,10 @@ interface RawService {
/**
* Specific case for the well-known file. Cache validity is 8 hours
* @param domain the domain to get the .well-known file, for instance "matrix.org".
* The URL will be "https://{domain}/.well-known/matrix/client"
*/
suspend fun getWellknown(userId: String): String
suspend fun getWellknown(domain: String): String
/**
* Clear all the cache data

View file

@ -21,8 +21,8 @@ import org.matrix.android.sdk.api.util.JsonDict
import org.matrix.android.sdk.internal.auth.data.Availability
import org.matrix.android.sdk.internal.auth.data.LoginFlowResponse
import org.matrix.android.sdk.internal.auth.data.PasswordLoginParams
import org.matrix.android.sdk.internal.auth.data.RiotConfig
import org.matrix.android.sdk.internal.auth.data.TokenLoginParams
import org.matrix.android.sdk.internal.auth.data.WebClientConfig
import org.matrix.android.sdk.internal.auth.login.ResetPasswordMailConfirmed
import org.matrix.android.sdk.internal.auth.registration.AddThreePidRegistrationParams
import org.matrix.android.sdk.internal.auth.registration.AddThreePidRegistrationResponse
@ -44,16 +44,16 @@ import retrofit2.http.Url
*/
internal interface AuthAPI {
/**
* Get a Riot config file, using the name including the domain
* Get a Web client config file, using the name including the domain
*/
@GET("config.{domain}.json")
suspend fun getRiotConfigDomain(@Path("domain") domain: String): RiotConfig
suspend fun getWebClientConfigDomain(@Path("domain") domain: String): WebClientConfig
/**
* Get a Riot config file
* Get a Web client default config file
*/
@GET("config.json")
suspend fun getRiotConfig(): RiotConfig
suspend fun getWebClientConfig(): WebClientConfig
/**
* Get the version information of the homeserver

View file

@ -19,6 +19,8 @@ package org.matrix.android.sdk.internal.auth
import android.net.Uri
import dagger.Lazy
import okhttp3.OkHttpClient
import org.matrix.android.sdk.api.MatrixPatterns
import org.matrix.android.sdk.api.MatrixPatterns.getDomain
import org.matrix.android.sdk.api.auth.AuthenticationService
import org.matrix.android.sdk.api.auth.data.Credentials
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
@ -28,10 +30,11 @@ import org.matrix.android.sdk.api.auth.login.LoginWizard
import org.matrix.android.sdk.api.auth.registration.RegistrationWizard
import org.matrix.android.sdk.api.auth.wellknown.WellknownResult
import org.matrix.android.sdk.api.failure.Failure
import org.matrix.android.sdk.api.failure.MatrixIdFailure
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.util.appendParamToUrl
import org.matrix.android.sdk.internal.SessionManager
import org.matrix.android.sdk.internal.auth.data.RiotConfig
import org.matrix.android.sdk.internal.auth.data.WebClientConfig
import org.matrix.android.sdk.internal.auth.db.PendingSessionData
import org.matrix.android.sdk.internal.auth.login.DefaultLoginWizard
import org.matrix.android.sdk.internal.auth.login.DirectLoginTask
@ -122,7 +125,7 @@ internal class DefaultAuthenticationService @Inject constructor(
private fun getHomeServerUrlBase(): String? {
return pendingSessionData
?.homeServerConnectionConfig
?.homeServerUri
?.homeServerUriBase
?.toString()
?.trim { it == '/' }
}
@ -143,9 +146,9 @@ internal class DefaultAuthenticationService @Inject constructor(
return result.fold(
{
// The homeserver exists and up to date, keep the config
// Homeserver url may have been changed, if it was a Riot url
// Homeserver url may have been changed, if it was a Web client url
val alteredHomeServerConnectionConfig = homeServerConnectionConfig.copy(
homeServerUri = Uri.parse(it.homeServerUrl)
homeServerUriBase = Uri.parse(it.homeServerUrl)
)
pendingSessionData = PendingSessionData(alteredHomeServerConnectionConfig)
@ -154,7 +157,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
}
@ -165,46 +168,57 @@ internal class DefaultAuthenticationService @Inject constructor(
private suspend fun getLoginFlowInternal(homeServerConnectionConfig: HomeServerConnectionConfig): LoginFlowResult {
val authAPI = buildAuthAPI(homeServerConnectionConfig)
// First check the homeserver version
return runCatching {
executeRequest(null) {
authAPI.versions()
// First check if there is a well-known file
return try {
getWellknownLoginFlowInternal(homeServerConnectionConfig)
} catch (failure: Throwable) {
if (failure is Failure.OtherServerError
&& failure.httpCode == HttpsURLConnection.HTTP_NOT_FOUND /* 404 */) {
// 404, no well-known data, try direct access to the API
// First check the homeserver version
return runCatching {
executeRequest(null) {
authAPI.versions()
}
}
.map { versions ->
// Ok, it seems that the homeserver url is valid
getLoginFlowResult(authAPI, versions, homeServerConnectionConfig.homeServerUriBase.toString())
}
.fold(
{
it
},
{
if (it is Failure.OtherServerError
&& it.httpCode == HttpsURLConnection.HTTP_NOT_FOUND /* 404 */) {
// It's maybe a Web client url?
getWebClientDomainLoginFlowInternal(homeServerConnectionConfig)
} else {
throw it
}
}
)
} else {
throw failure
}
}
.map { versions ->
// Ok, it seems that the homeserver url is valid
getLoginFlowResult(authAPI, versions, homeServerConnectionConfig.homeServerUri.toString())
}
.fold(
{
it
},
{
if (it is Failure.OtherServerError
&& it.httpCode == HttpsURLConnection.HTTP_NOT_FOUND /* 404 */) {
// It's maybe a Riot url?
getRiotDomainLoginFlowInternal(homeServerConnectionConfig)
} else {
throw it
}
}
)
}
private suspend fun getRiotDomainLoginFlowInternal(homeServerConnectionConfig: HomeServerConnectionConfig): LoginFlowResult {
private suspend fun getWebClientDomainLoginFlowInternal(homeServerConnectionConfig: HomeServerConnectionConfig): LoginFlowResult {
val authAPI = buildAuthAPI(homeServerConnectionConfig)
val domain = homeServerConnectionConfig.homeServerUri.host
?: return getRiotLoginFlowInternal(homeServerConnectionConfig)
?: return getWebClientLoginFlowInternal(homeServerConnectionConfig)
// Ok, try to get the config.domain.json file of a RiotWeb client
// Ok, try to get the config.domain.json file of a Web client
return runCatching {
executeRequest(null) {
authAPI.getRiotConfigDomain(domain)
authAPI.getWebClientConfigDomain(domain)
}
}
.map { riotConfig ->
onRiotConfigRetrieved(homeServerConnectionConfig, riotConfig)
.map { webClientConfig ->
onWebClientConfigRetrieved(homeServerConnectionConfig, webClientConfig)
}
.fold(
{
@ -214,7 +228,7 @@ internal class DefaultAuthenticationService @Inject constructor(
if (it is Failure.OtherServerError
&& it.httpCode == HttpsURLConnection.HTTP_NOT_FOUND /* 404 */) {
// Try with config.json
getRiotLoginFlowInternal(homeServerConnectionConfig)
getWebClientLoginFlowInternal(homeServerConnectionConfig)
} else {
throw it
}
@ -222,40 +236,24 @@ internal class DefaultAuthenticationService @Inject constructor(
)
}
private suspend fun getRiotLoginFlowInternal(homeServerConnectionConfig: HomeServerConnectionConfig): LoginFlowResult {
private suspend fun getWebClientLoginFlowInternal(homeServerConnectionConfig: HomeServerConnectionConfig): LoginFlowResult {
val authAPI = buildAuthAPI(homeServerConnectionConfig)
// Ok, try to get the config.json file of a RiotWeb client
return runCatching {
executeRequest(null) {
authAPI.getRiotConfig()
}
// Ok, try to get the config.json file of a Web client
return executeRequest(null) {
authAPI.getWebClientConfig()
}
.map { riotConfig ->
onRiotConfigRetrieved(homeServerConnectionConfig, riotConfig)
.let { webClientConfig ->
onWebClientConfigRetrieved(homeServerConnectionConfig, webClientConfig)
}
.fold(
{
it
},
{
if (it is Failure.OtherServerError
&& it.httpCode == HttpsURLConnection.HTTP_NOT_FOUND /* 404 */) {
// Try with wellknown
getWellknownLoginFlowInternal(homeServerConnectionConfig)
} else {
throw it
}
}
)
}
private suspend fun onRiotConfigRetrieved(homeServerConnectionConfig: HomeServerConnectionConfig, riotConfig: RiotConfig): LoginFlowResult {
val defaultHomeServerUrl = riotConfig.getPreferredHomeServerUrl()
private suspend fun onWebClientConfigRetrieved(homeServerConnectionConfig: HomeServerConnectionConfig, webClientConfig: WebClientConfig): LoginFlowResult {
val defaultHomeServerUrl = webClientConfig.getPreferredHomeServerUrl()
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)
@ -275,15 +273,13 @@ internal class DefaultAuthenticationService @Inject constructor(
val domain = homeServerConnectionConfig.homeServerUri.host
?: throw Failure.OtherServerError("", HttpsURLConnection.HTTP_NOT_FOUND /* 404 */)
// Create a fake userId, for the getWellknown task
val fakeUserId = "@alice:$domain"
val wellknownResult = getWellknownTask.execute(GetWellknownTask.Params(fakeUserId, homeServerConnectionConfig))
val wellknownResult = getWellknownTask.execute(GetWellknownTask.Params(domain, homeServerConnectionConfig))
return when (wellknownResult) {
is WellknownResult.Prompt -> {
val newHomeServerConnectionConfig = homeServerConnectionConfig.copy(
homeServerUri = Uri.parse(wellknownResult.homeServerUrl),
identityServerUri = wellknownResult.identityServerUrl?.let { Uri.parse(it) }
homeServerUriBase = Uri.parse(wellknownResult.homeServerUrl),
identityServerUri = wellknownResult.identityServerUrl?.let { Uri.parse(it) } ?: homeServerConnectionConfig.identityServerUri
)
val newAuthAPI = buildAuthAPI(newHomeServerConnectionConfig)
@ -379,7 +375,14 @@ internal class DefaultAuthenticationService @Inject constructor(
override suspend fun getWellKnownData(matrixId: String,
homeServerConnectionConfig: HomeServerConnectionConfig?): WellknownResult {
return getWellknownTask.execute(GetWellknownTask.Params(matrixId, homeServerConnectionConfig))
if (!MatrixPatterns.isUserId(matrixId)) {
throw MatrixIdFailure.InvalidMatrixId
}
return getWellknownTask.execute(GetWellknownTask.Params(
domain = matrixId.getDomain(),
homeServerConnectionConfig = homeServerConnectionConfig)
)
}
override suspend fun directAuthentication(homeServerConnectionConfig: HomeServerConnectionConfig,
@ -390,7 +393,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)
}

View file

@ -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)

View file

@ -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 == '/' }

View file

@ -20,7 +20,7 @@ import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
internal data class RiotConfig(
internal data class WebClientConfig(
/**
* This is now deprecated, but still used first, rather than value from "default_server_config"
*/
@ -28,7 +28,7 @@ internal data class RiotConfig(
val defaultHomeServerUrl: String?,
@Json(name = "default_server_config")
val defaultServerConfig: RiotConfigDefaultServerConfig?
val defaultServerConfig: WebClientConfigDefaultServerConfig?
) {
fun getPreferredHomeServerUrl(): String? {
return defaultHomeServerUrl
@ -38,13 +38,13 @@ internal data class RiotConfig(
}
@JsonClass(generateAdapter = true)
internal data class RiotConfigDefaultServerConfig(
internal data class WebClientConfigDefaultServerConfig(
@Json(name = "m.homeserver")
val homeServer: RiotConfigBaseConfig? = null
val homeServer: WebClientConfigBaseConfig? = null
)
@JsonClass(generateAdapter = true)
internal data class RiotConfigBaseConfig(
internal data class WebClientConfigBaseConfig(
@Json(name = "base_url")
val baseURL: String? = null
)

View file

@ -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))
}
}
}

View file

@ -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)

View file

@ -37,7 +37,8 @@ internal abstract class FederationModule {
fun providesFederationAPI(@Unauthenticated okHttpClient: Lazy<OkHttpClient>,
sessionParams: SessionParams,
retrofitFactory: RetrofitFactory): FederationAPI {
return retrofitFactory.create(okHttpClient, sessionParams.homeServerUrl).create(FederationAPI::class.java)
return retrofitFactory.create(okHttpClient, sessionParams.homeServerUrlBase)
.create(FederationAPI::class.java)
}
}

View file

@ -253,7 +253,7 @@ internal object CertUtil {
val list = ArrayList<ConnectionSpec>()
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

View file

@ -29,10 +29,9 @@ internal class DefaultRawService @Inject constructor(
return getUrlTask.execute(GetUrlTask.Params(url, cacheStrategy))
}
override suspend fun getWellknown(userId: String): String {
val homeServerDomain = userId.substringAfter(":")
override suspend fun getWellknown(domain: String): String {
return getUrl(
"https://$homeServerDomain/.well-known/matrix/client",
"https://$domain/.well-known/matrix/client",
CacheStrategy.TtlCache(TimeUnit.HOURS.toMillis(8), false)
)
}

View file

@ -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 {

View file

@ -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

View file

@ -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"

View file

@ -17,6 +17,7 @@
package org.matrix.android.sdk.internal.session.homeserver
import com.zhuinden.monarchy.Monarchy
import org.matrix.android.sdk.api.MatrixPatterns.getDomain
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
import org.matrix.android.sdk.api.auth.wellknown.WellknownResult
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities
@ -89,7 +90,10 @@ internal class DefaultGetHomeServerCapabilitiesTask @Inject constructor(
}.getOrNull()
val wellknownResult = runCatching {
getWellknownTask.execute(GetWellknownTask.Params(userId, homeServerConnectionConfig))
getWellknownTask.execute(GetWellknownTask.Params(
domain = userId.getDomain(),
homeServerConnectionConfig = homeServerConnectionConfig
))
}.getOrNull()
insertInDb(capabilities, mediaConfig, versions, wellknownResult)

View file

@ -16,6 +16,7 @@
package org.matrix.android.sdk.internal.session.permalinks
import org.matrix.android.sdk.api.MatrixPatterns.getDomain
import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams
import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.internal.di.UserId
@ -47,9 +48,9 @@ internal class ViaParameterFinder @Inject constructor(
}
fun computeViaParams(userId: String, roomId: String, max: Int): List<String> {
val userHomeserver = userId.substringAfter(":")
val userHomeserver = userId.getDomain()
return getUserIdsOfJoinedMembers(roomId)
.map { it.substringAfter(":") }
.map { it.getDomain() }
.groupBy { it }
.mapValues { it.value.size }
.toMutableMap()

View file

@ -16,6 +16,7 @@
package org.matrix.android.sdk.internal.session.room.alias
import org.matrix.android.sdk.api.MatrixPatterns.getDomain
import org.matrix.android.sdk.api.failure.Failure
import org.matrix.android.sdk.api.session.room.alias.RoomAliasError
import org.matrix.android.sdk.internal.di.UserId
@ -64,6 +65,6 @@ internal class RoomAliasAvailabilityChecker @Inject constructor(
}
companion object {
internal fun String.toFullLocalAlias(userId: String) = "#" + this + ":" + userId.substringAfter(":")
internal fun String.toFullLocalAlias(userId: String) = "#" + this + ":" + userId.getDomain()
}
}

View file

@ -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 ->

View file

@ -18,7 +18,6 @@ package org.matrix.android.sdk.internal.wellknown
import android.util.MalformedJsonException
import dagger.Lazy
import org.matrix.android.sdk.api.MatrixPatterns
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
import org.matrix.android.sdk.api.auth.data.WellKnown
import org.matrix.android.sdk.api.auth.wellknown.WellknownResult
@ -39,7 +38,11 @@ import javax.net.ssl.HttpsURLConnection
internal interface GetWellknownTask : Task<GetWellknownTask.Params, WellknownResult> {
data class Params(
val matrixId: String,
/**
* domain, for instance "matrix.org"
* the URL will be https://{domain}/.well-known/matrix/client
*/
val domain: String,
val homeServerConnectionConfig: HomeServerConnectionConfig?
)
}
@ -54,14 +57,8 @@ internal class DefaultGetWellknownTask @Inject constructor(
) : GetWellknownTask {
override suspend fun execute(params: GetWellknownTask.Params): WellknownResult {
if (!MatrixPatterns.isUserId(params.matrixId)) {
return WellknownResult.InvalidMatrixId
}
val homeServerDomain = params.matrixId.substringAfter(":")
val client = buildClient(params.homeServerConnectionConfig)
return findClientConfig(homeServerDomain, client)
return findClientConfig(params.domain, client)
}
private fun buildClient(homeServerConnectionConfig: HomeServerConnectionConfig?): OkHttpClient {

View file

@ -50,7 +50,15 @@ 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 = activity,
unrecognizedFingerprint = unrecognizedFingerprint,
existing = true,
callback = callback,
userId = userId,
homeServerUrl = hsConfig.homeServerUriBase.toString(),
homeServerConnectionConfigHasFingerprints = hsConfig.allowedFingerprints.isNotEmpty()
)
}
/**
@ -60,7 +68,15 @@ class UnrecognizedCertificateDialog @Inject constructor(
unrecognizedFingerprint: Fingerprint,
homeServerUrl: String,
callback: Callback) {
internalShow(activity, unrecognizedFingerprint, false, callback, null, homeServerUrl, false)
internalShow(
activity = activity,
unrecognizedFingerprint = unrecognizedFingerprint,
existing = false,
callback = callback,
userId = null,
homeServerUrl = homeServerUrl,
homeServerConnectionConfigHasFingerprints = false
)
}
/**

View file

@ -21,6 +21,7 @@ import im.vector.app.core.resources.StringProvider
import im.vector.app.features.call.dialpad.DialPadLookup
import org.matrix.android.sdk.api.failure.Failure
import org.matrix.android.sdk.api.failure.MatrixError
import org.matrix.android.sdk.api.failure.MatrixIdFailure
import org.matrix.android.sdk.api.failure.isInvalidPassword
import org.matrix.android.sdk.api.session.identity.IdentityServiceError
import java.net.HttpURLConnection
@ -39,9 +40,9 @@ class DefaultErrorFormatter @Inject constructor(
override fun toHumanReadable(throwable: Throwable?): String {
return when (throwable) {
null -> null
is IdentityServiceError -> identityServerError(throwable)
is Failure.NetworkConnection -> {
null -> null
is IdentityServiceError -> identityServerError(throwable)
is Failure.NetworkConnection -> {
when (throwable.ioException) {
is SocketTimeoutException ->
stringProvider.getString(R.string.error_network_timeout)
@ -54,7 +55,7 @@ class DefaultErrorFormatter @Inject constructor(
stringProvider.getString(R.string.error_no_network)
}
}
is Failure.ServerError -> {
is Failure.ServerError -> {
when {
throwable.error.code == MatrixError.M_CONSENT_NOT_GIVEN -> {
// Special case for terms and conditions
@ -104,23 +105,25 @@ class DefaultErrorFormatter @Inject constructor(
}
}
}
is Failure.OtherServerError -> {
is Failure.OtherServerError -> {
when (throwable.httpCode) {
HttpURLConnection.HTTP_NOT_FOUND ->
HttpURLConnection.HTTP_NOT_FOUND ->
// homeserver not found
stringProvider.getString(R.string.login_error_no_homeserver_found)
HttpURLConnection.HTTP_UNAUTHORIZED ->
// uia errors?
stringProvider.getString(R.string.error_unauthorized)
else ->
else ->
throwable.localizedMessage
}
}
is DialPadLookup.Failure.NumberIsYours ->
is DialPadLookup.Failure.NumberIsYours ->
stringProvider.getString(R.string.cannot_call_yourself)
is DialPadLookup.Failure.NoResult ->
is DialPadLookup.Failure.NoResult ->
stringProvider.getString(R.string.call_dial_pad_lookup_error)
else -> throwable.localizedMessage
is MatrixIdFailure.InvalidMatrixId ->
stringProvider.getString(R.string.login_signin_matrix_id_error_invalid_matrix_id)
else -> throwable.localizedMessage
}
?: stringProvider.getString(R.string.unknown_error)
}

View file

@ -56,7 +56,7 @@ class JitsiService @Inject constructor(
// Build data for a jitsi widget
val widgetId: String = WidgetType.Jitsi.preferred + "_" + session.myUserId + "_" + System.currentTimeMillis()
val preferredJitsiDomain = tryOrNull {
rawService.getElementWellknown(session.myUserId)
rawService.getElementWellknown(session.sessionParams)
?.jitsiServer
?.preferredDomain
}

View file

@ -86,7 +86,7 @@ class CreateDirectRoomViewModel @AssistedInject constructor(@Assisted
setState { copy(createAndInviteState = Loading()) }
viewModelScope.launch(Dispatchers.IO) {
val adminE2EByDefault = rawService.getElementWellknown(session.myUserId)
val adminE2EByDefault = rawService.getElementWellknown(session.sessionParams)
?.isE2EByDefault()
?: true

View file

@ -35,7 +35,7 @@ class DirectRoomHelper @Inject constructor(
if (existingRoomId != null) {
roomId = existingRoomId
} else {
val adminE2EByDefault = rawService.getElementWellknown(session.myUserId)
val adminE2EByDefault = rawService.getElementWellknown(session.sessionParams)
?.isE2EByDefault()
?: true

View file

@ -70,7 +70,7 @@ class HomeServerCapabilitiesViewModel @AssistedInject constructor(
private fun initAdminE2eByDefault() {
viewModelScope.launch(Dispatchers.IO) {
val adminE2EByDefault = tryOrNull {
rawService.getElementWellknown(session.myUserId)
rawService.getElementWellknown(session.sessionParams)
?.isE2EByDefault()
?: true
} ?: true

View file

@ -174,7 +174,7 @@ class LoginFragment @Inject constructor() : AbstractSSOLoginFragment<FragmentLog
ServerType.MatrixOrg -> {
views.loginServerIcon.isVisible = true
views.loginServerIcon.setImageResource(R.drawable.ic_logo_matrix_org)
views.loginTitle.text = getString(resId, state.homeServerUrl.toReducedUrl())
views.loginTitle.text = getString(resId, state.homeServerUrlFromUser.toReducedUrl())
views.loginNotice.text = getString(R.string.login_server_matrix_org_text)
}
ServerType.EMS -> {
@ -185,7 +185,7 @@ class LoginFragment @Inject constructor() : AbstractSSOLoginFragment<FragmentLog
}
ServerType.Other -> {
views.loginServerIcon.isVisible = false
views.loginTitle.text = getString(resId, state.homeServerUrl.toReducedUrl())
views.loginTitle.text = getString(resId, state.homeServerUrlFromUser.toReducedUrl())
views.loginNotice.text = getString(R.string.login_server_other_text)
}
ServerType.Unknown -> Unit /* Should not happen */

View file

@ -55,7 +55,7 @@ class LoginResetPasswordFragment @Inject constructor() : AbstractLoginFragment<F
}
private fun setupUi(state: LoginViewState) {
views.resetPasswordTitle.text = getString(R.string.login_reset_password_on, state.homeServerUrl.toReducedUrl())
views.resetPasswordTitle.text = getString(R.string.login_reset_password_on, state.homeServerUrlFromUser.toReducedUrl())
}
private fun setupSubmitButton() {

View file

@ -53,19 +53,19 @@ class LoginSignUpSignInSelectionFragment @Inject constructor() : AbstractSSOLogi
ServerType.MatrixOrg -> {
views.loginSignupSigninServerIcon.setImageResource(R.drawable.ic_logo_matrix_org)
views.loginSignupSigninServerIcon.isVisible = true
views.loginSignupSigninTitle.text = getString(R.string.login_connect_to, state.homeServerUrl.toReducedUrl())
views.loginSignupSigninTitle.text = getString(R.string.login_connect_to, state.homeServerUrlFromUser.toReducedUrl())
views.loginSignupSigninText.text = getString(R.string.login_server_matrix_org_text)
}
ServerType.EMS -> {
views.loginSignupSigninServerIcon.setImageResource(R.drawable.ic_logo_element_matrix_services)
views.loginSignupSigninServerIcon.isVisible = true
views.loginSignupSigninTitle.text = getString(R.string.login_connect_to_modular)
views.loginSignupSigninText.text = state.homeServerUrl.toReducedUrl()
views.loginSignupSigninText.text = state.homeServerUrlFromUser.toReducedUrl()
}
ServerType.Other -> {
views.loginSignupSigninServerIcon.isVisible = false
views.loginSignupSigninTitle.text = getString(R.string.login_server_other_title)
views.loginSignupSigninText.text = getString(R.string.login_connect_to, state.homeServerUrl.toReducedUrl())
views.loginSignupSigninText.text = getString(R.string.login_connect_to, state.homeServerUrlFromUser.toReducedUrl())
}
ServerType.Unknown -> Unit /* Should not happen */
}

View file

@ -40,6 +40,7 @@ import im.vector.app.core.utils.ensureTrailingSlash
import im.vector.app.features.signout.soft.SoftLogoutActivity
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.MatrixPatterns.getDomain
import org.matrix.android.sdk.api.auth.AuthenticationService
import org.matrix.android.sdk.api.auth.HomeServerHistoryService
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
@ -51,6 +52,7 @@ import org.matrix.android.sdk.api.auth.registration.RegistrationWizard
import org.matrix.android.sdk.api.auth.registration.Stage
import org.matrix.android.sdk.api.auth.wellknown.WellknownResult
import org.matrix.android.sdk.api.failure.Failure
import org.matrix.android.sdk.api.failure.MatrixIdFailure
import org.matrix.android.sdk.api.session.Session
import timber.log.Timber
import java.util.concurrent.CancellationException
@ -213,6 +215,7 @@ class LoginViewModel @AssistedInject constructor(
copy(
signMode = SignMode.SignIn,
loginMode = LoginMode.Sso(action.ssoIdentityProviders),
homeServerUrlFromUser = action.homeServerUrl,
homeServerUrl = action.homeServerUrl,
deviceId = action.deviceId
)
@ -364,6 +367,7 @@ class LoginViewModel @AssistedInject constructor(
setState {
copy(
asyncHomeServerLoginFlowRequest = Uninitialized,
homeServerUrlFromUser = null,
homeServerUrl = null,
loginMode = LoginMode.Unknown,
serverType = ServerType.Unknown,
@ -560,24 +564,16 @@ class LoginViewModel @AssistedInject constructor(
return@launch
}
when (data) {
is WellknownResult.Prompt ->
is WellknownResult.Prompt ->
onWellknownSuccess(action, data, homeServerConnectionConfig)
is WellknownResult.FailPrompt ->
is WellknownResult.FailPrompt ->
// Relax on IS discovery if home server is valid
if (data.homeServerUrl != null && data.wellKnown != null) {
onWellknownSuccess(action, WellknownResult.Prompt(data.homeServerUrl!!, null, data.wellKnown!!), homeServerConnectionConfig)
} else {
onWellKnownError()
}
is WellknownResult.InvalidMatrixId -> {
setState {
copy(
asyncLoginAction = Uninitialized
)
}
_viewEvents.post(LoginViewEvents.Failure(Exception(stringProvider.getString(R.string.login_signin_matrix_id_error_invalid_matrix_id))))
}
else -> {
else -> {
onWellKnownError()
}
}.exhaustive
@ -598,11 +594,12 @@ 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(
homeServerUri = Uri.parse(wellKnownPrompt.homeServerUrl),
homeServerUri = Uri.parse("https://${action.username.getDomain()}"),
homeServerUriBase = Uri.parse(wellKnownPrompt.homeServerUrl),
identityServerUri = wellKnownPrompt.identityServerUrl?.let { Uri.parse(it) }
)
@ -620,19 +617,23 @@ class LoginViewModel @AssistedInject constructor(
}
private fun onDirectLoginError(failure: Throwable) {
if (failure is Failure.UnrecognizedCertificateFailure) {
// Display this error in a dialog
_viewEvents.post(LoginViewEvents.Failure(failure))
setState {
copy(
asyncLoginAction = Uninitialized
)
when (failure) {
is MatrixIdFailure.InvalidMatrixId,
is Failure.UnrecognizedCertificateFailure -> {
// Display this error in a dialog
_viewEvents.post(LoginViewEvents.Failure(failure))
setState {
copy(
asyncLoginAction = Uninitialized
)
}
}
} else {
setState {
copy(
asyncLoginAction = Fail(failure)
)
else -> {
setState {
copy(
asyncLoginAction = Fail(failure)
)
}
}
}
}
@ -775,7 +776,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 {
@ -791,6 +792,7 @@ class LoginViewModel @AssistedInject constructor(
setState {
copy(
asyncHomeServerLoginFlowRequest = Uninitialized,
homeServerUrlFromUser = homeServerConnectionConfig.homeServerUri.toString(),
homeServerUrl = data.homeServerUrl,
loginMode = loginMode,
loginModeSupportedTypes = data.supportedLoginTypes.toList()

View file

@ -38,7 +38,12 @@ data class LoginViewState(
@PersistState
val resetPasswordEmail: String? = null,
@PersistState
val homeServerUrlFromUser: String? = null,
// Can be modified after a Wellknown request
@PersistState
val homeServerUrl: String? = null,
// For SSO session recovery
@PersistState
val deviceId: String? = null,

View file

@ -112,7 +112,7 @@ class LoginTermsFragment @Inject constructor(
}
override fun updateWithState(state: LoginViewState) {
policyController.homeServer = state.homeServerUrl.toReducedUrl()
policyController.homeServer = state.homeServerUrlFromUser.toReducedUrl()
renderState()
}

View file

@ -41,6 +41,7 @@ import im.vector.app.features.login.LoginMode
import im.vector.app.features.login.ReAuthHelper
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.MatrixPatterns.getDomain
import org.matrix.android.sdk.api.auth.AuthenticationService
import org.matrix.android.sdk.api.auth.HomeServerHistoryService
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
@ -595,10 +596,6 @@ class LoginViewModel2 @AssistedInject constructor(
} else {
onWellKnownError()
}
is WellknownResult.InvalidMatrixId -> {
setState { copy(isLoading = false) }
_viewEvents.post(LoginViewEvents2.Failure(Exception(stringProvider.getString(R.string.login_signin_matrix_id_error_invalid_matrix_id))))
}
else -> {
onWellKnownError()
}
@ -616,7 +613,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(
@ -655,7 +652,7 @@ class LoginViewModel2 @AssistedInject constructor(
}
viewEvent?.let { _viewEvents.post(it) }
val urlFromUser = action.username.substringAfter(":")
val urlFromUser = action.username.getDomain()
setState {
copy(
isLoading = false,
@ -756,7 +753,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 {

View file

@ -16,11 +16,15 @@
package im.vector.app.features.raw.wellknown
import org.matrix.android.sdk.api.MatrixPatterns.getDomain
import org.matrix.android.sdk.api.auth.data.SessionParams
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.raw.RawService
suspend fun RawService.getElementWellknown(userId: String): ElementWellKnown? {
return tryOrNull { getWellknown(userId) }
suspend fun RawService.getElementWellknown(sessionParams: SessionParams): ElementWellKnown? {
// By default we use the domain of the userId to retrieve the .well-known data
val domain = sessionParams.userId.getDomain()
return tryOrNull { getWellknown(domain) }
?.let { ElementWellKnownMapper.from(it) }
}

View file

@ -34,6 +34,7 @@ import im.vector.app.features.raw.wellknown.getElementWellknown
import im.vector.app.features.raw.wellknown.isE2EByDefault
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.MatrixPatterns.getDomain
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.raw.RawService
import org.matrix.android.sdk.api.session.Session
@ -62,7 +63,7 @@ class CreateRoomViewModel @AssistedInject constructor(@Assisted private val init
private fun initHomeServerName() {
setState {
copy(
homeServerName = session.myUserId.substringAfter(":")
homeServerName = session.myUserId.getDomain()
)
}
}
@ -72,7 +73,7 @@ class CreateRoomViewModel @AssistedInject constructor(@Assisted private val init
private fun initAdminE2eByDefault() {
viewModelScope.launch(Dispatchers.IO) {
adminE2EByDefault = tryOrNull {
rawService.getElementWellknown(session.myUserId)
rawService.getElementWellknown(session.sessionParams)
?.isE2EByDefault()
?: true
} ?: true

View file

@ -20,6 +20,7 @@ import im.vector.app.R
import im.vector.app.core.resources.StringArrayProvider
import im.vector.app.features.roomdirectory.RoomDirectoryData
import im.vector.app.features.roomdirectory.RoomDirectoryServer
import org.matrix.android.sdk.api.MatrixPatterns.getDomain
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.room.model.thirdparty.ThirdPartyProtocol
import javax.inject.Inject
@ -36,7 +37,7 @@ class RoomDirectoryListCreator @Inject constructor(
val protocols = ArrayList<RoomDirectoryData>()
// Add user homeserver name
val userHsName = session.myUserId.substringAfter(":")
val userHsName = session.myUserId.getDomain()
// Add default protocol
protocols.add(

View file

@ -31,6 +31,7 @@ import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.powerlevel.PowerLevelsObservableFactory
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.MatrixPatterns.getDomain
import org.matrix.android.sdk.api.query.QueryStringValue
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.events.model.EventType
@ -101,7 +102,7 @@ class RoomAliasViewModel @AssistedInject constructor(@Assisted initialState: Roo
private fun initHomeServerName() {
setState {
copy(
homeServerName = session.myUserId.substringAfter(":")
homeServerName = session.myUserId.getDomain()
)
}
}

View file

@ -157,7 +157,7 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor(
findPreference<VectorPreference>(VectorPreferences.SETTINGS_CRYPTOGRAPHY_HS_ADMIN_DISABLED_E2E_DEFAULT)?.isVisible =
vectorActivity.getVectorComponent()
.rawService()
.getElementWellknown(session.myUserId)
.getElementWellknown(session.sessionParams)
?.isE2EByDefault() == false
}
}

View file

@ -23,7 +23,8 @@ import org.matrix.android.sdk.api.federation.FederationVersion
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities
data class HomeServerSettingsViewState(
val baseUrl: String = "",
val homeserverUrl: String = "",
val homeserverClientServerApiUrl: String = "",
val homeServerCapabilities: HomeServerCapabilities = HomeServerCapabilities(),
val federationVersion: Async<FederationVersion> = Uninitialized
) : MvRxState

View file

@ -29,13 +29,15 @@ import im.vector.app.core.resources.StringProvider
import im.vector.app.features.discovery.settingsCenteredImageItem
import im.vector.app.features.discovery.settingsInfoItem
import im.vector.app.features.discovery.settingsSectionTitleItem
import im.vector.app.features.settings.VectorPreferences
import org.matrix.android.sdk.api.federation.FederationVersion
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities
import javax.inject.Inject
class HomeserverSettingsController @Inject constructor(
private val stringProvider: StringProvider,
private val errorFormatter: ErrorFormatter
private val errorFormatter: ErrorFormatter,
private val vectorPreferences: VectorPreferences
) : TypedEpoxyController<HomeServerSettingsViewState>() {
var callback: Callback? = null
@ -78,7 +80,17 @@ class HomeserverSettingsController @Inject constructor(
}
settingsInfoItem {
id("urlValue")
helperText(state.baseUrl)
helperText(state.homeserverUrl)
}
if (vectorPreferences.developerMode()) {
settingsSectionTitleItem {
id("urlApiTitle")
titleResId(R.string.hs_client_url)
}
settingsInfoItem {
id("urlApiValue")
helperText(state.homeserverClientServerApiUrl)
}
}
}

View file

@ -53,7 +53,8 @@ class HomeserverSettingsViewModel @AssistedInject constructor(
init {
setState {
copy(
baseUrl = session.sessionParams.homeServerUrl,
homeserverUrl = session.sessionParams.homeServerUrl,
homeserverClientServerApiUrl = session.sessionParams.homeServerUrlBase,
homeServerCapabilities = session.getHomeServerCapabilities()
)
}

View file

@ -36,6 +36,7 @@ import im.vector.app.core.resources.StringProvider
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.MatrixPatterns
import org.matrix.android.sdk.api.MatrixPatterns.getDomain
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.room.AliasAvailabilityResult
import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure
@ -51,7 +52,7 @@ class CreateSpaceViewModel @AssistedInject constructor(
init {
setState {
copy(
homeServerName = session.myUserId.substringAfter(":")
homeServerName = session.myUserId.getDomain()
)
}
}

View file

@ -75,7 +75,7 @@ class CreateSpaceViewModelTask @Inject constructor(
val childIds = mutableListOf<String>()
val e2eByDefault = tryOrNull {
rawService.getElementWellknown(session.myUserId)
rawService.getElementWellknown(session.sessionParams)
?.isE2EByDefault()
?: true
} ?: true

View file

@ -81,7 +81,7 @@ class SpacePeopleViewModel @AssistedInject constructor(
setState { copy(createAndInviteState = Loading()) }
viewModelScope.launch(Dispatchers.IO) {
val adminE2EByDefault = rawService.getElementWellknown(session.myUserId)
val adminE2EByDefault = rawService.getElementWellknown(session.sessionParams)
?.isE2EByDefault()
?: true

View file

@ -538,6 +538,7 @@
<string name="login">Log in</string>
<string name="logout">Sign out</string>
<string name="hs_url">Homeserver URL</string>
<string name="hs_client_url">Homeserver API URL</string>
<string name="identity_url">Identity Server URL</string>
<string name="search">Search</string>