diff --git a/Cargo.lock b/Cargo.lock index dc959cf6c68125eab1e3e61444f9e855a2a02c82..733c0a92ed110cb667ca6caebdbfc99ebcfcb951 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1031,6 +1031,7 @@ name = "durs-core" version = "0.3.0-dev" dependencies = [ "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "dubp-currency-params 0.2.0", diff --git a/lib/core/conf/src/keys.rs b/lib/core/conf/src/keys.rs index 1c9c0e758ac888cf29d82b3091faf4138695fc5a..86a3b1109ac26b1499db503fa47d56735e21a269 100644 --- a/lib/core/conf/src/keys.rs +++ b/lib/core/conf/src/keys.rs @@ -71,16 +71,46 @@ pub fn modify_member_keys( key_pairs } -/// Clear keys command -pub fn clear_keys(network: bool, member: bool, mut key_pairs: DuniterKeyPairs) -> DuniterKeyPairs { +/// Ask user for confirmation and Clear keys command +pub fn clear_keys(network: bool, member: bool, key_pairs: DuniterKeyPairs) -> DuniterKeyPairs { + inner_clear_keys( + if network { + match question_prompt("Clear your network keypair?", &["y", "n"]) { + Ok(answer) if answer == "y" => { + println!("Generating a new network keypair!"); + true + } + _ => false, + } + } else { + false + }, + if member { + match question_prompt("Clear your member keypair?", &["y", "n"]) { + Ok(answer) if answer == "y" => { + println!("Deleting member keypair!"); + true + } + _ => false, + } + } else { + false + }, + key_pairs, + ) +} + +/// Private function to Clear keys +fn inner_clear_keys( + network: bool, + member: bool, + mut key_pairs: DuniterKeyPairs, +) -> DuniterKeyPairs { if network { key_pairs.network_keypair = generate_random_keypair(KeysAlgo::Ed25519); } if member { - key_pairs.member_keypair = None; - } - if !network && !member { - println!("No key was cleared. Please specify a key to clear.") + key_pairs.member_keypair = None } key_pairs } @@ -111,7 +141,7 @@ pub fn save_keypairs( Ok(()) } -fn question_prompt(question: &str, answers: Vec<String>) -> Result<String, WizardError> { +fn question_prompt<'a>(question: &str, answers: &[&'a str]) -> Result<&'a str, WizardError> { let mut buf = String::new(); println!("{} ({}):", question, answers.join("/")); @@ -119,9 +149,9 @@ fn question_prompt(question: &str, answers: Vec<String>) -> Result<String, Wizar match res { Ok(_) => { - let answer = answers.into_iter().find(|x| x == buf.trim()); + let answer = answers.iter().find(|x| **x == buf.trim()); match answer { - Some(value) => Ok(value), + Some(&value) => Ok(value), None => Err(WizardError::Canceled), } } @@ -149,18 +179,12 @@ fn salt_password_prompt() -> Result<KeyPairEnum, WizardError> { /// The wizard key function pub fn key_wizard(mut key_pairs: DuniterKeyPairs) -> Result<DuniterKeyPairs, WizardError> { - let mut answer = question_prompt( - "Modify your network keypair?", - vec!["y".to_string(), "n".to_string()], - )?; + let mut answer = question_prompt("Modify your network keypair?", &["y", "n"])?; if answer == "y" { key_pairs.network_keypair = salt_password_prompt()?; } - answer = question_prompt( - "Modify your member keypair?", - vec!["y".to_string(), "n".to_string(), "d".to_string()], - )?; + answer = question_prompt("Modify your member keypair?", &["y", "n", "d"])?; if answer == "y" { key_pairs.member_keypair = Some(salt_password_prompt()?); } else if answer == "d" { @@ -281,7 +305,7 @@ mod tests { .expect("conf : keypairs file : fail to parse network_pub !"), })), }; - let result_key_pairs = clear_keys(true, false, key_pairs); + let result_key_pairs = inner_clear_keys(true, false, key_pairs); // We expect network key to be reset to a new random key assert_ne!( result_key_pairs.network_keypair.public_key(), @@ -337,7 +361,7 @@ mod tests { .expect("conf : keypairs file : fail to parse network_pub !"), })), }; - let result_key_pairs = clear_keys(false, true, key_pairs); + let result_key_pairs = inner_clear_keys(false, true, key_pairs); // We expect network key not to change assert_eq!( result_key_pairs.network_keypair.public_key(), diff --git a/lib/core/core/Cargo.toml b/lib/core/core/Cargo.toml index b8bc60d018df9bac5cf9f39a5a8b1962adfdf1b1..b32dd51d5ce6c0fa9ed766314ead4c0e4442c5c2 100644 --- a/lib/core/core/Cargo.toml +++ b/lib/core/core/Cargo.toml @@ -11,6 +11,7 @@ path = "src/lib.rs" [dependencies] chrono = "0.4" +clap = "2.33.0" clear_on_drop = "0.2.3" dirs = "2.0.2" durs-bc = { path = "../../modules/blockchain/blockchain" } diff --git a/lib/core/core/src/commands/keys.rs b/lib/core/core/src/commands/keys.rs index b67fef8e3cb472b4d5e241187f222ff9dac21715..8bf320f9a0182d0df4581467fb4823bd22a2d020 100644 --- a/lib/core/core/src/commands/keys.rs +++ b/lib/core/core/src/commands/keys.rs @@ -18,6 +18,7 @@ use crate::commands::DursExecutableCoreCommand; use crate::errors::DursCoreError; use crate::DursCore; +use clap::arg_enum; use clear_on_drop::clear::Clear; use durs_conf::keys::*; use durs_conf::DuRsConf; @@ -91,20 +92,33 @@ pub enum ModifySubCommand { NetworkSaltPassword(SaltPasswordOpt), } +arg_enum! { + /// KeyKind + #[derive(Debug, Copy, Clone, PartialEq)] + enum KeyKind { + MEMBER, + NETWORK, + ALL, + } +} + +impl KeyKind { + /// Returns if key kind is member + pub fn is_member(self) -> bool { + self == KeyKind::MEMBER || self == KeyKind::ALL + } + /// Returns if key kind is network + pub fn is_network(self) -> bool { + self == KeyKind::NETWORK || self == KeyKind::ALL + } +} + #[derive(StructOpt, Debug, Copy, Clone)] /// ClearOpt pub struct ClearOpt { - #[structopt(short = "m", long = "member")] - /// True if we change member key - pub member: bool, - - #[structopt(short = "n", long = "network")] - /// True if we change network key - pub network: bool, - - #[structopt(short = "a", long = "all")] - /// True if we change member and network key - pub all: bool, + /// Key to clear + #[structopt(possible_values = &KeyKind::variants(), case_insensitive = true)] + key: KeyKind, } #[derive(StructOpt, Debug, Clone)] @@ -169,8 +183,8 @@ impl DursExecutableCoreCommand for KeysOpt { }, KeysSubCommand::Clear(clear_opt) => { let new_keypairs = clear_keys( - clear_opt.network || clear_opt.all, - clear_opt.member || clear_opt.all, + clear_opt.key.is_network(), + clear_opt.key.is_member(), keypairs, ); save_keypairs(profile_path, &keypairs_file, new_keypairs)