From ab1848bcdef52dcb20b9b1245e1054c12a42683f Mon Sep 17 00:00:00 2001
From: Taras Smakula <tarassmakula@gmail.com>
Date: Fri, 28 Jun 2024 13:51:17 +0300
Subject: [PATCH] Pass user id as param for login

---
 .../org/futo/circles/view/PostHeaderView.kt   |  4 ++--
 .../auth/feature/log_in/LogInFragment.kt      |  5 ++--
 .../auth/feature/log_in/LogInViewModel.kt     | 12 +++++-----
 .../auth/feature/log_in/LoginDataSource.kt    | 24 +++++++++----------
 .../switch_user/SwitchUserDataSource.kt       |  3 +--
 .../UserIdUtils.kt}                           | 21 +++++++++++++---
 .../core/extensions/MatrixUserExtensions.kt   |  4 ++--
 .../select_users/SelectUsersDataSource.kt     |  4 ++--
 .../core/mapping/RoomSummaryMapping.kt        |  4 ++--
 .../circles/core/utils/HomeServerUtils.kt     |  6 +++++
 .../utils/{UserUtils.kt => UserIdUtils.kt}    |  3 ++-
 11 files changed, 55 insertions(+), 35 deletions(-)
 rename auth/src/main/java/org/futo/circles/auth/{feature/log_in/UserIdValidator.kt => utils/UserIdUtils.kt} (73%)
 rename core/src/main/java/org/futo/circles/core/utils/{UserUtils.kt => UserIdUtils.kt} (96%)

diff --git a/app/src/main/java/org/futo/circles/view/PostHeaderView.kt b/app/src/main/java/org/futo/circles/view/PostHeaderView.kt
index 2c0d7e17c..741bfbca3 100644
--- a/app/src/main/java/org/futo/circles/view/PostHeaderView.kt
+++ b/app/src/main/java/org/futo/circles/view/PostHeaderView.kt
@@ -13,7 +13,7 @@ import org.futo.circles.core.extensions.setIsEncryptedIcon
 import org.futo.circles.core.extensions.setIsVisible
 import org.futo.circles.core.model.Post
 import org.futo.circles.core.provider.MatrixSessionProvider
-import org.futo.circles.core.utils.UserUtils
+import org.futo.circles.core.utils.UserIdUtils
 import org.futo.circles.databinding.ViewPostHeaderBinding
 import org.futo.circles.feature.timeline.list.PostOptionsListener
 import java.util.Date
@@ -69,7 +69,7 @@ class PostHeaderView(
                 }
             }
             tvUserName.text = name
-            tvUserId.text = UserUtils.removeDomainSuffix(userId)
+            tvUserId.text = UserIdUtils.removeDomainSuffix(userId)
             ivEncrypted.setIsEncryptedIcon(isEncrypted)
             tvMessageTime.text = DateFormat.format("MMM dd, h:mm a", Date(timestamp))
 
diff --git a/auth/src/main/java/org/futo/circles/auth/feature/log_in/LogInFragment.kt b/auth/src/main/java/org/futo/circles/auth/feature/log_in/LogInFragment.kt
index 7d581a4ed..b40ab2aa5 100644
--- a/auth/src/main/java/org/futo/circles/auth/feature/log_in/LogInFragment.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/log_in/LogInFragment.kt
@@ -19,6 +19,7 @@ import org.futo.circles.auth.model.InvalidUserId
 import org.futo.circles.auth.model.RemoveUser
 import org.futo.circles.auth.model.SuggestedUserId
 import org.futo.circles.auth.model.ValidUserId
+import org.futo.circles.auth.utils.UserIdUtils
 import org.futo.circles.core.base.fragment.BaseBindingFragment
 import org.futo.circles.core.base.fragment.HasLoadingState
 import org.futo.circles.core.base.list.BaseRvDecoration
