mirror of
https://github.com/element-hq/element-android
synced 2024-11-23 18:05:36 +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
|
||||
|
||||
import org.matrix.android.sdk.api.auth.LoginType
|
||||
|
||||
/**
|
||||
* This data class holds necessary data to open a session.
|
||||
* 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.
|
||||
*/
|
||||
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
|
||||
|
|
|
@ -83,6 +83,9 @@ internal abstract class AuthModule {
|
|||
@Binds
|
||||
abstract fun bindSessionCreator(creator: DefaultSessionCreator): SessionCreator
|
||||
|
||||
@Binds
|
||||
abstract fun bindSessionParamsCreator(creator: DefaultSessionParamsCreator): SessionParamsCreator
|
||||
|
||||
@Binds
|
||||
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.getServerName
|
||||
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.HomeServerConnectionConfig
|
||||
import org.matrix.android.sdk.api.auth.data.LoginFlowResult
|
||||
|
@ -361,7 +362,7 @@ internal class DefaultAuthenticationService @Inject constructor(
|
|||
homeServerConnectionConfig: HomeServerConnectionConfig,
|
||||
credentials: Credentials
|
||||
): Session {
|
||||
return sessionCreator.createSession(credentials, homeServerConnectionConfig)
|
||||
return sessionCreator.createSession(credentials, homeServerConnectionConfig, LoginType.SSO)
|
||||
}
|
||||
|
||||
override suspend fun getWellKnownData(
|
||||
|
|
|
@ -16,69 +16,41 @@
|
|||
|
||||
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 org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.internal.SessionManager
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
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(
|
||||
private val sessionParamsStore: SessionParamsStore,
|
||||
private val sessionManager: SessionManager,
|
||||
private val pendingSessionStore: PendingSessionStore,
|
||||
private val isValidClientServerApiTask: IsValidClientServerApiTask
|
||||
private val sessionParamsCreator: SessionParamsCreator,
|
||||
) : SessionCreator {
|
||||
|
||||
/**
|
||||
* Credentials can affect the homeServerConnectionConfig, override homeserver url and/or
|
||||
* 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
|
||||
pendingSessionStore.delete()
|
||||
|
||||
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)
|
||||
|
||||
val sessionParams = sessionParamsCreator.create(credentials, homeServerConnectionConfig, loginType)
|
||||
sessionParamsStore.save(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.MigrateAuthTo003
|
||||
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 javax.inject.Inject
|
||||
|
||||
|
@ -33,7 +34,7 @@ internal class AuthRealmMigration @Inject constructor() : RealmMigration {
|
|||
override fun equals(other: Any?) = other is AuthRealmMigration
|
||||
override fun hashCode() = 4000
|
||||
|
||||
val schemaVersion = 4L
|
||||
val schemaVersion = 5L
|
||||
|
||||
override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
|
||||
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 < 3) MigrateAuthTo003(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 = "",
|
||||
// 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
|
||||
var isTokenValid: Boolean = true
|
||||
var isTokenValid: Boolean = true,
|
||||
var loginType: String = "",
|
||||
) : RealmObject()
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package org.matrix.android.sdk.internal.auth.db
|
||||
|
||||
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.HomeServerConnectionConfig
|
||||
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) {
|
||||
return null
|
||||
}
|
||||
return SessionParams(credentials, homeServerConnectionConfig, entity.isTokenValid)
|
||||
return SessionParams(credentials, homeServerConnectionConfig, entity.isTokenValid, LoginType.fromName(entity.loginType))
|
||||
}
|
||||
|
||||
fun map(sessionParams: SessionParams?): SessionParamsEntity? {
|
||||
|
@ -54,7 +55,8 @@ internal class SessionParamsMapper @Inject constructor(moshi: Moshi) {
|
|||
sessionParams.userId,
|
||||
credentialsJson,
|
||||
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
|
||||
|
||||
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.LoginWizard
|
||||
import org.matrix.android.sdk.api.auth.registration.RegisterThreePid
|
||||
|
@ -78,7 +79,7 @@ internal class DefaultLoginWizard(
|
|||
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)
|
||||
}
|
||||
|
||||
return sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig)
|
||||
return sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig, LoginType.SSO)
|
||||
}
|
||||
|
||||
override suspend fun loginCustom(data: JsonDict): Session {
|
||||
|
@ -100,7 +101,7 @@ internal class DefaultLoginWizard(
|
|||
authAPI.login(data)
|
||||
}
|
||||
|
||||
return sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig)
|
||||
return sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig, LoginType.CUSTOM)
|
||||
}
|
||||
|
||||
override suspend fun resetPassword(email: String) {
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.auth.login
|
|||
|
||||
import dagger.Lazy
|
||||
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.failure.Failure
|
||||
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 {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package org.matrix.android.sdk.internal.auth.registration
|
||||
|
||||
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.LoginFlowTypes
|
||||
import org.matrix.android.sdk.api.auth.registration.RegisterThreePid
|
||||
|
@ -36,9 +37,9 @@ import org.matrix.android.sdk.internal.auth.db.PendingSessionData
|
|||
* This class execute the registration request and is responsible to keep the session of interactive authentication.
|
||||
*/
|
||||
internal class DefaultRegistrationWizard(
|
||||
authAPI: AuthAPI,
|
||||
private val sessionCreator: SessionCreator,
|
||||
private val pendingSessionStore: PendingSessionStore
|
||||
authAPI: AuthAPI,
|
||||
private val sessionCreator: SessionCreator,
|
||||
private val pendingSessionStore: PendingSessionStore
|
||||
) : RegistrationWizard {
|
||||
|
||||
private var pendingSessionData: PendingSessionData = pendingSessionStore.getPendingSessionData() ?: error("Pending session data should exist here")
|
||||
|
@ -64,7 +65,7 @@ internal class DefaultRegistrationWizard(
|
|||
|
||||
override suspend fun getRegistrationFlow(): RegistrationResult {
|
||||
val params = RegistrationParams()
|
||||
return performRegistrationRequest(params)
|
||||
return performRegistrationRequest(params, LoginType.PASSWORD)
|
||||
}
|
||||
|
||||
override suspend fun createAccount(
|
||||
|
@ -73,43 +74,43 @@ internal class DefaultRegistrationWizard(
|
|||
initialDeviceDisplayName: String?
|
||||
): RegistrationResult {
|
||||
val params = RegistrationParams(
|
||||
username = userName,
|
||||
password = password,
|
||||
initialDeviceDisplayName = initialDeviceDisplayName
|
||||
username = userName,
|
||||
password = password,
|
||||
initialDeviceDisplayName = initialDeviceDisplayName
|
||||
)
|
||||
return performRegistrationRequest(params)
|
||||
.also {
|
||||
pendingSessionData = pendingSessionData.copy(isRegistrationStarted = true)
|
||||
.also { pendingSessionStore.savePendingSessionData(it) }
|
||||
}
|
||||
return performRegistrationRequest(params, LoginType.PASSWORD)
|
||||
.also {
|
||||
pendingSessionData = pendingSessionData.copy(isRegistrationStarted = true)
|
||||
.also { pendingSessionStore.savePendingSessionData(it) }
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun performReCaptcha(response: String): RegistrationResult {
|
||||
val safeSession = pendingSessionData.currentSession
|
||||
?: throw IllegalStateException("developer error, call createAccount() method first")
|
||||
?: throw IllegalStateException("developer error, call createAccount() method first")
|
||||
|
||||
val params = RegistrationParams(auth = AuthParams.createForCaptcha(safeSession, response))
|
||||
return performRegistrationRequest(params)
|
||||
return performRegistrationRequest(params, LoginType.PASSWORD)
|
||||
}
|
||||
|
||||
override suspend fun acceptTerms(): RegistrationResult {
|
||||
val safeSession = pendingSessionData.currentSession
|
||||
?: 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))
|
||||
return performRegistrationRequest(params)
|
||||
return performRegistrationRequest(params, LoginType.PASSWORD)
|
||||
}
|
||||
|
||||
override suspend fun addThreePid(threePid: RegisterThreePid): RegistrationResult {
|
||||
pendingSessionData = pendingSessionData.copy(currentThreePidData = null)
|
||||
.also { pendingSessionStore.savePendingSessionData(it) }
|
||||
.also { pendingSessionStore.savePendingSessionData(it) }
|
||||
|
||||
return sendThreePid(threePid)
|
||||
}
|
||||
|
||||
override suspend fun sendAgainThreePid(): RegistrationResult {
|
||||
val safeCurrentThreePid = pendingSessionData.currentThreePidData?.threePid
|
||||
?: throw IllegalStateException("developer error, call createAccount() method first")
|
||||
?: throw IllegalStateException("developer error, call createAccount() method first")
|
||||
|
||||
return sendThreePid(safeCurrentThreePid)
|
||||
}
|
||||
|
@ -125,7 +126,7 @@ internal class DefaultRegistrationWizard(
|
|||
)
|
||||
|
||||
pendingSessionData = pendingSessionData.copy(sendAttempt = pendingSessionData.sendAttempt + 1)
|
||||
.also { pendingSessionStore.savePendingSessionData(it) }
|
||||
.also { pendingSessionStore.savePendingSessionData(it) }
|
||||
|
||||
val params = RegistrationParams(
|
||||
auth = if (threePid is RegisterThreePid.Email) {
|
||||
|
@ -148,17 +149,17 @@ internal class DefaultRegistrationWizard(
|
|||
)
|
||||
// Store data
|
||||
pendingSessionData = pendingSessionData.copy(currentThreePidData = ThreePidData.from(threePid, response, params))
|
||||
.also { pendingSessionStore.savePendingSessionData(it) }
|
||||
.also { pendingSessionStore.savePendingSessionData(it) }
|
||||
|
||||
// and send the sid a first time
|
||||
return performRegistrationRequest(params)
|
||||
return performRegistrationRequest(params, LoginType.PASSWORD)
|
||||
}
|
||||
|
||||
override suspend fun checkIfEmailHasBeenValidated(delayMillis: Long): RegistrationResult {
|
||||
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 {
|
||||
|
@ -167,19 +168,19 @@ internal class DefaultRegistrationWizard(
|
|||
|
||||
private suspend fun validateThreePid(code: String): RegistrationResult {
|
||||
val registrationParams = pendingSessionData.currentThreePidData?.registrationParams
|
||||
?: throw IllegalStateException("developer error, no pending three pid")
|
||||
?: throw IllegalStateException("developer error, no pending three pid")
|
||||
val safeCurrentData = pendingSessionData.currentThreePidData ?: throw IllegalStateException("developer error, call createAccount() method first")
|
||||
val url = safeCurrentData.addThreePidRegistrationResponse.submitUrl ?: throw IllegalStateException("Missing url to send the code")
|
||||
val validationBody = ValidationCodeBody(
|
||||
clientSecret = pendingSessionData.clientSecret,
|
||||
sid = safeCurrentData.addThreePidRegistrationResponse.sid,
|
||||
code = code
|
||||
clientSecret = pendingSessionData.clientSecret,
|
||||
sid = safeCurrentData.addThreePidRegistrationResponse.sid,
|
||||
code = code
|
||||
)
|
||||
val validationResponse = validateCodeTask.execute(ValidateCodeTask.Params(url, validationBody))
|
||||
if (validationResponse.isSuccess()) {
|
||||
// The entered code is correct
|
||||
// Same than validate email
|
||||
return performRegistrationRequest(registrationParams, 3_000)
|
||||
return performRegistrationRequest(registrationParams, LoginType.PASSWORD, 3_000)
|
||||
} else {
|
||||
// The code is not correct
|
||||
throw Failure.SuccessError
|
||||
|
@ -188,10 +189,10 @@ internal class DefaultRegistrationWizard(
|
|||
|
||||
override suspend fun dummy(): RegistrationResult {
|
||||
val safeSession = pendingSessionData.currentSession
|
||||
?: 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))
|
||||
return performRegistrationRequest(params)
|
||||
return performRegistrationRequest(params, LoginType.PASSWORD)
|
||||
}
|
||||
|
||||
override suspend fun registrationCustom(
|
||||
|
@ -204,25 +205,28 @@ internal class DefaultRegistrationWizard(
|
|||
mutableParams["session"] = safeSession
|
||||
|
||||
val params = RegistrationCustomParams(auth = mutableParams)
|
||||
return performRegistrationOtherRequest(params)
|
||||
return performRegistrationOtherRequest(LoginType.CUSTOM, params)
|
||||
}
|
||||
|
||||
private suspend fun performRegistrationRequest(
|
||||
registrationParams: RegistrationParams,
|
||||
loginType: LoginType,
|
||||
delayMillis: Long = 0
|
||||
): RegistrationResult {
|
||||
delay(delayMillis)
|
||||
return register { registerTask.execute(RegisterTask.Params(registrationParams)) }
|
||||
return register(loginType) { registerTask.execute(RegisterTask.Params(registrationParams)) }
|
||||
}
|
||||
|
||||
private suspend fun performRegistrationOtherRequest(
|
||||
registrationCustomParams: RegistrationCustomParams
|
||||
loginType: LoginType,
|
||||
registrationCustomParams: RegistrationCustomParams,
|
||||
): RegistrationResult {
|
||||
return register { registerCustomTask.execute(RegisterCustomTask.Params(registrationCustomParams)) }
|
||||
return register(loginType) { registerCustomTask.execute(RegisterCustomTask.Params(registrationCustomParams)) }
|
||||
}
|
||||
|
||||
private suspend fun register(
|
||||
execute: suspend () -> Credentials
|
||||
loginType: LoginType,
|
||||
execute: suspend () -> Credentials,
|
||||
): RegistrationResult {
|
||||
val credentials = try {
|
||||
execute.invoke()
|
||||
|
@ -237,8 +241,7 @@ internal class DefaultRegistrationWizard(
|
|||
}
|
||||
}
|
||||
|
||||
val session =
|
||||
sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig)
|
||||
val session = sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig, loginType)
|
||||
return RegistrationResult.Success(session)
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import android.content.Context
|
|||
import io.realm.Realm
|
||||
import io.realm.RealmConfiguration
|
||||
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.DiscoveryInformation
|
||||
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
|
||||
|
@ -145,7 +146,8 @@ internal class DefaultLegacySessionImporter @Inject constructor(
|
|||
forceUsageTlsVersions = legacyConfig.forceUsageOfTlsVersions()
|
||||
),
|
||||
// If token is not valid, this boolean will be updated later
|
||||
isTokenValid = true
|
||||
isTokenValid = true,
|
||||
loginType = LoginType.UNKNOWN,
|
||||
)
|
||||
|
||||
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.validateBackPressed
|
||||
import im.vector.app.core.platform.VectorBaseActivity
|
||||
import im.vector.app.core.utils.openUrlInChromeCustomTab
|
||||
import im.vector.app.databinding.ActivityLoginBinding
|
||||
import im.vector.app.features.analytics.plan.MobileScreen
|
||||
import im.vector.app.features.home.HomeActivity
|
||||
|
@ -231,9 +232,9 @@ open class LoginActivity : VectorBaseActivity<ActivityLoginBinding>(), UnlockedA
|
|||
}
|
||||
|
||||
private fun inferAuthDescription(loginViewState: LoginViewState) = when (loginViewState.signMode) {
|
||||
SignMode.Unknown -> null
|
||||
SignMode.SignUp -> AuthenticationDescription.Register(type = AuthenticationDescription.AuthenticationType.Other)
|
||||
SignMode.SignIn -> AuthenticationDescription.Login
|
||||
SignMode.Unknown -> null
|
||||
SignMode.SignUp -> AuthenticationDescription.Register(type = AuthenticationDescription.AuthenticationType.Other)
|
||||
SignMode.SignIn -> AuthenticationDescription.Login
|
||||
SignMode.SignInWithMatrixId -> AuthenticationDescription.Login
|
||||
}
|
||||
|
||||
|
@ -272,8 +273,8 @@ open class LoginActivity : VectorBaseActivity<ActivityLoginBinding>(), UnlockedA
|
|||
SignMode.SignIn -> {
|
||||
// It depends on the LoginMode
|
||||
when (state.loginMode) {
|
||||
LoginMode.Unknown,
|
||||
is LoginMode.Sso -> error("Developer error")
|
||||
LoginMode.Unknown -> error("Developer error")
|
||||
is LoginMode.Sso -> launchSsoFlow()
|
||||
is LoginMode.SsoAndPassword,
|
||||
LoginMode.Password -> addFragmentToBackstack(
|
||||
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.
|
||||
*/
|
||||
|
|
|
@ -18,6 +18,7 @@ package im.vector.app.features.signout.soft
|
|||
|
||||
import com.airbnb.epoxy.EpoxyController
|
||||
import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.Incomplete
|
||||
import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.Success
|
||||
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.loginTitleItem
|
||||
import im.vector.app.features.signout.soft.epoxy.loginTitleSmallItem
|
||||
import org.matrix.android.sdk.api.auth.LoginType
|
||||
import javax.inject.Inject
|
||||
|
||||
class SoftLogoutController @Inject constructor(
|
||||
|
@ -91,55 +93,76 @@ class SoftLogoutController @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun buildForm(state: SoftLogoutViewState) {
|
||||
private fun buildForm(state: SoftLogoutViewState) = when (state.asyncHomeServerLoginFlowRequest) {
|
||||
is Fail -> buildLoginErrorWithRetryItem(state.asyncHomeServerLoginFlowRequest.error)
|
||||
is Success -> buildLoginSuccessItem(state)
|
||||
is Loading, Uninitialized -> buildLoadingItem()
|
||||
is Incomplete -> Unit
|
||||
}
|
||||
|
||||
private fun buildLoadingItem() {
|
||||
loadingItem {
|
||||
id("loading")
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildLoginErrorWithRetryItem(error: Throwable) {
|
||||
val host = this
|
||||
when (state.asyncHomeServerLoginFlowRequest) {
|
||||
Uninitialized,
|
||||
is Loading -> {
|
||||
loadingItem {
|
||||
id("loading")
|
||||
}
|
||||
}
|
||||
is Fail -> {
|
||||
loginErrorWithRetryItem {
|
||||
id("errorRetry")
|
||||
text(host.errorFormatter.toHumanReadable(state.asyncHomeServerLoginFlowRequest.error))
|
||||
listener { host.listener?.retry() }
|
||||
}
|
||||
}
|
||||
is Success -> {
|
||||
when (state.asyncHomeServerLoginFlowRequest.invoke()) {
|
||||
LoginMode.Password -> {
|
||||
loginPasswordFormItem {
|
||||
id("passwordForm")
|
||||
stringProvider(host.stringProvider)
|
||||
passwordValue(state.enteredPassword)
|
||||
submitEnabled(state.enteredPassword.isNotEmpty())
|
||||
onPasswordEdited { host.listener?.passwordEdited(it) }
|
||||
errorText((state.asyncLoginAction as? Fail)?.error?.let { host.errorFormatter.toHumanReadable(it) })
|
||||
forgetPasswordClickListener { host.listener?.forgetPasswordClicked() }
|
||||
submitClickListener { host.listener?.submit() }
|
||||
}
|
||||
}
|
||||
is LoginMode.Sso -> {
|
||||
loginCenterButtonItem {
|
||||
id("sso")
|
||||
text(host.stringProvider.getString(R.string.login_signin_sso))
|
||||
listener { host.listener?.signinFallbackSubmit() }
|
||||
}
|
||||
}
|
||||
is LoginMode.SsoAndPassword -> {
|
||||
}
|
||||
LoginMode.Unsupported -> {
|
||||
loginCenterButtonItem {
|
||||
id("fallback")
|
||||
text(host.stringProvider.getString(R.string.login_signin))
|
||||
listener { host.listener?.signinFallbackSubmit() }
|
||||
}
|
||||
}
|
||||
LoginMode.Unknown -> Unit // Should not happen
|
||||
}
|
||||
}
|
||||
loginErrorWithRetryItem {
|
||||
id("errorRetry")
|
||||
text(host.errorFormatter.toHumanReadable(error))
|
||||
listener { host.listener?.retry() }
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildLoginSuccessItem(state: SoftLogoutViewState) = when (state.asyncHomeServerLoginFlowRequest.invoke()) {
|
||||
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 {
|
||||
id("passwordForm")
|
||||
stringProvider(host.stringProvider)
|
||||
passwordValue(state.enteredPassword)
|
||||
submitEnabled(state.enteredPassword.isNotEmpty())
|
||||
onPasswordEdited { host.listener?.passwordEdited(it) }
|
||||
errorText((state.asyncLoginAction as? Fail)?.error?.let { host.errorFormatter.toHumanReadable(it) })
|
||||
forgetPasswordClickListener { host.listener?.forgetPasswordClicked() }
|
||||
submitClickListener { host.listener?.submit() }
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildLoginSSOForm() {
|
||||
val host = this
|
||||
loginCenterButtonItem {
|
||||
id("sso")
|
||||
text(host.stringProvider.getString(R.string.login_signin_sso))
|
||||
listener { host.listener?.signinFallbackSubmit() }
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildLoginUnsupportedForm() {
|
||||
val host = this
|
||||
loginCenterButtonItem {
|
||||
id("fallback")
|
||||
text(host.stringProvider.getString(R.string.login_signin))
|
||||
listener { host.listener?.signinFallbackSubmit() }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,14 +35,12 @@ import im.vector.app.core.platform.VectorViewModel
|
|||
import im.vector.app.features.login.LoginMode
|
||||
import kotlinx.coroutines.launch
|
||||
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.session.Session
|
||||
import org.matrix.android.sdk.api.session.getUser
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* TODO Test push: disable the pushers?
|
||||
*/
|
||||
class SoftLogoutViewModel @AssistedInject constructor(
|
||||
@Assisted initialState: SoftLogoutViewState,
|
||||
private val session: Session,
|
||||
|
@ -70,7 +68,8 @@ class SoftLogoutViewModel @AssistedInject constructor(
|
|||
userId = userId,
|
||||
deviceId = session.sessionParams.deviceId.orEmpty(),
|
||||
userDisplayName = session.getUser(userId)?.displayName ?: userId,
|
||||
hasUnsavedKeys = session.hasUnsavedKeys()
|
||||
hasUnsavedKeys = session.hasUnsavedKeys(),
|
||||
loginType = session.sessionParams.loginType,
|
||||
)
|
||||
} else {
|
||||
SoftLogoutViewState(
|
||||
|
@ -78,7 +77,8 @@ class SoftLogoutViewModel @AssistedInject constructor(
|
|||
userId = "",
|
||||
deviceId = "",
|
||||
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.Uninitialized
|
||||
import im.vector.app.features.login.LoginMode
|
||||
import org.matrix.android.sdk.api.auth.LoginType
|
||||
|
||||
data class SoftLogoutViewState(
|
||||
val asyncHomeServerLoginFlowRequest: Async<LoginMode> = Uninitialized,
|
||||
|
@ -31,7 +32,8 @@ data class SoftLogoutViewState(
|
|||
val deviceId: String,
|
||||
val userDisplayName: String,
|
||||
val hasUnsavedKeys: Boolean,
|
||||
val enteredPassword: String = ""
|
||||
val loginType: LoginType,
|
||||
val enteredPassword: String = "",
|
||||
) : MavericksState {
|
||||
|
||||
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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
Loading…
Reference in a new issue