diff --git a/changelog.d/6735.bugfix b/changelog.d/6735.bugfix new file mode 100644 index 0000000000..814bf3f47c --- /dev/null +++ b/changelog.d/6735.bugfix @@ -0,0 +1 @@ +Fixes crash when entering non ascii characters during account creation diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Extensions.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Extensions.kt index 6e198fb98c..68b931b33c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Extensions.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Extensions.kt @@ -62,7 +62,10 @@ fun Throwable.isUsernameInUse() = this is Failure.ServerError && error.code == MatrixError.M_USER_IN_USE fun Throwable.isInvalidUsername() = this is Failure.ServerError && - error.code == MatrixError.M_INVALID_USERNAME + (error.code == MatrixError.M_INVALID_USERNAME || usernameContainsNonAsciiCharacters()) + +private fun Failure.ServerError.usernameContainsNonAsciiCharacters() = error.code == MatrixError.M_UNKNOWN && + error.message == "Query parameter \'username\' must be ascii" fun Throwable.isInvalidPassword() = this is Failure.ServerError && error.code == MatrixError.M_FORBIDDEN && diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt index 8136dc379b..73288bd6d5 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt @@ -193,25 +193,32 @@ class OnboardingViewModel @AssistedInject constructor( } private suspend fun checkUserNameAvailability(userName: String) { - when (val result = registrationWizard.registrationAvailable(userName)) { - RegistrationAvailability.Available -> { - setState { - copy( - registrationState = RegistrationState( - isUserNameAvailable = true, - selectedMatrixId = when { - userName.isMatrixId() -> userName - else -> "@$userName:${selectedHomeserver.userFacingUrl.toReducedUrl()}" - }, - ) - ) - } - } + runCatching { registrationWizard.registrationAvailable(userName) }.fold( + onSuccess = { result -> + when (result) { + RegistrationAvailability.Available -> { + setState { + copy( + registrationState = RegistrationState( + isUserNameAvailable = true, + selectedMatrixId = when { + userName.isMatrixId() -> userName + else -> "@$userName:${selectedHomeserver.userFacingUrl.toReducedUrl()}" + }, + ) + ) + } + } - is RegistrationAvailability.NotAvailable -> { - _viewEvents.post(OnboardingViewEvents.Failure(result.failure)) - } - } + is RegistrationAvailability.NotAvailable -> { + _viewEvents.post(OnboardingViewEvents.Failure(result.failure)) + } + } + }, + onFailure = { + _viewEvents.post(OnboardingViewEvents.Failure(it)) + } + ) } private fun withAction(action: OnboardingAction, block: (OnboardingAction) -> Unit) { diff --git a/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt b/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt index b8a0be9529..b505d05944 100644 --- a/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt +++ b/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt @@ -478,6 +478,20 @@ class OnboardingViewModelTest { .finish() } + @Test + fun `given available username throws, when a register username is entered, then emits error`() = runTest { + viewModelWith(initialRegistrationState(A_HOMESERVER_URL)) + fakeAuthenticationService.givenRegistrationWizard(FakeRegistrationWizard().also { it.givenUserNameIsAvailableThrows(A_USERNAME, AN_ERROR) }) + val test = viewModel.test() + + viewModel.handle(OnboardingAction.UserNameEnteredAction.Registration(A_USERNAME)) + + test + .assertStates(initialState) + .assertEvents(OnboardingViewEvents.Failure(AN_ERROR)) + .finish() + } + @Test fun `given available username, when a register username is entered, then emits available registration state`() = runTest { viewModelWith(initialRegistrationState(A_HOMESERVER_URL)) diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeRegistrationWizard.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeRegistrationWizard.kt index 4f0b1fe083..6cacd6c1e5 100644 --- a/vector/src/test/java/im/vector/app/test/fakes/FakeRegistrationWizard.kt +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeRegistrationWizard.kt @@ -57,6 +57,10 @@ class FakeRegistrationWizard : RegistrationWizard by mockk(relaxed = false) { coEvery { registrationAvailable(userName) } returns RegistrationAvailability.Available } + fun givenUserNameIsAvailableThrows(userName: String, cause: Throwable) { + coEvery { registrationAvailable(userName) } throws cause + } + fun givenUserNameIsUnavailable(userName: String, failure: Failure.ServerError) { coEvery { registrationAvailable(userName) } returns RegistrationAvailability.NotAvailable(failure) }