From 9f76d171f0b567deb5571ac33b2548e024cc8f51 Mon Sep 17 00:00:00 2001 From: classabbyamp Date: Thu, 18 Aug 2022 19:08:34 -0400 Subject: add support for raw json output fixes #36 --- README.md | 3 ++- src/bin/rbw/commands.rs | 25 +++++++++++++++++++------ src/bin/rbw/main.rs | 4 ++++ 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 386c0f2..5efe1f8 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,8 @@ functionality. Run `rbw get ` to get your passwords. If you also want to get the username or the note associated, you can use the flag `--full`. You can also use the flag -`--field={field}` to get whatever default or custom field you want. +`--field={field}` to get whatever default or custom field you want. The `--raw` +flag will show the output as JSON. *Note to users of the official Bitwarden server (at bitwarden.com)*: The official server has a tendency to detect command line traffic as bot traffic diff --git a/src/bin/rbw/commands.rs b/src/bin/rbw/commands.rs index 93f00da..ad083eb 100644 --- a/src/bin/rbw/commands.rs +++ b/src/bin/rbw/commands.rs @@ -1,6 +1,7 @@ use anyhow::Context as _; use std::io; use std::io::prelude::Write; +use serde::Serialize; const MISSING_CONFIG_HELP: &str = "Before using rbw, you must configure the email address you would like to \ @@ -12,7 +13,7 @@ const MISSING_CONFIG_HELP: &str = and, if your server has a non-default identity url:\n\n \ rbw config set identity_url \n"; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize)] #[cfg_attr(test, derive(Eq, PartialEq))] struct DecryptedCipher { id: String, @@ -421,6 +422,14 @@ impl DecryptedCipher { } } + fn display_json(&self, desc: &str) -> anyhow::Result<()> { + serde_json::to_writer_pretty(std::io::stdout(), &self) + .context(format!("failed to write entry '{desc}' to stdout"))?; + println!(); + + Ok(()) + } + fn exact_match( &self, name: &str, @@ -512,7 +521,8 @@ impl DecryptedCipher { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize)] +#[serde(untagged)] #[cfg_attr(test, derive(Eq, PartialEq))] enum DecryptedData { Login { @@ -551,21 +561,21 @@ enum DecryptedData { SecureNote, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize)] #[cfg_attr(test, derive(Eq, PartialEq))] struct DecryptedField { name: Option, value: Option, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize)] #[cfg_attr(test, derive(Eq, PartialEq))] struct DecryptedHistoryEntry { last_used_date: String, password: String, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize)] #[cfg_attr(test, derive(Eq, PartialEq))] struct DecryptedUri { uri: String, @@ -763,6 +773,7 @@ pub fn get( folder: Option<&str>, field: Option<&str>, full: bool, + raw: bool, ) -> anyhow::Result<()> { unlock()?; @@ -776,7 +787,9 @@ pub fn get( let (_, decrypted) = find_entry(&db, name, user, folder) .with_context(|| format!("couldn't find entry for '{desc}'"))?; - if full { + if raw { + decrypted.display_json(&desc)?; + } else if full { decrypted.display_long(&desc); } else if field.is_some() { decrypted.display_field(&desc, field.unwrap()); diff --git a/src/bin/rbw/main.rs b/src/bin/rbw/main.rs index 822819a..fd34d11 100644 --- a/src/bin/rbw/main.rs +++ b/src/bin/rbw/main.rs @@ -81,6 +81,8 @@ enum Opt { field: Option, #[arg(long, help = "Display the notes in addition to the password")] full: bool, + #[structopt(long, help = "Display output as JSON")] + raw: bool, }, #[command(about = "Display the authenticator code for a given entry")] @@ -319,12 +321,14 @@ fn main() { folder, field, full, + raw, } => commands::get( name, user.as_deref(), folder.as_deref(), field.as_deref(), *full, + *raw, ), Opt::Code { name, user, folder } => { commands::code(name, user.as_deref(), folder.as_deref()) -- cgit v1.2.3-54-g00ecf