mirror of
https://github.com/bitwarden/android.git
synced 2026-03-21 22:00:42 -05:00
[PM-16120] Defer passkey authentication until vault data is loaded (#4524)
This commit is contained in:
@@ -28,16 +28,20 @@ import androidx.credentials.provider.ProviderClearCredentialStateRequest
|
||||
import androidx.credentials.provider.PublicKeyCredentialEntry
|
||||
import com.bitwarden.fido.Fido2CredentialAutofillView
|
||||
import com.bitwarden.sdk.Fido2CredentialStore
|
||||
import com.bitwarden.vault.CipherView
|
||||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.data.auth.repository.AuthRepository
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.UserState
|
||||
import com.x8bit.bitwarden.data.autofill.fido2.manager.Fido2CredentialManager
|
||||
import com.x8bit.bitwarden.data.autofill.util.isActiveWithFido2Credentials
|
||||
import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager
|
||||
import com.x8bit.bitwarden.data.platform.repository.model.DataState
|
||||
import com.x8bit.bitwarden.data.platform.repository.util.takeUntilLoaded
|
||||
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.DecryptFido2CredentialAutofillViewResult
|
||||
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.fold
|
||||
import kotlinx.coroutines.launch
|
||||
import java.time.Clock
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
@@ -224,10 +228,14 @@ class Fido2ProviderProcessorImpl(
|
||||
): List<CredentialEntry> {
|
||||
val cipherViews = vaultRepository
|
||||
.ciphersStateFlow
|
||||
.value
|
||||
.data
|
||||
?.filter { it.isActiveWithFido2Credentials }
|
||||
?: emptyList()
|
||||
.takeUntilLoaded()
|
||||
.fold(emptyList<CipherView>()) { _, dataState ->
|
||||
when (dataState) {
|
||||
is DataState.Loaded -> dataState.data.filter { it.isActiveWithFido2Credentials }
|
||||
|
||||
else -> emptyList()
|
||||
}
|
||||
}
|
||||
val result = vaultRepository
|
||||
.getDecryptedFido2CredentialAutofillViews(cipherViews)
|
||||
return when (result) {
|
||||
|
||||
@@ -170,14 +170,6 @@ class VaultItemListingViewModel @Inject constructor(
|
||||
),
|
||||
)
|
||||
}
|
||||
?: state.fido2CredentialAssertionRequest
|
||||
?.let { request ->
|
||||
sendAction(
|
||||
VaultItemListingsAction.Internal.Fido2AssertionDataReceive(
|
||||
data = request,
|
||||
),
|
||||
)
|
||||
}
|
||||
?: observeVaultData()
|
||||
}
|
||||
|
||||
@@ -1334,6 +1326,14 @@ class VaultItemListingViewModel @Inject constructor(
|
||||
),
|
||||
)
|
||||
}
|
||||
?: state.fido2CredentialAssertionRequest
|
||||
?.let { request ->
|
||||
trySendAction(
|
||||
VaultItemListingsAction.Internal.Fido2AssertionDataReceive(
|
||||
data = request,
|
||||
),
|
||||
)
|
||||
}
|
||||
?: mutableStateFlow.update { it.copy(isRefreshing = false) }
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ import com.x8bit.bitwarden.data.vault.repository.model.DecryptFido2CredentialAut
|
||||
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
|
||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.util.createMockPasskeyAssertionOptions
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.coVerify
|
||||
import io.mockk.every
|
||||
import io.mockk.just
|
||||
import io.mockk.mockk
|
||||
@@ -461,6 +462,13 @@ class Fido2ProviderProcessorTest {
|
||||
val mockIntent: PendingIntent = mockk()
|
||||
val mockPublicKeyCredentialEntry: PublicKeyCredentialEntry = mockk()
|
||||
mutableUserStateFlow.value = DEFAULT_USER_STATE
|
||||
|
||||
// verify Loading state is ignored
|
||||
mutableCiphersStateFlow.value = DataState.Loading
|
||||
coVerify(exactly = 0) {
|
||||
vaultRepository.getDecryptedFido2CredentialAutofillViews(any())
|
||||
}
|
||||
|
||||
mutableCiphersStateFlow.value = DataState.Loaded(mockCipherViews)
|
||||
every { cancellationSignal.setOnCancelListener(any()) } just runs
|
||||
every { callback.onResult(capture(captureSlot)) } just runs
|
||||
|
||||
@@ -2531,6 +2531,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||
@Test
|
||||
fun `Fido2AssertionRequest should display loading dialog then request user verification when user is not verified and verification is REQUIRED`() =
|
||||
runTest {
|
||||
setupMockUri()
|
||||
val mockAssertionRequest = createMockFido2CredentialAssertionRequest(number = 1)
|
||||
.copy(cipherId = "mockId-1")
|
||||
val mockFido2CredentialList = createMockSdkFido2CredentialList(number = 1)
|
||||
@@ -2561,7 +2562,17 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||
),
|
||||
)
|
||||
|
||||
val dataState = DataState.Loaded(
|
||||
data = VaultData(
|
||||
cipherViewList = listOf(mockCipherView),
|
||||
folderViewList = listOf(createMockFolderView(number = 1)),
|
||||
collectionViewList = listOf(createMockCollectionView(number = 1)),
|
||||
sendViewList = listOf(createMockSendView(number = 1)),
|
||||
),
|
||||
)
|
||||
val viewModel = createVaultItemListingViewModel()
|
||||
mutableVaultDataStateFlow.value = dataState
|
||||
|
||||
viewModel.eventFlow.test {
|
||||
assertEquals(
|
||||
VaultItemListingState.DialogState.Loading(R.string.loading.asText()),
|
||||
@@ -2582,6 +2593,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||
@Test
|
||||
fun `Fido2AssertionRequest should display loading dialog then request user verification when user is not verified and verification is PREFERED`() =
|
||||
runTest {
|
||||
setupMockUri()
|
||||
val mockAssertionRequest = createMockFido2CredentialAssertionRequest(number = 1)
|
||||
.copy(cipherId = "mockId-1")
|
||||
val mockFido2CredentialList = createMockSdkFido2CredentialList(number = 1)
|
||||
@@ -2612,7 +2624,17 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||
),
|
||||
)
|
||||
|
||||
val dataState = DataState.Loaded(
|
||||
data = VaultData(
|
||||
cipherViewList = listOf(mockCipherView),
|
||||
folderViewList = listOf(createMockFolderView(number = 1)),
|
||||
collectionViewList = listOf(createMockCollectionView(number = 1)),
|
||||
sendViewList = listOf(createMockSendView(number = 1)),
|
||||
),
|
||||
)
|
||||
|
||||
val viewModel = createVaultItemListingViewModel()
|
||||
mutableVaultDataStateFlow.value = dataState
|
||||
viewModel.eventFlow.test {
|
||||
assertEquals(
|
||||
VaultItemListingState.DialogState.Loading(R.string.loading.asText()),
|
||||
@@ -2633,6 +2655,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||
@Test
|
||||
fun `Fido2AssertionRequest should skip user verification when user is not verified and verification is DISCOURAGED`() =
|
||||
runTest {
|
||||
setupMockUri()
|
||||
val mockAssertionRequest = createMockFido2CredentialAssertionRequest(number = 1)
|
||||
.copy(cipherId = "mockId-1")
|
||||
val mockFido2CredentialList = createMockSdkFido2CredentialList(number = 1)
|
||||
@@ -2671,7 +2694,16 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||
)
|
||||
} returns Fido2CredentialAssertionResult.Success(responseJson = "responseJson")
|
||||
|
||||
val dataState = DataState.Loaded(
|
||||
data = VaultData(
|
||||
cipherViewList = listOf(mockCipherView),
|
||||
folderViewList = listOf(createMockFolderView(number = 1)),
|
||||
collectionViewList = listOf(createMockCollectionView(number = 1)),
|
||||
sendViewList = listOf(createMockSendView(number = 1)),
|
||||
),
|
||||
)
|
||||
createVaultItemListingViewModel()
|
||||
mutableVaultDataStateFlow.value = dataState
|
||||
|
||||
coVerify {
|
||||
fido2CredentialManager.isUserVerified
|
||||
@@ -2687,9 +2719,14 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||
@Test
|
||||
fun `Fido2AssertionRequest should show error dialog when assertion options are null`() =
|
||||
runTest {
|
||||
setupMockUri()
|
||||
val mockAssertionRequest = createMockFido2CredentialAssertionRequest(number = 1)
|
||||
.copy(cipherId = "mockId-1")
|
||||
val mockFido2CredentialList = createMockSdkFido2CredentialList(number = 1)
|
||||
val mockCipherView = createMockCipherView(
|
||||
number = 1,
|
||||
fido2Credentials = mockFido2CredentialList,
|
||||
)
|
||||
specialCircumstanceManager.specialCircumstance = SpecialCircumstance.Fido2Assertion(
|
||||
mockAssertionRequest,
|
||||
)
|
||||
@@ -2698,19 +2735,24 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||
.ciphersStateFlow
|
||||
.value
|
||||
.data
|
||||
} returns listOf(
|
||||
createMockCipherView(
|
||||
number = 1,
|
||||
fido2Credentials = mockFido2CredentialList,
|
||||
),
|
||||
)
|
||||
} returns listOf(mockCipherView)
|
||||
every {
|
||||
fido2CredentialManager.getPasskeyAssertionOptionsOrNull(
|
||||
mockAssertionRequest.requestJson,
|
||||
)
|
||||
} returns null
|
||||
|
||||
val dataState = DataState.Loaded(
|
||||
data = VaultData(
|
||||
cipherViewList = listOf(mockCipherView),
|
||||
folderViewList = listOf(createMockFolderView(number = 1)),
|
||||
collectionViewList = listOf(createMockCollectionView(number = 1)),
|
||||
sendViewList = listOf(createMockSendView(number = 1)),
|
||||
),
|
||||
)
|
||||
val viewModel = createVaultItemListingViewModel()
|
||||
mutableVaultDataStateFlow.value = dataState
|
||||
|
||||
assertEquals(
|
||||
VaultItemListingState.DialogState.Fido2OperationFail(
|
||||
title = R.string.an_error_has_occurred.asText(),
|
||||
@@ -2724,9 +2766,14 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||
|
||||
@Test
|
||||
fun `Fido2AssertionRequest should show error dialog when relyingPartyId is null`() = runTest {
|
||||
setupMockUri()
|
||||
val mockAssertionRequest = createMockFido2CredentialAssertionRequest(number = 1)
|
||||
.copy(cipherId = "mockId-1")
|
||||
val mockFido2CredentialList = createMockSdkFido2CredentialList(number = 1)
|
||||
val mockCipherView = createMockCipherView(
|
||||
number = 1,
|
||||
fido2Credentials = mockFido2CredentialList,
|
||||
)
|
||||
specialCircumstanceManager.specialCircumstance = SpecialCircumstance.Fido2Assertion(
|
||||
mockAssertionRequest,
|
||||
)
|
||||
@@ -2735,12 +2782,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||
.ciphersStateFlow
|
||||
.value
|
||||
.data
|
||||
} returns listOf(
|
||||
createMockCipherView(
|
||||
number = 1,
|
||||
fido2Credentials = mockFido2CredentialList,
|
||||
),
|
||||
)
|
||||
} returns listOf(mockCipherView)
|
||||
every {
|
||||
fido2CredentialManager.getPasskeyAssertionOptionsOrNull(
|
||||
mockAssertionRequest.requestJson,
|
||||
@@ -2751,7 +2793,17 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||
relyingPartyId = null,
|
||||
)
|
||||
|
||||
val dataState = DataState.Loaded(
|
||||
data = VaultData(
|
||||
cipherViewList = listOf(mockCipherView),
|
||||
folderViewList = listOf(createMockFolderView(number = 1)),
|
||||
collectionViewList = listOf(createMockCollectionView(number = 1)),
|
||||
sendViewList = listOf(createMockSendView(number = 1)),
|
||||
),
|
||||
)
|
||||
val viewModel = createVaultItemListingViewModel()
|
||||
mutableVaultDataStateFlow.value = dataState
|
||||
|
||||
assertEquals(
|
||||
VaultItemListingState.DialogState.Fido2OperationFail(
|
||||
title = R.string.an_error_has_occurred.asText(),
|
||||
@@ -2766,6 +2818,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||
@Test
|
||||
fun `Fido2AssertionRequest should show error dialog when validateOrigin is not Success`() =
|
||||
runTest {
|
||||
setupMockUri()
|
||||
val mockAssertionRequest = createMockFido2CredentialAssertionRequest(number = 1)
|
||||
.copy(cipherId = "mockId-1")
|
||||
val mockAssertionOptions = createMockPasskeyAssertionOptions(
|
||||
@@ -2773,6 +2826,10 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||
userVerificationRequirement = UserVerificationRequirement.DISCOURAGED,
|
||||
)
|
||||
val mockFido2CredentialList = createMockSdkFido2CredentialList(number = 1)
|
||||
val mockCipherView = createMockCipherView(
|
||||
number = 1,
|
||||
fido2Credentials = mockFido2CredentialList,
|
||||
)
|
||||
specialCircumstanceManager.specialCircumstance = SpecialCircumstance.Fido2Assertion(
|
||||
mockAssertionRequest,
|
||||
)
|
||||
@@ -2781,12 +2838,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||
.ciphersStateFlow
|
||||
.value
|
||||
.data
|
||||
} returns listOf(
|
||||
createMockCipherView(
|
||||
number = 1,
|
||||
fido2Credentials = mockFido2CredentialList,
|
||||
),
|
||||
)
|
||||
} returns listOf(mockCipherView)
|
||||
every {
|
||||
fido2CredentialManager.getPasskeyAssertionOptionsOrNull(
|
||||
requestJson = mockAssertionRequest.requestJson,
|
||||
@@ -2796,7 +2848,16 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||
fido2OriginManager.validateOrigin(any(), any())
|
||||
} returns Fido2ValidateOriginResult.Error.Unknown
|
||||
|
||||
val dataState = DataState.Loaded(
|
||||
data = VaultData(
|
||||
cipherViewList = listOf(mockCipherView),
|
||||
folderViewList = listOf(createMockFolderView(number = 1)),
|
||||
collectionViewList = listOf(createMockCollectionView(number = 1)),
|
||||
sendViewList = listOf(createMockSendView(number = 1)),
|
||||
),
|
||||
)
|
||||
val viewModel = createVaultItemListingViewModel()
|
||||
mutableVaultDataStateFlow.value = dataState
|
||||
|
||||
viewModel.stateFlow.test {
|
||||
assertEquals(
|
||||
@@ -2855,7 +2916,17 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||
.data
|
||||
} returns null
|
||||
|
||||
val dataState = DataState.Loaded(
|
||||
data = VaultData(
|
||||
cipherViewList = emptyList(),
|
||||
folderViewList = listOf(createMockFolderView(number = 1)),
|
||||
collectionViewList = listOf(createMockCollectionView(number = 1)),
|
||||
sendViewList = listOf(createMockSendView(number = 1)),
|
||||
),
|
||||
)
|
||||
val viewModel = createVaultItemListingViewModel()
|
||||
mutableVaultDataStateFlow.value = dataState
|
||||
|
||||
assertEquals(
|
||||
VaultItemListingState.DialogState.Fido2OperationFail(
|
||||
title = R.string.an_error_has_occurred.asText(),
|
||||
@@ -2870,8 +2941,13 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||
@Test
|
||||
fun `Fido2AssertionRequest should show error dialog when cipher state flow data has no matching cipher`() =
|
||||
runTest {
|
||||
setupMockUri()
|
||||
val mockAssertionRequest = createMockFido2CredentialAssertionRequest(number = 1)
|
||||
val mockFido2CredentialList = createMockSdkFido2CredentialList(number = 1)
|
||||
val mockCipherView = createMockCipherView(
|
||||
number = 1,
|
||||
fido2Credentials = mockFido2CredentialList,
|
||||
)
|
||||
specialCircumstanceManager.specialCircumstance = SpecialCircumstance.Fido2Assertion(
|
||||
mockAssertionRequest,
|
||||
)
|
||||
@@ -2880,14 +2956,19 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||
.ciphersStateFlow
|
||||
.value
|
||||
.data
|
||||
} returns listOf(
|
||||
createMockCipherView(
|
||||
number = 1,
|
||||
fido2Credentials = mockFido2CredentialList,
|
||||
} returns listOf(mockCipherView)
|
||||
|
||||
val dataState = DataState.Loaded(
|
||||
data = VaultData(
|
||||
cipherViewList = listOf(mockCipherView),
|
||||
folderViewList = listOf(createMockFolderView(number = 1)),
|
||||
collectionViewList = listOf(createMockCollectionView(number = 1)),
|
||||
sendViewList = listOf(createMockSendView(number = 1)),
|
||||
),
|
||||
)
|
||||
|
||||
val viewModel = createVaultItemListingViewModel()
|
||||
mutableVaultDataStateFlow.value = dataState
|
||||
|
||||
assertEquals(
|
||||
VaultItemListingState.DialogState.Fido2OperationFail(
|
||||
title = R.string.an_error_has_occurred.asText(),
|
||||
@@ -2900,6 +2981,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||
|
||||
@Test
|
||||
fun `Fido2AssertionRequest should skip user verification when user is verified`() = runTest {
|
||||
setupMockUri()
|
||||
val mockAssertionRequest = createMockFido2CredentialAssertionRequest(number = 1)
|
||||
.copy(cipherId = "mockId-1")
|
||||
val mockFido2CredentialList = createMockSdkFido2CredentialList(number = 1)
|
||||
@@ -2932,12 +3014,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||
.ciphersStateFlow
|
||||
.value
|
||||
.data
|
||||
} returns listOf(
|
||||
createMockCipherView(
|
||||
number = 1,
|
||||
fido2Credentials = mockFido2CredentialList,
|
||||
),
|
||||
)
|
||||
} returns listOf(mockCipherView)
|
||||
every {
|
||||
fido2CredentialManager.getPasskeyAssertionOptionsOrNull(
|
||||
mockAssertionRequest.requestJson,
|
||||
@@ -2945,7 +3022,16 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||
} returns createMockPasskeyAssertionOptions(number = 1)
|
||||
every { authRepository.activeUserId } returns "activeUserId"
|
||||
|
||||
val dataState = DataState.Loaded(
|
||||
data = VaultData(
|
||||
cipherViewList = listOf(mockCipherView),
|
||||
folderViewList = listOf(createMockFolderView(number = 1)),
|
||||
collectionViewList = listOf(createMockCollectionView(number = 1)),
|
||||
sendViewList = listOf(createMockSendView(number = 1)),
|
||||
),
|
||||
)
|
||||
createVaultItemListingViewModel()
|
||||
mutableVaultDataStateFlow.value = dataState
|
||||
|
||||
coVerify {
|
||||
fido2CredentialManager.isUserVerified
|
||||
@@ -2959,9 +3045,14 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||
|
||||
@Test
|
||||
fun `Fido2AssertionRequest should show error dialog when active user id is null`() = runTest {
|
||||
setupMockUri()
|
||||
val mockAssertionRequest = createMockFido2CredentialAssertionRequest(number = 1)
|
||||
.copy(cipherId = "mockId-1")
|
||||
val mockFido2CredentialList = createMockSdkFido2CredentialList(number = 1)
|
||||
val mockCipherView = createMockCipherView(
|
||||
number = 1,
|
||||
fido2Credentials = mockFido2CredentialList,
|
||||
)
|
||||
specialCircumstanceManager.specialCircumstance = SpecialCircumstance.Fido2Assertion(
|
||||
mockAssertionRequest,
|
||||
)
|
||||
@@ -2979,12 +3070,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||
.ciphersStateFlow
|
||||
.value
|
||||
.data
|
||||
} returns listOf(
|
||||
createMockCipherView(
|
||||
number = 1,
|
||||
fido2Credentials = mockFido2CredentialList,
|
||||
),
|
||||
)
|
||||
} returns listOf(mockCipherView)
|
||||
every {
|
||||
fido2CredentialManager.getPasskeyAssertionOptionsOrNull(
|
||||
mockAssertionRequest.requestJson,
|
||||
@@ -2992,7 +3078,16 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||
} returns createMockPasskeyAssertionOptions(number = 1)
|
||||
every { authRepository.activeUserId } returns null
|
||||
|
||||
val dataState = DataState.Loaded(
|
||||
data = VaultData(
|
||||
cipherViewList = listOf(mockCipherView),
|
||||
folderViewList = listOf(createMockFolderView(number = 1)),
|
||||
collectionViewList = listOf(createMockCollectionView(number = 1)),
|
||||
sendViewList = listOf(createMockSendView(number = 1)),
|
||||
),
|
||||
)
|
||||
val viewModel = createVaultItemListingViewModel()
|
||||
mutableVaultDataStateFlow.value = dataState
|
||||
|
||||
coVerify(exactly = 0) {
|
||||
fido2CredentialManager.authenticateFido2Credential(
|
||||
@@ -3015,9 +3110,15 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `Fido2AssertionRequest should prompt for master password when passkey is protected and user has master password`() {
|
||||
setupMockUri()
|
||||
val mockAssertionRequest = createMockFido2CredentialAssertionRequest(number = 1)
|
||||
.copy(cipherId = "mockId-1")
|
||||
val mockFido2CredentialList = createMockSdkFido2CredentialList(number = 1)
|
||||
val mockCipherView = createMockCipherView(
|
||||
number = 1,
|
||||
fido2Credentials = mockFido2CredentialList,
|
||||
repromptType = CipherRepromptType.PASSWORD,
|
||||
)
|
||||
specialCircumstanceManager.specialCircumstance = SpecialCircumstance.Fido2Assertion(
|
||||
mockAssertionRequest,
|
||||
)
|
||||
@@ -3035,13 +3136,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||
.ciphersStateFlow
|
||||
.value
|
||||
.data
|
||||
} returns listOf(
|
||||
createMockCipherView(
|
||||
number = 1,
|
||||
fido2Credentials = mockFido2CredentialList,
|
||||
repromptType = CipherRepromptType.PASSWORD,
|
||||
),
|
||||
)
|
||||
} returns listOf(mockCipherView)
|
||||
every {
|
||||
fido2CredentialManager.getPasskeyAssertionOptionsOrNull(
|
||||
mockAssertionRequest.requestJson,
|
||||
@@ -3049,7 +3144,16 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||
} returns createMockPasskeyAssertionOptions(number = 1)
|
||||
every { authRepository.activeUserId } returns null
|
||||
|
||||
val dataState = DataState.Loaded(
|
||||
data = VaultData(
|
||||
cipherViewList = listOf(mockCipherView),
|
||||
folderViewList = listOf(createMockFolderView(number = 1)),
|
||||
collectionViewList = listOf(createMockCollectionView(number = 1)),
|
||||
sendViewList = listOf(createMockSendView(number = 1)),
|
||||
),
|
||||
)
|
||||
val viewModel = createVaultItemListingViewModel()
|
||||
mutableVaultDataStateFlow.value = dataState
|
||||
|
||||
assertEquals(
|
||||
VaultItemListingState.DialogState.Fido2MasterPasswordPrompt(
|
||||
@@ -3063,6 +3167,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||
@Test
|
||||
fun `Fido2AssertionRequest should not re-prompt master password when user does not have a master password`() =
|
||||
runTest {
|
||||
setupMockUri()
|
||||
val mockAssertionRequest = createMockFido2CredentialAssertionRequest(number = 1)
|
||||
.copy(cipherId = "mockId-1")
|
||||
val mockFido2CredentialList = createMockSdkFido2CredentialList(number = 1)
|
||||
@@ -3117,7 +3222,16 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
|
||||
)
|
||||
} returns Fido2CredentialAssertionResult.Success("responseJson")
|
||||
|
||||
val dataState = DataState.Loaded(
|
||||
data = VaultData(
|
||||
cipherViewList = listOf(mockCipherView),
|
||||
folderViewList = listOf(createMockFolderView(number = 1)),
|
||||
collectionViewList = listOf(createMockCollectionView(number = 1)),
|
||||
sendViewList = listOf(createMockSendView(number = 1)),
|
||||
),
|
||||
)
|
||||
createVaultItemListingViewModel()
|
||||
mutableVaultDataStateFlow.value = dataState
|
||||
|
||||
coVerify {
|
||||
fido2CredentialManager.authenticateFido2Credential(
|
||||
|
||||
Reference in New Issue
Block a user