Skip to content

Commit 221f5b5

Browse files
committed
[PM-15863] Request master password before revealing private SSH key
Adds a master password prompt before revealing the private SSH key if the content requires reprompt.
1 parent 3329dfa commit 221f5b5

File tree

2 files changed

+36
-8
lines changed

2 files changed

+36
-8
lines changed

app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModel.kt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,16 @@ class VaultItemViewModel @Inject constructor(
804804
action: VaultItemAction.ItemType.SshKey.PrivateKeyVisibilityClicked,
805805
) {
806806
onSshKeyContent { content, sshKey ->
807+
if (content.common.requiresReprompt) {
808+
updateDialogState(
809+
VaultItemState.DialogState.MasterPasswordDialog(
810+
action = PasswordRepromptAction.ViewPrivateKeyClicked(
811+
isVisible = action.isVisible,
812+
),
813+
),
814+
)
815+
return@onSshKeyContent
816+
}
807817
mutableStateFlow.update { currentState ->
808818
currentState.copy(
809819
viewState = content.copy(
@@ -2231,4 +2241,18 @@ sealed class PasswordRepromptAction : Parcelable {
22312241
override val vaultItemAction: VaultItemAction
22322242
get() = VaultItemAction.Common.RestoreVaultItemClick
22332243
}
2244+
2245+
/**
2246+
* Indicates that we should launch the
2247+
* [VaultItemAction.ItemType.SshKey.PrivateKeyVisibilityClicked] upon password validation.
2248+
*/
2249+
@Parcelize
2250+
data class ViewPrivateKeyClicked(
2251+
val isVisible: Boolean,
2252+
) : PasswordRepromptAction() {
2253+
override val vaultItemAction: VaultItemAction
2254+
get() = VaultItemAction.ItemType.SshKey.PrivateKeyVisibilityClicked(
2255+
isVisible = isVisible,
2256+
)
2257+
}
22342258
}

app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModelTest.kt

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2492,9 +2492,6 @@ class VaultItemViewModelTest : BaseViewModelTest() {
24922492
@Test
24932493
fun `on PrivateKeyVisibilityClick should show password dialog when re-prompt is required`() =
24942494
runTest {
2495-
val sshKeyViewState = createViewState(
2496-
common = DEFAULT_COMMON.copy(requiresReprompt = false),
2497-
)
24982495
val sshKeyState = DEFAULT_STATE.copy(viewState = SSH_KEY_VIEW_STATE)
24992496
every {
25002497
mockCipherView.toViewState(
@@ -2518,15 +2515,22 @@ class VaultItemViewModelTest : BaseViewModelTest() {
25182515
)
25192516
assertEquals(
25202517
sshKeyState.copy(
2521-
viewState = sshKeyViewState.copy(
2522-
common = DEFAULT_COMMON,
2523-
type = DEFAULT_SSH_KEY_TYPE.copy(
2524-
showPrivateKey = true,
2525-
),
2518+
dialog = VaultItemState.DialogState.MasterPasswordDialog(
2519+
PasswordRepromptAction.ViewPrivateKeyClicked(isVisible = true),
25262520
),
25272521
),
25282522
viewModel.stateFlow.value,
25292523
)
2524+
verify(exactly = 1) {
2525+
mockCipherView.toViewState(
2526+
previousState = null,
2527+
isPremiumUser = true,
2528+
hasMasterPassword = true,
2529+
totpCodeItemData = null,
2530+
canDelete = true,
2531+
canAssignToCollections = true,
2532+
)
2533+
}
25302534
}
25312535

25322536
@Test

0 commit comments

Comments
 (0)