From bee7ab319171394ca9682cf26b59095c009548c2 Mon Sep 17 00:00:00 2001 From: Taras Smakula <tarassmakula@gmail.com> Date: Fri, 23 Feb 2024 16:52:49 +0200 Subject: [PATCH] Prepare stages for forgot password --- .../auth/feature/log_in/LogInViewModel.kt | 6 +-- .../auth/feature/log_in/LoginDataSource.kt | 47 +++++++++++++++---- 2 files changed, 42 insertions(+), 11 deletions(-) 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 8fe718a67..006376514 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 decc0120d..b117d4fc2 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 -- GitLab