Add screen lock protection to delete account flow.

This commit is contained in:
Greyson Parrelli
2026-09-18 12:46:36 -04:00
parent dcb6db177f
commit 8134c3b64f
6 changed files with 52 additions and 3 deletions
@@ -78,7 +78,13 @@ class AccountSettingsFragment : ComposeFragment() {
onAuthenticationFailed = { viewModel.onEvent(AccountSettingsEvent.AuthenticationFailed) }
)
CollectActions(viewModel.actions) { action -> handleAction(action, removalBiometrics, signalLoginBiometrics) }
val deleteAccountBiometrics = rememberBiometricsAuthentication(
promptTitle = stringResource(AppSettingsR.string.AccountSettingsFragment__unlock_to_confirm_its_you),
educationSheetMessage = stringResource(AppSettingsR.string.AccountSettingsFragment__to_delete_your_account_confirm_its_you),
onAuthenticationFailed = { viewModel.onEvent(AccountSettingsEvent.AuthenticationFailed) }
)
CollectActions(viewModel.actions) { action -> handleAction(action, removalBiometrics, signalLoginBiometrics, deleteAccountBiometrics) }
AccountSettingsScreen(
state = state,
@@ -86,7 +92,12 @@ class AccountSettingsFragment : ComposeFragment() {
)
}
private fun handleAction(action: AccountSettingsAction, removalBiometrics: BiometricsAuthentication, signalLoginBiometrics: BiometricsAuthentication) {
private fun handleAction(
action: AccountSettingsAction,
removalBiometrics: BiometricsAuthentication,
signalLoginBiometrics: BiometricsAuthentication,
deleteAccountBiometrics: BiometricsAuthentication
) {
when (action) {
AccountSettingsAction.NavigateBack -> requireActivity().onBackPressedDispatcher.onBackPressed()
AccountSettingsAction.LaunchCreatePinFlow -> pinFlowLauncher.launch(CreateSvrPinActivity.getIntentForPinCreate(requireContext()))
@@ -118,6 +129,11 @@ class AccountSettingsFragment : ComposeFragment() {
AccountSettingsAction.NavigateToChangePhoneNumber -> findNavController().safeNavigate(R.id.action_accountSettingsFragment_to_changePhoneNumberFragment)
AccountSettingsAction.NavigateToDeviceTransfer -> findNavController().safeNavigate(R.id.action_accountSettingsFragment_to_oldDeviceTransferActivity)
AccountSettingsAction.NavigateToExportAccountData -> findNavController().safeNavigate(R.id.action_accountSettingsFragment_to_exportAccountFragment)
AccountSettingsAction.AuthenticateToDeleteAccount -> {
deleteAccountBiometrics.withBiometricsAuthentication {
viewModel.onEvent(AccountSettingsEvent.DeleteAccountAuthenticated)
}
}
AccountSettingsAction.NavigateToDeleteAccount -> findNavController().safeNavigate(R.id.action_accountSettingsFragment_to_deleteAccountFragment)
AccountSettingsAction.OpenPlayStore -> PlayStoreUtil.openPlayStoreOrOurApkDownloadPage(requireContext())
AccountSettingsAction.LaunchReRegistration -> startActivity(RegistrationActivity.newIntentForReRegistration(requireContext()))
@@ -138,6 +138,9 @@ class AccountSettingsViewModel(
_actions.send(AccountSettingsAction.ShowDataWipeFailed)
}
AccountSettingsEvent.DeleteAccountClicked -> {
_actions.send(AccountSettingsAction.AuthenticateToDeleteAccount)
}
AccountSettingsEvent.DeleteAccountAuthenticated -> {
_actions.send(AccountSettingsAction.NavigateToDeleteAccount)
}
AccountSettingsEvent.DialogDismissed -> {
@@ -591,6 +591,26 @@ class AccountSettingsViewModelTest {
assertThat(actions.last()).isEqualTo(AccountSettingsAction.NavigateToSignalLoginDetails)
}
@Test
fun `DeleteAccountClicked asks for the screen lock first`() = runTest(testDispatcher) {
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(AccountSettingsEvent.DeleteAccountClicked)
assertThat(actions.last()).isEqualTo(AccountSettingsAction.AuthenticateToDeleteAccount)
}
@Test
fun `DeleteAccountAuthenticated opens the delete account screen`() = runTest(testDispatcher) {
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(AccountSettingsEvent.DeleteAccountAuthenticated)
assertThat(actions.last()).isEqualTo(AccountSettingsAction.NavigateToDeleteAccount)
}
private fun methods(vararg methods: TwoFactorMethod) = AccountSettingsRepository.TwoFactorMethodsResult.Success(methods.toList())
private fun createViewModel(): AccountSettingsViewModel = AccountSettingsViewModel(repository)