@@ -115,12 +116,12 @@ class LogInFragment : BaseBindingFragment<FragmentLogInBinding>(FragmentLogInBin
 
     private fun startLogin(isForgotPassword: Boolean) {
         val userId = binding.tilUserId.getText()
-        when (UserIdValidator.validateUserId(userId)) {
+        when (val status = UserIdUtils.validateUserId(userId)) {
             EmptyUserId -> showError(getString(R.string.user_id_can_not_be_empty))
             InvalidUserId -> showError(getString(R.string.invalid_user_id))
             is SuggestedUserId -> findNavController().navigateSafe(
                 LogInFragmentDirections.toLoginSuggestionBottomSheet(
-                    userId, isForgotPassword
+                    status.suggestedUserId, isForgotPassword
                 )
             )
 
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 006376514..998817009 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
@@ -17,14 +17,14 @@ class LogInViewModel @Inject constructor(
     private val refreshTokenManager: RefreshTokenManager
 ) : ViewModel() {
 
-    val loginResultLiveData = SingleEventLiveData<Response<Unit>>()
+    val loginResultLiveData = SingleEventLiveData<Response<Unit?>>()
     val switchUsersLiveData = MutableLiveData(switchUserDataSource.getSwitchUsersList())
     val navigateToBottomMenuScreenLiveData = SingleEventLiveData<Unit>()
 
-    fun startLogInFlow(userName: String, domain: String, isForgotPassword: Boolean) {
-        switchUserDataSource.getSessionCredentialsIdByUserInfo(userName, domain)
+    fun startLogInFlow(userId: String, isForgotPassword: Boolean) {
+        switchUserDataSource.getSessionCredentialsIdByUserInfo(userId)
             ?.let { resumeSwitchUserSession(it) }
-            ?: login(userName, domain, isForgotPassword)
+            ?: login(userId, isForgotPassword)
     }
 
     fun removeSwitchUser(id: String) {
@@ -43,9 +43,9 @@ class LogInViewModel @Inject constructor(
         }
     }
 
-    private fun login(userName: String, domain: String, isForgotPassword: Boolean) {
+    private fun login(userId: String, isForgotPassword: Boolean) {
         launchBg {
-            val loginResult = loginDataSource.startLogin(userName, domain, isForgotPassword)
+            val loginResult = loginDataSource.startLogin(userId, 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 15f135767..726a4e478 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
@@ -14,9 +14,10 @@ import org.futo.circles.auth.feature.uia.UIADataSource.Companion.TYPE_PARAM_KEY
 import org.futo.circles.auth.feature.uia.UIADataSource.Companion.USER_PARAM_KEY
 import org.futo.circles.auth.feature.uia.UIADataSourceProvider
 import org.futo.circles.auth.model.UIAFlowType
+import org.futo.circles.auth.utils.UserIdUtils
 import org.futo.circles.core.extensions.createResult
 import org.futo.circles.core.provider.MatrixInstanceProvider
-import org.futo.circles.core.utils.HomeServerUtils.buildHomeServerConfigFromDomain
+import org.futo.circles.core.utils.HomeServerUtils.buildHomeServerConfigFromUserId
 import org.matrix.android.sdk.api.auth.registration.Stage
 import javax.inject.Inject
 
@@ -29,30 +30,28 @@ class LoginDataSource @Inject constructor(
     private val authService by lazy { MatrixInstanceProvider.matrix.authenticationService() }
 
     suspend fun startLogin(
-        userName: String,
-        domain: String,
+        userId: String,
         isForgotPassword: Boolean
     ) = createResult {
         authService.cancelPendingLoginOrRegistration()
-        val stages = prepareLoginStages(userName, domain, isForgotPassword)
+        val stages = prepareLoginStages(userId, isForgotPassword)
         val uiaDataSource = UIADataSourceProvider.create(
             if (isForgotPassword) UIAFlowType.ForgotPassword else UIAFlowType.Login,
             uiaFactory
         )
+        val (userName, domain) = UserIdUtils.getNameAndDomainFromId(userId)
         uiaDataSource.startUIAStages(stages, domain, userName)
     }
 
     private suspend fun prepareLoginStages(
-        userName: String,
-        domain: String,
+        userId: String,
         isForgotPassword: Boolean
     ): List<Stage> {
-        val homeServerConfig = buildHomeServerConfigFromDomain(domain)
+        val homeServerConfig = buildHomeServerConfigFromUserId(userId)
         val supportedLoginMethods =
             authService.getLoginFlow(homeServerConfig).supportedLoginTypes
-        val stages =
-            getCircleStages(userName, domain, isForgotPassword)
-                ?: getPasswordStagesIfAvailable(supportedLoginMethods, isForgotPassword)
+        val stages = getCircleStages(userId, isForgotPassword)
+            ?: getPasswordStagesIfAvailable(supportedLoginMethods, isForgotPassword)
 
         return stages
             ?: throw IllegalArgumentException(context.getString(R.string.unsupported_login_method))
@@ -68,12 +67,11 @@ class LoginDataSource @Inject constructor(
     } else null
 
     private suspend fun getCircleStages(
-        userName: String,
-        domain: String,
+        userId: String,
         isForgotPassword: Boolean
     ): List<Stage>? {
         val identifierParams = mapOf(
-            USER_PARAM_KEY to "@$userName:$domain",
+            USER_PARAM_KEY to userId,
             TYPE_PARAM_KEY to LOGIN_PASSWORD_USER_ID_TYPE
         )
         val flows = authService.getLoginWizard()
diff --git a/auth/src/main/java/org/futo/circles/auth/feature/log_in/switch_user/SwitchUserDataSource.kt b/auth/src/main/java/org/futo/circles/auth/feature/log_in/switch_user/SwitchUserDataSource.kt
index 4cc7e3d4b..381ca47e9 100644
--- a/auth/src/main/java/org/futo/circles/auth/feature/log_in/switch_user/SwitchUserDataSource.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/log_in/switch_user/SwitchUserDataSource.kt
@@ -36,8 +36,7 @@ class SwitchUserDataSource @Inject constructor() {
     private fun getSessionWithId(id: String): Session? =
         getSwitchUsersList().firstOrNull { it.id == id }?.session
 
-    fun getSessionCredentialsIdByUserInfo(userName: String, domain: String): String? {
-        val userId = "@$userName:$domain"
+    fun getSessionCredentialsIdByUserInfo(userId: String): String? {
         return getSwitchUsersList().firstOrNull { it.user.userId == userId }?.id
     }
 
diff --git a/auth/src/main/java/org/futo/circles/auth/feature/log_in/UserIdValidator.kt b/auth/src/main/java/org/futo/circles/auth/utils/UserIdUtils.kt
similarity index 73%
rename from auth/src/main/java/org/futo/circles/auth/feature/log_in/UserIdValidator.kt
rename to auth/src/main/java/org/futo/circles/auth/utils/UserIdUtils.kt
index d01f36108..7d79964d0 100644
--- a/auth/src/main/java/org/futo/circles/auth/feature/log_in/UserIdValidator.kt
+++ b/auth/src/main/java/org/futo/circles/auth/utils/UserIdUtils.kt
@@ -1,4 +1,4 @@
-package org.futo.circles.auth.feature.log_in
+package org.futo.circles.auth.utils
 
 import org.futo.circles.auth.model.EmptyUserId
 import org.futo.circles.auth.model.InvalidUserId
@@ -8,10 +8,23 @@ import org.futo.circles.auth.model.ValidateUserIdStatus
 import org.futo.circles.core.base.CirclesAppConfig
 import org.matrix.android.sdk.api.MatrixPatterns
 
-object UserIdValidator {
+
+object UserIdUtils {
 
     private val defaultDomain = CirclesAppConfig.usDomain
 
+
+    fun getNameAndDomainFromId(userId: String): Pair<String, String> {
+        if (!MatrixPatterns.isUserId(userId)) throw IllegalArgumentException("Invalid userId $userId")
+
+        return userId.split(":").takeIf { it.size == 2 }?.let {
+            val userName = it.first().replace("@", "")
+            val domain = it[1]
+            userName to domain
+        } ?: throw IllegalArgumentException("Invalid userId $userId")
+    }
+
+
     fun validateUserId(input: String): ValidateUserIdStatus {
         if (input.isEmpty()) return EmptyUserId
         if (MatrixPatterns.isUserId(input)) return ValidUserId(input)
@@ -30,11 +43,13 @@ object UserIdValidator {
 
     private fun handleEmailToUserIdTransform(input: String): ValidateUserIdStatus {
         val parts = input.split("@")
-            .takeIf { it.size == 2 && !it.first().contains(":") } ?: return InvalidUserId
+            .takeIf { it.size == 2 && !it.first().contains(":") }
+            ?: return InvalidUserId
         return SuggestedUserId("@${parts.first()}:${parts[1]}")
     }
 
     private fun handleNoDomainInput(input: String): ValidateUserIdStatus {
         return SuggestedUserId("$input$defaultDomain")
     }
+
 }
\ No newline at end of file
diff --git a/core/src/main/java/org/futo/circles/core/extensions/MatrixUserExtensions.kt b/core/src/main/java/org/futo/circles/core/extensions/MatrixUserExtensions.kt
index 6884a5172..2ebc3145a 100644
--- a/core/src/main/java/org/futo/circles/core/extensions/MatrixUserExtensions.kt
+++ b/core/src/main/java/org/futo/circles/core/extensions/MatrixUserExtensions.kt
@@ -1,6 +1,6 @@
 package org.futo.circles.core.extensions
 
-import org.futo.circles.core.utils.UserUtils
+import org.futo.circles.core.utils.UserIdUtils
 import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
 import org.matrix.android.sdk.api.session.room.sender.SenderInfo
 import org.matrix.android.sdk.api.session.user.model.User
@@ -15,5 +15,5 @@ fun SenderInfo.notEmptyDisplayName(): String = getName(userId, displayName)
 private fun getName(userId: String, displayName: String?): String {
     val name = displayName?.takeIf { it.isNotEmpty() }
         ?: userId.replace("@", "").substringBefore(":")
-    return UserUtils.removeDomainSuffix(name)
+    return UserIdUtils.removeDomainSuffix(name)
 }
\ No newline at end of file
diff --git a/core/src/main/java/org/futo/circles/core/feature/select_users/SelectUsersDataSource.kt b/core/src/main/java/org/futo/circles/core/feature/select_users/SelectUsersDataSource.kt
index bc477494e..52b70036a 100644
--- a/core/src/main/java/org/futo/circles/core/feature/select_users/SelectUsersDataSource.kt
+++ b/core/src/main/java/org/futo/circles/core/feature/select_users/SelectUsersDataSource.kt
@@ -15,7 +15,7 @@ import org.futo.circles.core.model.InviteMemberListItem
 import org.futo.circles.core.model.NoResultsItem
 import org.futo.circles.core.model.UserListItem
 import org.futo.circles.core.provider.MatrixSessionProvider
-import org.futo.circles.core.utils.UserUtils
+import org.futo.circles.core.utils.UserIdUtils
 import org.matrix.android.sdk.api.MatrixPatterns
 import org.matrix.android.sdk.api.session.getRoom
 import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams
@@ -95,7 +95,7 @@ class SelectUsersDataSource @Inject constructor(
             list.add(HeaderItem.suggestionHeader)
             list.add(
                 UserListItem(
-                    CirclesUserSummary(query, UserUtils.removeDomainSuffix(query), ""),
+                    CirclesUserSummary(query, UserIdUtils.removeDomainSuffix(query), ""),
                     selectedUsers.containsWithId(query)
                 )
             )
diff --git a/core/src/main/java/org/futo/circles/core/mapping/RoomSummaryMapping.kt b/core/src/main/java/org/futo/circles/core/mapping/RoomSummaryMapping.kt
index ce2d5c152..388ba0ddd 100644
--- a/core/src/main/java/org/futo/circles/core/mapping/RoomSummaryMapping.kt
+++ b/core/src/main/java/org/futo/circles/core/mapping/RoomSummaryMapping.kt
@@ -11,7 +11,7 @@ import org.futo.circles.core.model.SelectRoomTypeArg
 import org.futo.circles.core.model.SelectableRoomListItem
 import org.futo.circles.core.model.isCircle
 import org.futo.circles.core.provider.MatrixSessionProvider
-import org.futo.circles.core.utils.UserUtils
+import org.futo.circles.core.utils.UserIdUtils
 import org.futo.circles.core.utils.getKnocksCount
 import org.matrix.android.sdk.api.query.QueryStringValue
 import org.matrix.android.sdk.api.session.events.model.EventType
@@ -52,7 +52,7 @@ fun RoomMemberSummary.toKnockRequestListItem(roomId: String, roomType: CircleRoo
             ?: "",
         roomType = roomType,
         requesterId = userId,
-        requesterName = displayName ?: UserUtils.removeDomainSuffix(userId),
+        requesterName = displayName ?: UserIdUtils.removeDomainSuffix(userId),
         requesterAvatarUrl = avatarUrl,
         message = getReasonMessage(roomId, userId)
     )
diff --git a/core/src/main/java/org/futo/circles/core/utils/HomeServerUtils.kt b/core/src/main/java/org/futo/circles/core/utils/HomeServerUtils.kt
index 97125d5e8..d11f90ca9 100644
--- a/core/src/main/java/org/futo/circles/core/utils/HomeServerUtils.kt
+++ b/core/src/main/java/org/futo/circles/core/utils/HomeServerUtils.kt
@@ -5,6 +5,12 @@ import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
 
 object HomeServerUtils {
 
+    fun buildHomeServerConfigFromUserId(userId: String): HomeServerConnectionConfig {
+        val domain = UserIdUtils.getServerDomain(userId)
+        return buildHomeServerConfigFromDomain(domain)
+    }
+
+
     fun buildHomeServerConfigFromDomain(domain: String) = HomeServerConnectionConfig
         .Builder()
         .withHomeServerUri(Uri.parse("https://$domain"))
diff --git a/core/src/main/java/org/futo/circles/core/utils/UserUtils.kt b/core/src/main/java/org/futo/circles/core/utils/UserIdUtils.kt
similarity index 96%
rename from core/src/main/java/org/futo/circles/core/utils/UserUtils.kt
rename to core/src/main/java/org/futo/circles/core/utils/UserIdUtils.kt
index f364c610a..708293e3c 100644
--- a/core/src/main/java/org/futo/circles/core/utils/UserUtils.kt
+++ b/core/src/main/java/org/futo/circles/core/utils/UserIdUtils.kt
@@ -3,7 +3,7 @@ package org.futo.circles.core.utils
 import org.futo.circles.core.provider.MatrixSessionProvider
 
 
-object UserUtils {
+object UserIdUtils {
 
     fun removeDomainSuffix(userId: String): String {
         val serverDomain = MatrixSessionProvider.currentSession?.sessionParams?.homeServerHost ?: ""
@@ -17,4 +17,5 @@ object UserUtils {
     }
 
     fun getServerDomain(userId: String) = userId.substringAfter(":")
+
 }
\ No newline at end of file
-- 
GitLab