From 1d38e8ae2a7db505fa9bf6d592bcf8cf6ce841bd Mon Sep 17 00:00:00 2001 From: cgeek <cem.moreau@gmail.com> Date: Mon, 11 Oct 2021 19:08:18 +0200 Subject: [PATCH] refact: lighter main --- .gitignore | 1 + src/bma/lookup_identity.rs | 2 +- src/cli/certify.rs | 2 +- src/cli/mod.rs | 99 ++++++++++++++++++++++++++++++++------ src/main.rs | 23 +++++---- 5 files changed, 100 insertions(+), 27 deletions(-) diff --git a/.gitignore b/.gitignore index ea8c4bf..6b39d31 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +.idea/ \ No newline at end of file diff --git a/src/bma/lookup_identity.rs b/src/bma/lookup_identity.rs index d15c01e..398b54f 100644 --- a/src/bma/lookup_identity.rs +++ b/src/bma/lookup_identity.rs @@ -23,7 +23,7 @@ impl LookupIdentity { } } -pub fn lookup(node: BmaNode, uid_or_pub: String) -> () { +pub fn lookup(node: &BmaNode, uid_or_pub: &String) -> () { let address = node.get_address(); let resp = reqwest::blocking::get(format!("{}/wot/lookup/{}", address, uid_or_pub)).expect("Could not fetch lookup data from distant node"); lookup_print(&LookupResult(&resp.json().expect("Could not get JSON result from distant node"))); diff --git a/src/cli/certify.rs b/src/cli/certify.rs index 84b8052..b6441c9 100644 --- a/src/cli/certify.rs +++ b/src/cli/certify.rs @@ -5,7 +5,7 @@ use crate::crypto::duniter_key::ToDuniterKey; use crate::dubp::documents::certification::Certification; use crate::dubp::signable::Signable; -pub fn certify(node: BmaNode, uid_or_pub: String) -> Result<(), String> { +pub fn certify(node: &BmaNode, uid_or_pub: &String) -> Result<(), String> { let address = node.get_address(); println!("Fetching identity using \"{}\" pattern...", uid_or_pub); let resp = reqwest::blocking::get(format!("{}/wot/lookup/{}", address, uid_or_pub)).expect("Could not fetch lookup data from distant node"); diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 4f69eae..a6c4df6 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -3,62 +3,131 @@ use std::env::Args; use crate::cli::Command::*; use crate::bma::BmaNode; use std::env; +use crate::{bma, cli, compute_key, compute_pub, compute_sec}; +use crate::crypto::duniter_key::ScryptDuniterKey; +use core::fmt; pub mod certify; const DEFAULT_NODE: &str = "https://g1-test.duniter.org"; +// TODO: constantize pub, sec, etc + pub enum Command { /// Compute the public key from salt/passwd and displays it - PUB(String, String), + PUB(String, String, String), /// Compute the secret key from salt/passwd and displays it - SEC(String, String), + SEC(String, String, String), /// Compute the keyring from salt/passwd and displays it - KEYRING(String, String), + KEYRING(String, String, String), /// Search an identity on a Duniter node (BMA API) - LOOKUP(BmaNode, String), + LOOKUP(String, BmaNode, String), /// Search an identity on a Duniter node (BMA API) and certify it - CERTIFY(BmaNode, String), - /// Unknown command - UNKNOWN(String) + CERTIFY(String, BmaNode, String), + /// Some unknown command + UNKNOWN(String), } impl Command { - pub fn from(mut args: Args) -> Command { + pub fn name(&self) -> String { + let str_name = match self { + PUB(_, _, _) => "pub", + SEC(_, _, _) => "sec", + KEYRING(_, _, _) => "keyring", + LOOKUP(_, _, _) => "lookup", + CERTIFY(_, _, _) => "certify", + UNKNOWN(name) => name.as_str(), + }; + str_name.to_string() + } + + pub fn execute(&self) -> Result<(), String> { + match self { + PUB(_, salt, passwd) => { + println!("{}", compute_pub(ScryptDuniterKey::new(salt.to_string(), passwd.to_string()))); + } + SEC(_, salt, passwd) => println!("{}", compute_sec(ScryptDuniterKey::new(salt.to_string(), passwd.to_string()))), + KEYRING(_, salt, passwd) => println!("{}", compute_key(ScryptDuniterKey::new(salt.to_string(), passwd.to_string()))), + LOOKUP(_, bma_node, uid_or_pub) => bma::lookup_identity::lookup(bma_node, uid_or_pub), + CERTIFY(_, bma_node, uid_or_pub) => cli::certify::certify(bma_node, uid_or_pub).unwrap_or_else(|e| eprintln!("{}", e)), + UNKNOWN(cmd) => eprintln!("Unknown command {}", cmd), + _ => return Err("Not handled command yet".to_string()) + } + Ok(()) + } + + pub fn from<I>(mut args: I) -> Option<Command> + where I:Iterator<Item = String> { args.next(); - let command = args.next().expect("Command must be provided"); + let command = match args.next() { + None => return None, + Some(cmd_name) => cmd_name + }; let command = command.as_str(); match command { "pub" => { let salt = args.next().expect("Salt must be provided"); let passwd = args.next().expect("Password must be provided"); - PUB(salt, passwd) + Some(PUB(command.to_string(), salt, passwd)) }, "sec" => { let salt = args.next().expect("Salt must be provided"); let passwd = args.next().expect("Password must be provided"); - SEC(salt, passwd) + Some(SEC(command.to_string(), salt, passwd)) }, "keyring" => { let salt = args.next().expect("Salt must be provided"); let passwd = args.next().expect("Password must be provided"); - KEYRING(salt, passwd) + Some(KEYRING(command.to_string(), salt, passwd)) }, "lookup" => { let uid_or_pub = args.next().expect("UID or pubkey must be provided"); let default = String::from(DEFAULT_NODE); let bma_node = BmaNode::new(env::var("DUNITER_NODE").unwrap_or(default).as_str()); - LOOKUP(bma_node, uid_or_pub) + Some(LOOKUP(command.to_string(), bma_node, uid_or_pub)) }, "cert" => { let uid_or_pub = args.next().expect("UID or pubkey must be provided"); let default = String::from(DEFAULT_NODE); let bma_node = BmaNode::new(env::var("DUNITER_NODE").unwrap_or(default).as_str()); - CERTIFY(bma_node, uid_or_pub) + Some(CERTIFY(command.to_string(), bma_node, uid_or_pub)) }, - _ => UNKNOWN(String::from(command)), + _ => Some(UNKNOWN(command.to_string())), } } +} + +#[cfg(test)] +mod tests { + use crate::cli::Command; + use crate::cli::Command::PUB; + + #[test] + fn known_command () { + let args = vec!["", "pub", "abc", "def"]; + let cmd = Command::from(args.into_iter().map(|x| x.to_string())); + assert!(cmd.is_some()); + let cmd = cmd.unwrap(); + let is_expected_cmd = if let Command::PUB(..) = cmd { true } else { false }; + assert!(is_expected_cmd); + } + + #[test] + fn unknown_command () { + let args = vec!["", "abracadabra"]; + let cmd = Command::from(args.into_iter().map(|x| x.to_string())); + assert!(cmd.is_some()); + let cmd = cmd.unwrap(); + let is_expected_cmd = if let Command::UNKNOWN(..) = cmd { true } else { false }; + assert!(is_expected_cmd); + } + + #[test] + fn no_command () { + let args = vec![""]; + let cmd = Command::from(args.into_iter().map(|x| x.to_string())); + assert!(cmd.is_none()); + } } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 0eb54a9..8d327d3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,21 +1,24 @@ use std::env; +use std::process::exit; use duniter_mini_client::{compute_pub, compute_sec, compute_key, cli, bma}; use duniter_mini_client::cli::Command; -use duniter_mini_client::cli::Command::{UNKNOWN, PUB, SEC, KEYRING, LOOKUP, CERTIFY}; +use duniter_mini_client::cli::Command::{PUB, SEC, KEYRING, LOOKUP, CERTIFY}; use duniter_mini_client::crypto::duniter_key::ScryptDuniterKey; fn main() { let command = Command::from(env::args()); - // TODO: Result<(), String> - - match command { - PUB(salt, passwd) => println!("{}", compute_pub(ScryptDuniterKey::new(salt, passwd))), - SEC(salt, passwd) => println!("{}", compute_sec(ScryptDuniterKey::new(salt, passwd))), - KEYRING(salt, passwd) => println!("{}", compute_key(ScryptDuniterKey::new(salt, passwd))), - LOOKUP(bma_node, uid_or_pub) => bma::lookup_identity::lookup(bma_node, uid_or_pub), - CERTIFY(bma_node, uid_or_pub) => cli::certify::certify(bma_node, uid_or_pub).unwrap_or_else(|e| eprintln!("{}", e)), - UNKNOWN(cmd) => eprintln!("Unknown command {}", cmd), + let command = match command { + Some(c) => c, + None => { + eprintln!("No command found"); + exit(1); + } }; + + if let Err(e) = command.execute() { + eprintln!("Command executed with error: {}", e); + exit(2); + } } \ No newline at end of file -- GitLab