[PM-23278] Check and show if user needs KDF update on vault load.

This commit is contained in:
André Bispo
2025-09-18 10:56:16 +01:00
parent d07e8f9ae2
commit 7c5a6ac2d8
2 changed files with 74 additions and 1 deletions

View File

@@ -3,6 +3,7 @@ package com.x8bit.bitwarden.ui.vault.feature.vault
import android.os.Parcelable
import androidx.compose.ui.graphics.Color
import androidx.lifecycle.viewModelScope
import com.bitwarden.core.data.manager.toast.ToastManager
import com.bitwarden.core.data.repository.model.DataState
import com.bitwarden.core.util.persistentListOfNotNull
import com.bitwarden.data.repository.util.baseIconUrl
@@ -24,6 +25,7 @@ import com.bitwarden.vault.DecryptCipherListResult
import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.auth.repository.model.LogoutReason
import com.x8bit.bitwarden.data.auth.repository.model.SwitchAccountResult
import com.x8bit.bitwarden.data.auth.repository.model.UpdateKdfMinimumsResult
import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.auth.repository.model.ValidatePasswordResult
import com.x8bit.bitwarden.data.platform.datasource.disk.model.FlightRecorderDataSet
@@ -97,6 +99,7 @@ class VaultViewModel @Inject constructor(
private val reviewPromptManager: ReviewPromptManager,
private val specialCircumstanceManager: SpecialCircumstanceManager,
private val networkConnectionManager: NetworkConnectionManager,
private val toastManager: ToastManager,
snackbarRelayManager: SnackbarRelayManager,
) : BaseViewModel<VaultState, VaultEvent, VaultAction>(
initialState = run {
@@ -256,6 +259,10 @@ class VaultViewModel @Inject constructor(
VaultAction.ShareAllCipherDecryptionErrorsClick -> {
handleShareAllCipherDecryptionErrorsClick()
}
is VaultAction.KdfUpdatePasswordRepromptSubmit -> {
handleKdfUpdatePasswordRepromptSubmit(action)
}
}
}
@@ -909,7 +916,8 @@ class VaultViewModel @Inject constructor(
}
val shouldShowDecryptionAlert = !state.hasShownDecryptionFailureAlert &&
vaultData.data.decryptCipherListResult.failures.isNotEmpty()
vaultData.data.decryptCipherListResult.failures.isNotEmpty() &&
state.dialog == null
updateVaultState(
vaultData = vaultData.data,
@@ -929,6 +937,21 @@ class VaultViewModel @Inject constructor(
state.hasShownDecryptionFailureAlert
},
)
// Check if user needs to update kdf settings to minimums
viewModelScope.launch {
if (authRepository.needsKdfUpdateToMinimums()) {
mutableStateFlow.update { currentState ->
@Suppress("MaxLineLength")
currentState.copy(
dialog = VaultState.DialogState.VaultLoadKdfUpdateRequired(
title = BitwardenString.update_your_encryption_settings.asText(),
message = BitwardenString.the_new_recommended_encryption_settings_will_improve_your_account_security_desc_long.asText(),
),
)
}
}
}
}
private fun updateVaultState(
@@ -1089,6 +1112,48 @@ class VaultViewModel @Inject constructor(
is GetCipherResult.Success -> result.cipherView
}
private fun handleKdfUpdatePasswordRepromptSubmit(
action: VaultAction.KdfUpdatePasswordRepromptSubmit,
) {
mutableStateFlow.update {
it.copy(dialog = null)
}
viewModelScope.launch {
val result = authRepository.updateKdfToMinimumsIfNeeded(action.password)
when (result) {
UpdateKdfMinimumsResult.AccountNotFound -> {
showGenericError()
Timber.e(message = "Failed to update kdf to minimums: Account not found")
}
UpdateKdfMinimumsResult.ActiveAccountNotFound -> {
showGenericError()
Timber.e(message = "Failed to update kdf to minimums: Active account not found")
}
is UpdateKdfMinimumsResult.Error -> {
showGenericError(error = result.error)
Timber.e(message = "Failed to update kdf to minimums: ${result.error}")
}
UpdateKdfMinimumsResult.Success -> {
toastManager.show(messageId = BitwardenString.encryption_settings_updated)
}
}
}
}
private fun showGenericError(
error: Throwable? = null,
) {
mutableStateFlow.update {
it.copy(
dialog = VaultState.DialogState.Error(
BitwardenString.an_error_has_occurred.asText(),
BitwardenString.generic_error_message.asText(),
error = error,
),
)
}
}
}
/**
@@ -1724,6 +1789,13 @@ sealed class VaultAction {
val selectedCipherId: String,
) : VaultAction()
/**
* Click to submit the update kdf password reprompt form.
*/
data class KdfUpdatePasswordRepromptSubmit(
val password: String,
) : VaultAction()
/**
* Click to share all cipher decryption error details.
*/

View File

@@ -1085,6 +1085,7 @@ Do you want to switch to this account?</string>
<string name="advanced_option_with_increased_risk_of_exposing_credentials">“Starts with” is an advanced option with increased risk of exposing credentials.</string>
<string name="advanced_option_increased_risk_exposing_credentials_used_incorrectly">“Regular expression” is an advanced option with increased risk of exposing credentials if used incorrectly.</string>
<string name="later">Later</string>
<string name="encryption_settings_updated">Encryption settings updated</string>
<string name="update_your_encryption_settings">Update your encryption settings</string>
<string name="the_new_recommended_encryption_settings_will_improve_your_account_security_desc_long">The new recommended encryption settings will improve your account security. Enter your master password to update now.</string>
</resources>