aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2024-04-20 17:11:11 -0400
committerJesse Luehrs <doy@tozt.net>2024-04-20 17:11:11 -0400
commit869d36481c398ad65595e01b32714720dd6cfb1e (patch)
tree1d6c411d3be9d5c626a10574eb9d295cab108499
parent5619d5cd662b639c7d22f033c043a998ed82d6b7 (diff)
downloadrbw-869d36481c398ad65595e01b32714720dd6cfb1e.tar.gz
rbw-869d36481c398ad65595e01b32714720dd6cfb1e.zip
don't delete custom fields when editing passwords
-rw-r--r--src/actions.rs4
-rw-r--r--src/api.rs94
-rw-r--r--src/bin/rbw/commands.rs7
-rw-r--r--src/db.rs2
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,
diff --git a/src/api.rs b/src/api.rs
index 85d2265..9a58f9e 100644
--- a/src/api.rs
+++ b/src/api.rs
@@ -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,
diff --git a/src/db.rs b/src/db.rs
index 73a69d1..ab742ea 100644
--- a/src/db.rs
+++ b/src/db.rs
@@ -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(