PM-15062 Checking if the user has a no longer supported biometric as their only way of unlocking their account. (#4338)

This commit is contained in:
Dave Severns
2024-11-20 15:45:26 -05:00
committed by GitHub
parent 3092ba1fc6
commit ec8e934bf4
10 changed files with 194 additions and 20 deletions

View File

@@ -1266,17 +1266,17 @@ private const val USER_STATE_JSON = """
"kdfIterations": 600000,
"kdfMemory": 16,
"kdfParallelism": 4,
"accountDecryptionOptions": {
"HasMasterPassword": true,
"TrustedDeviceOption": {
"EncryptedPrivateKey": "encryptedPrivateKey",
"EncryptedUserKey": "encryptedUserKey",
"HasAdminApproval": true,
"HasLoginApprovingDevice": true,
"HasManageResetPasswordPermission": true
"userDecryptionOptions": {
"hasMasterPassword": true,
"trustedDeviceOption": {
"encryptedPrivateKey": "encryptedPrivateKey",
"encryptedUserKey": "encryptedUserKey",
"hasAdminApproval": true,
"hasLoginApprovingDevice": true,
"hasManageResetPasswordPermission": true
},
"KeyConnectorOption": {
"KeyConnectorUrl": "keyConnectorUrl"
"keyConnectorOption": {
"keyConnectorUrl": "keyConnectorUrl"
}
}
},

View File

@@ -541,6 +541,51 @@ class VaultUnlockScreenTest : BaseComposeTest() {
.assertDoesNotExist()
composeTestRule.onNodeWithText("Unlock").assertDoesNotExist()
}
@Test
fun `biometrics not supported dialog shows correctly`() {
mutableStateFlow.update {
it.copy(dialog = VaultUnlockState.VaultUnlockDialog.BiometricsNoLongerSupported)
}
composeTestRule
.onNodeWithText("Biometrics are no longer supported on this device")
.assertIsDisplayed()
}
@Test
fun `DismissBiometricsNoLongerSupportedDialog should be sent when dialog is dismissed`() {
mutableStateFlow.update {
it.copy(dialog = VaultUnlockState.VaultUnlockDialog.BiometricsNoLongerSupported)
}
composeTestRule
.onNodeWithText("Biometrics are no longer supported on this device")
.assertIsDisplayed()
composeTestRule
.onNodeWithText("Ok")
.performClick()
verify {
viewModel.trySendAction(VaultUnlockAction.DismissBiometricsNoLongerSupportedDialog)
}
}
@Suppress("MaxLineLength")
@Test
fun `when biometric is needed but no longer supported BiometricsNoLongerSupported action is sent`() {
every { biometricsManager.isBiometricsSupported } returns false
mutableStateFlow.update {
it.copy(
isBiometricEnabled = true,
hasMasterPassword = false,
vaultUnlockType = VaultUnlockType.MASTER_PASSWORD,
)
}
composeTestRule.waitForIdle()
verify {
viewModel.trySendAction(VaultUnlockAction.BiometricsNoLongerSupported)
}
}
}
private const val DEFAULT_ENVIRONMENT_URL: String = "vault.bitwarden.com"
@@ -588,4 +633,5 @@ private val DEFAULT_STATE: VaultUnlockState = VaultUnlockState(
showBiometricInvalidatedMessage = false,
userId = ACTIVE_ACCOUNT_SUMMARY.userId,
vaultUnlockType = VaultUnlockType.MASTER_PASSWORD,
hasMasterPassword = true,
)

View File

@@ -1227,6 +1227,35 @@ class VaultUnlockViewModelTest : BaseViewModelTest() {
verify { fido2CredentialManager.isUserVerified = false }
}
@Test
fun `on BiometricsNoLongerSupported should show correct dialog state`() {
val viewModel = createViewModel()
viewModel.trySendAction(VaultUnlockAction.BiometricsNoLongerSupported)
assertEquals(
DEFAULT_STATE.copy(
dialog = VaultUnlockState.VaultUnlockDialog.BiometricsNoLongerSupported,
),
viewModel.stateFlow.value,
)
}
@Suppress("MaxLineLength")
@Test
fun `on DismissBiometricsNoLongerSupportedDialog should dismiss dialog state and log the user out`() {
val viewModel = createViewModel()
viewModel.trySendAction(VaultUnlockAction.DismissBiometricsNoLongerSupportedDialog)
assertEquals(
DEFAULT_STATE.copy(
dialog = null,
),
viewModel.stateFlow.value,
)
verify(exactly = 1) {
authRepository.logout()
authRepository.hasPendingAccountAddition = true
}
}
private fun createViewModel(
state: VaultUnlockState? = null,
unlockType: UnlockType = UnlockType.STANDARD,
@@ -1275,6 +1304,7 @@ private val DEFAULT_STATE: VaultUnlockState = VaultUnlockState(
showBiometricInvalidatedMessage = false,
userId = USER_ID,
vaultUnlockType = VaultUnlockType.MASTER_PASSWORD,
hasMasterPassword = true,
)
private val TRUSTED_DEVICE: UserState.TrustedDevice = UserState.TrustedDevice(