aboutsummaryrefslogtreecommitdiffstats
path: root/src/bin/rbw/commands.rs
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2020-04-12 00:08:03 -0400
committerJesse Luehrs <doy@tozt.net>2020-04-12 00:08:03 -0400
commit236f06736e45c2a70f43589c9d447a0a3ef240b5 (patch)
treec390d4cbfec5223ac1aefe3947f8e1bb885757d2 /src/bin/rbw/commands.rs
parent91d1d1890bdc3ee75b69e00d5368c5b29a4f461c (diff)
downloadrbw-236f06736e45c2a70f43589c9d447a0a3ef240b5.tar.gz
rbw-236f06736e45c2a70f43589c9d447a0a3ef240b5.zip
improve error handling and reporting
Diffstat (limited to 'src/bin/rbw/commands.rs')
-rw-r--r--src/bin/rbw/commands.rs164
1 files changed, 108 insertions, 56 deletions
diff --git a/src/bin/rbw/commands.rs b/src/bin/rbw/commands.rs
index b76658c..83c6c81 100644
--- a/src/bin/rbw/commands.rs
+++ b/src/bin/rbw/commands.rs
@@ -1,76 +1,108 @@
-pub fn config_show() {
- let config = rbw::config::Config::load().unwrap();
- serde_json::to_writer_pretty(std::io::stdout(), &config).unwrap();
+use anyhow::Context as _;
+
+pub fn config_show() -> anyhow::Result<()> {
+ let config =
+ rbw::config::Config::load().context("failed to load config")?;
+ serde_json::to_writer_pretty(std::io::stdout(), &config)
+ .context("failed to write config to stdout")?;
println!();
+
+ Ok(())
}
-pub fn config_set(key: &str, value: &str) {
+pub fn config_set(key: &str, value: &str) -> anyhow::Result<()> {
let mut config = rbw::config::Config::load()
.unwrap_or_else(|_| rbw::config::Config::new());
match key {
"email" => config.email = Some(value.to_string()),
"base_url" => config.base_url = Some(value.to_string()),
"identity_url" => config.identity_url = Some(value.to_string()),
- "lock_timeout" => config.lock_timeout = value.parse().unwrap(),
- _ => unimplemented!(),
+ "lock_timeout" => {
+ config.lock_timeout = value
+ .parse()
+ .context("failed to parse value for lock_timeout")?
+ }
+ _ => return Err(anyhow::anyhow!("invalid config key: {}", key)),
}
- config.save().unwrap();
+ config.save().context("failed to save config file")?;
+
+ Ok(())
}
-pub fn login() {
- ensure_agent();
- crate::actions::login();
+pub fn login() -> anyhow::Result<()> {
+ ensure_agent()?;
+ crate::actions::login()?;
+
+ Ok(())
}
-pub fn unlock() {
- ensure_agent();
- crate::actions::login();
- crate::actions::unlock();
+pub fn unlock() -> anyhow::Result<()> {
+ ensure_agent()?;
+ crate::actions::login()?;
+ crate::actions::unlock()?;
+
+ Ok(())
}
-pub fn sync() {
- ensure_agent();
- crate::actions::login();
- crate::actions::sync();
+pub fn sync() -> anyhow::Result<()> {
+ ensure_agent()?;
+ crate::actions::login()?;
+ crate::actions::sync()?;
+
+ Ok(())
}
-pub fn list() {
- unlock();
+pub fn list() -> anyhow::Result<()> {
+ unlock()?;
- let email = config_email();
- let db = rbw::db::Db::load(&email).unwrap_or_else(|_| rbw::db::Db::new());
+ let email = config_email()?;
+ let db = rbw::db::Db::load(&email)
+ .context("failed to load password database")?;
for cipher in db.ciphers {
- println!("{}", crate::actions::decrypt(&cipher.name));
+ println!(
+ "{}",
+ crate::actions::decrypt(&cipher.name)
+ .context("failed to decrypt entry name")?
+ );
}
+
+ Ok(())
}
-pub fn get(name: &str, user: Option<&str>) {
- unlock();
+pub fn get(name: &str, user: Option<&str>) -> anyhow::Result<()> {
+ unlock()?;
- let email = config_email();
- let db = rbw::db::Db::load(&email).unwrap_or_else(|_| rbw::db::Db::new());
+ let email = config_email()?;
+ let db = rbw::db::Db::load(&email)
+ .context("failed to load password database")?;
for cipher in db.ciphers {
- let cipher_name = crate::actions::decrypt(&cipher.name);
+ let cipher_name = crate::actions::decrypt(&cipher.name)
+ .context("failed to decrypt entry name")?;
if name == cipher_name {
- let cipher_user = crate::actions::decrypt(&cipher.login.username);
+ let cipher_user = crate::actions::decrypt(&cipher.login.username)
+ .context("failed to decrypt entry username")?;
if let Some(user) = user {
if user == cipher_user {
let pass =
- crate::actions::decrypt(&cipher.login.password);
+ crate::actions::decrypt(&cipher.login.password)
+ .context("failed to decrypt entry password")?;
println!("{}", pass);
- return;
+ return Ok(());
}
} else {
- let pass = crate::actions::decrypt(&cipher.login.password);
+ let pass = crate::actions::decrypt(&cipher.login.password)
+ .context("failed to decrypt entry password")?;
println!("{}", pass);
- return;
+ return Ok(());
}
}
}
+
+ Ok(())
}
-pub fn add() {
- unlock();
+pub fn add() -> anyhow::Result<()> {
+ unlock()?;
todo!()
}
@@ -80,62 +112,82 @@ pub fn generate(
user: Option<&str>,
len: usize,
ty: rbw::pwgen::Type,
-) {
+) -> anyhow::Result<()> {
let pw = rbw::pwgen::pwgen(ty, len);
+ // unwrap is safe because pwgen is guaranteed to always return valid utf8
println!("{}", std::str::from_utf8(pw.data()).unwrap());
if name.is_some() && user.is_some() {
- unlock();
+ unlock()?;
todo!();
}
+
+ Ok(())
}
-pub fn edit() {
- unlock();
+pub fn edit() -> anyhow::Result<()> {
+ unlock()?;
todo!()
}
-pub fn remove() {
- unlock();
+pub fn remove() -> anyhow::Result<()> {
+ unlock()?;
todo!()
}
-pub fn lock() {
- ensure_agent();
- crate::actions::lock();
+pub fn lock() -> anyhow::Result<()> {
+ ensure_agent()?;
+ crate::actions::lock()?;
+
+ Ok(())
}
-pub fn purge() {
- stop_agent();
+pub fn purge() -> anyhow::Result<()> {
+ stop_agent()?;
+
+ let email = config_email()?;
+ rbw::db::Db::remove(&email).context("failed to remove database")?;
- let email = config_email();
- rbw::db::Db::remove(&email).unwrap();
+ Ok(())
}
-pub fn stop_agent() {
- crate::actions::quit();
+pub fn stop_agent() -> anyhow::Result<()> {
+ crate::actions::quit()?;
+
+ Ok(())
}
-fn ensure_agent() {
+fn ensure_agent() -> anyhow::Result<()> {
let agent_path = std::env::var("RBW_AGENT");
let agent_path = agent_path
.as_ref()
.map(|s| s.as_str())
.unwrap_or("rbw-agent");
- let status = std::process::Command::new(agent_path).status().unwrap();
+ let status = std::process::Command::new(agent_path)
+ .status()
+ .context("failed to run rbw-agent")?;
if !status.success() {
if let Some(code) = status.code() {
if code != 23 {
- panic!("failed to run agent: {}", status);
+ return Err(anyhow::anyhow!(
+ "failed to run rbw-agent: {}",
+ status
+ ));
}
}
}
+
+ Ok(())
}
-fn config_email() -> String {
- let config = rbw::config::Config::load().unwrap();
- config.email.unwrap()
+fn config_email() -> anyhow::Result<String> {
+ let config = rbw::config::Config::load()?;
+ if let Some(email) = config.email {
+ Ok(email)
+ } else {
+ Err(anyhow::anyhow!("failed to find email address in config"))
+ }
}