From 272bd4725a9ce68923e59f1a8765dba0a6b4280f Mon Sep 17 00:00:00 2001 From: dvermd <888-dvermd@users.noreply.git.duniter.org> Date: Wed, 19 Feb 2020 11:42:44 +0100 Subject: [PATCH] [feat] conf: Replace keys modify salt/password opt by interactive input Closes #201 --- Cargo.lock | 2 +- lib/core/conf/Cargo.toml | 1 + lib/core/conf/src/keypairs/cli.rs | 289 +++++++++++++++-------------- lib/core/core/Cargo.toml | 1 - lib/core/core/src/commands/keys.rs | 66 +++---- lib/core/core/src/errors.rs | 10 +- 6 files changed, 189 insertions(+), 180 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index afae57ad..f8273605 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -983,6 +983,7 @@ dependencies = [ "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "mockall 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "once_cell 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rpassword 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1017,7 +1018,6 @@ dependencies = [ "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", "structopt 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "unwrap 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/lib/core/conf/Cargo.toml b/lib/core/conf/Cargo.toml index 7c2092f4..3428cc94 100644 --- a/lib/core/conf/Cargo.toml +++ b/lib/core/conf/Cargo.toml @@ -29,6 +29,7 @@ unwrap = "1.2.1" [dev-dependencies] durs-module = { path = "../module", features = ["module-test"] } maplit = "1.0.2" +mockall = { version = "0.6.0"} once_cell = "1.3.1" [features] diff --git a/lib/core/conf/src/keypairs/cli.rs b/lib/core/conf/src/keypairs/cli.rs index 22b5c245..215432ac 100644 --- a/lib/core/conf/src/keypairs/cli.rs +++ b/lib/core/conf/src/keypairs/cli.rs @@ -28,11 +28,25 @@ )] use crate::*; +#[cfg(test)] +use mockall::*; use std::io; +#[cfg_attr(test, automock)] +trait UserPasswordInput { + fn get_password(&self, prompt: &str) -> std::io::Result<String>; +} + +impl UserPasswordInput for std::io::Stdin { + #[inline] + fn get_password(&self, prompt: &str) -> std::io::Result<String> { + Ok(rpassword::prompt_password_stdout(prompt)?) + } +} + #[derive(Debug, Copy, Clone)] -/// Errors encountered by the wizard -pub enum WizardError { +/// Errors encountered by the user interaction +pub enum CliError { /// Canceled Canceled, @@ -40,83 +54,87 @@ pub enum WizardError { BadInput, } -impl From<std::io::Error> for WizardError { +impl From<std::io::Error> for CliError { fn from(_e: std::io::Error) -> Self { - WizardError::BadInput + CliError::BadInput } } +#[inline] /// Modify network keys command -pub fn modify_network_keys( - salt: String, - password: String, - mut key_pairs: DuniterKeyPairs, -) -> DuniterKeyPairs { - let generator = ed25519::KeyPairFromSaltedPasswordGenerator::with_default_parameters(); - key_pairs.network_keypair = - KeyPairEnum::Ed25519(generator.generate(ed25519::SaltedPassword::new(salt, password))); - key_pairs +pub fn modify_network_keys(key_pairs: DuniterKeyPairs) -> Result<DuniterKeyPairs, CliError> { + inner_modify_network_keys(std::io::stdin(), key_pairs) } -/// Modify member keys command -pub fn modify_member_keys( - salt: String, - password: String, +/// Private function to modify network keys +fn inner_modify_network_keys<T: UserPasswordInput>( + stdin: T, mut key_pairs: DuniterKeyPairs, -) -> DuniterKeyPairs { - let generator = ed25519::KeyPairFromSaltedPasswordGenerator::with_default_parameters(); - key_pairs.member_keypair = Some(KeyPairEnum::Ed25519( - generator.generate(ed25519::SaltedPassword::new(salt, password)), - )); - key_pairs +) -> Result<DuniterKeyPairs, CliError> { + key_pairs.network_keypair = salt_password_prompt(stdin)?; + Ok(key_pairs) } -/// 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 { - if let Ok("y") = question_prompt("Clear your network keypair?", &["y", "n"]) { - println!("Generating a new network keypair!"); - true - } else { - false - } - } else { - false - }, - if member { - if let Ok("y") = question_prompt("Clear your member keypair?", &["y", "n"]) { - println!("Deleting member keypair!"); - true - } else { - false - } - } else { - false - }, - key_pairs, - ) +#[inline] +/// Modify member keys command +pub fn modify_member_keys(key_pairs: DuniterKeyPairs) -> Result<DuniterKeyPairs, CliError> { + inner_modify_member_keys(std::io::stdin(), key_pairs) } -/// Private function to Clear keys -fn inner_clear_keys( - network: bool, - member: bool, +/// Private function to modify network keys +fn inner_modify_member_keys<T: UserPasswordInput>( + stdin: T, mut key_pairs: DuniterKeyPairs, -) -> DuniterKeyPairs { +) -> Result<DuniterKeyPairs, CliError> { + key_pairs.member_keypair = Some(salt_password_prompt(stdin)?); + Ok(key_pairs) +} + +/// Ask user for confirmation and Clear keys command +pub fn clear_keys(network: bool, member: bool, mut key_pairs: DuniterKeyPairs) -> DuniterKeyPairs { if network { - key_pairs.network_keypair = super::generate_random_keypair(KeysAlgo::Ed25519); + if let Ok("y") = question_prompt("Clear your network keypair?", &["y", "n"]) { + println!("Generating a new network keypair!"); + clear_network_key(&mut key_pairs); + } } if member { - key_pairs.member_keypair = None + if let Ok("y") = question_prompt("Clear your member keypair?", &["y", "n"]) { + println!("Deleting member keypair!"); + clear_member_key(&mut key_pairs); + } } key_pairs } +#[inline] +/// Private function to Clear keys +fn clear_network_key(key_pairs: &mut DuniterKeyPairs) { + key_pairs.network_keypair = super::generate_random_keypair(KeysAlgo::Ed25519); +} + +#[inline] +/// Private function to Clear member key +fn clear_member_key(key_pairs: &mut DuniterKeyPairs) { + key_pairs.member_keypair = None; +} + /// Show keys command pub fn show_keys(key_pairs: DuniterKeyPairs) { + show_network_keys(&key_pairs); + show_member_keys(&key_pairs); +} + +#[inline] +/// Show network keys +pub fn show_network_keys(key_pairs: &DuniterKeyPairs) { println!("Network key: {}", key_pairs.network_keypair); - match key_pairs.member_keypair { +} + +#[inline] +/// Show member keys +pub fn show_member_keys(key_pairs: &DuniterKeyPairs) { + match &key_pairs.member_keypair { None => println!("No member key configured"), Some(key) => println!("Member key: {}", key), } @@ -126,7 +144,7 @@ pub fn show_keys(key_pairs: DuniterKeyPairs) { pub fn save_keypairs( profile_path: PathBuf, keypairs_file_path: &Option<PathBuf>, - key_pairs: DuniterKeyPairs, + key_pairs: &DuniterKeyPairs, ) -> Result<(), std::io::Error> { let conf_keys_path: PathBuf = if let Some(keypairs_file_path) = keypairs_file_path { keypairs_file_path.to_path_buf() @@ -135,32 +153,30 @@ pub fn save_keypairs( conf_keys_path.push(crate::constants::KEYPAIRS_FILENAME); conf_keys_path }; - super::write_keypairs_file(&conf_keys_path, &key_pairs)?; - Ok(()) + super::write_keypairs_file(&conf_keys_path, &key_pairs) } -fn question_prompt<'a>(question: &str, answers: &[&'a str]) -> Result<&'a str, WizardError> { +fn question_prompt<'a>(question: &str, answers: &[&'a str]) -> Result<&'a str, CliError> { let mut buf = String::new(); println!("{} ({}):", question, answers.join("/")); let res = io::stdin().read_line(&mut buf); - match res { - Ok(_) => { - let answer = answers.iter().find(|x| **x == buf.trim()); - match answer { - Some(&value) => Ok(value), - None => Err(WizardError::Canceled), - } - } - Err(_) => Err(WizardError::Canceled), + if res.is_ok() { + answers + .iter() + .find(|x| **x == buf.trim()) + .copied() + .ok_or(CliError::Canceled) + } else { + Err(CliError::Canceled) } } -fn salt_password_prompt() -> Result<KeyPairEnum, WizardError> { - let salt = rpassword::prompt_password_stdout("Salt: ")?; +fn salt_password_prompt<T: UserPasswordInput>(stdin: T) -> Result<KeyPairEnum, CliError> { + let salt = stdin.get_password("Salt: ")?; if !salt.is_empty() { - let password = rpassword::prompt_password_stdout("Password: ")?; + let password = stdin.get_password("Password: ")?; if !password.is_empty() { let generator = ed25519::KeyPairFromSaltedPasswordGenerator::with_default_parameters(); let key_pairs = KeyPairEnum::Ed25519( @@ -168,26 +184,26 @@ fn salt_password_prompt() -> Result<KeyPairEnum, WizardError> { ); Ok(key_pairs) } else { - Err(WizardError::BadInput) + Err(CliError::BadInput) } } else { - Err(WizardError::BadInput) + Err(CliError::BadInput) } } /// The wizard key function -pub fn key_wizard(mut key_pairs: DuniterKeyPairs) -> Result<DuniterKeyPairs, WizardError> { +pub fn key_wizard(mut key_pairs: DuniterKeyPairs) -> Result<DuniterKeyPairs, CliError> { let mut answer = question_prompt("Modify your network keypair?", &["y", "n"])?; if answer == "y" { - key_pairs.network_keypair = salt_password_prompt()?; + key_pairs.network_keypair = salt_password_prompt(std::io::stdin())?; } answer = question_prompt("Modify your member keypair?", &["y", "n", "d"])?; if answer == "y" { - key_pairs.member_keypair = Some(salt_password_prompt()?); + key_pairs.member_keypair = Some(salt_password_prompt(std::io::stdin())?); } else if answer == "d" { println!("Deleting member keypair!"); - key_pairs.member_keypair = None; + clear_member_key(&mut key_pairs); } Ok(key_pairs) @@ -201,27 +217,60 @@ mod tests { static BASE58_SEED_INIT: &'static str = "4iXXx5GgRkZ85BVPwn8vFXvztdXAAa5yB573ErcAnngA"; static BASE58_PUB_INIT: &'static str = "otDgSpKvKAPPmE1MUYxc3UQ3RtEnKYz4iGD3BmwKPzM"; - //static SALT_INIT: &'static str = "initsalt"; - //static PASSWORD_INIT: &'static str = "initpassword"; static BASE58_SEED_TEST: &'static str = "ELjDWGPyCGMuhr7R7H2aip6UJA9qLRepmK77pcD41UqQ"; static BASE58_PUB_TEST: &'static str = "6sewkaNWyEMqkEa2PVRWrDb3hxWtjPdUSB1zXVCqhdWV"; static SALT_TEST: &'static str = "testsalt"; static PASSWORD_TEST: &'static str = "testpassword"; - #[test] - fn test_modify_member_keys() { - let key_pairs = DuniterKeyPairs { + fn setup_user_password_input() -> MockUserPasswordInput { + let mut stdin_mock = MockUserPasswordInput::new(); + stdin_mock + .expect_get_password() + .returning(|prompt| { + if prompt.starts_with("Salt:") { + Ok(SALT_TEST.to_owned()) + } else if prompt.starts_with("Password:") { + Ok(PASSWORD_TEST.to_owned()) + } else { + Err(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + format!("should not be called with {}", prompt), + )) + } + }) + .times(2); + stdin_mock + } + + fn setup_keys(both_keys: bool) -> DuniterKeyPairs { + let member_keypair = if both_keys { + Some(KeyPairEnum::Ed25519(ed25519::Ed25519KeyPair { + seed: Seed32::from_base58(BASE58_SEED_INIT) + .expect("conf : keypairs file : fail to parse network_seed !"), + pubkey: ed25519::PublicKey::from_base58(BASE58_PUB_INIT) + .expect("conf : keypairs file : fail to parse network_pub !"), + })) + } else { + None + }; + DuniterKeyPairs { network_keypair: KeyPairEnum::Ed25519(ed25519::Ed25519KeyPair { seed: Seed32::from_base58(BASE58_SEED_INIT) .expect("conf : keypairs file : fail to parse network_seed !"), pubkey: ed25519::PublicKey::from_base58(BASE58_PUB_INIT) .expect("conf : keypairs file : fail to parse network_pub !"), }), - member_keypair: None, - }; + member_keypair, + } + } + + #[test] + fn test_modify_member_keys() { + let key_pairs = setup_keys(false); + let stdin_mock = setup_user_password_input(); let result_key_pairs = - modify_member_keys(SALT_TEST.to_owned(), PASSWORD_TEST.to_owned(), key_pairs); + inner_modify_member_keys(stdin_mock, key_pairs).expect("Fail to read new member keys"); // We expect network key not to change assert_eq!( result_key_pairs.network_keypair.public_key(), @@ -260,17 +309,10 @@ mod tests { #[test] fn test_modify_network_keys() { - let key_pairs = DuniterKeyPairs { - network_keypair: KeyPairEnum::Ed25519(ed25519::Ed25519KeyPair { - seed: Seed32::from_base58(BASE58_SEED_INIT) - .expect("conf : keypairs file : fail to parse network_seed !"), - pubkey: ed25519::PublicKey::from_base58(BASE58_PUB_INIT) - .expect("conf : keypairs file : fail to parse network_pub !"), - }), - member_keypair: None, - }; - let result_key_pairs = - modify_network_keys(SALT_TEST.to_owned(), PASSWORD_TEST.to_owned(), key_pairs); + let key_pairs = setup_keys(false); + let stdin_mock = setup_user_password_input(); + let result_key_pairs = inner_modify_network_keys(stdin_mock, key_pairs) + .expect("Fail to read new network keys"); // We expect network key to update assert_eq!( result_key_pairs.network_keypair.public_key(), @@ -289,31 +331,18 @@ mod tests { #[test] fn test_clear_network_keys() { - let key_pairs = DuniterKeyPairs { - network_keypair: KeyPairEnum::Ed25519(ed25519::Ed25519KeyPair { - seed: Seed32::from_base58(BASE58_SEED_INIT) - .expect("conf : keypairs file : fail to parse network_seed !"), - pubkey: ed25519::PublicKey::from_base58(BASE58_PUB_INIT) - .expect("conf : keypairs file : fail to parse network_pub !"), - }), - member_keypair: Some(KeyPairEnum::Ed25519(ed25519::Ed25519KeyPair { - seed: Seed32::from_base58(BASE58_SEED_INIT) - .expect("conf : keypairs file : fail to parse network_seed !"), - pubkey: ed25519::PublicKey::from_base58(BASE58_PUB_INIT) - .expect("conf : keypairs file : fail to parse network_pub !"), - })), - }; - let result_key_pairs = inner_clear_keys(true, false, key_pairs); + let mut key_pairs = setup_keys(true); + clear_network_key(&mut key_pairs); // We expect network key to be reset to a new random key assert_ne!( - result_key_pairs.network_keypair.public_key(), + key_pairs.network_keypair.public_key(), PubKey::Ed25519( ed25519::PublicKey::from_base58(BASE58_PUB_INIT) .expect("Wrong data in BASE58_PUB_TEST") ) ); assert_ne!( - result_key_pairs.network_keypair.seed().clone(), + key_pairs.network_keypair.seed().clone(), unwrap!( Seed32::from_base58(BASE58_SEED_INIT), "Wrong data in BASE58_SEED_TEST" @@ -323,8 +352,8 @@ mod tests { // We expect member key not to change assert_eq!( unwrap!( - result_key_pairs.member_keypair.clone(), - "conf: result_keypair must have a value" + key_pairs.member_keypair.clone(), + "conf: keypair must have a value" ) .public_key(), PubKey::Ed25519( @@ -333,10 +362,10 @@ mod tests { ) ); assert_eq!( - result_key_pairs + key_pairs .member_keypair .clone() - .expect("conf: result_keypair must have a value") + .expect("conf: keypair must have a value") .seed() .clone(), Seed32::from_base58(BASE58_SEED_INIT).expect("Wrong data in BASE58_SEED_TEST") @@ -345,36 +374,22 @@ mod tests { #[test] fn test_clear_member_keys() { - let key_pairs = DuniterKeyPairs { - network_keypair: KeyPairEnum::Ed25519(ed25519::Ed25519KeyPair { - seed: Seed32::from_base58(BASE58_SEED_INIT) - .expect("conf : keypairs file : fail to parse network_seed !"), - pubkey: ed25519::PublicKey::from_base58(BASE58_PUB_INIT) - .expect("conf : keypairs file : fail to parse network_pub !"), - }), - member_keypair: Some(KeyPairEnum::Ed25519(ed25519::Ed25519KeyPair { - seed: Seed32::from_base58(BASE58_SEED_INIT) - .expect("conf : keypairs file : fail to parse network_seed !"), - pubkey: ed25519::PublicKey::from_base58(BASE58_PUB_INIT) - .expect("conf : keypairs file : fail to parse network_pub !"), - })), - }; - let result_key_pairs = inner_clear_keys(false, true, key_pairs); + let mut key_pairs = setup_keys(true); + clear_member_key(&mut key_pairs); // We expect network key not to change assert_eq!( - result_key_pairs.network_keypair.public_key(), + key_pairs.network_keypair.public_key(), PubKey::Ed25519( ed25519::PublicKey::from_base58(BASE58_PUB_INIT) .expect("Wrong data in BASE58_PUB_TEST") ) ); assert_eq!( - result_key_pairs.network_keypair.seed().clone(), + key_pairs.network_keypair.seed().clone(), Seed32::from_base58(BASE58_SEED_INIT).expect("Wrong data in BASE58_SEED_TEST") ); // We expect member key to change - assert_eq!(result_key_pairs.member_keypair, None); - assert_eq!(result_key_pairs.member_keypair, None); + assert_eq!(key_pairs.member_keypair, None); } } diff --git a/lib/core/core/Cargo.toml b/lib/core/core/Cargo.toml index 96b60338..92ba2279 100644 --- a/lib/core/core/Cargo.toml +++ b/lib/core/core/Cargo.toml @@ -32,6 +32,5 @@ serde_derive = "1.0.*" serde_json = "1.0.*" structopt= "0.3.9" unwrap = "1.2.1" -zeroize = { version = "1.1.0", features = ["zeroize_derive"] } [features] diff --git a/lib/core/core/src/commands/keys.rs b/lib/core/core/src/commands/keys.rs index 8686a4b6..a1c49ed7 100644 --- a/lib/core/core/src/commands/keys.rs +++ b/lib/core/core/src/commands/keys.rs @@ -21,9 +21,8 @@ use crate::DursCore; use clap::arg_enum; use durs_conf::keypairs::cli::*; use durs_conf::DuRsConf; -use zeroize::Zeroize; -#[derive(StructOpt, Debug, Clone)] +#[derive(StructOpt, Debug, Clone, Copy)] #[structopt( name = "keys", author = "inso <inso@tuta.io>", @@ -36,7 +35,7 @@ pub struct KeysOpt { pub subcommand: KeysSubCommand, } -#[derive(StructOpt, Debug, Clone)] +#[derive(StructOpt, Debug, Clone, Copy)] /// keys subcommands pub enum KeysSubCommand { /// Modify keys @@ -72,7 +71,7 @@ pub enum KeysSubCommand { Wizard(WizardOpt), } -#[derive(StructOpt, Debug, Clone)] +#[derive(StructOpt, Debug, Clone, Copy)] /// ModifyOpt pub struct ModifyOpt { #[structopt(subcommand)] @@ -80,16 +79,16 @@ pub struct ModifyOpt { pub subcommand: ModifySubCommand, } -#[derive(StructOpt, Debug, Clone)] +#[derive(StructOpt, Debug, Clone, Copy)] /// keys modify subcommands pub enum ModifySubCommand { #[structopt(name = "member", setting(structopt::clap::AppSettings::ColoredHelp))] /// Salt and password of member key - MemberSaltPassword(SaltPasswordOpt), + MemberSaltPassword, #[structopt(name = "network", setting(structopt::clap::AppSettings::ColoredHelp))] /// Salt and password of network key - NetworkSaltPassword(SaltPasswordOpt), + NetworkSaltPassword, } arg_enum! { @@ -121,19 +120,6 @@ pub struct ClearOpt { key: KeyKind, } -#[derive(StructOpt, Debug, Clone, Zeroize)] -#[zeroize(drop)] -/// SaltPasswordOpt -pub struct SaltPasswordOpt { - #[structopt(long = "salt")] - /// Salt of key generator - pub salt: String, - - #[structopt(long = "password")] - /// Password of key generator - pub password: String, -} - #[derive(StructOpt, Debug, Copy, Clone)] /// WizardOpt pub struct WizardOpt {} @@ -151,27 +137,31 @@ impl DursExecutableCoreCommand for KeysOpt { match self.subcommand { KeysSubCommand::Wizard(_) => { let new_keypairs = key_wizard(keypairs)?; - save_keypairs(profile_path, &keypairs_file, new_keypairs) + save_keypairs(profile_path, &keypairs_file, &new_keypairs) .map_err(DursCoreError::FailWriteKeypairsFile) + .and_then(|_| { + show_keys(new_keypairs); + Ok(()) + }) } KeysSubCommand::Modify(modify_opt) => match modify_opt.subcommand { - ModifySubCommand::NetworkSaltPassword(network_opt) => { - let new_keypairs = modify_network_keys( - network_opt.salt.clone(), - network_opt.password.clone(), - keypairs, - ); - save_keypairs(profile_path, &keypairs_file, new_keypairs) + ModifySubCommand::NetworkSaltPassword => { + let new_keypairs = modify_network_keys(keypairs)?; + save_keypairs(profile_path, &keypairs_file, &new_keypairs) .map_err(DursCoreError::FailWriteKeypairsFile) + .and_then(|_| { + show_network_keys(&new_keypairs); + Ok(()) + }) } - ModifySubCommand::MemberSaltPassword(member_opt) => { - let new_keypairs = modify_member_keys( - member_opt.salt.clone(), - member_opt.password.clone(), - keypairs, - ); - save_keypairs(profile_path, &keypairs_file, new_keypairs) + ModifySubCommand::MemberSaltPassword => { + let new_keypairs = modify_member_keys(keypairs)?; + save_keypairs(profile_path, &keypairs_file, &new_keypairs) .map_err(DursCoreError::FailWriteKeypairsFile) + .and_then(|_| { + show_member_keys(&new_keypairs); + Ok(()) + }) } }, KeysSubCommand::Clear(clear_opt) => { @@ -180,8 +170,12 @@ impl DursExecutableCoreCommand for KeysOpt { clear_opt.key.is_member(), keypairs, ); - save_keypairs(profile_path, &keypairs_file, new_keypairs) + save_keypairs(profile_path, &keypairs_file, &new_keypairs) .map_err(DursCoreError::FailWriteKeypairsFile) + .and_then(|_| { + show_keys(new_keypairs); + Ok(()) + }) } KeysSubCommand::Show(_) => { show_keys(keypairs); diff --git a/lib/core/core/src/errors.rs b/lib/core/core/src/errors.rs index 9e40dd0e..dd9d85ab 100644 --- a/lib/core/core/src/errors.rs +++ b/lib/core/core/src/errors.rs @@ -17,7 +17,7 @@ use crate::logger::InitLoggerError; use dubp_currency_params::db::CurrencyParamsDbError; -use durs_conf::keypairs::cli::WizardError; +use durs_conf::keypairs::cli::CliError; use durs_module::{ModuleStaticName, PlugModuleError}; use failure::{Error, Fail}; @@ -66,8 +66,8 @@ pub enum DursCoreError { #[fail(display = "Please specify the url of a trusted node or use the --local option.")] SyncWithoutSource, /// Error on keys sub-command - #[fail(display = "Error en keys sub-command")] - WizardKeysError(WizardError), + #[fail(display = "Error on keys sub-command")] + WizardKeysError(CliError), } impl From<InitLoggerError> for DursCoreError { @@ -76,8 +76,8 @@ impl From<InitLoggerError> for DursCoreError { } } -impl From<WizardError> for DursCoreError { - fn from(e: WizardError) -> Self { +impl From<CliError> for DursCoreError { + fn from(e: CliError) -> Self { DursCoreError::WizardKeysError(e) } } -- GitLab