-
Notifications
You must be signed in to change notification settings - Fork 952
[PM-32009] feat: Add infrastructure for new vault item types #6828
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -36,6 +36,7 @@ import com.bitwarden.vault.SecureNote | |
| import com.bitwarden.vault.SecureNoteType | ||
| import com.bitwarden.vault.SshKey | ||
| import com.bitwarden.vault.UriMatchType | ||
| import timber.log.Timber | ||
|
|
||
| /** | ||
| * Converts a Bitwarden SDK [Cipher] object to a corresponding | ||
|
|
@@ -66,6 +67,9 @@ fun Cipher.toEncryptedNetworkCipher( | |
| card = card?.toEncryptedNetworkCard(), | ||
| key = key, | ||
| sshKey = sshKey?.toEncryptedNetworkSshKey(), | ||
| bankAccount = null, | ||
| driversLicense = null, | ||
| passport = null, | ||
| archivedDate = archivedDate, | ||
| encryptedFor = encryptedFor, | ||
| ) | ||
|
|
@@ -96,6 +100,9 @@ fun Cipher.toEncryptedNetworkCipherResponse( | |
| card = card?.toEncryptedNetworkCard(), | ||
| attachments = attachments?.toNetworkAttachmentList(), | ||
| sshKey = sshKey?.toEncryptedNetworkSshKey(), | ||
| bankAccount = null, | ||
| driversLicense = null, | ||
| passport = null, | ||
| shouldOrganizationUseTotp = organizationUseTotp, | ||
| shouldEdit = edit, | ||
| revisionDate = revisionDate, | ||
|
|
@@ -380,7 +387,11 @@ private fun CipherType.toNetworkCipherType(): CipherTypeJson = | |
| * Bitwarden SDK [Cipher] objects. | ||
| */ | ||
| fun List<SyncResponseJson.Cipher>.toEncryptedSdkCipherList(): List<Cipher> = | ||
| map { it.toEncryptedSdkCipher() } | ||
| mapNotNull { | ||
| runCatching { it.toEncryptedSdkCipher() } | ||
| .onFailure { e -> Timber.w(e, "Failed to convert cipher: %s", it.id) } | ||
| .getOrNull() | ||
| } | ||
|
|
||
| /** | ||
| * Converts a [SyncResponseJson.Cipher] object to a corresponding | ||
|
|
@@ -607,6 +618,10 @@ fun CipherTypeJson.toSdkCipherType(): CipherType = | |
| CipherTypeJson.CARD -> CipherType.CARD | ||
| CipherTypeJson.IDENTITY -> CipherType.IDENTITY | ||
| CipherTypeJson.SSH_KEY -> CipherType.SSH_KEY | ||
| CipherTypeJson.BANK_ACCOUNT, | ||
| CipherTypeJson.DRIVERS_LICENSE, | ||
| CipherTypeJson.PASSPORT, | ||
| -> throw IllegalArgumentException("SDK mapping not yet available for $this") | ||
|
Comment on lines
+621
to
+624
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Details and fixThe PR description states "the mapping layer defensively drops unknown types instead of throwing, keeping sync resilient." That promise only holds for
Trigger path: A web vault with the server-side flag enabled stores a bank account cipher. Mobile syncs (storing the Suggested fix: either (a) filter new types out of the disk source before they reach these call sites, or (b) make
Comment on lines
+621
to
+624
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Details and fixThe PR description states "the mapping layer defensively drops unknown types instead of throwing, keeping sync resilient." That promise only holds for
Trigger path: A web vault with the server-side flag enabled stores a bank account cipher. Mobile syncs (storing the Suggested fix: either (a) filter new types out of the disk source before they reach these call sites, or (b) make |
||
| } | ||
|
|
||
| /** | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -89,6 +89,7 @@ import com.x8bit.bitwarden.ui.vault.model.VaultCardExpirationMonth | |
| import com.x8bit.bitwarden.ui.vault.model.VaultCollection | ||
| import com.x8bit.bitwarden.ui.vault.model.VaultIdentityTitle | ||
| import com.x8bit.bitwarden.ui.vault.model.VaultItemCipherType | ||
| import com.x8bit.bitwarden.ui.vault.model.VaultBankAccountType | ||
| import com.x8bit.bitwarden.ui.vault.model.VaultLinkedFieldType | ||
| import com.x8bit.bitwarden.ui.vault.util.detectCardBrand | ||
| import dagger.hilt.android.lifecycle.HiltViewModel | ||
|
|
@@ -439,6 +440,14 @@ class VaultAddEditViewModel @Inject constructor( | |
|
|
||
| @Suppress("LongMethod") | ||
| private fun handleSaveClick() = onContent { content -> | ||
| if (!content.type.isSdkSupported) { | ||
| sendEvent( | ||
| VaultAddEditEvent.ShowSnackbar( | ||
| message = BitwardenString.an_error_has_occurred.asText(), | ||
| ), | ||
| ) | ||
| return@onContent | ||
| } | ||
| if (hasValidationErrors(content)) return@onContent | ||
|
|
||
| mutableStateFlow.update { | ||
|
|
@@ -2552,6 +2561,9 @@ data class VaultAddEditState( | |
| VaultItemCipherType.IDENTITY -> BitwardenString.new_identity.asText() | ||
| VaultItemCipherType.SECURE_NOTE -> BitwardenString.new_note.asText() | ||
| VaultItemCipherType.SSH_KEY -> BitwardenString.new_ssh_key.asText() | ||
| VaultItemCipherType.BANK_ACCOUNT -> BitwardenString.new_bank_account.asText() | ||
| VaultItemCipherType.DRIVERS_LICENSE -> BitwardenString.new_drivers_license.asText() | ||
| VaultItemCipherType.PASSPORT -> BitwardenString.new_passport.asText() | ||
| } | ||
|
|
||
| is VaultAddEditType.EditItem -> when (cipherType) { | ||
|
|
@@ -2560,6 +2572,9 @@ data class VaultAddEditState( | |
| VaultItemCipherType.IDENTITY -> BitwardenString.edit_identity.asText() | ||
| VaultItemCipherType.SECURE_NOTE -> BitwardenString.edit_note.asText() | ||
| VaultItemCipherType.SSH_KEY -> BitwardenString.edit_ssh_key.asText() | ||
| VaultItemCipherType.BANK_ACCOUNT -> BitwardenString.edit_bank_account.asText() | ||
| VaultItemCipherType.DRIVERS_LICENSE -> BitwardenString.edit_drivers_license.asText() | ||
| VaultItemCipherType.PASSPORT -> BitwardenString.edit_passport.asText() | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -2653,6 +2668,9 @@ data class VaultAddEditState( | |
| IDENTITY(BitwardenString.type_identity), | ||
| SECURE_NOTES(BitwardenString.type_secure_note), | ||
| SSH_KEYS(BitwardenString.type_ssh_key), | ||
| BANK_ACCOUNT(BitwardenString.type_bank_account), | ||
| DRIVERS_LICENSE(BitwardenString.type_drivers_license), | ||
| PASSPORT(BitwardenString.type_passport), | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -2761,6 +2779,11 @@ data class VaultAddEditState( | |
| */ | ||
| abstract val vaultLinkedFieldTypes: ImmutableList<VaultLinkedFieldType> | ||
|
|
||
| /** | ||
| * Whether this item type has SDK support for save operations. | ||
| */ | ||
| open val isSdkSupported: Boolean get() = true | ||
|
|
||
| /** | ||
| * Represents the login item information. | ||
| * | ||
|
|
@@ -2936,6 +2959,83 @@ data class VaultAddEditState( | |
| override val vaultLinkedFieldTypes: ImmutableList<VaultLinkedFieldType> | ||
| get() = persistentListOf() | ||
| } | ||
|
|
||
| /** | ||
| * Represents the bank account item information. | ||
| */ | ||
| @Parcelize | ||
| data class BankAccount( | ||
| val bankName: String = "", | ||
| val nameOnAccount: String = "", | ||
| val accountType: VaultBankAccountType = VaultBankAccountType.SELECT, | ||
| val accountNumber: String = "", | ||
| val routingNumber: String = "", | ||
| val branchNumber: String = "", | ||
| val pin: String = "", | ||
| val swiftCode: String = "", | ||
| val iban: String = "", | ||
| val bankContactPhone: String = "", | ||
| ) : ItemType() { | ||
| override val itemTypeOption: ItemTypeOption | ||
| get() = ItemTypeOption.BANK_ACCOUNT | ||
|
|
||
| override val isSdkSupported: Boolean get() = false | ||
|
|
||
| override val vaultLinkedFieldTypes: ImmutableList<VaultLinkedFieldType> | ||
| get() = persistentListOf() | ||
| } | ||
|
|
||
| /** | ||
| * Represents the driver's license item information. | ||
| */ | ||
| @Parcelize | ||
| data class DriversLicense( | ||
| val firstName: String = "", | ||
| val middleName: String = "", | ||
| val lastName: String = "", | ||
| val licenseNumber: String = "", | ||
| val issuingCountry: String = "", | ||
| val issuingState: String = "", | ||
| val expirationMonth: String = "", | ||
| val expirationYear: String = "", | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All this still should also be made for |
||
| val licenseClass: String = "", | ||
| ) : ItemType() { | ||
| override val itemTypeOption: ItemTypeOption | ||
| get() = ItemTypeOption.DRIVERS_LICENSE | ||
|
|
||
| override val isSdkSupported: Boolean get() = false | ||
|
|
||
| override val vaultLinkedFieldTypes: ImmutableList<VaultLinkedFieldType> | ||
| get() = persistentListOf() | ||
| } | ||
|
|
||
| /** | ||
| * Represents the passport item information. | ||
| */ | ||
| @Parcelize | ||
| data class Passport( | ||
| val surname: String = "", | ||
| val givenName: String = "", | ||
| val dobMonth: String = "", | ||
| val dobYear: String = "", | ||
| val nationality: String = "", | ||
| val passportNumber: String = "", | ||
| val passportType: String = "", | ||
| val issuingCountry: String = "", | ||
| val issuingAuthority: String = "", | ||
| val issueMonth: String = "", | ||
| val issueYear: String = "", | ||
| val expirationMonth: String = "", | ||
| val expirationYear: String = "", | ||
| ) : ItemType() { | ||
| override val itemTypeOption: ItemTypeOption | ||
| get() = ItemTypeOption.PASSPORT | ||
|
|
||
| override val isSdkSupported: Boolean get() = false | ||
|
|
||
| override val vaultLinkedFieldTypes: ImmutableList<VaultLinkedFieldType> | ||
| get() = persistentListOf() | ||
| } | ||
| } | ||
|
|
||
| /** | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,4 +26,10 @@ fun VaultItemCipherType.toItemType(): VaultAddEditState.ViewState.Content.ItemTy | |
| VaultItemCipherType.IDENTITY -> VaultAddEditState.ViewState.Content.ItemType.Identity() | ||
| VaultItemCipherType.SECURE_NOTE -> VaultAddEditState.ViewState.Content.ItemType.SecureNotes | ||
| VaultItemCipherType.SSH_KEY -> VaultAddEditState.ViewState.Content.ItemType.SshKey() | ||
| VaultItemCipherType.BANK_ACCOUNT -> | ||
| VaultAddEditState.ViewState.Content.ItemType.BankAccount() | ||
| VaultItemCipherType.DRIVERS_LICENSE -> | ||
| VaultAddEditState.ViewState.Content.ItemType.DriversLicense() | ||
| VaultItemCipherType.PASSPORT -> | ||
| VaultAddEditState.ViewState.Content.ItemType.Passport() | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ding on formatting |
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why would this need to be wrapped in
runCatching