aboutsummaryrefslogtreecommitdiffstats
path: root/src/bin/rbw/commands.rs
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2020-04-19 05:10:23 -0400
committerJesse Luehrs <doy@tozt.net>2020-04-19 05:10:23 -0400
commit988296d6c9e053d632ee5610ba3432a02776b132 (patch)
tree5b5e1318e3d72b6ff21782436b17793ca2d74197 /src/bin/rbw/commands.rs
parentfe359afea6f2d3e0138af7773469914db9a1da7a (diff)
downloadrbw-988296d6c9e053d632ee5610ba3432a02776b132.tar.gz
rbw-988296d6c9e053d632ee5610ba3432a02776b132.zip
track password history
Diffstat (limited to 'src/bin/rbw/commands.rs')
-rw-r--r--src/bin/rbw/commands.rs31
1 files changed, 31 insertions, 0 deletions
diff --git a/src/bin/rbw/commands.rs b/src/bin/rbw/commands.rs
index 1b6f9ee..7152a59 100644
--- a/src/bin/rbw/commands.rs
+++ b/src/bin/rbw/commands.rs
@@ -8,6 +8,14 @@ struct DecryptedCipher {
username: Option<String>,
password: Option<String>,
notes: Option<String>,
+ history: Vec<DecryptedHistoryEntry>,
+}
+
+#[derive(Debug, Clone)]
+#[cfg_attr(test, derive(Eq, PartialEq))]
+struct DecryptedHistoryEntry {
+ last_used_date: String,
+ password: String,
}
const HELP: &str = r#"
@@ -231,6 +239,15 @@ pub fn edit(name: &str, username: Option<&str>) -> anyhow::Result<()> {
let notes = notes
.map(|notes| crate::actions::encrypt(&notes))
.transpose()?;
+ let mut history = entry.history.clone();
+ let new_history_entry = rbw::db::HistoryEntry {
+ last_used_date: format!(
+ "{}",
+ humantime::format_rfc3339(std::time::SystemTime::now())
+ ),
+ password: entry.password.unwrap_or_else(String::new),
+ };
+ history.insert(0, new_history_entry);
if let (Some(access_token), ()) = rbw::actions::edit(
&access_token,
@@ -240,6 +257,7 @@ pub fn edit(name: &str, username: Option<&str>) -> anyhow::Result<()> {
entry.username.as_deref(),
password.as_deref(),
notes.as_deref(),
+ &history,
)? {
db.access_token = Some(access_token);
db.save(&email).context("failed to save database")?;
@@ -453,12 +471,23 @@ fn decrypt_cipher(entry: &rbw::db::Entry) -> anyhow::Result<DecryptedCipher> {
None
}
};
+ let history = entry
+ .history
+ .iter()
+ .map(|entry| {
+ Ok(DecryptedHistoryEntry {
+ last_used_date: entry.last_used_date.clone(),
+ password: crate::actions::decrypt(&entry.password)?,
+ })
+ })
+ .collect::<anyhow::Result<_>>()?;
Ok(DecryptedCipher {
id: entry.id.clone(),
name: crate::actions::decrypt(&entry.name)?,
username,
password,
notes,
+ history,
})
}
@@ -581,6 +610,7 @@ mod test {
.map(|_| "this is the encrypted username".to_string()),
password: None,
notes: None,
+ history: vec![],
},
DecryptedCipher {
id: "irrelevant".to_string(),
@@ -588,6 +618,7 @@ mod test {
username: username.map(std::string::ToString::to_string),
password: None,
notes: None,
+ history: vec![],
},
)
}