diff --git a/auth/src/main/java/org/futo/circles/auth/feature/log_in/LogInViewModel.kt b/auth/src/main/java/org/futo/circles/auth/feature/log_in/LogInViewModel.kt index 8fe718a67f008581776be1a2cbab57860eebb20c..006376514579c6b6155eccb07c8b6d68bd1d57cb 100644 --- a/auth/src/main/java/org/futo/circles/auth/feature/log_in/LogInViewModel.kt +++ b/auth/src/main/java/org/futo/circles/auth/feature/log_in/LogInViewModel.kt @@ -24,7 +24,7 @@ class LogInViewModel @Inject constructor( fun startLogInFlow(userName: String, domain: String, isForgotPassword: Boolean) { switchUserDataSource.getSessionCredentialsIdByUserInfo(userName, domain) ?.let { resumeSwitchUserSession(it) } - ?: login(userName, domain) + ?: login(userName, domain, isForgotPassword) } fun removeSwitchUser(id: String) { @@ -43,9 +43,9 @@ class LogInViewModel @Inject constructor( } } - private fun login(userName: String, domain: String) { + private fun login(userName: String, domain: String, isForgotPassword: Boolean) { launchBg { - val loginResult = loginDataSource.startLogin(userName, domain) + val loginResult = loginDataSource.startLogin(userName, domain, isForgotPassword) loginResultLiveData.postValue(loginResult) } } diff --git a/auth/src/main/java/org/futo/circles/auth/feature/log_in/LoginDataSource.kt b/auth/src/main/java/org/futo/circles/auth/feature/log_in/LoginDataSource.kt index decc0120ddd640a542156b46c10cd5c6ce953282..b117d4fc2234467daac3cf3d4da32bb277a1e5fd 100644 --- a/auth/src/main/java/org/futo/circles/auth/feature/log_in/LoginDataSource.kt +++ b/auth/src/main/java/org/futo/circles/auth/feature/log_in/LoginDataSource.kt @@ -3,12 +3,14 @@ package org.futo.circles.auth.feature.log_in import android.content.Context import dagger.hilt.android.qualifiers.ApplicationContext import org.futo.circles.auth.R +import org.futo.circles.auth.base.BaseLoginStagesDataSource import org.futo.circles.auth.base.BaseLoginStagesDataSource.Companion.DIRECT_LOGIN_PASSWORD_TYPE import org.futo.circles.auth.base.BaseLoginStagesDataSource.Companion.LOGIN_PASSWORD_TYPE import org.futo.circles.auth.base.BaseLoginStagesDataSource.Companion.LOGIN_PASSWORD_USER_ID_TYPE import org.futo.circles.auth.base.BaseLoginStagesDataSource.Companion.TYPE_PARAM_KEY import org.futo.circles.auth.base.BaseLoginStagesDataSource.Companion.USER_PARAM_KEY import org.futo.circles.auth.feature.log_in.stages.LoginStagesDataSource +import org.futo.circles.auth.feature.sign_up.SignUpDataSource import org.futo.circles.core.extensions.createResult import org.futo.circles.core.provider.MatrixInstanceProvider import org.futo.circles.core.utils.HomeServerUtils.buildHomeServerConfigFromDomain @@ -24,35 +26,64 @@ class LoginDataSource @Inject constructor( suspend fun startLogin( userName: String, - domain: String + domain: String, + isForgotPassword: Boolean ) = createResult { authService.cancelPendingLoginOrRegistration() - val stages = prepareLoginStages(userName, domain) + val stages = prepareLoginStages(userName, domain, isForgotPassword) loginStagesDataSource.startLoginStages(stages, userName, domain) } private suspend fun prepareLoginStages( userName: String, - domain: String + domain: String, + isForgotPassword: Boolean ): List<Stage> { val homeServerConfig = buildHomeServerConfigFromDomain(domain) val supportedLoginMethods = authService.getLoginFlow(homeServerConfig).supportedLoginTypes - return if (isPasswordLogin(supportedLoginMethods)) - listOf(Stage.Other(true, DIRECT_LOGIN_PASSWORD_TYPE, null)) - else getCircleLoginStages(userName, domain) + return if (isPasswordLogin(supportedLoginMethods)) { + if (isForgotPassword) throw IllegalArgumentException("Forgot password is only available for Circles domains") + else listOf(Stage.Other(true, DIRECT_LOGIN_PASSWORD_TYPE, null)) + } else getCircleStages(userName, domain, isForgotPassword) } private fun isPasswordLogin(methods: List<String>) = methods.contains(LOGIN_PASSWORD_TYPE) - private suspend fun getCircleLoginStages(userName: String, domain: String): List<Stage> { + private suspend fun getCircleStages( + userName: String, + domain: String, + isForgotPassword: Boolean + ): List<Stage> { val identifierParams = mapOf( USER_PARAM_KEY to "@$userName:$domain", TYPE_PARAM_KEY to LOGIN_PASSWORD_USER_ID_TYPE ) val flows = authService.getLoginWizard() .getAllLoginFlows(identifierParams, context.getString(R.string.initial_device_name)) - return flows.firstOrNull() + + val stages = if (isForgotPassword) getCircleStagesForForgotPassword(flows) + else getCircleStagesForLogin(flows) + + return stages ?: throw IllegalArgumentException(context.getString(R.string.unsupported_login_method)) } + + private fun getCircleStagesForLogin(flows: List<List<Stage>>): List<Stage>? = + flows.firstOrNull { stages -> + stages.firstOrNull { stage -> + (stage as? Stage.Other)?.type == BaseLoginStagesDataSource.LOGIN_BSSPEKE_VERIFY_TYPE + } != null + } + + private fun getCircleStagesForForgotPassword(flows: List<List<Stage>>): List<Stage>? = + flows.firstOrNull { stages -> + val containsEmailStage = stages.firstOrNull { stage -> + (stage as? Stage.Other)?.type == SignUpDataSource.REGISTRATION_EMAIL_SUBMIT_TOKEN_TYPE + } != null + val containsSetPassword = stages.firstOrNull { stage -> + (stage as? Stage.Other)?.type == SignUpDataSource.REGISTRATION_BSSPEKE_SAVE_TYPE + } != null + containsEmailStage && containsSetPassword + } } \ No newline at end of file