use crate::io::CliInputOutput;
use crate::io::OutputType;
use crate::password;
use crate::password::v2::Password;
use csv::Writer;
use rtoolbox::safe_string::SafeString;
use serde::{Deserialize, Serialize};
use serde_json;
use std::io::Cursor;
use std::ops::Deref;
#[derive(Serialize, Deserialize)]
pub struct JsonExport {
passwords: Vec<Password>,
}
pub fn callback_exec(
matches: &clap::ArgMatches,
store: &mut password::v2::PasswordStore,
io: &mut impl CliInputOutput,
) -> Result<(), i32> {
let subcommand_name = matches.subcommand_name().unwrap();
let subcommand_matches = matches.subcommand_matches(subcommand_name).unwrap();
match subcommand_name {
"json" => export_to_json(subcommand_matches, store, io),
"csv" | "1password" => export_to_csv(subcommand_matches, store, io),
_ => unimplemented!("Invalid export destination"),
}
}
fn export_to_csv(
_matches: &clap::ArgMatches,
store: &mut password::v2::PasswordStore,
io: &mut impl CliInputOutput,
) -> Result<(), i32> {
let passwords_ref = store.get_all_passwords();
let output_cursor: Cursor<Vec<u8>> = Cursor::new(Vec::new());
let mut csv_writer = Writer::from_writer(output_cursor);
for password in passwords_ref {
match csv_writer.write_record([
&password.name,
&password.username,
password.password.deref().as_str(),
]) {
Ok(_) => {}
Err(_) => return Err(1),
}
}
io.write(
String::from_utf8(csv_writer.into_inner().unwrap().into_inner()).unwrap(),
OutputType::Standard,
);
Ok(())
}
fn export_to_json(
_matches: &clap::ArgMatches,
store: &mut password::v2::PasswordStore,
io: &mut impl CliInputOutput,
) -> Result<(), i32> {
let export = JsonExport {
passwords: store.get_all_passwords().into_iter().cloned().collect(),
};
let passwords_json = match serde_json::to_string(&export) {
Ok(passwords_json) => passwords_json,
Err(json_err) => {
io.error(
format!(
"Woops, I could not encode the passwords into JSON (reason: {:?}).",
json_err
),
OutputType::Error,
);
return Err(1);
}
};
let passwords = SafeString::from_string(passwords_json);
io.write(passwords.deref().to_string(), OutputType::Standard);
Ok(())
}