Skip to content

Commit

Permalink
Add SSH key cipher type
Browse files Browse the repository at this point in the history
  • Loading branch information
SaintPatrck committed Oct 25, 2024
1 parent 0960f61 commit 304e96e
Show file tree
Hide file tree
Showing 73 changed files with 2,444 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ private const val CARD_DIGITS_DISPLAYED: Int = 4
val CipherView.subtitle: String?
get() = when (type) {
CipherType.LOGIN -> this.login?.username.orEmpty()
CipherType.SECURE_NOTE -> null
CipherType.CARD -> {
this
.card
Expand All @@ -45,6 +44,10 @@ val CipherView.subtitle: String?
}
}
}

CipherType.SECURE_NOTE,
CipherType.SSH_KEY,
-> null
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ data class CipherJsonRequest(
@SerialName("secureNote")
val secureNote: SyncResponseJson.Cipher.SecureNote?,

@SerialName("sshKey")
val sshKey: SyncResponseJson.Cipher.SshKey?,

@SerialName("folderId")
val folderId: String?,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ enum class CipherTypeJson {
*/
@SerialName("4")
IDENTITY,

/**
* A SSH key.
*/
@SerialName("5")
SSH_KEY,
}

@Keep
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,9 @@ data class SyncResponseJson(
@SerialName("identity")
val identity: Identity?,

@SerialName("sshKey")
val sshKey: SshKey?,

@SerialName("collectionIds")
val collectionIds: List<String>?,

Expand Down Expand Up @@ -718,6 +721,25 @@ data class SyncResponseJson(
)
}

/**
* Represents a SSH key in the vault response.
*
* @property publicKey The public key of the SSH key.
* @property privateKey The private key of the SSH key.
* @property keyFingerprint The key fingerprint of the SSH key.
*/
@Serializable
data class SshKey(
@SerialName("publicKey")
val publicKey: String?,

@SerialName("privateKey")
val privateKey: String?,

@SerialName("keyFingerprint")
val keyFingerprint: String?,
)

/**
* Represents password history in the vault response.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import com.bitwarden.vault.LoginUri
import com.bitwarden.vault.PasswordHistory
import com.bitwarden.vault.SecureNote
import com.bitwarden.vault.SecureNoteType
import com.bitwarden.vault.SshKey
import com.bitwarden.vault.UriMatchType
import com.x8bit.bitwarden.data.platform.util.SpecialCharWithPrecedenceComparator
import com.x8bit.bitwarden.data.vault.datasource.network.model.AttachmentJsonRequest
Expand Down Expand Up @@ -55,6 +56,7 @@ fun Cipher.toEncryptedNetworkCipher(): CipherJsonRequest =
isFavorite = favorite,
card = card?.toEncryptedNetworkCard(),
key = key,
sshKey = sshKey?.toEncryptedNetworkSshKey(),
)

/**
Expand All @@ -77,6 +79,7 @@ fun Cipher.toEncryptedNetworkCipherResponse(): SyncResponseJson.Cipher =
isFavorite = favorite,
card = card?.toEncryptedNetworkCard(),
attachments = attachments?.toNetworkAttachmentList(),
sshKey = sshKey?.toEncryptedNetworkSshKey(),
shouldOrganizationUseTotp = organizationUseTotp,
shouldEdit = edit,
revisionDate = ZonedDateTime.ofInstant(revisionDate, ZoneOffset.UTC),
Expand All @@ -102,6 +105,13 @@ private fun Card.toEncryptedNetworkCard(): SyncResponseJson.Cipher.Card =
brand = brand,
)

private fun SshKey.toEncryptedNetworkSshKey(): SyncResponseJson.Cipher.SshKey =
SyncResponseJson.Cipher.SshKey(
publicKey = publicKey,
privateKey = privateKey,
keyFingerprint = fingerprint,
)

/**
* Converts a list of Bitwarden SDK [Field] objects to a corresponding
* list of [SyncResponseJson.Cipher.Field] objects.
Expand Down Expand Up @@ -309,6 +319,7 @@ private fun CipherType.toNetworkCipherType(): CipherTypeJson =
CipherType.SECURE_NOTE -> CipherTypeJson.SECURE_NOTE
CipherType.CARD -> CipherTypeJson.CARD
CipherType.IDENTITY -> CipherTypeJson.IDENTITY
CipherType.SSH_KEY -> CipherTypeJson.SSH_KEY
}

/**
Expand All @@ -334,6 +345,7 @@ fun SyncResponseJson.Cipher.toEncryptedSdkCipher(): Cipher =
type = type.toSdkCipherType(),
login = login?.toSdkLogin(),
identity = identity?.toSdkIdentity(),
sshKey = sshKey?.toSdkSshKey(),
card = card?.toSdkCard(),
secureNote = secureNote?.toSdkSecureNote(),
favorite = isFavorite,
Expand Down Expand Up @@ -432,6 +444,17 @@ fun SyncResponseJson.Cipher.SecureNote.toSdkSecureNote(): SecureNote =
},
)

/**
* Transforms a [SyncResponseJson.Cipher.SshKey] into
* the corresponding Bitwarden SDK [SshKey].
*/
fun SyncResponseJson.Cipher.SshKey.toSdkSshKey(): SshKey =
SshKey(
publicKey = publicKey,
privateKey = privateKey,
fingerprint = keyFingerprint,
)

/**
* Transforms a list of [SyncResponseJson.Cipher.Login.Uri] into
* a corresponding list of Bitwarden SDK [LoginUri].
Expand Down Expand Up @@ -517,6 +540,7 @@ fun CipherTypeJson.toSdkCipherType(): CipherType =
CipherTypeJson.SECURE_NOTE -> CipherType.SECURE_NOTE
CipherTypeJson.CARD -> CipherType.CARD
CipherTypeJson.IDENTITY -> CipherType.IDENTITY
CipherTypeJson.SSH_KEY -> CipherType.SSH_KEY
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ private const val SEARCH_TYPE_VAULT_TRASH: String = "search_type_vault_trash"
private const val SEARCH_TYPE_VAULT_VERIFICATION_CODES: String =
"search_type_vault_verification_codes"
private const val SEARCH_TYPE_ID: String = "search_type_id"
private const val SEARCH_TYPE_VAULT_SSH_KEYS: String = "search_type_vault_ssh_keys"

private const val SEARCH_ROUTE_PREFIX: String = "search"
private const val SEARCH_ROUTE: String = "$SEARCH_ROUTE_PREFIX/{$SEARCH_TYPE}/{$SEARCH_TYPE_ID}"
Expand Down Expand Up @@ -122,6 +123,7 @@ private fun SearchType.toTypeString(): String =
SearchType.Vault.SecureNotes -> SEARCH_TYPE_VAULT_SECURE_NOTES
SearchType.Vault.Trash -> SEARCH_TYPE_VAULT_TRASH
SearchType.Vault.VerificationCodes -> SEARCH_TYPE_VAULT_VERIFICATION_CODES
SearchType.Vault.SshKeys -> SEARCH_TYPE_VAULT_SSH_KEYS
}

private fun SearchType.toIdOrNull(): String? =
Expand All @@ -139,4 +141,5 @@ private fun SearchType.toIdOrNull(): String? =
SearchType.Vault.SecureNotes -> null
SearchType.Vault.Trash -> null
SearchType.Vault.VerificationCodes -> null
SearchType.Vault.SshKeys -> null
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.x8bit.bitwarden.data.auth.repository.model.ValidatePasswordResult
import com.x8bit.bitwarden.data.autofill.accessibility.manager.AccessibilitySelectionManager
import com.x8bit.bitwarden.data.autofill.manager.AutofillSelectionManager
import com.x8bit.bitwarden.data.autofill.model.AutofillSelectionData
import com.x8bit.bitwarden.data.platform.annotation.OmitFromCoverage
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
import com.x8bit.bitwarden.data.platform.manager.SpecialCircumstanceManager
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
Expand Down Expand Up @@ -876,6 +877,7 @@ sealed class SearchTypeData : Parcelable {
* Indicates that we should be searching vault items.
*/
@Parcelize
@OmitFromCoverage
sealed class Vault : SearchTypeData() {
/**
* Indicates that we should be searching all vault items.
Expand Down Expand Up @@ -924,6 +926,16 @@ sealed class SearchTypeData : Parcelable {
.concat(R.string.secure_notes.asText())
}

/**
* Indicates that we should be searching only ssh key ciphers.
*/
data object SshKeys : Vault() {
override val title: Text
get() = R.string.search.asText()
.concat(" ".asText())
.concat(R.string.ssh_keys.asText())
}

/**
* Indicates that we should be searching only ciphers in the given collection.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ sealed class SearchType : Parcelable {
*/
data object SecureNotes : Vault()

/**
* Indicates that we should be searching only SSH key ciphers.
*/
data object SshKeys : Vault()

/**
* Indicates that we should be searching only ciphers in the given collection.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ fun SearchTypeData.updateWithAdditionalDataIfNecessary(
SearchTypeData.Vault.SecureNotes -> this
SearchTypeData.Vault.Trash -> this
SearchTypeData.Vault.VerificationCodes -> this
SearchTypeData.Vault.SshKeys -> this
}

/**
Expand Down Expand Up @@ -114,6 +115,7 @@ private fun CipherView.filterBySearchType(
is SearchTypeData.Vault.Identities -> type == CipherType.IDENTITY && deletedDate == null
is SearchTypeData.Vault.Logins -> type == CipherType.LOGIN && deletedDate == null
is SearchTypeData.Vault.SecureNotes -> type == CipherType.SECURE_NOTE && deletedDate == null
is SearchTypeData.Vault.SshKeys -> type == CipherType.SSH_KEY && deletedDate == null
is SearchTypeData.Vault.VerificationCodes -> login?.totp != null && deletedDate == null
is SearchTypeData.Vault.Trash -> deletedDate != null
}
Expand Down Expand Up @@ -255,6 +257,7 @@ private val CipherType.iconRes: Int
CipherType.SECURE_NOTE -> R.drawable.ic_note
CipherType.CARD -> R.drawable.ic_payment_card
CipherType.IDENTITY -> R.drawable.ic_id_card
CipherType.SSH_KEY -> R.drawable.ic_ssh_key
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ fun SearchType.toSearchTypeData(): SearchTypeData =
SearchType.Vault.SecureNotes -> SearchTypeData.Vault.SecureNotes
SearchType.Vault.Trash -> SearchTypeData.Vault.Trash
SearchType.Vault.VerificationCodes -> SearchTypeData.Vault.VerificationCodes
SearchType.Vault.SshKeys -> SearchTypeData.Vault.SshKeys
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,24 @@ import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditCardTyp
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditCommonHandlers
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditIdentityTypeHandlers
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditLoginTypeHandlers
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditSshKeyTypeHandlers
import kotlinx.collections.immutable.toImmutableList

/**
* The top level content UI state for the [VaultAddEditScreen].
*/
@Composable
@Suppress("LongMethod")
@Suppress("LongMethod", "CyclomaticComplexMethod")
fun VaultAddEditContent(
state: VaultAddEditState.ViewState.Content,
isAddItemMode: Boolean,
typeOptions: List<VaultAddEditState.ItemTypeOption>,
onTypeOptionClicked: (VaultAddEditState.ItemTypeOption) -> Unit,
commonTypeHandlers: VaultAddEditCommonHandlers,
loginItemTypeHandlers: VaultAddEditLoginTypeHandlers,
identityItemTypeHandlers: VaultAddEditIdentityTypeHandlers,
cardItemTypeHandlers: VaultAddEditCardTypeHandlers,
sshKeyItemTypeHandlers: VaultAddEditSshKeyTypeHandlers,
modifier: Modifier = Modifier,
permissionsManager: PermissionsManager,
) {
Expand All @@ -45,6 +48,7 @@ fun VaultAddEditContent(
is VaultAddEditState.ViewState.Content.ItemType.SecureNotes -> Unit
is VaultAddEditState.ViewState.Content.ItemType.Card -> Unit
is VaultAddEditState.ViewState.Content.ItemType.Identity -> Unit
is VaultAddEditState.ViewState.Content.ItemType.SshKey -> Unit
is VaultAddEditState.ViewState.Content.ItemType.Login -> {
loginItemTypeHandlers.onSetupTotpClick(isGranted)
}
Expand Down Expand Up @@ -77,6 +81,7 @@ fun VaultAddEditContent(
item {
Spacer(modifier = Modifier.height(8.dp))
TypeOptionsItem(
entries = typeOptions,
itemType = state.type,
onTypeOptionClicked = onTypeOptionClicked,
modifier = Modifier
Expand Down Expand Up @@ -131,6 +136,15 @@ fun VaultAddEditContent(
commonTypeHandlers = commonTypeHandlers,
)
}

is VaultAddEditState.ViewState.Content.ItemType.SshKey -> {
vaultAddEditSshKeyItems(
commonState = state.common,
sshKeyState = state.type,
commonTypeHandlers = commonTypeHandlers,
sshKeyTypeHandlers = sshKeyItemTypeHandlers,
)
}
}

item {
Expand All @@ -141,12 +155,12 @@ fun VaultAddEditContent(

@Composable
private fun TypeOptionsItem(
entries: List<VaultAddEditState.ItemTypeOption>,
itemType: VaultAddEditState.ViewState.Content.ItemType,
onTypeOptionClicked: (VaultAddEditState.ItemTypeOption) -> Unit,
modifier: Modifier = Modifier,
) {
val possibleMainStates = VaultAddEditState.ItemTypeOption.entries.toList()
val optionsWithStrings = possibleMainStates.associateWith { stringResource(id = it.labelRes) }
val optionsWithStrings = entries.associateWith { stringResource(id = it.labelRes) }

BitwardenMultiSelectButton(
label = stringResource(id = R.string.type),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ private const val LOGIN: String = "login"
private const val CARD: String = "card"
private const val IDENTITY: String = "identity"
private const val SECURE_NOTE: String = "secure_note"
private const val SSH_KEY: String = "ssh_key"
private const val ADD_ITEM_TYPE: String = "vault_add_item_type"

private const val ADD_EDIT_ITEM_PREFIX: String = "vault_add_edit_item"
Expand Down Expand Up @@ -127,6 +128,7 @@ private fun VaultItemCipherType.toTypeString(): String =
VaultItemCipherType.CARD -> CARD
VaultItemCipherType.IDENTITY -> IDENTITY
VaultItemCipherType.SECURE_NOTE -> SECURE_NOTE
VaultItemCipherType.SSH_KEY -> SSH_KEY
}

private fun String.toVaultItemCipherType(): VaultItemCipherType =
Expand All @@ -135,6 +137,7 @@ private fun String.toVaultItemCipherType(): VaultItemCipherType =
CARD -> VaultItemCipherType.CARD
IDENTITY -> VaultItemCipherType.IDENTITY
SECURE_NOTE -> VaultItemCipherType.SECURE_NOTE
SSH_KEY -> VaultItemCipherType.SSH_KEY
else -> throw IllegalStateException(
"Edit Item string arguments for VaultAddEditNavigation must match!",
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditCardTyp
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditCommonHandlers
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditIdentityTypeHandlers
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditLoginTypeHandlers
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditSshKeyTypeHandlers
import com.x8bit.bitwarden.ui.vault.feature.addedit.handlers.VaultAddEditUserVerificationHandlers

/**
Expand Down Expand Up @@ -155,6 +156,10 @@ fun VaultAddEditScreen(
VaultAddEditCardTypeHandlers.create(viewModel = viewModel)
}

val sshKeyItemTypeHandlers = remember(viewModel) {
VaultAddEditSshKeyTypeHandlers.create(viewModel = viewModel)
}

val confirmDeleteClickAction = remember(viewModel) {
{ viewModel.trySendAction(VaultAddEditAction.Common.ConfirmDeleteClick) }
}
Expand Down Expand Up @@ -321,6 +326,7 @@ fun VaultAddEditScreen(
VaultAddEditContent(
state = viewState,
isAddItemMode = state.isAddItemMode,
typeOptions = state.supportedItemTypes,
onTypeOptionClicked = remember(viewModel) {
{ viewModel.trySendAction(VaultAddEditAction.Common.TypeOptionSelect(it)) }
},
Expand All @@ -329,6 +335,7 @@ fun VaultAddEditScreen(
permissionsManager = permissionsManager,
identityItemTypeHandlers = identityItemTypeHandlers,
cardItemTypeHandlers = cardItemTypeHandlers,
sshKeyItemTypeHandlers = sshKeyItemTypeHandlers,
modifier = Modifier
.imePadding()
.padding(innerPadding)
Expand Down
Loading

0 comments on commit 304e96e

Please sign in to comment.