Merge branch 'feature/color-output' into develop
Diff
Cargo.toml | 3 ++-
src/bwutil.rs | 5 +++--
src/main.rs | 44 ++++++++++++++++++++++++++++++++------------
3 files changed, 37 insertions(+), 15 deletions(-)
@@ -9,4 +9,5 @@ edition = "2021"
gumdrop = "0.8.1"
anyhow = "1.0.72"
serde = { version = "1.0.177", features = ["derive"] }
serde_json = "1.0.104"
\ No newline at end of file
serde_json = "1.0.104"
colored = "2.0.4"
\ No newline at end of file
@@ -1,4 +1,5 @@
use std::process::{Command, Output, Stdio};
use colored::*;
use serde::Deserialize;
use anyhow::{anyhow, Result, Context};
@@ -77,7 +78,7 @@ pub fn exec_folder_search(session: &str, folder_name: &str) -> Result<Vec<Bitwar
["list", "folders", "--search", &folder_name, "--session", &session].to_vec());
let result: String = String::from_utf8_lossy(&folders.stdout).to_string();
if result.is_empty() {
Err(anyhow!("Could not authenticate."))
Err(anyhow!("Could not authenticate. This could mean your session has expired.".red()))
}
else {
Ok(serde_json::from_str(&result).with_context(|| "Could not deserialize folder search results.")?)
@@ -90,7 +91,7 @@ pub fn exec_list_folder_items(session: &str, folder_id: &str) -> Result<Vec<Bitw
["list", "items", "--folderid", &folder_id, "--session", &session].to_vec());
let result = String::from_utf8_lossy(&items.stdout).to_string();
if result.is_empty() {
Err(anyhow!("Could not authenticate."))
Err(anyhow!("Could not authenticate. This could mean your session has expired.".red()))
}
else {
Ok(serde_json::from_str(&result).with_context(|| "Could not deserialize item search results.")?)
@@ -1,24 +1,41 @@
use std::{env, process::{Command, Stdio}};
use std::{env, process::{Command, Stdio}, ffi::OsString};
use std::str::FromStr;
use gumdrop::Options;
use anyhow::{Result, Context};
use colored::*;
mod util;
mod bwutil;
const SESSION_ENV_KEY: &str = "BW_SESSION";
const BW_SSH_DEBUG_ENV_KEY: &str = "BW_SSH_DEBUG";
const BW_FIELD_KEY_PASSPHRASE: &str = "BW_KEY_PASSPHRASE";
macro_rules! debug_println {
($debug:expr, $($arg:tt)*) => {
if $debug {
println!($($arg)*);
($($arg:tt)*) => {
if let Ok(enabled) = env::var(BW_SSH_DEBUG_ENV_KEY) {
if bool::from_str(&enabled).unwrap_or(false) {
println!("{}",format!($($arg)*).yellow());
}
}
}
}
macro_rules! warn_println {
($($arg:tt)*) => {
println!("{}",format!($($arg)*).yellow());
}
}
macro_rules! info_println {
($($arg:tt)*) => {
println!("{}",format!($($arg)*).green());
}
}
fn main() -> Result<()> {
let unlock_passphrase = env::var(BW_FIELD_KEY_PASSPHRASE);
@@ -27,7 +44,10 @@ fn main() -> Result<()> {
return Ok(())
}
let args: util::Cli = util::Cli::parse_args_default_or_exit();
env::set_var(BW_SSH_DEBUG_ENV_KEY, OsString::from(args.debug.to_string()));
if args.version {
println!("{}", &util::get_version_string()?);
return Ok(());
@@ -36,12 +56,13 @@ fn main() -> Result<()> {
let session_token: String = check_session_token(&args)?;
if !session_token.is_empty() {
let folders = bwutil::exec_folder_search(&session_token, &args.folder)?;
debug_println!(args.debug, "Found {} folder(s) named `{}`", folders.len(), args.folder);
debug_println!("Found {} folder(s) named `{}`", folders.len().to_string().cyan(), args.folder.cyan());
for folder in folders {
let folder_items = bwutil::exec_list_folder_items(&session_token, &folder.id)?;
debug_println!(args.debug, "Found {} item(s) in folder `{}` id({})", folder_items.len(), folder.name, folder.id);
debug_println!("Found {} item(s) in folder `{}` id({}) with at least one custom field and attachment", folder_items.len().to_string().cyan(), folder.name.cyan(), folder.id.cyan());
for item in folder_items {
@@ -65,7 +86,6 @@ fn main() -> Result<()> {
if let Some(attachments) = &item.attachments {
for attachment in attachments {
if attachment.file_name.eq(&key_filename) {
debug_println!(args.debug, "Item `{}` id({}) meets all requirements. Adding to `ssh-agent`", item.name, item.id);
let _key = register_key(&item.id, &attachment.id, &key_passphrase, &session_token)?;
}
}
@@ -85,7 +105,7 @@ fn main() -> Result<()> {
fn check_session_token(args: &util::Cli) -> Result<String> {
println!("Getting Bitwarden session...");
info_println!("Getting Bitwarden session...");
let mut session_token: String = String::new();
if args.session.trim().is_empty() {
@@ -93,18 +113,18 @@ fn check_session_token(args: &util::Cli) -> Result<String> {
let env_key = env::var(SESSION_ENV_KEY);
match env_key {
Ok(key) => {
println!("{} is set. Reusing existing session.", SESSION_ENV_KEY);
info_println!("{} is set. Reusing existing session.", SESSION_ENV_KEY);
session_token.push_str(&key);
},
Err(_) => {
println!("{} is not set. Attempting to login.", SESSION_ENV_KEY);
warn_println!("{} is not set. Attempting to login.", SESSION_ENV_KEY);
let token: &String = &bwutil::get_session_token()?;
if !token.is_empty() {
println!("Successfully unlocked. To re-use this session, run:");
println!("export {}=\"{}\"", SESSION_ENV_KEY, token);
info_println!("Successfully unlocked. To re-use this session, run:");
info_println!("export {}=\"{}\"", SESSION_ENV_KEY, token);
}
session_token.push_str(token)
}