aboutsummaryrefslogtreecommitdiffstats
path: root/src/bin/rbw/commands.rs
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2020-04-18 01:30:32 -0400
committerJesse Luehrs <doy@tozt.net>2020-04-18 01:58:08 -0400
commit840f53b84206f9efe0a5cdea3414c472908a22e4 (patch)
treee8d95614a3f0c1ae1bfd4c9616ce6143cc3e6e0b /src/bin/rbw/commands.rs
parentdd7ef574e84ca6c1a548422904c6865048ae8e30 (diff)
downloadrbw-840f53b84206f9efe0a5cdea3414c472908a22e4.tar.gz
rbw-840f53b84206f9efe0a5cdea3414c472908a22e4.zip
implement add command
Diffstat (limited to 'src/bin/rbw/commands.rs')
-rw-r--r--src/bin/rbw/commands.rs70
1 files changed, 68 insertions, 2 deletions
diff --git a/src/bin/rbw/commands.rs b/src/bin/rbw/commands.rs
index 5f1c2f1..360c967 100644
--- a/src/bin/rbw/commands.rs
+++ b/src/bin/rbw/commands.rs
@@ -1,5 +1,11 @@
use anyhow::Context as _;
+const HELP: &str = r#"
+# The first line of this file will be the password, and the remainder of the
+# file (after any blank lines after the password) will be stored as a note.
+# Lines with leading # will be ignored.
+"#;
+
pub fn config_show() -> anyhow::Result<()> {
let config =
rbw::config::Config::load().context("failed to load config")?;
@@ -120,10 +126,70 @@ pub fn get(name: &str, user: Option<&str>) -> anyhow::Result<()> {
Ok(())
}
-pub fn add() -> anyhow::Result<()> {
+pub fn add(name: &str, username: Option<&str>) -> anyhow::Result<()> {
unlock()?;
- todo!()
+ let email = config_email()?;
+ let mut db = rbw::db::Db::load(&email)?;
+ // unwrap is safe here because the call to unlock above is guaranteed to
+ // populate it or error
+ let access_token = db.access_token.unwrap();
+
+ let name = crate::actions::encrypt(name)?;
+
+ let username = username
+ .map(|username| crate::actions::encrypt(username))
+ .transpose()?;
+
+ let contents = rbw::edit::edit("", HELP)?;
+ let mut lines = contents.lines();
+
+ // XXX unwrap
+ let password = lines.next().unwrap();
+ let password = crate::actions::encrypt(password)?;
+
+ let mut note: String = lines
+ .skip_while(|line| *line == "")
+ .filter(|line| !line.starts_with('#'))
+ .map(|line| format!("{}\n", line))
+ .collect();
+ while note.ends_with('\n') {
+ note.pop();
+ }
+ let note = if note == "" {
+ None
+ } else {
+ Some(crate::actions::encrypt(&note)?)
+ };
+
+ let cipher = rbw::api::Cipher {
+ name,
+ login: rbw::api::Login {
+ username,
+ password: Some(password),
+ },
+ };
+
+ let res = rbw::actions::add(&access_token, &cipher);
+ if let Err(e) = &res {
+ if let rbw::error::Error::RequestUnauthorized = e {
+ if let Some(refresh_token) = &db.refresh_token {
+ let access_token =
+ rbw::actions::exchange_refresh_token(refresh_token)?;
+ db.access_token = Some(access_token.clone());
+ db.save(&email).context("failed to save database")?;
+ rbw::actions::add(&access_token, &cipher)?;
+ } else {
+ return Err(anyhow::anyhow!(
+ "failed to find refresh token in db"
+ ));
+ }
+ }
+ }
+
+ crate::actions::sync()?;
+
+ Ok(())
}
pub fn generate(