mirror of
https://github.com/bitwarden/android.git
synced 2026-04-29 20:38:41 -05:00
BIT-2246: Update link for recovery code process (#1303)
This commit is contained in:
committed by
Álison Fernandes
parent
86bf2d0877
commit
a80f903df0
@@ -32,7 +32,6 @@ import androidx.compose.ui.text.input.ImeAction
|
|||||||
import androidx.compose.ui.text.input.KeyboardType
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.core.net.toUri
|
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
@@ -97,8 +96,8 @@ fun TwoFactorLoginScreen(
|
|||||||
when (event) {
|
when (event) {
|
||||||
TwoFactorLoginEvent.NavigateBack -> onNavigateBack()
|
TwoFactorLoginEvent.NavigateBack -> onNavigateBack()
|
||||||
|
|
||||||
TwoFactorLoginEvent.NavigateToRecoveryCode -> {
|
is TwoFactorLoginEvent.NavigateToRecoveryCode -> {
|
||||||
intentManager.launchUri("https://bitwarden.com/help/lost-two-step-device".toUri())
|
intentManager.launchUri(uri = event.uri)
|
||||||
}
|
}
|
||||||
|
|
||||||
is TwoFactorLoginEvent.NavigateToCaptcha -> {
|
is TwoFactorLoginEvent.NavigateToCaptcha -> {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.x8bit.bitwarden.ui.auth.feature.twofactorlogin
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
|
import androidx.core.net.toUri
|
||||||
import androidx.lifecycle.SavedStateHandle
|
import androidx.lifecycle.SavedStateHandle
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.x8bit.bitwarden.R
|
import com.x8bit.bitwarden.R
|
||||||
@@ -19,6 +20,8 @@ import com.x8bit.bitwarden.data.auth.repository.util.CaptchaCallbackTokenResult
|
|||||||
import com.x8bit.bitwarden.data.auth.repository.util.DuoCallbackTokenResult
|
import com.x8bit.bitwarden.data.auth.repository.util.DuoCallbackTokenResult
|
||||||
import com.x8bit.bitwarden.data.auth.repository.util.generateUriForCaptcha
|
import com.x8bit.bitwarden.data.auth.repository.util.generateUriForCaptcha
|
||||||
import com.x8bit.bitwarden.data.auth.util.YubiKeyResult
|
import com.x8bit.bitwarden.data.auth.util.YubiKeyResult
|
||||||
|
import com.x8bit.bitwarden.data.platform.repository.EnvironmentRepository
|
||||||
|
import com.x8bit.bitwarden.data.platform.repository.util.baseWebVaultUrlOrDefault
|
||||||
import com.x8bit.bitwarden.ui.auth.feature.twofactorlogin.util.button
|
import com.x8bit.bitwarden.ui.auth.feature.twofactorlogin.util.button
|
||||||
import com.x8bit.bitwarden.ui.auth.feature.twofactorlogin.util.imageRes
|
import com.x8bit.bitwarden.ui.auth.feature.twofactorlogin.util.imageRes
|
||||||
import com.x8bit.bitwarden.ui.auth.feature.twofactorlogin.util.isDuo
|
import com.x8bit.bitwarden.ui.auth.feature.twofactorlogin.util.isDuo
|
||||||
@@ -44,6 +47,7 @@ private const val KEY_STATE = "state"
|
|||||||
@Suppress("TooManyFunctions")
|
@Suppress("TooManyFunctions")
|
||||||
class TwoFactorLoginViewModel @Inject constructor(
|
class TwoFactorLoginViewModel @Inject constructor(
|
||||||
private val authRepository: AuthRepository,
|
private val authRepository: AuthRepository,
|
||||||
|
private val environmentRepository: EnvironmentRepository,
|
||||||
savedStateHandle: SavedStateHandle,
|
savedStateHandle: SavedStateHandle,
|
||||||
) : BaseViewModel<TwoFactorLoginState, TwoFactorLoginEvent, TwoFactorLoginAction>(
|
) : BaseViewModel<TwoFactorLoginState, TwoFactorLoginEvent, TwoFactorLoginAction>(
|
||||||
initialState = savedStateHandle[KEY_STATE]
|
initialState = savedStateHandle[KEY_STATE]
|
||||||
@@ -60,6 +64,16 @@ class TwoFactorLoginViewModel @Inject constructor(
|
|||||||
password = TwoFactorLoginArgs(savedStateHandle).password,
|
password = TwoFactorLoginArgs(savedStateHandle).password,
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
private val recover2faUri: Uri
|
||||||
|
get() {
|
||||||
|
val baseUrl = environmentRepository
|
||||||
|
.environment
|
||||||
|
.environmentUrlData
|
||||||
|
.baseWebVaultUrlOrDefault
|
||||||
|
return "$baseUrl/#/recover-2fa".toUri()
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// As state updates, write to saved state handle.
|
// As state updates, write to saved state handle.
|
||||||
stateFlow
|
stateFlow
|
||||||
@@ -357,7 +371,7 @@ class TwoFactorLoginViewModel @Inject constructor(
|
|||||||
private fun handleSelectAuthMethod(action: TwoFactorLoginAction.SelectAuthMethod) {
|
private fun handleSelectAuthMethod(action: TwoFactorLoginAction.SelectAuthMethod) {
|
||||||
when (action.authMethod) {
|
when (action.authMethod) {
|
||||||
TwoFactorAuthMethod.RECOVERY_CODE -> {
|
TwoFactorAuthMethod.RECOVERY_CODE -> {
|
||||||
sendEvent(TwoFactorLoginEvent.NavigateToRecoveryCode)
|
sendEvent(TwoFactorLoginEvent.NavigateToRecoveryCode(recover2faUri))
|
||||||
}
|
}
|
||||||
|
|
||||||
TwoFactorAuthMethod.EMAIL -> {
|
TwoFactorAuthMethod.EMAIL -> {
|
||||||
@@ -520,8 +534,10 @@ sealed class TwoFactorLoginEvent {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Navigates to the recovery code help page.
|
* Navigates to the recovery code help page.
|
||||||
|
*
|
||||||
|
* @param uri The recovery uri.
|
||||||
*/
|
*/
|
||||||
data object NavigateToRecoveryCode : TwoFactorLoginEvent()
|
data class NavigateToRecoveryCode(val uri: Uri) : TwoFactorLoginEvent()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows a toast with the given [message].
|
* Shows a toast with the given [message].
|
||||||
|
|||||||
@@ -255,9 +255,10 @@ class TwoFactorLoginScreenTest : BaseComposeTest() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `NavigateToRecoveryCode should launch the recovery code uri`() {
|
fun `NavigateToRecoveryCode should launch the recovery code uri`() {
|
||||||
mutableEventFlow.tryEmit(TwoFactorLoginEvent.NavigateToRecoveryCode)
|
val mockUri = mockk<Uri>()
|
||||||
|
mutableEventFlow.tryEmit(TwoFactorLoginEvent.NavigateToRecoveryCode(mockUri))
|
||||||
verify {
|
verify {
|
||||||
intentManager.launchUri(any())
|
intentManager.launchUri(mockUri)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.x8bit.bitwarden.ui.auth.feature.twofactorlogin
|
package com.x8bit.bitwarden.ui.auth.feature.twofactorlogin
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import androidx.core.net.toUri
|
||||||
import androidx.lifecycle.SavedStateHandle
|
import androidx.lifecycle.SavedStateHandle
|
||||||
import app.cash.turbine.test
|
import app.cash.turbine.test
|
||||||
import com.x8bit.bitwarden.R
|
import com.x8bit.bitwarden.R
|
||||||
@@ -14,6 +15,8 @@ import com.x8bit.bitwarden.data.auth.repository.util.CaptchaCallbackTokenResult
|
|||||||
import com.x8bit.bitwarden.data.auth.repository.util.DuoCallbackTokenResult
|
import com.x8bit.bitwarden.data.auth.repository.util.DuoCallbackTokenResult
|
||||||
import com.x8bit.bitwarden.data.auth.repository.util.generateUriForCaptcha
|
import com.x8bit.bitwarden.data.auth.repository.util.generateUriForCaptcha
|
||||||
import com.x8bit.bitwarden.data.auth.util.YubiKeyResult
|
import com.x8bit.bitwarden.data.auth.util.YubiKeyResult
|
||||||
|
import com.x8bit.bitwarden.data.platform.repository.EnvironmentRepository
|
||||||
|
import com.x8bit.bitwarden.data.platform.repository.util.baseWebVaultUrlOrDefault
|
||||||
import com.x8bit.bitwarden.data.platform.repository.util.bufferedMutableSharedFlow
|
import com.x8bit.bitwarden.data.platform.repository.util.bufferedMutableSharedFlow
|
||||||
import com.x8bit.bitwarden.ui.platform.base.BaseViewModelTest
|
import com.x8bit.bitwarden.ui.platform.base.BaseViewModelTest
|
||||||
import com.x8bit.bitwarden.ui.platform.base.util.asText
|
import com.x8bit.bitwarden.ui.platform.base.util.asText
|
||||||
@@ -45,6 +48,11 @@ class TwoFactorLoginViewModelTest : BaseViewModelTest() {
|
|||||||
every { duoTokenResultFlow } returns mutableDuoTokenResultFlow
|
every { duoTokenResultFlow } returns mutableDuoTokenResultFlow
|
||||||
every { yubiKeyResultFlow } returns mutableYubiKeyResultFlow
|
every { yubiKeyResultFlow } returns mutableYubiKeyResultFlow
|
||||||
}
|
}
|
||||||
|
private val environmentRepository: EnvironmentRepository = mockk(relaxed = true) {
|
||||||
|
every {
|
||||||
|
environment.environmentUrlData.baseWebVaultUrlOrDefault
|
||||||
|
} returns "https://vault.bitwarden.com"
|
||||||
|
}
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
@@ -515,6 +523,11 @@ class TwoFactorLoginViewModelTest : BaseViewModelTest() {
|
|||||||
@Test
|
@Test
|
||||||
fun `SelectAuthMethod with RECOVERY_CODE should launch the NavigateToRecoveryCode event`() =
|
fun `SelectAuthMethod with RECOVERY_CODE should launch the NavigateToRecoveryCode event`() =
|
||||||
runTest {
|
runTest {
|
||||||
|
val mockkUri = mockk<Uri>()
|
||||||
|
every {
|
||||||
|
Uri.parse("https://vault.bitwarden.com/#/recover-2fa")
|
||||||
|
} returns mockkUri
|
||||||
|
|
||||||
val viewModel = createViewModel()
|
val viewModel = createViewModel()
|
||||||
viewModel.eventFlow.test {
|
viewModel.eventFlow.test {
|
||||||
viewModel.trySendAction(
|
viewModel.trySendAction(
|
||||||
@@ -523,7 +536,9 @@ class TwoFactorLoginViewModelTest : BaseViewModelTest() {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
assertEquals(
|
assertEquals(
|
||||||
TwoFactorLoginEvent.NavigateToRecoveryCode,
|
TwoFactorLoginEvent.NavigateToRecoveryCode(
|
||||||
|
uri = "https://vault.bitwarden.com/#/recover-2fa".toUri(),
|
||||||
|
),
|
||||||
awaitItem(),
|
awaitItem(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -611,6 +626,7 @@ class TwoFactorLoginViewModelTest : BaseViewModelTest() {
|
|||||||
): TwoFactorLoginViewModel =
|
): TwoFactorLoginViewModel =
|
||||||
TwoFactorLoginViewModel(
|
TwoFactorLoginViewModel(
|
||||||
authRepository = authRepository,
|
authRepository = authRepository,
|
||||||
|
environmentRepository = environmentRepository,
|
||||||
savedStateHandle = SavedStateHandle().also {
|
savedStateHandle = SavedStateHandle().also {
|
||||||
it["state"] = state
|
it["state"] = state
|
||||||
it["email_address"] = "example@email.com"
|
it["email_address"] = "example@email.com"
|
||||||
|
|||||||
Reference in New Issue
Block a user