diff --git a/crates/bitwarden-vault/src/cipher/cipher.rs b/crates/bitwarden-vault/src/cipher/cipher.rs index aa612210..05c5926b 100644 --- a/crates/bitwarden-vault/src/cipher/cipher.rs +++ b/crates/bitwarden-vault/src/cipher/cipher.rs @@ -14,6 +14,7 @@ use uuid::Uuid; use super::{ attachment, card, field, identity, local_data::{LocalData, LocalDataView}, + login::LoginListView, secure_note, ssh_key, }; use crate::{ @@ -133,10 +134,7 @@ pub struct CipherView { #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "uniffi", derive(uniffi::Enum))] pub enum CipherListViewType { - Login { - has_fido2: bool, - totp: Option, - }, + Login(LoginListView), SecureNote, Card, Identity, @@ -182,10 +180,11 @@ impl CipherListView { let cipher_key = Cipher::get_cipher_key(key, &self.key)?; let key = cipher_key.as_ref().unwrap_or(key); - let totp = if let CipherListViewType::Login { totp, .. } = self.r#type { - totp.decrypt_with_key(key)? - } else { - None + let totp = match self.r#type { + CipherListViewType::Login(LoginListView { totp, .. }) => { + totp.map(|t| t.decrypt_with_key(key)).transpose()? + } + _ => None, }; Ok(totp) @@ -562,10 +561,7 @@ impl KeyDecryptable for Cipher { .login .as_ref() .ok_or(CryptoError::MissingField("login"))?; - CipherListViewType::Login { - has_fido2: login.fido2_credentials.is_some(), - totp: login.totp.clone(), - } + CipherListViewType::Login(login.decrypt_with_key(key)?) } CipherType::SecureNote => CipherListViewType::SecureNote, CipherType::Card => CipherListViewType::Card, @@ -803,10 +799,11 @@ mod tests { key: cipher.key, name: "My test login".to_string(), sub_title: "test_username".to_string(), - r#type: CipherListViewType::Login { + r#type: CipherListViewType::Login(LoginListView { has_fido2: true, - totp: cipher.login.as_ref().unwrap().totp.clone() - }, + totp: cipher.login.as_ref().unwrap().totp.clone(), + uris: None, + }), favorite: cipher.favorite, reprompt: cipher.reprompt, edit: cipher.edit, diff --git a/crates/bitwarden-vault/src/cipher/login.rs b/crates/bitwarden-vault/src/cipher/login.rs index 4b476b07..c09119f1 100644 --- a/crates/bitwarden-vault/src/cipher/login.rs +++ b/crates/bitwarden-vault/src/cipher/login.rs @@ -11,7 +11,7 @@ use serde_repr::{Deserialize_repr, Serialize_repr}; use crate::VaultParseError; -#[derive(Clone, Copy, Serialize_repr, Deserialize_repr, Debug, JsonSchema)] +#[derive(Clone, Copy, Serialize_repr, Deserialize_repr, Debug, JsonSchema, PartialEq)] #[repr(u8)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "uniffi", derive(uniffi::Enum))] @@ -33,7 +33,7 @@ pub struct LoginUri { pub uri_checksum: Option, } -#[derive(Serialize, Deserialize, Debug, JsonSchema, Clone)] +#[derive(Serialize, Deserialize, Debug, JsonSchema, Clone, PartialEq)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "uniffi", derive(uniffi::Record))] pub struct LoginUriView { @@ -268,6 +268,15 @@ pub struct LoginView { pub fido2_credentials: Option>, } +#[derive(Serialize, Deserialize, Debug, JsonSchema, Clone, PartialEq)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[cfg_attr(feature = "uniffi", derive(uniffi::Record))] +pub struct LoginListView { + pub has_fido2: bool, + pub totp: Option, + pub uris: Option>, +} + impl KeyEncryptable for LoginUriView { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(LoginUri { @@ -316,6 +325,16 @@ impl KeyDecryptable for Login { } } +impl KeyDecryptable for Login { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + Ok(LoginListView { + has_fido2: self.fido2_credentials.is_some(), + totp: self.totp.clone(), + uris: self.uris.decrypt_with_key(key).ok().flatten(), + }) + } +} + impl KeyEncryptable for Fido2CredentialView { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Fido2Credential { diff --git a/crates/bitwarden-vault/src/totp.rs b/crates/bitwarden-vault/src/totp.rs index d6167a1a..db42f43e 100644 --- a/crates/bitwarden-vault/src/totp.rs +++ b/crates/bitwarden-vault/src/totp.rs @@ -266,7 +266,7 @@ mod tests { use uuid::Uuid; use super::*; - use crate::{cipher::cipher::CipherListViewType, CipherRepromptType}; + use crate::{cipher::cipher::CipherListViewType, login::LoginListView, CipherRepromptType}; #[test] fn test_decode_b32() { @@ -377,10 +377,11 @@ mod tests { key: None, name: "My test login".to_string(), sub_title: "test_username".to_string(), - r#type: CipherListViewType::Login { + r#type: CipherListViewType::Login(LoginListView{ has_fido2: true, totp: Some("2.hqdioUAc81FsKQmO1XuLQg==|oDRdsJrQjoFu9NrFVy8tcJBAFKBx95gHaXZnWdXbKpsxWnOr2sKipIG43pKKUFuq|3gKZMiboceIB5SLVOULKg2iuyu6xzos22dfJbvx0EHk=".parse().unwrap()), - }, + uris: None, + }), favorite: false, reprompt: CipherRepromptType::None, edit: true,