refactor: bitwarden operations moved to the `bwutil` module
Diff
Cargo.toml | 4 ++-
src/bwutil.rs | 68 ++++++++++++++++++++++++++++++++++++++++++++++-
src/main.rs | 88 ++++++++++++++++++------------------------------------------
3 files changed, 98 insertions(+), 62 deletions(-)
@@ -7,4 +7,6 @@ edition = "2021"
[dependencies]
gumdrop = "0.8.1"
anyhow = "1.0.72"
\ No newline at end of file
anyhow = "1.0.72"
serde = { version = "1.0.177", features = ["derive"] }
serde_json = "1.0.104"
\ No newline at end of file
@@ -0,0 +1,68 @@
use std::process::{Command, Output, Stdio};
use serde::Deserialize;
use anyhow::{anyhow, Result, Context};
#[derive(Default, Debug, Clone, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BitwardenFolder {
object: String,
id: String,
name: String
}
pub fn is_logged_in() -> Result<bool> {
let logged_in = Command::new("bw")
.arg("login")
.arg("--check")
.output()?;
Ok(logged_in.stdout.len() > 0)
}
pub fn get_session_token() -> Result<String> {
let mut token = String::new();
let mut operation = String::new();
if is_logged_in()? {
println!("Vault is locked.");
operation.push_str("unlock")
}
else {
println!("You are not logged in.");
operation.push_str("login")
}
let success: Output = exec_interactive_command("bw",
["--raw", &operation].to_vec());
if success.status.success() {
token.push_str(&String::from_utf8(success.stdout)?);
}
Ok(token)
}
fn exec_interactive_command(cmd: &str, args: Vec<&str>) -> Output {
let cli_command = match Command::new(cmd)
.args(&args)
.stdin(Stdio::inherit())
.stdout(Stdio::piped())
.stderr(Stdio::inherit())
.spawn()
{
Err(err) => panic!("Error spawning: {}", err),
Ok(process) => process,
};
let output = cli_command.wait_with_output().unwrap();
return output;
}
@@ -1,7 +1,9 @@
use std::{env, process::{Command, Stdio, Output}};
use std::env;
use gumdrop::Options;
use anyhow::Result;
mod bwutil;
#[derive(Debug, Options)]
struct Cli {
@@ -33,86 +35,50 @@ fn main() -> Result<()> {
return Ok(());
}
let session: String = get_session(&args)?;
if !session.is_empty() {
println!("Successfully unlocked. To re-use this session, run:");
println!("export {}=\"{}\"", SESSION_ENV_KEY, session);
let session_token: String = check_session_token(&args)?;
if !session_token.is_empty() {
todo!()
}
Ok(())
}
fn get_session(args: &Cli) -> Result<String> {
fn check_session_token(args: &Cli) -> Result<String> {
println!("Getting Bitwarden session...");
let mut session_key: String = String::new();
let mut session_token: String = String::new();
if args.session.trim().is_empty() {
let key = env::var(SESSION_ENV_KEY);
match key {
let env_key = env::var(SESSION_ENV_KEY);
match env_key {
Ok(key) => {
println!("Existing Bitwarden session found.");
println!("{} is set. Reusing existing session.", SESSION_ENV_KEY);
session_key.push_str(&key);
session_token.push_str(&key);
},
Err(_) => {
let logged_in = Command::new("bw")
.arg("login")
.arg("--check")
.arg("--quiet")
.output()?;
let mut operation = String::new();
if !logged_in.status.success() {
println!("Not logged in.");
operation.push_str("login");
}
else {
println!("Vault is locked.");
operation.push_str("unlock")
}
println!("{} is not set. Attempting to login.", SESSION_ENV_KEY);
let token: &String = &bwutil::get_session_token()?;
let success: Output = exec_interactive_command("bw", ["--raw", &operation].to_vec());
if success.status.success() {
session_key.push_str(&String::from_utf8(success.stdout)?);
if !token.is_empty() {
println!("Successfully unlocked. To re-use this session, run:");
println!("export {}=\"{}\"", SESSION_ENV_KEY, token);
}
session_token.push_str(token)
}
}
}
else {
session_key.push_str(&args.session);
session_token.push_str(&args.session);
}
Ok(session_key)
}
fn exec_interactive_command(cmd: &str, args: Vec<&str>) -> Output {
let cli_command = match Command::new(cmd)
.args(&args)
.stdin(Stdio::inherit())
.stdout(Stdio::piped())
.stderr(Stdio::inherit())
.spawn()
{
Err(err) => panic!("Error spawning: {}", err),
Ok(process) => process,
};
let output = cli_command.wait_with_output().unwrap();
return output;
Ok(session_token)
}