diff --git a/app/src/main/kotlin/com/wire/android/ui/authentication/login/LoginScreen.kt b/app/src/main/kotlin/com/wire/android/ui/authentication/login/LoginScreen.kt
index 3c5e63e03c8..bc620fa6d00 100644
--- a/app/src/main/kotlin/com/wire/android/ui/authentication/login/LoginScreen.kt
+++ b/app/src/main/kotlin/com/wire/android/ui/authentication/login/LoginScreen.kt
@@ -307,13 +307,22 @@ fun LoginErrorDialog(
dismissOnClickOutside = false
)
- LoginState.Error.DialogError.PasswordNeededToRegisterClient -> TODO()
-
- else -> LoginDialogErrorData(
- title = stringResource(R.string.error_unknown_title),
- body = AnnotatedString(stringResource(R.string.error_unknown_message)),
- onDismiss = onDialogDismiss
- )
+ LoginState.Error.DialogError.Request2FAWithHandle -> {
+ LoginDialogErrorData(
+ title = stringResource(R.string.login_error_request_2fa_with_handle_title),
+ body = AnnotatedString(stringResource(R.string.login_error_request_2fa_with_handle_message)),
+ onDismiss = onDialogDismiss
+ )
+ }
+ LoginState.Error.TextFieldError.InvalidValue,
+ LoginState.Error.DialogError.PasswordNeededToRegisterClient,
+ LoginState.Error.TooManyDevicesError -> {
+ LoginDialogErrorData(
+ title = stringResource(R.string.error_unknown_title),
+ body = AnnotatedString(stringResource(R.string.error_unknown_message)),
+ onDismiss = onDialogDismiss
+ )
+ }
}
WireDialog(
diff --git a/app/src/main/kotlin/com/wire/android/ui/authentication/login/LoginState.kt b/app/src/main/kotlin/com/wire/android/ui/authentication/login/LoginState.kt
index a96243cccce..15658002e13 100644
--- a/app/src/main/kotlin/com/wire/android/ui/authentication/login/LoginState.kt
+++ b/app/src/main/kotlin/com/wire/android/ui/authentication/login/LoginState.kt
@@ -37,6 +37,7 @@ sealed class LoginState {
data object InvalidSSOCodeError : DialogError()
data object UserAlreadyExists : DialogError()
data object PasswordNeededToRegisterClient : DialogError()
+ data object Request2FAWithHandle : DialogError()
data class SSOResultError(val result: SSOFailureCodes) :
DialogError()
data object ServerVersionNotSupported : DialogError()
diff --git a/app/src/main/kotlin/com/wire/android/ui/authentication/login/email/LoginEmailViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/authentication/login/email/LoginEmailViewModel.kt
index eedd8a7b86b..e4c1e6251b3 100644
--- a/app/src/main/kotlin/com/wire/android/ui/authentication/login/email/LoginEmailViewModel.kt
+++ b/app/src/main/kotlin/com/wire/android/ui/authentication/login/email/LoginEmailViewModel.kt
@@ -246,7 +246,14 @@ class LoginEmailViewModel @Inject constructor(
}
private suspend fun request2FACode(authScope: AuthenticationScope) {
- val email = userIdentifierTextState.text.trim().toString()
+ val email = userIdentifierTextState.text.trim().toString().also {
+ // user is using handle to login when 2FA is required
+ if (!it.contains("@")) {
+ updateEmailFlowState(LoginState.Error.DialogError.Request2FAWithHandle)
+ return
+ }
+ }
+
val result = authScope.requestSecondFactorVerificationCode(
email = email,
verifiableAction = VerifiableAction.LOGIN_OR_CLIENT_REGISTRATION
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 9309f671a99..54e810dbe7e 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -369,6 +369,8 @@
SSO CODE OR EMAIL
Please enter a valid SSO code.
Enter a valid SSO code
+ Login with email
+ You can\'t use your username as two-factor authentication is activated. Please log in with your email instead.
Deleted account
You were logged out because your account was
deleted.
@@ -1637,5 +1639,4 @@ In group conversations, the group admin can overwrite this setting.
You\'ve created or joined a team with this email address on another device.
Wire could not complete your team creation due to a slow internet connection.
Wire could not complete your team creation due to an unknown error.
-
diff --git a/app/src/test/kotlin/com/wire/android/ui/authentication/login/email/LoginEmailViewModelTest.kt b/app/src/test/kotlin/com/wire/android/ui/authentication/login/email/LoginEmailViewModelTest.kt
index 2e79269e277..9c63b46196b 100644
--- a/app/src/test/kotlin/com/wire/android/ui/authentication/login/email/LoginEmailViewModelTest.kt
+++ b/app/src/test/kotlin/com/wire/android/ui/authentication/login/email/LoginEmailViewModelTest.kt
@@ -65,6 +65,7 @@ import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
+import org.amshove.kluent.internal.assertEquals
import org.amshove.kluent.shouldBe
import org.amshove.kluent.shouldBeEqualTo
import org.amshove.kluent.shouldBeInstanceOf
@@ -490,6 +491,19 @@ class LoginEmailViewModelTest {
advanceUntilIdle()
coVerify(exactly = 1) { getOrRegisterClientUseCase(match { it.secondFactorVerificationCode == null }) }
}
+ @Test
+ fun `given 2fa is needed, when user used handle to login, then show correct error message` () = runTest {
+ val email = "some.handle"
+ val code = "123456"
+ coEvery { loginUseCase(any(), any(), any(), any(), any()) } returns AuthenticationResult.Failure.InvalidCredentials.Missing2FA
+
+ loginViewModel.userIdentifierTextState.setTextAndPlaceCursorAtEnd(email)
+ loginViewModel.secondFactorVerificationCodeTextState.setTextAndPlaceCursorAtEnd(code)
+ advanceUntilIdle()
+ coVerify(exactly = 0) { addAuthenticatedUserUseCase(any(), any(), any(), any()) }
+ coVerify(exactly = 0) { getOrRegisterClientUseCase(any()) }
+ assertEquals(LoginState.Error.DialogError.Request2FAWithHandle, loginViewModel.loginState.flowState)
+ }
companion object {
val CLIENT = TestClient.CLIENT