mirror of
https://github.com/element-hq/element-android
synced 2024-11-24 02:15:35 +03:00
Merge pull request #5398 from vector-im/bugfix/eric/softlogout-ux-broken
Fixes broken SoftLogout UX for homeservers that support both Password and SSO
This commit is contained in:
commit
bdb49f5946
37 changed files with 1058 additions and 150 deletions
1
changelog.d/5398.bugfix
Normal file
1
changelog.d/5398.bugfix
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Adds LoginType to SessionParams to fix soft logout form not showing for SSO and Password type
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.auth
|
||||||
|
|
||||||
|
enum class LoginType {
|
||||||
|
PASSWORD,
|
||||||
|
SSO,
|
||||||
|
UNSUPPORTED,
|
||||||
|
CUSTOM,
|
||||||
|
DIRECT,
|
||||||
|
UNKNOWN;
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
fun fromName(name: String) = when (name) {
|
||||||
|
PASSWORD.name -> PASSWORD
|
||||||
|
SSO.name -> SSO
|
||||||
|
UNSUPPORTED.name -> UNSUPPORTED
|
||||||
|
CUSTOM.name -> CUSTOM
|
||||||
|
DIRECT.name -> DIRECT
|
||||||
|
else -> UNKNOWN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
package org.matrix.android.sdk.api.auth.data
|
package org.matrix.android.sdk.api.auth.data
|
||||||
|
|
||||||
|
import org.matrix.android.sdk.api.auth.LoginType
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This data class holds necessary data to open a session.
|
* This data class holds necessary data to open a session.
|
||||||
* You don't have to manually instantiate it.
|
* You don't have to manually instantiate it.
|
||||||
|
@ -34,7 +36,12 @@ data class SessionParams(
|
||||||
/**
|
/**
|
||||||
* Set to false if the current token is not valid anymore. Application should not have to use this info.
|
* Set to false if the current token is not valid anymore. Application should not have to use this info.
|
||||||
*/
|
*/
|
||||||
val isTokenValid: Boolean
|
val isTokenValid: Boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The authentication method that was used to create the session.
|
||||||
|
*/
|
||||||
|
val loginType: LoginType,
|
||||||
) {
|
) {
|
||||||
/*
|
/*
|
||||||
* Shortcuts. Usually the application should only need to use these shortcuts
|
* Shortcuts. Usually the application should only need to use these shortcuts
|
||||||
|
|
|
@ -83,6 +83,9 @@ internal abstract class AuthModule {
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun bindSessionCreator(creator: DefaultSessionCreator): SessionCreator
|
abstract fun bindSessionCreator(creator: DefaultSessionCreator): SessionCreator
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
abstract fun bindSessionParamsCreator(creator: DefaultSessionParamsCreator): SessionParamsCreator
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun bindDirectLoginTask(task: DefaultDirectLoginTask): DirectLoginTask
|
abstract fun bindDirectLoginTask(task: DefaultDirectLoginTask): DirectLoginTask
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ import okhttp3.OkHttpClient
|
||||||
import org.matrix.android.sdk.api.MatrixPatterns
|
import org.matrix.android.sdk.api.MatrixPatterns
|
||||||
import org.matrix.android.sdk.api.MatrixPatterns.getServerName
|
import org.matrix.android.sdk.api.MatrixPatterns.getServerName
|
||||||
import org.matrix.android.sdk.api.auth.AuthenticationService
|
import org.matrix.android.sdk.api.auth.AuthenticationService
|
||||||
|
import org.matrix.android.sdk.api.auth.LoginType
|
||||||
import org.matrix.android.sdk.api.auth.data.Credentials
|
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.HomeServerConnectionConfig
|
||||||
import org.matrix.android.sdk.api.auth.data.LoginFlowResult
|
import org.matrix.android.sdk.api.auth.data.LoginFlowResult
|
||||||
|
@ -361,7 +362,7 @@ internal class DefaultAuthenticationService @Inject constructor(
|
||||||
homeServerConnectionConfig: HomeServerConnectionConfig,
|
homeServerConnectionConfig: HomeServerConnectionConfig,
|
||||||
credentials: Credentials
|
credentials: Credentials
|
||||||
): Session {
|
): Session {
|
||||||
return sessionCreator.createSession(credentials, homeServerConnectionConfig)
|
return sessionCreator.createSession(credentials, homeServerConnectionConfig, LoginType.SSO)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getWellKnownData(
|
override suspend fun getWellKnownData(
|
||||||
|
|
|
@ -16,69 +16,41 @@
|
||||||
|
|
||||||
package org.matrix.android.sdk.internal.auth
|
package org.matrix.android.sdk.internal.auth
|
||||||
|
|
||||||
import android.net.Uri
|
import org.matrix.android.sdk.api.auth.LoginType
|
||||||
import org.matrix.android.sdk.api.auth.data.Credentials
|
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.HomeServerConnectionConfig
|
||||||
import org.matrix.android.sdk.api.auth.data.SessionParams
|
|
||||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
import org.matrix.android.sdk.internal.SessionManager
|
import org.matrix.android.sdk.internal.SessionManager
|
||||||
import timber.log.Timber
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal interface SessionCreator {
|
internal interface SessionCreator {
|
||||||
suspend fun createSession(credentials: Credentials, homeServerConnectionConfig: HomeServerConnectionConfig): Session
|
|
||||||
|
suspend fun createSession(
|
||||||
|
credentials: Credentials,
|
||||||
|
homeServerConnectionConfig: HomeServerConnectionConfig,
|
||||||
|
loginType: LoginType,
|
||||||
|
): Session
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class DefaultSessionCreator @Inject constructor(
|
internal class DefaultSessionCreator @Inject constructor(
|
||||||
private val sessionParamsStore: SessionParamsStore,
|
private val sessionParamsStore: SessionParamsStore,
|
||||||
private val sessionManager: SessionManager,
|
private val sessionManager: SessionManager,
|
||||||
private val pendingSessionStore: PendingSessionStore,
|
private val pendingSessionStore: PendingSessionStore,
|
||||||
private val isValidClientServerApiTask: IsValidClientServerApiTask
|
private val sessionParamsCreator: SessionParamsCreator,
|
||||||
) : SessionCreator {
|
) : SessionCreator {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Credentials can affect the homeServerConnectionConfig, override homeserver url and/or
|
* Credentials can affect the homeServerConnectionConfig, override homeserver url and/or
|
||||||
* identity server url if provided in the credentials.
|
* identity server url if provided in the credentials.
|
||||||
*/
|
*/
|
||||||
override suspend fun createSession(credentials: Credentials, homeServerConnectionConfig: HomeServerConnectionConfig): Session {
|
override suspend fun createSession(
|
||||||
|
credentials: Credentials,
|
||||||
|
homeServerConnectionConfig: HomeServerConnectionConfig,
|
||||||
|
loginType: LoginType,
|
||||||
|
): Session {
|
||||||
// We can cleanup the pending session params
|
// We can cleanup the pending session params
|
||||||
pendingSessionStore.delete()
|
pendingSessionStore.delete()
|
||||||
|
val sessionParams = sessionParamsCreator.create(credentials, homeServerConnectionConfig, loginType)
|
||||||
val overriddenUrl = credentials.discoveryInformation?.homeServer?.baseURL
|
|
||||||
// remove trailing "/"
|
|
||||||
?.trim { it == '/' }
|
|
||||||
?.takeIf { it.isNotBlank() }
|
|
||||||
// It can be the same value, so in this case, do not check again the validity
|
|
||||||
?.takeIf { it != homeServerConnectionConfig.homeServerUriBase.toString() }
|
|
||||||
?.also { Timber.d("Overriding homeserver url to $it (will check if valid)") }
|
|
||||||
?.let { Uri.parse(it) }
|
|
||||||
?.takeIf {
|
|
||||||
// Validate the URL, if the configuration is wrong server side, do not override
|
|
||||||
tryOrNull {
|
|
||||||
isValidClientServerApiTask.execute(
|
|
||||||
IsValidClientServerApiTask.Params(
|
|
||||||
homeServerConnectionConfig.copy(homeServerUriBase = it)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.also { Timber.d("Overriding homeserver url: $it") }
|
|
||||||
} ?: true // In case of other error (no network, etc.), consider it is valid...
|
|
||||||
}
|
|
||||||
|
|
||||||
val sessionParams = SessionParams(
|
|
||||||
credentials = credentials,
|
|
||||||
homeServerConnectionConfig = homeServerConnectionConfig.copy(
|
|
||||||
homeServerUriBase = overriddenUrl ?: homeServerConnectionConfig.homeServerUriBase,
|
|
||||||
identityServerUri = credentials.discoveryInformation?.identityServer?.baseURL
|
|
||||||
// remove trailing "/"
|
|
||||||
?.trim { it == '/' }
|
|
||||||
?.takeIf { it.isNotBlank() }
|
|
||||||
?.also { Timber.d("Overriding identity server url to $it") }
|
|
||||||
?.let { Uri.parse(it) }
|
|
||||||
?: homeServerConnectionConfig.identityServerUri
|
|
||||||
),
|
|
||||||
isTokenValid = true)
|
|
||||||
|
|
||||||
sessionParamsStore.save(sessionParams)
|
sessionParamsStore.save(sessionParams)
|
||||||
return sessionManager.getOrCreateSession(sessionParams)
|
return sessionManager.getOrCreateSession(sessionParams)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.internal.auth
|
||||||
|
|
||||||
|
import android.net.Uri
|
||||||
|
import org.matrix.android.sdk.api.auth.LoginType
|
||||||
|
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.SessionParams
|
||||||
|
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||||
|
import timber.log.Timber
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
internal interface SessionParamsCreator {
|
||||||
|
|
||||||
|
suspend fun create(
|
||||||
|
credentials: Credentials,
|
||||||
|
homeServerConnectionConfig: HomeServerConnectionConfig,
|
||||||
|
loginType: LoginType,
|
||||||
|
): SessionParams
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class DefaultSessionParamsCreator @Inject constructor(
|
||||||
|
private val isValidClientServerApiTask: IsValidClientServerApiTask
|
||||||
|
) : SessionParamsCreator {
|
||||||
|
|
||||||
|
override suspend fun create(
|
||||||
|
credentials: Credentials,
|
||||||
|
homeServerConnectionConfig: HomeServerConnectionConfig,
|
||||||
|
loginType: LoginType,
|
||||||
|
) = SessionParams(
|
||||||
|
credentials = credentials,
|
||||||
|
homeServerConnectionConfig = homeServerConnectionConfig.overrideWithCredentials(credentials),
|
||||||
|
isTokenValid = true,
|
||||||
|
loginType = loginType,
|
||||||
|
)
|
||||||
|
|
||||||
|
private suspend fun HomeServerConnectionConfig.overrideWithCredentials(credentials: Credentials) = copy(
|
||||||
|
homeServerUriBase = credentials.getHomeServerUri(this) ?: homeServerUriBase,
|
||||||
|
identityServerUri = credentials.getIdentityServerUri() ?: identityServerUri
|
||||||
|
)
|
||||||
|
|
||||||
|
private suspend fun Credentials.getHomeServerUri(homeServerConnectionConfig: HomeServerConnectionConfig) =
|
||||||
|
discoveryInformation?.homeServer?.baseURL
|
||||||
|
?.trim { it == '/' }
|
||||||
|
?.takeIf { it.isNotBlank() }
|
||||||
|
// It can be the same value, so in this case, do not check again the validity
|
||||||
|
?.takeIf { it != homeServerConnectionConfig.homeServerUriBase.toString() }
|
||||||
|
?.also { Timber.d("Overriding homeserver url to $it (will check if valid)") }
|
||||||
|
?.let { Uri.parse(it) }
|
||||||
|
?.takeIf { validateUri(it, homeServerConnectionConfig) }
|
||||||
|
|
||||||
|
private suspend fun validateUri(uri: Uri, homeServerConnectionConfig: HomeServerConnectionConfig) =
|
||||||
|
// Validate the URL, if the configuration is wrong server side, do not override
|
||||||
|
tryOrNull {
|
||||||
|
performClientServerApiValidation(uri, homeServerConnectionConfig)
|
||||||
|
} ?: true // In case of other error (no network, etc.), consider it is valid...
|
||||||
|
|
||||||
|
private suspend fun performClientServerApiValidation(uri: Uri, homeServerConnectionConfig: HomeServerConnectionConfig) =
|
||||||
|
isValidClientServerApiTask.execute(
|
||||||
|
IsValidClientServerApiTask.Params(homeServerConnectionConfig.copy(homeServerUriBase = uri))
|
||||||
|
).also { Timber.d("Overriding homeserver url: $it") }
|
||||||
|
|
||||||
|
private fun Credentials.getIdentityServerUri() = discoveryInformation?.identityServer?.baseURL
|
||||||
|
?.trim { it == '/' }
|
||||||
|
?.takeIf { it.isNotBlank() }
|
||||||
|
?.also { Timber.d("Overriding identity server url to $it") }
|
||||||
|
?.let { Uri.parse(it) }
|
||||||
|
}
|
|
@ -22,6 +22,7 @@ import org.matrix.android.sdk.internal.auth.db.migration.MigrateAuthTo001
|
||||||
import org.matrix.android.sdk.internal.auth.db.migration.MigrateAuthTo002
|
import org.matrix.android.sdk.internal.auth.db.migration.MigrateAuthTo002
|
||||||
import org.matrix.android.sdk.internal.auth.db.migration.MigrateAuthTo003
|
import org.matrix.android.sdk.internal.auth.db.migration.MigrateAuthTo003
|
||||||
import org.matrix.android.sdk.internal.auth.db.migration.MigrateAuthTo004
|
import org.matrix.android.sdk.internal.auth.db.migration.MigrateAuthTo004
|
||||||
|
import org.matrix.android.sdk.internal.auth.db.migration.MigrateAuthTo005
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -33,7 +34,7 @@ internal class AuthRealmMigration @Inject constructor() : RealmMigration {
|
||||||
override fun equals(other: Any?) = other is AuthRealmMigration
|
override fun equals(other: Any?) = other is AuthRealmMigration
|
||||||
override fun hashCode() = 4000
|
override fun hashCode() = 4000
|
||||||
|
|
||||||
val schemaVersion = 4L
|
val schemaVersion = 5L
|
||||||
|
|
||||||
override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
|
override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
|
||||||
Timber.d("Migrating Auth Realm from $oldVersion to $newVersion")
|
Timber.d("Migrating Auth Realm from $oldVersion to $newVersion")
|
||||||
|
@ -42,5 +43,6 @@ internal class AuthRealmMigration @Inject constructor() : RealmMigration {
|
||||||
if (oldVersion < 2) MigrateAuthTo002(realm).perform()
|
if (oldVersion < 2) MigrateAuthTo002(realm).perform()
|
||||||
if (oldVersion < 3) MigrateAuthTo003(realm).perform()
|
if (oldVersion < 3) MigrateAuthTo003(realm).perform()
|
||||||
if (oldVersion < 4) MigrateAuthTo004(realm).perform()
|
if (oldVersion < 4) MigrateAuthTo004(realm).perform()
|
||||||
|
if (oldVersion < 5) MigrateAuthTo005(realm).perform()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,5 +26,6 @@ internal open class SessionParamsEntity(
|
||||||
var homeServerConnectionConfigJson: String = "",
|
var homeServerConnectionConfigJson: String = "",
|
||||||
// Set to false when the token is invalid and the user has been soft logged out
|
// Set to false when the token is invalid and the user has been soft logged out
|
||||||
// In case of hard logout, this object is deleted from DB
|
// In case of hard logout, this object is deleted from DB
|
||||||
var isTokenValid: Boolean = true
|
var isTokenValid: Boolean = true,
|
||||||
|
var loginType: String = "",
|
||||||
) : RealmObject()
|
) : RealmObject()
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package org.matrix.android.sdk.internal.auth.db
|
package org.matrix.android.sdk.internal.auth.db
|
||||||
|
|
||||||
import com.squareup.moshi.Moshi
|
import com.squareup.moshi.Moshi
|
||||||
|
import org.matrix.android.sdk.api.auth.LoginType
|
||||||
import org.matrix.android.sdk.api.auth.data.Credentials
|
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.HomeServerConnectionConfig
|
||||||
import org.matrix.android.sdk.api.auth.data.SessionParams
|
import org.matrix.android.sdk.api.auth.data.SessionParams
|
||||||
|
@ -37,7 +38,7 @@ internal class SessionParamsMapper @Inject constructor(moshi: Moshi) {
|
||||||
if (credentials == null || homeServerConnectionConfig == null) {
|
if (credentials == null || homeServerConnectionConfig == null) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
return SessionParams(credentials, homeServerConnectionConfig, entity.isTokenValid)
|
return SessionParams(credentials, homeServerConnectionConfig, entity.isTokenValid, LoginType.fromName(entity.loginType))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun map(sessionParams: SessionParams?): SessionParamsEntity? {
|
fun map(sessionParams: SessionParams?): SessionParamsEntity? {
|
||||||
|
@ -54,7 +55,8 @@ internal class SessionParamsMapper @Inject constructor(moshi: Moshi) {
|
||||||
sessionParams.userId,
|
sessionParams.userId,
|
||||||
credentialsJson,
|
credentialsJson,
|
||||||
homeServerConnectionConfigJson,
|
homeServerConnectionConfigJson,
|
||||||
sessionParams.isTokenValid
|
sessionParams.isTokenValid,
|
||||||
|
sessionParams.loginType.name,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.internal.auth.db.migration
|
||||||
|
|
||||||
|
import io.realm.DynamicRealm
|
||||||
|
import org.matrix.android.sdk.api.auth.LoginType
|
||||||
|
import org.matrix.android.sdk.internal.auth.db.SessionParamsEntityFields
|
||||||
|
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
|
internal class MigrateAuthTo005(realm: DynamicRealm) : RealmMigrator(realm, 5) {
|
||||||
|
|
||||||
|
override fun doMigrate(realm: DynamicRealm) {
|
||||||
|
Timber.d("Update SessionParamsEntity to add LoginType")
|
||||||
|
|
||||||
|
realm.schema.get("SessionParamsEntity")
|
||||||
|
?.addField(SessionParamsEntityFields.LOGIN_TYPE, String::class.java)
|
||||||
|
?.setRequired(SessionParamsEntityFields.LOGIN_TYPE, true)
|
||||||
|
?.transform { it.set(SessionParamsEntityFields.LOGIN_TYPE, LoginType.UNKNOWN.name) }
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,7 @@
|
||||||
package org.matrix.android.sdk.internal.auth.login
|
package org.matrix.android.sdk.internal.auth.login
|
||||||
|
|
||||||
import android.util.Patterns
|
import android.util.Patterns
|
||||||
|
import org.matrix.android.sdk.api.auth.LoginType
|
||||||
import org.matrix.android.sdk.api.auth.login.LoginProfileInfo
|
import org.matrix.android.sdk.api.auth.login.LoginProfileInfo
|
||||||
import org.matrix.android.sdk.api.auth.login.LoginWizard
|
import org.matrix.android.sdk.api.auth.login.LoginWizard
|
||||||
import org.matrix.android.sdk.api.auth.registration.RegisterThreePid
|
import org.matrix.android.sdk.api.auth.registration.RegisterThreePid
|
||||||
|
@ -78,7 +79,7 @@ internal class DefaultLoginWizard(
|
||||||
authAPI.login(loginParams)
|
authAPI.login(loginParams)
|
||||||
}
|
}
|
||||||
|
|
||||||
return sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig)
|
return sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig, LoginType.PASSWORD)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -92,7 +93,7 @@ internal class DefaultLoginWizard(
|
||||||
authAPI.login(loginParams)
|
authAPI.login(loginParams)
|
||||||
}
|
}
|
||||||
|
|
||||||
return sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig)
|
return sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig, LoginType.SSO)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun loginCustom(data: JsonDict): Session {
|
override suspend fun loginCustom(data: JsonDict): Session {
|
||||||
|
@ -100,7 +101,7 @@ internal class DefaultLoginWizard(
|
||||||
authAPI.login(data)
|
authAPI.login(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
return sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig)
|
return sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig, LoginType.CUSTOM)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun resetPassword(email: String) {
|
override suspend fun resetPassword(email: String) {
|
||||||
|
|
|
@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.auth.login
|
||||||
|
|
||||||
import dagger.Lazy
|
import dagger.Lazy
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
import org.matrix.android.sdk.api.auth.LoginType
|
||||||
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
|
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
|
||||||
import org.matrix.android.sdk.api.failure.Failure
|
import org.matrix.android.sdk.api.failure.Failure
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
|
@ -77,7 +78,7 @@ internal class DefaultDirectLoginTask @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return sessionCreator.createSession(credentials, params.homeServerConnectionConfig)
|
return sessionCreator.createSession(credentials, params.homeServerConnectionConfig, LoginType.DIRECT)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildClient(homeServerConnectionConfig: HomeServerConnectionConfig): OkHttpClient {
|
private fun buildClient(homeServerConnectionConfig: HomeServerConnectionConfig): OkHttpClient {
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package org.matrix.android.sdk.internal.auth.registration
|
package org.matrix.android.sdk.internal.auth.registration
|
||||||
|
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
import org.matrix.android.sdk.api.auth.LoginType
|
||||||
import org.matrix.android.sdk.api.auth.data.Credentials
|
import org.matrix.android.sdk.api.auth.data.Credentials
|
||||||
import org.matrix.android.sdk.api.auth.data.LoginFlowTypes
|
import org.matrix.android.sdk.api.auth.data.LoginFlowTypes
|
||||||
import org.matrix.android.sdk.api.auth.registration.RegisterThreePid
|
import org.matrix.android.sdk.api.auth.registration.RegisterThreePid
|
||||||
|
@ -64,7 +65,7 @@ internal class DefaultRegistrationWizard(
|
||||||
|
|
||||||
override suspend fun getRegistrationFlow(): RegistrationResult {
|
override suspend fun getRegistrationFlow(): RegistrationResult {
|
||||||
val params = RegistrationParams()
|
val params = RegistrationParams()
|
||||||
return performRegistrationRequest(params)
|
return performRegistrationRequest(params, LoginType.PASSWORD)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun createAccount(
|
override suspend fun createAccount(
|
||||||
|
@ -77,7 +78,7 @@ internal class DefaultRegistrationWizard(
|
||||||
password = password,
|
password = password,
|
||||||
initialDeviceDisplayName = initialDeviceDisplayName
|
initialDeviceDisplayName = initialDeviceDisplayName
|
||||||
)
|
)
|
||||||
return performRegistrationRequest(params)
|
return performRegistrationRequest(params, LoginType.PASSWORD)
|
||||||
.also {
|
.also {
|
||||||
pendingSessionData = pendingSessionData.copy(isRegistrationStarted = true)
|
pendingSessionData = pendingSessionData.copy(isRegistrationStarted = true)
|
||||||
.also { pendingSessionStore.savePendingSessionData(it) }
|
.also { pendingSessionStore.savePendingSessionData(it) }
|
||||||
|
@ -89,7 +90,7 @@ internal class DefaultRegistrationWizard(
|
||||||
?: throw IllegalStateException("developer error, call createAccount() method first")
|
?: throw IllegalStateException("developer error, call createAccount() method first")
|
||||||
|
|
||||||
val params = RegistrationParams(auth = AuthParams.createForCaptcha(safeSession, response))
|
val params = RegistrationParams(auth = AuthParams.createForCaptcha(safeSession, response))
|
||||||
return performRegistrationRequest(params)
|
return performRegistrationRequest(params, LoginType.PASSWORD)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun acceptTerms(): RegistrationResult {
|
override suspend fun acceptTerms(): RegistrationResult {
|
||||||
|
@ -97,7 +98,7 @@ internal class DefaultRegistrationWizard(
|
||||||
?: throw IllegalStateException("developer error, call createAccount() method first")
|
?: throw IllegalStateException("developer error, call createAccount() method first")
|
||||||
|
|
||||||
val params = RegistrationParams(auth = AuthParams(type = LoginFlowTypes.TERMS, session = safeSession))
|
val params = RegistrationParams(auth = AuthParams(type = LoginFlowTypes.TERMS, session = safeSession))
|
||||||
return performRegistrationRequest(params)
|
return performRegistrationRequest(params, LoginType.PASSWORD)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun addThreePid(threePid: RegisterThreePid): RegistrationResult {
|
override suspend fun addThreePid(threePid: RegisterThreePid): RegistrationResult {
|
||||||
|
@ -151,14 +152,14 @@ internal class DefaultRegistrationWizard(
|
||||||
.also { pendingSessionStore.savePendingSessionData(it) }
|
.also { pendingSessionStore.savePendingSessionData(it) }
|
||||||
|
|
||||||
// and send the sid a first time
|
// and send the sid a first time
|
||||||
return performRegistrationRequest(params)
|
return performRegistrationRequest(params, LoginType.PASSWORD)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun checkIfEmailHasBeenValidated(delayMillis: Long): RegistrationResult {
|
override suspend fun checkIfEmailHasBeenValidated(delayMillis: Long): RegistrationResult {
|
||||||
val safeParam = pendingSessionData.currentThreePidData?.registrationParams
|
val safeParam = pendingSessionData.currentThreePidData?.registrationParams
|
||||||
?: throw IllegalStateException("developer error, no pending three pid")
|
?: throw IllegalStateException("developer error, no pending three pid")
|
||||||
|
|
||||||
return performRegistrationRequest(safeParam, delayMillis)
|
return performRegistrationRequest(safeParam, LoginType.PASSWORD, delayMillis)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun handleValidateThreePid(code: String): RegistrationResult {
|
override suspend fun handleValidateThreePid(code: String): RegistrationResult {
|
||||||
|
@ -179,7 +180,7 @@ internal class DefaultRegistrationWizard(
|
||||||
if (validationResponse.isSuccess()) {
|
if (validationResponse.isSuccess()) {
|
||||||
// The entered code is correct
|
// The entered code is correct
|
||||||
// Same than validate email
|
// Same than validate email
|
||||||
return performRegistrationRequest(registrationParams, 3_000)
|
return performRegistrationRequest(registrationParams, LoginType.PASSWORD, 3_000)
|
||||||
} else {
|
} else {
|
||||||
// The code is not correct
|
// The code is not correct
|
||||||
throw Failure.SuccessError
|
throw Failure.SuccessError
|
||||||
|
@ -191,7 +192,7 @@ internal class DefaultRegistrationWizard(
|
||||||
?: throw IllegalStateException("developer error, call createAccount() method first")
|
?: throw IllegalStateException("developer error, call createAccount() method first")
|
||||||
|
|
||||||
val params = RegistrationParams(auth = AuthParams(type = LoginFlowTypes.DUMMY, session = safeSession))
|
val params = RegistrationParams(auth = AuthParams(type = LoginFlowTypes.DUMMY, session = safeSession))
|
||||||
return performRegistrationRequest(params)
|
return performRegistrationRequest(params, LoginType.PASSWORD)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun registrationCustom(
|
override suspend fun registrationCustom(
|
||||||
|
@ -204,25 +205,28 @@ internal class DefaultRegistrationWizard(
|
||||||
mutableParams["session"] = safeSession
|
mutableParams["session"] = safeSession
|
||||||
|
|
||||||
val params = RegistrationCustomParams(auth = mutableParams)
|
val params = RegistrationCustomParams(auth = mutableParams)
|
||||||
return performRegistrationOtherRequest(params)
|
return performRegistrationOtherRequest(LoginType.CUSTOM, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun performRegistrationRequest(
|
private suspend fun performRegistrationRequest(
|
||||||
registrationParams: RegistrationParams,
|
registrationParams: RegistrationParams,
|
||||||
|
loginType: LoginType,
|
||||||
delayMillis: Long = 0
|
delayMillis: Long = 0
|
||||||
): RegistrationResult {
|
): RegistrationResult {
|
||||||
delay(delayMillis)
|
delay(delayMillis)
|
||||||
return register { registerTask.execute(RegisterTask.Params(registrationParams)) }
|
return register(loginType) { registerTask.execute(RegisterTask.Params(registrationParams)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun performRegistrationOtherRequest(
|
private suspend fun performRegistrationOtherRequest(
|
||||||
registrationCustomParams: RegistrationCustomParams
|
loginType: LoginType,
|
||||||
|
registrationCustomParams: RegistrationCustomParams,
|
||||||
): RegistrationResult {
|
): RegistrationResult {
|
||||||
return register { registerCustomTask.execute(RegisterCustomTask.Params(registrationCustomParams)) }
|
return register(loginType) { registerCustomTask.execute(RegisterCustomTask.Params(registrationCustomParams)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun register(
|
private suspend fun register(
|
||||||
execute: suspend () -> Credentials
|
loginType: LoginType,
|
||||||
|
execute: suspend () -> Credentials,
|
||||||
): RegistrationResult {
|
): RegistrationResult {
|
||||||
val credentials = try {
|
val credentials = try {
|
||||||
execute.invoke()
|
execute.invoke()
|
||||||
|
@ -237,8 +241,7 @@ internal class DefaultRegistrationWizard(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val session =
|
val session = sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig, loginType)
|
||||||
sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig)
|
|
||||||
return RegistrationResult.Success(session)
|
return RegistrationResult.Success(session)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ import android.content.Context
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
import io.realm.RealmConfiguration
|
import io.realm.RealmConfiguration
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import org.matrix.android.sdk.api.auth.LoginType
|
||||||
import org.matrix.android.sdk.api.auth.data.Credentials
|
import org.matrix.android.sdk.api.auth.data.Credentials
|
||||||
import org.matrix.android.sdk.api.auth.data.DiscoveryInformation
|
import org.matrix.android.sdk.api.auth.data.DiscoveryInformation
|
||||||
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
|
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
|
||||||
|
@ -145,7 +146,8 @@ internal class DefaultLegacySessionImporter @Inject constructor(
|
||||||
forceUsageTlsVersions = legacyConfig.forceUsageOfTlsVersions()
|
forceUsageTlsVersions = legacyConfig.forceUsageOfTlsVersions()
|
||||||
),
|
),
|
||||||
// If token is not valid, this boolean will be updated later
|
// If token is not valid, this boolean will be updated later
|
||||||
isTokenValid = true
|
isTokenValid = true,
|
||||||
|
loginType = LoginType.UNKNOWN,
|
||||||
)
|
)
|
||||||
|
|
||||||
Timber.d("Migration: save session")
|
Timber.d("Migration: save session")
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.internal.auth.db.migration
|
||||||
|
|
||||||
|
import org.junit.Test
|
||||||
|
import org.matrix.android.sdk.test.fakes.internal.auth.db.migration.Fake005MigrationRealm
|
||||||
|
|
||||||
|
class MigrateAuthTo005Test {
|
||||||
|
|
||||||
|
private val fakeRealm = Fake005MigrationRealm()
|
||||||
|
private val migrator = MigrateAuthTo005(fakeRealm.instance)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when doMigrate, then LoginType field added`() {
|
||||||
|
migrator.doMigrate(fakeRealm.instance)
|
||||||
|
|
||||||
|
fakeRealm.verifyLoginTypeAdded()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.internal.auth.login
|
||||||
|
|
||||||
|
import org.amshove.kluent.shouldBeEqualTo
|
||||||
|
import org.amshove.kluent.shouldNotBeEqualTo
|
||||||
|
import org.junit.Test
|
||||||
|
import org.matrix.android.sdk.api.auth.LoginType
|
||||||
|
|
||||||
|
class LoginTypeTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when getting type fromName, then map correctly`() {
|
||||||
|
LoginType.fromName(LoginType.PASSWORD.name) shouldBeEqualTo LoginType.PASSWORD
|
||||||
|
LoginType.fromName(LoginType.SSO.name) shouldBeEqualTo LoginType.SSO
|
||||||
|
LoginType.fromName(LoginType.UNSUPPORTED.name) shouldBeEqualTo LoginType.UNSUPPORTED
|
||||||
|
LoginType.fromName(LoginType.CUSTOM.name) shouldBeEqualTo LoginType.CUSTOM
|
||||||
|
LoginType.fromName(LoginType.DIRECT.name) shouldBeEqualTo LoginType.DIRECT
|
||||||
|
LoginType.fromName(LoginType.UNKNOWN.name) shouldBeEqualTo LoginType.UNKNOWN
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test // The failure of this test means that an existing type has not been correctly added to fromValue
|
||||||
|
fun `given non-unknown type name, when getting type fromName, then type is not UNKNOWN`() {
|
||||||
|
val types = LoginType.values()
|
||||||
|
|
||||||
|
types.forEach { type ->
|
||||||
|
if (type != LoginType.UNKNOWN) {
|
||||||
|
LoginType.fromName(type.name) shouldNotBeEqualTo LoginType.UNKNOWN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.test.fakes.api
|
||||||
|
|
||||||
|
import io.mockk.mockk
|
||||||
|
import org.matrix.android.sdk.api.session.Session
|
||||||
|
|
||||||
|
class FakeSession {
|
||||||
|
|
||||||
|
val instance: Session = mockk()
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.test.fakes.internal
|
||||||
|
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.verify
|
||||||
|
import org.amshove.kluent.shouldBeEqualTo
|
||||||
|
import org.matrix.android.sdk.api.auth.data.SessionParams
|
||||||
|
import org.matrix.android.sdk.api.session.Session
|
||||||
|
import org.matrix.android.sdk.internal.SessionManager
|
||||||
|
import org.matrix.android.sdk.test.fakes.api.FakeSession
|
||||||
|
|
||||||
|
internal class FakeSessionManager {
|
||||||
|
|
||||||
|
val instance: SessionManager = mockk()
|
||||||
|
|
||||||
|
init {
|
||||||
|
every { instance.getOrCreateSession(any()) } returns fakeSession.instance
|
||||||
|
}
|
||||||
|
|
||||||
|
fun assertSessionCreatedWithParams(session: Session, sessionParams: SessionParams) {
|
||||||
|
verify { instance.getOrCreateSession(sessionParams) }
|
||||||
|
|
||||||
|
session shouldBeEqualTo fakeSession.instance
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val fakeSession = FakeSession()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.test.fakes.internal.auth
|
||||||
|
|
||||||
|
import io.mockk.coEvery
|
||||||
|
import io.mockk.coVerify
|
||||||
|
import io.mockk.mockk
|
||||||
|
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
|
||||||
|
import org.matrix.android.sdk.internal.auth.IsValidClientServerApiTask
|
||||||
|
import org.matrix.android.sdk.internal.auth.IsValidClientServerApiTask.Params
|
||||||
|
|
||||||
|
internal class FakeIsValidClientServerApiTask {
|
||||||
|
|
||||||
|
init {
|
||||||
|
coEvery { instance.execute(any()) } returns true
|
||||||
|
}
|
||||||
|
|
||||||
|
val instance: IsValidClientServerApiTask = mockk()
|
||||||
|
|
||||||
|
fun givenValidationFails() {
|
||||||
|
coEvery { instance.execute(any()) } returns false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun verifyExecutionWithConfig(config: HomeServerConnectionConfig) {
|
||||||
|
coVerify { instance.execute(Params(config)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun verifyNoExecution() {
|
||||||
|
coVerify(inverse = true) { instance.execute(any()) }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.test.fakes.internal.auth
|
||||||
|
|
||||||
|
import io.mockk.coJustRun
|
||||||
|
import io.mockk.coVerify
|
||||||
|
import io.mockk.mockk
|
||||||
|
import org.matrix.android.sdk.internal.auth.PendingSessionStore
|
||||||
|
|
||||||
|
internal class FakePendingSessionStore {
|
||||||
|
|
||||||
|
val instance: PendingSessionStore = mockk()
|
||||||
|
|
||||||
|
init {
|
||||||
|
coJustRun { instance.delete() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun verifyPendingSessionDataCleared() {
|
||||||
|
coVerify { instance.delete() }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.test.fakes.internal.auth
|
||||||
|
|
||||||
|
import android.net.Uri
|
||||||
|
import io.mockk.coEvery
|
||||||
|
import io.mockk.coVerify
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.mockkStatic
|
||||||
|
import org.matrix.android.sdk.api.auth.LoginType
|
||||||
|
import org.matrix.android.sdk.api.auth.data.Credentials
|
||||||
|
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
|
||||||
|
import org.matrix.android.sdk.internal.auth.SessionParamsCreator
|
||||||
|
import org.matrix.android.sdk.test.fixtures.SessionParamsFixture.aSessionParams
|
||||||
|
|
||||||
|
internal class FakeSessionParamsCreator {
|
||||||
|
|
||||||
|
val instance: SessionParamsCreator = mockk()
|
||||||
|
|
||||||
|
init {
|
||||||
|
mockkStatic(Uri::class)
|
||||||
|
every { Uri.parse(any()) } returns mockk()
|
||||||
|
coEvery { instance.create(any(), any(), any()) } returns sessionParams
|
||||||
|
}
|
||||||
|
|
||||||
|
fun verifyCreatedWithParameters(
|
||||||
|
credentials: Credentials,
|
||||||
|
homeServerConnectionConfig: HomeServerConnectionConfig,
|
||||||
|
loginType: LoginType,
|
||||||
|
) {
|
||||||
|
coVerify { instance.create(credentials, homeServerConnectionConfig, loginType) }
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val sessionParams = aSessionParams()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.test.fakes.internal.auth
|
||||||
|
|
||||||
|
import io.mockk.coJustRun
|
||||||
|
import io.mockk.coVerify
|
||||||
|
import io.mockk.mockk
|
||||||
|
import org.matrix.android.sdk.api.auth.data.SessionParams
|
||||||
|
import org.matrix.android.sdk.internal.auth.SessionParamsStore
|
||||||
|
|
||||||
|
internal class FakeSessionParamsStore {
|
||||||
|
|
||||||
|
val instance: SessionParamsStore = mockk()
|
||||||
|
|
||||||
|
init {
|
||||||
|
coJustRun { instance.save(any()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun verifyParamsSaved(sessionParams: SessionParams) {
|
||||||
|
coVerify { instance.save(sessionParams) }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.test.fakes.internal.auth.db.migration
|
||||||
|
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.verifyOrder
|
||||||
|
import io.realm.DynamicRealm
|
||||||
|
import io.realm.RealmObjectSchema
|
||||||
|
import io.realm.RealmSchema
|
||||||
|
import org.matrix.android.sdk.internal.auth.db.SessionParamsEntityFields
|
||||||
|
|
||||||
|
class Fake005MigrationRealm {
|
||||||
|
|
||||||
|
val instance: DynamicRealm = mockk()
|
||||||
|
|
||||||
|
private val schema: RealmSchema = mockk()
|
||||||
|
private val objectSchema: RealmObjectSchema = mockk()
|
||||||
|
|
||||||
|
init {
|
||||||
|
every { instance.schema } returns schema
|
||||||
|
every { schema.get("SessionParamsEntity") } returns objectSchema
|
||||||
|
every { objectSchema.addField(any(), any()) } returns objectSchema
|
||||||
|
every { objectSchema.setRequired(any(), any()) } returns objectSchema
|
||||||
|
every { objectSchema.transform(any()) } returns objectSchema
|
||||||
|
}
|
||||||
|
|
||||||
|
fun verifyLoginTypeAdded() {
|
||||||
|
verifyLoginTypeFieldAddedAndTransformed()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun verifyLoginTypeFieldAddedAndTransformed() {
|
||||||
|
verifyOrder {
|
||||||
|
objectSchema["SessionParamsEntity"]
|
||||||
|
objectSchema.addField(SessionParamsEntityFields.LOGIN_TYPE, String::class.java)
|
||||||
|
objectSchema.setRequired(SessionParamsEntityFields.LOGIN_TYPE, true)
|
||||||
|
objectSchema.transform(any())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.test.fakes.internal.auth.db.sessionparams
|
||||||
|
|
||||||
|
import com.squareup.moshi.JsonAdapter
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import org.matrix.android.sdk.api.auth.data.Credentials
|
||||||
|
import org.matrix.android.sdk.test.fakes.internal.auth.db.sessionparams.FakeSessionParamsMapperMoshi.Companion.sessionParams
|
||||||
|
import org.matrix.android.sdk.test.fakes.internal.auth.db.sessionparams.FakeSessionParamsMapperMoshi.Companion.sessionParamsEntity
|
||||||
|
import org.matrix.android.sdk.test.fixtures.CredentialsFixture.aCredentials
|
||||||
|
|
||||||
|
internal class FakeCredentialsJsonAdapter {
|
||||||
|
|
||||||
|
val instance: JsonAdapter<Credentials> = mockk()
|
||||||
|
|
||||||
|
init {
|
||||||
|
every { instance.fromJson(sessionParamsEntity.credentialsJson) } returns credentials
|
||||||
|
every { instance.toJson(sessionParams.credentials) } returns CREDENTIALS_JSON
|
||||||
|
}
|
||||||
|
|
||||||
|
fun givenNullDeserialization() {
|
||||||
|
every { instance.fromJson(sessionParamsEntity.credentialsJson) } returns null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun givenNullSerialization() {
|
||||||
|
every { instance.toJson(credentials) } returns null
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val credentials = aCredentials()
|
||||||
|
const val CREDENTIALS_JSON = "credentials_json"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.test.fakes.internal.auth.db.sessionparams
|
||||||
|
|
||||||
|
import com.squareup.moshi.JsonAdapter
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
|
||||||
|
import org.matrix.android.sdk.test.fakes.internal.auth.db.sessionparams.FakeSessionParamsMapperMoshi.Companion.sessionParams
|
||||||
|
import org.matrix.android.sdk.test.fakes.internal.auth.db.sessionparams.FakeSessionParamsMapperMoshi.Companion.sessionParamsEntity
|
||||||
|
|
||||||
|
internal class FakeHomeServerConnectionConfigJsonAdapter {
|
||||||
|
|
||||||
|
val instance: JsonAdapter<HomeServerConnectionConfig> = mockk()
|
||||||
|
|
||||||
|
init {
|
||||||
|
every { instance.fromJson(sessionParamsEntity.homeServerConnectionConfigJson) } returns homeServerConnectionConfig
|
||||||
|
every { instance.toJson(sessionParams.homeServerConnectionConfig) } returns HOME_SERVER_CONNECTION_CONFIG_JSON
|
||||||
|
}
|
||||||
|
|
||||||
|
fun givenNullDeserialization() {
|
||||||
|
every { instance.fromJson(sessionParamsEntity.credentialsJson) } returns null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun givenNullSerialization() {
|
||||||
|
every { instance.toJson(homeServerConnectionConfig) } returns null
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val homeServerConnectionConfig = HomeServerConnectionConfig.Builder().withHomeServerUri("homeserver").build()
|
||||||
|
const val HOME_SERVER_CONNECTION_CONFIG_JSON = "home_server_connection_config_json"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.test.fakes.internal.auth.db.sessionparams
|
||||||
|
|
||||||
|
import android.net.Uri
|
||||||
|
import com.squareup.moshi.Moshi
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.mockkStatic
|
||||||
|
import org.amshove.kluent.shouldBeEqualTo
|
||||||
|
import org.amshove.kluent.shouldBeNull
|
||||||
|
import org.matrix.android.sdk.api.auth.LoginType
|
||||||
|
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.SessionParams
|
||||||
|
import org.matrix.android.sdk.api.auth.data.sessionId
|
||||||
|
import org.matrix.android.sdk.internal.auth.db.SessionParamsEntity
|
||||||
|
import org.matrix.android.sdk.test.fakes.internal.auth.db.sessionparams.FakeCredentialsJsonAdapter.Companion.CREDENTIALS_JSON
|
||||||
|
import org.matrix.android.sdk.test.fakes.internal.auth.db.sessionparams.FakeCredentialsJsonAdapter.Companion.credentials
|
||||||
|
import org.matrix.android.sdk.test.fakes.internal.auth.db.sessionparams.FakeHomeServerConnectionConfigJsonAdapter.Companion.HOME_SERVER_CONNECTION_CONFIG_JSON
|
||||||
|
import org.matrix.android.sdk.test.fakes.internal.auth.db.sessionparams.FakeHomeServerConnectionConfigJsonAdapter.Companion.homeServerConnectionConfig
|
||||||
|
import org.matrix.android.sdk.test.fixtures.SessionParamsEntityFixture.aSessionParamsEntity
|
||||||
|
import org.matrix.android.sdk.test.fixtures.SessionParamsFixture.aSessionParams
|
||||||
|
|
||||||
|
internal class FakeSessionParamsMapperMoshi {
|
||||||
|
|
||||||
|
val instance: Moshi = mockk()
|
||||||
|
private val credentialsJsonAdapter = FakeCredentialsJsonAdapter()
|
||||||
|
private val homeServerConnectionConfigAdapter = FakeHomeServerConnectionConfigJsonAdapter()
|
||||||
|
|
||||||
|
init {
|
||||||
|
mockkStatic(Uri::class)
|
||||||
|
every { Uri.parse(any()) } returns mockk()
|
||||||
|
every { instance.adapter(Credentials::class.java) } returns credentialsJsonAdapter.instance
|
||||||
|
every { instance.adapter(HomeServerConnectionConfig::class.java) } returns homeServerConnectionConfigAdapter.instance
|
||||||
|
}
|
||||||
|
|
||||||
|
fun assertSessionParamsWasMappedSuccessfully(sessionParams: SessionParams?) {
|
||||||
|
sessionParams shouldBeEqualTo SessionParams(
|
||||||
|
credentials,
|
||||||
|
homeServerConnectionConfig,
|
||||||
|
sessionParamsEntity.isTokenValid,
|
||||||
|
LoginType.fromName(sessionParamsEntity.loginType)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun assertSessionParamsIsNull(sessionParams: SessionParams?) {
|
||||||
|
sessionParams.shouldBeNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun assertSessionParamsEntityWasMappedSuccessfully(sessionParamsEntity: SessionParamsEntity?) {
|
||||||
|
sessionParamsEntity shouldBeEqualTo SessionParamsEntity(
|
||||||
|
sessionParams.credentials.sessionId(),
|
||||||
|
sessionParams.userId,
|
||||||
|
CREDENTIALS_JSON,
|
||||||
|
HOME_SERVER_CONNECTION_CONFIG_JSON,
|
||||||
|
sessionParams.isTokenValid,
|
||||||
|
sessionParams.loginType.name,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun assertSessionParamsEntityIsNull(sessionParamsEntity: SessionParamsEntity?) {
|
||||||
|
sessionParamsEntity.shouldBeNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val sessionParams = aSessionParams()
|
||||||
|
val sessionParamsEntity = aSessionParamsEntity()
|
||||||
|
val nullSessionParams: SessionParams? = null
|
||||||
|
val nullSessionParamsEntity: SessionParamsEntity? = null
|
||||||
|
}
|
||||||
|
}
|
38
matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fixtures/CredentialsFixture.kt
vendored
Normal file
38
matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fixtures/CredentialsFixture.kt
vendored
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.test.fixtures
|
||||||
|
|
||||||
|
import org.matrix.android.sdk.api.auth.data.Credentials
|
||||||
|
import org.matrix.android.sdk.api.auth.data.DiscoveryInformation
|
||||||
|
|
||||||
|
object CredentialsFixture {
|
||||||
|
fun aCredentials(
|
||||||
|
userId: String = "",
|
||||||
|
accessToken: String = "",
|
||||||
|
refreshToken: String? = null,
|
||||||
|
homeServer: String? = null,
|
||||||
|
deviceId: String? = null,
|
||||||
|
discoveryInformation: DiscoveryInformation? = null,
|
||||||
|
) = Credentials(
|
||||||
|
userId,
|
||||||
|
accessToken,
|
||||||
|
refreshToken,
|
||||||
|
homeServer,
|
||||||
|
deviceId,
|
||||||
|
discoveryInformation,
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.test.fixtures
|
||||||
|
|
||||||
|
import org.matrix.android.sdk.api.auth.data.DiscoveryInformation
|
||||||
|
import org.matrix.android.sdk.api.auth.data.WellKnownBaseConfig
|
||||||
|
|
||||||
|
object DiscoveryInformationFixture {
|
||||||
|
fun aDiscoveryInformation(
|
||||||
|
homeServer: WellKnownBaseConfig? = null,
|
||||||
|
identityServer: WellKnownBaseConfig? = null,
|
||||||
|
) = DiscoveryInformation(
|
||||||
|
homeServer,
|
||||||
|
identityServer
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.test.fixtures
|
||||||
|
|
||||||
|
import org.matrix.android.sdk.internal.auth.db.SessionParamsEntity
|
||||||
|
|
||||||
|
internal object SessionParamsEntityFixture {
|
||||||
|
fun aSessionParamsEntity(
|
||||||
|
sessionId: String = "",
|
||||||
|
userId: String = "",
|
||||||
|
credentialsJson: String = "",
|
||||||
|
homeServerConnectionConfigJson: String = "",
|
||||||
|
isTokenValid: Boolean = true,
|
||||||
|
loginType: String = "",
|
||||||
|
) = SessionParamsEntity(
|
||||||
|
sessionId,
|
||||||
|
userId,
|
||||||
|
credentialsJson,
|
||||||
|
homeServerConnectionConfigJson,
|
||||||
|
isTokenValid,
|
||||||
|
loginType,
|
||||||
|
)
|
||||||
|
}
|
37
matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fixtures/SessionParamsFixture.kt
vendored
Normal file
37
matrix-sdk-android/src/test/java/org/matrix/android/sdk/test/fixtures/SessionParamsFixture.kt
vendored
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.test.fixtures
|
||||||
|
|
||||||
|
import org.matrix.android.sdk.api.auth.LoginType
|
||||||
|
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.SessionParams
|
||||||
|
import org.matrix.android.sdk.test.fixtures.CredentialsFixture.aCredentials
|
||||||
|
|
||||||
|
object SessionParamsFixture {
|
||||||
|
fun aSessionParams(
|
||||||
|
credentials: Credentials = aCredentials(),
|
||||||
|
homeServerConnectionConfig: HomeServerConnectionConfig = HomeServerConnectionConfig.Builder().withHomeServerUri("homeserver").build(),
|
||||||
|
isTokenValid: Boolean = false,
|
||||||
|
loginType: LoginType = LoginType.UNKNOWN,
|
||||||
|
) = SessionParams(
|
||||||
|
credentials,
|
||||||
|
homeServerConnectionConfig,
|
||||||
|
isTokenValid,
|
||||||
|
loginType,
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.test.fixtures
|
||||||
|
|
||||||
|
import org.matrix.android.sdk.api.auth.data.WellKnownBaseConfig
|
||||||
|
|
||||||
|
object WellKnownBaseConfigFixture {
|
||||||
|
fun aWellKnownBaseConfig(
|
||||||
|
baseUrl: String? = null,
|
||||||
|
) = WellKnownBaseConfig(
|
||||||
|
baseUrl,
|
||||||
|
)
|
||||||
|
}
|
|
@ -37,6 +37,7 @@ import im.vector.app.core.extensions.addFragment
|
||||||
import im.vector.app.core.extensions.addFragmentToBackstack
|
import im.vector.app.core.extensions.addFragmentToBackstack
|
||||||
import im.vector.app.core.extensions.validateBackPressed
|
import im.vector.app.core.extensions.validateBackPressed
|
||||||
import im.vector.app.core.platform.VectorBaseActivity
|
import im.vector.app.core.platform.VectorBaseActivity
|
||||||
|
import im.vector.app.core.utils.openUrlInChromeCustomTab
|
||||||
import im.vector.app.databinding.ActivityLoginBinding
|
import im.vector.app.databinding.ActivityLoginBinding
|
||||||
import im.vector.app.features.analytics.plan.MobileScreen
|
import im.vector.app.features.analytics.plan.MobileScreen
|
||||||
import im.vector.app.features.home.HomeActivity
|
import im.vector.app.features.home.HomeActivity
|
||||||
|
@ -272,8 +273,8 @@ open class LoginActivity : VectorBaseActivity<ActivityLoginBinding>(), UnlockedA
|
||||||
SignMode.SignIn -> {
|
SignMode.SignIn -> {
|
||||||
// It depends on the LoginMode
|
// It depends on the LoginMode
|
||||||
when (state.loginMode) {
|
when (state.loginMode) {
|
||||||
LoginMode.Unknown,
|
LoginMode.Unknown -> error("Developer error")
|
||||||
is LoginMode.Sso -> error("Developer error")
|
is LoginMode.Sso -> launchSsoFlow()
|
||||||
is LoginMode.SsoAndPassword,
|
is LoginMode.SsoAndPassword,
|
||||||
LoginMode.Password -> addFragmentToBackstack(
|
LoginMode.Password -> addFragmentToBackstack(
|
||||||
views.loginFragmentContainer,
|
views.loginFragmentContainer,
|
||||||
|
@ -293,6 +294,16 @@ open class LoginActivity : VectorBaseActivity<ActivityLoginBinding>(), UnlockedA
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun launchSsoFlow() = withState(loginViewModel) { state ->
|
||||||
|
loginViewModel.getSsoUrl(
|
||||||
|
redirectUrl = SSORedirectRouterActivity.VECTOR_REDIRECT_URL,
|
||||||
|
deviceId = state.deviceId,
|
||||||
|
providerId = null,
|
||||||
|
)?.let { ssoUrl ->
|
||||||
|
openUrlInChromeCustomTab(this, null, ssoUrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle the SSO redirection here.
|
* Handle the SSO redirection here.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -18,6 +18,7 @@ package im.vector.app.features.signout.soft
|
||||||
|
|
||||||
import com.airbnb.epoxy.EpoxyController
|
import com.airbnb.epoxy.EpoxyController
|
||||||
import com.airbnb.mvrx.Fail
|
import com.airbnb.mvrx.Fail
|
||||||
|
import com.airbnb.mvrx.Incomplete
|
||||||
import com.airbnb.mvrx.Loading
|
import com.airbnb.mvrx.Loading
|
||||||
import com.airbnb.mvrx.Success
|
import com.airbnb.mvrx.Success
|
||||||
import com.airbnb.mvrx.Uninitialized
|
import com.airbnb.mvrx.Uninitialized
|
||||||
|
@ -35,6 +36,7 @@ import im.vector.app.features.signout.soft.epoxy.loginRedButtonItem
|
||||||
import im.vector.app.features.signout.soft.epoxy.loginTextItem
|
import im.vector.app.features.signout.soft.epoxy.loginTextItem
|
||||||
import im.vector.app.features.signout.soft.epoxy.loginTitleItem
|
import im.vector.app.features.signout.soft.epoxy.loginTitleItem
|
||||||
import im.vector.app.features.signout.soft.epoxy.loginTitleSmallItem
|
import im.vector.app.features.signout.soft.epoxy.loginTitleSmallItem
|
||||||
|
import org.matrix.android.sdk.api.auth.LoginType
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class SoftLogoutController @Inject constructor(
|
class SoftLogoutController @Inject constructor(
|
||||||
|
@ -91,25 +93,38 @@ class SoftLogoutController @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildForm(state: SoftLogoutViewState) {
|
private fun buildForm(state: SoftLogoutViewState) = when (state.asyncHomeServerLoginFlowRequest) {
|
||||||
val host = this
|
is Fail -> buildLoginErrorWithRetryItem(state.asyncHomeServerLoginFlowRequest.error)
|
||||||
when (state.asyncHomeServerLoginFlowRequest) {
|
is Success -> buildLoginSuccessItem(state)
|
||||||
Uninitialized,
|
is Loading, Uninitialized -> buildLoadingItem()
|
||||||
is Loading -> {
|
is Incomplete -> Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildLoadingItem() {
|
||||||
loadingItem {
|
loadingItem {
|
||||||
id("loading")
|
id("loading")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is Fail -> {
|
|
||||||
|
private fun buildLoginErrorWithRetryItem(error: Throwable) {
|
||||||
|
val host = this
|
||||||
loginErrorWithRetryItem {
|
loginErrorWithRetryItem {
|
||||||
id("errorRetry")
|
id("errorRetry")
|
||||||
text(host.errorFormatter.toHumanReadable(state.asyncHomeServerLoginFlowRequest.error))
|
text(host.errorFormatter.toHumanReadable(error))
|
||||||
listener { host.listener?.retry() }
|
listener { host.listener?.retry() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is Success -> {
|
|
||||||
when (state.asyncHomeServerLoginFlowRequest.invoke()) {
|
private fun buildLoginSuccessItem(state: SoftLogoutViewState) = when (state.asyncHomeServerLoginFlowRequest.invoke()) {
|
||||||
LoginMode.Password -> {
|
LoginMode.Password -> buildLoginPasswordForm(state)
|
||||||
|
is LoginMode.Sso -> buildLoginSSOForm()
|
||||||
|
is LoginMode.SsoAndPassword -> disambiguateLoginSSOAndPasswordForm(state)
|
||||||
|
LoginMode.Unsupported -> buildLoginUnsupportedForm()
|
||||||
|
LoginMode.Unknown, null -> Unit // Should not happen
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildLoginPasswordForm(state: SoftLogoutViewState) {
|
||||||
|
val host = this
|
||||||
loginPasswordFormItem {
|
loginPasswordFormItem {
|
||||||
id("passwordForm")
|
id("passwordForm")
|
||||||
stringProvider(host.stringProvider)
|
stringProvider(host.stringProvider)
|
||||||
|
@ -121,27 +136,35 @@ class SoftLogoutController @Inject constructor(
|
||||||
submitClickListener { host.listener?.submit() }
|
submitClickListener { host.listener?.submit() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is LoginMode.Sso -> {
|
|
||||||
|
private fun buildLoginSSOForm() {
|
||||||
|
val host = this
|
||||||
loginCenterButtonItem {
|
loginCenterButtonItem {
|
||||||
id("sso")
|
id("sso")
|
||||||
text(host.stringProvider.getString(R.string.login_signin_sso))
|
text(host.stringProvider.getString(R.string.login_signin_sso))
|
||||||
listener { host.listener?.signinFallbackSubmit() }
|
listener { host.listener?.signinFallbackSubmit() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is LoginMode.SsoAndPassword -> {
|
|
||||||
|
private fun disambiguateLoginSSOAndPasswordForm(state: SoftLogoutViewState) {
|
||||||
|
when (state.loginType) {
|
||||||
|
LoginType.PASSWORD -> buildLoginPasswordForm(state)
|
||||||
|
LoginType.SSO -> buildLoginSSOForm()
|
||||||
|
LoginType.DIRECT,
|
||||||
|
LoginType.CUSTOM,
|
||||||
|
LoginType.UNSUPPORTED -> buildLoginUnsupportedForm()
|
||||||
|
LoginType.UNKNOWN -> Unit
|
||||||
}
|
}
|
||||||
LoginMode.Unsupported -> {
|
}
|
||||||
|
|
||||||
|
private fun buildLoginUnsupportedForm() {
|
||||||
|
val host = this
|
||||||
loginCenterButtonItem {
|
loginCenterButtonItem {
|
||||||
id("fallback")
|
id("fallback")
|
||||||
text(host.stringProvider.getString(R.string.login_signin))
|
text(host.stringProvider.getString(R.string.login_signin))
|
||||||
listener { host.listener?.signinFallbackSubmit() }
|
listener { host.listener?.signinFallbackSubmit() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LoginMode.Unknown -> Unit // Should not happen
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun buildClearDataSection() {
|
private fun buildClearDataSection() {
|
||||||
val host = this
|
val host = this
|
||||||
|
|
|
@ -35,14 +35,12 @@ import im.vector.app.core.platform.VectorViewModel
|
||||||
import im.vector.app.features.login.LoginMode
|
import im.vector.app.features.login.LoginMode
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.matrix.android.sdk.api.auth.AuthenticationService
|
import org.matrix.android.sdk.api.auth.AuthenticationService
|
||||||
|
import org.matrix.android.sdk.api.auth.LoginType
|
||||||
import org.matrix.android.sdk.api.auth.data.LoginFlowTypes
|
import org.matrix.android.sdk.api.auth.data.LoginFlowTypes
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
import org.matrix.android.sdk.api.session.getUser
|
import org.matrix.android.sdk.api.session.getUser
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO Test push: disable the pushers?
|
|
||||||
*/
|
|
||||||
class SoftLogoutViewModel @AssistedInject constructor(
|
class SoftLogoutViewModel @AssistedInject constructor(
|
||||||
@Assisted initialState: SoftLogoutViewState,
|
@Assisted initialState: SoftLogoutViewState,
|
||||||
private val session: Session,
|
private val session: Session,
|
||||||
|
@ -70,7 +68,8 @@ class SoftLogoutViewModel @AssistedInject constructor(
|
||||||
userId = userId,
|
userId = userId,
|
||||||
deviceId = session.sessionParams.deviceId.orEmpty(),
|
deviceId = session.sessionParams.deviceId.orEmpty(),
|
||||||
userDisplayName = session.getUser(userId)?.displayName ?: userId,
|
userDisplayName = session.getUser(userId)?.displayName ?: userId,
|
||||||
hasUnsavedKeys = session.hasUnsavedKeys()
|
hasUnsavedKeys = session.hasUnsavedKeys(),
|
||||||
|
loginType = session.sessionParams.loginType,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
SoftLogoutViewState(
|
SoftLogoutViewState(
|
||||||
|
@ -78,7 +77,8 @@ class SoftLogoutViewModel @AssistedInject constructor(
|
||||||
userId = "",
|
userId = "",
|
||||||
deviceId = "",
|
deviceId = "",
|
||||||
userDisplayName = "",
|
userDisplayName = "",
|
||||||
hasUnsavedKeys = false
|
hasUnsavedKeys = false,
|
||||||
|
loginType = LoginType.UNKNOWN,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import com.airbnb.mvrx.MavericksState
|
||||||
import com.airbnb.mvrx.Success
|
import com.airbnb.mvrx.Success
|
||||||
import com.airbnb.mvrx.Uninitialized
|
import com.airbnb.mvrx.Uninitialized
|
||||||
import im.vector.app.features.login.LoginMode
|
import im.vector.app.features.login.LoginMode
|
||||||
|
import org.matrix.android.sdk.api.auth.LoginType
|
||||||
|
|
||||||
data class SoftLogoutViewState(
|
data class SoftLogoutViewState(
|
||||||
val asyncHomeServerLoginFlowRequest: Async<LoginMode> = Uninitialized,
|
val asyncHomeServerLoginFlowRequest: Async<LoginMode> = Uninitialized,
|
||||||
|
@ -31,7 +32,8 @@ data class SoftLogoutViewState(
|
||||||
val deviceId: String,
|
val deviceId: String,
|
||||||
val userDisplayName: String,
|
val userDisplayName: String,
|
||||||
val hasUnsavedKeys: Boolean,
|
val hasUnsavedKeys: Boolean,
|
||||||
val enteredPassword: String = ""
|
val loginType: LoginType,
|
||||||
|
val enteredPassword: String = "",
|
||||||
) : MavericksState {
|
) : MavericksState {
|
||||||
|
|
||||||
fun isLoading(): Boolean {
|
fun isLoading(): Boolean {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 New Vector Ltd
|
* Copyright (c) 2022 New Vector Ltd
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
Loading…
Reference in a new issue