diff options
author | Jesse Luehrs <doy@tozt.net> | 2024-04-20 17:11:11 -0400 |
---|---|---|
committer | Jesse Luehrs <doy@tozt.net> | 2024-04-20 17:11:11 -0400 |
commit | 869d36481c398ad65595e01b32714720dd6cfb1e (patch) | |
tree | 1d6c411d3be9d5c626a10574eb9d295cab108499 | |
parent | 5619d5cd662b639c7d22f033c043a998ed82d6b7 (diff) | |
download | rbw-869d36481c398ad65595e01b32714720dd6cfb1e.tar.gz rbw-869d36481c398ad65595e01b32714720dd6cfb1e.zip |
don't delete custom fields when editing passwords
-rw-r--r-- | src/actions.rs | 4 | ||||
-rw-r--r-- | src/api.rs | 94 | ||||
-rw-r--r-- | src/bin/rbw/commands.rs | 7 | ||||
-rw-r--r-- | src/db.rs | 2 |
4 files changed, 93 insertions, 14 deletions
diff --git a/src/actions.rs b/src/actions.rs index b07cf44..7ee1fa4 100644 --- a/src/actions.rs +++ b/src/actions.rs @@ -185,6 +185,7 @@ pub fn edit( org_id: Option<&str>, name: &str, data: &crate::db::EntryData, + fields: &[crate::db::Field], notes: Option<&str>, folder_uuid: Option<&str>, history: &[crate::db::HistoryEntry], @@ -196,6 +197,7 @@ pub fn edit( org_id, name, data, + fields, notes, folder_uuid, history, @@ -209,6 +211,7 @@ fn edit_once( org_id: Option<&str>, name: &str, data: &crate::db::EntryData, + fields: &[crate::db::Field], notes: Option<&str>, folder_uuid: Option<&str>, history: &[crate::db::HistoryEntry], @@ -220,6 +223,7 @@ fn edit_once( org_id, name, data, + fields, notes, folder_uuid, history, @@ -362,7 +362,7 @@ struct SyncResCipher { #[serde(rename = "PasswordHistory", alias = "passwordHistory")] password_history: Option<Vec<SyncResPasswordHistory>>, #[serde(rename = "Fields", alias = "fields")] - fields: Option<Vec<SyncResField>>, + fields: Option<Vec<CipherField>>, #[serde(rename = "DeletedDate", alias = "deletedDate")] deleted_date: Option<String>, } @@ -463,8 +463,10 @@ impl SyncResCipher { fields .iter() .map(|field| crate::db::Field { + ty: field.ty, name: field.name.clone(), value: field.value.clone(), + linked_id: field.linked_id, }) .collect() }); @@ -582,6 +584,75 @@ struct CipherIdentity { username: Option<String>, } +#[derive( + serde_repr::Serialize_repr, + serde_repr::Deserialize_repr, + Debug, + Clone, + Copy, + PartialEq, + Eq, +)] +#[repr(u16)] +pub enum FieldType { + Text = 0, + Hidden = 1, + Boolean = 2, + Linked = 3, +} + +#[derive( + serde_repr::Serialize_repr, + serde_repr::Deserialize_repr, + Debug, + Clone, + Copy, + PartialEq, + Eq, +)] +#[repr(u16)] +pub enum LinkedIdType { + LoginUsername = 100, + LoginPassword = 101, + CardCardholderName = 300, + CardExpMonth = 301, + CardExpYear = 302, + CardCode = 303, + CardBrand = 304, + CardNumber = 305, + IdentityTitle = 400, + IdentityMiddleName = 401, + IdentityAddress1 = 402, + IdentityAddress2 = 403, + IdentityAddress3 = 404, + IdentityCity = 405, + IdentityState = 406, + IdentityPostalCode = 407, + IdentityCountry = 408, + IdentityCompany = 409, + IdentityEmail = 410, + IdentityPhone = 411, + IdentitySsn = 412, + IdentityUsername = 413, + IdentityPassportNumber = 414, + IdentityLicenseNumber = 415, + IdentityFirstName = 416, + IdentityLastName = 417, + IdentityFullName = 418, +} + +#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] +struct CipherField { + #[serde(rename = "Type", alias = "type")] + ty: FieldType, + #[serde(rename = "Name", alias = "name")] + name: Option<String>, + #[serde(rename = "Value", alias = "value")] + value: Option<String>, + #[serde(rename = "LinkedId", alias = "linkedId")] + linked_id: Option<LinkedIdType>, +} + // this is just a name and some notes, both of which are already on the cipher // object #[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] @@ -595,16 +666,6 @@ struct SyncResPasswordHistory { password: Option<String>, } -#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] -struct SyncResField { - #[serde(rename = "Type", alias = "type")] - ty: u32, - #[serde(rename = "Name", alias = "name")] - name: Option<String>, - #[serde(rename = "Value", alias = "value")] - value: Option<String>, -} - #[derive(serde::Serialize, Debug)] struct CiphersPostReq { #[serde(rename = "type")] @@ -633,6 +694,7 @@ struct CiphersPutReq { login: Option<CipherLogin>, card: Option<CipherCard>, identity: Option<CipherIdentity>, + fields: Vec<CipherField>, #[serde(rename = "secureNote")] secure_note: Option<CipherSecureNote>, #[serde(rename = "passwordHistory")] @@ -1042,6 +1104,7 @@ impl Client { org_id: Option<&str>, name: &str, data: &crate::db::EntryData, + fields: &[crate::db::Field], notes: Option<&str>, folder_uuid: Option<&str>, history: &[crate::db::HistoryEntry], @@ -1061,6 +1124,15 @@ impl Client { card: None, identity: None, secure_note: None, + fields: fields + .iter() + .map(|field| CipherField { + ty: field.ty, + name: field.name.clone(), + value: field.value.clone(), + linked_id: field.linked_id, + }) + .collect(), password_history: history .iter() .map(|entry| CiphersPutReqHistory { diff --git a/src/bin/rbw/commands.rs b/src/bin/rbw/commands.rs index a4a513b..3329f76 100644 --- a/src/bin/rbw/commands.rs +++ b/src/bin/rbw/commands.rs @@ -1266,7 +1266,7 @@ pub fn edit( find_entry(&db, &Needle::Name(name.to_string()), username, folder) .with_context(|| format!("couldn't find entry for '{desc}'"))?; - let (data, notes, history) = match &decrypted.data { + let (data, fields, notes, history) = match &decrypted.data { DecryptedData::Login { password, .. } => { let mut contents = format!("{}\n", password.as_deref().unwrap_or("")); @@ -1320,7 +1320,7 @@ pub fn edit( uris: entry_uris.clone(), totp: entry_totp.clone(), }; - (data, notes, history) + (data, entry.fields, notes, history) } DecryptedData::SecureNote {} => { let data = rbw::db::EntryData::SecureNote {}; @@ -1340,7 +1340,7 @@ pub fn edit( }) .transpose()?; - (data, notes, entry.history) + (data, entry.fields, notes, entry.history) } _ => { return Err(anyhow::anyhow!( @@ -1356,6 +1356,7 @@ pub fn edit( entry.org_id.as_deref(), &entry.name, &data, + &fields, notes.as_deref(), entry.folder_id.as_deref(), &history, @@ -147,8 +147,10 @@ pub enum EntryData { serde::Serialize, serde::Deserialize, Debug, Clone, Eq, PartialEq, )] pub struct Field { + pub ty: crate::api::FieldType, pub name: Option<String>, pub value: Option<String>, + pub linked_id: Option<crate::api::LinkedIdType>, } #[derive( |