diff --git a/conf/Cargo.toml b/conf/Cargo.toml index d856fbb..b0b9fd0 100644 --- a/conf/Cargo.toml +++ b/conf/Cargo.toml @@ -11,7 +11,10 @@ edition = "2018" path = "src/lib.rs" [dependencies] +duniter-core = { git = "https://git.duniter.org/nodes/rust/duniter-core" } +read_input = "0.8" serde = { version = "1.0.105", features = ["derive"] } +structopt = "0.3" [dev-dependencies] diff --git a/conf/src/lib.rs b/conf/src/lib.rs index 77d65d5..5773014 100644 --- a/conf/src/lib.rs +++ b/conf/src/lib.rs @@ -13,11 +13,14 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . +use duniter_core::module_cli::anyhow; +use read_input::prelude::*; use serde::{Deserialize, Serialize}; use std::{ + collections::HashSet, net::{IpAddr, Ipv4Addr, Ipv6Addr}, - vec, }; +use structopt::StructOpt; #[derive(Clone, Debug, Deserialize, Serialize)] pub struct GvaConf { @@ -96,3 +99,157 @@ impl GvaConf { .unwrap_or_else(|| self.subscriptions_path.clone()) } } + +#[derive(StructOpt)] +pub struct GvaCli {} + +#[derive(StructOpt)] +pub struct GvaCliConfigure {} + +impl duniter_core::module_cli::DuniterModuleCli for GvaCli { + const MODULE_NAME: &'static str = "gva"; + + type Conf = GvaConf; + + type ConfigureOpt = GvaCliConfigure; + + type Opt = Self; + + fn configure(mut conf: Self::Conf, _: Self::ConfigureOpt) -> Self::Conf { + // Enable GVA API? + let res = input().msg("Enable GVA API? [Y/n]").default('Y').get(); + conf.enabled = res != 'n'; + + if conf.enabled { + // ip4 + conf.ip4 = input() + .msg(format!("Listen to ip v4 ? [{}]", conf.ip4)) + .default(conf.ip4) + .get(); + // ip6 + let res = input().msg("Listen to ip v6? [Y/n]").default('Y').get(); + if res != 'n' { + let proposed_ip6 = conf.ip6.unwrap_or(Ipv6Addr::UNSPECIFIED); + conf.ip6 = Some( + input() + .msg(format!("Enter ip v6: [{}]", proposed_ip6)) + .default(proposed_ip6) + .get(), + ); + } else { + conf.ip6 = None; + } + // port + conf.port = input() + .msg(format!("Listen to port ? [{}]", conf.port)) + .default(conf.port) + .get(); + // path + conf.path = input() + .msg(format!("Path ? [{}]", conf.path)) + .default(conf.path) + .get(); + // subscriptionsPath + conf.subscriptions_path = input() + .msg(format!( + "Subscriptions path ? [{}]", + conf.subscriptions_path + )) + .default(conf.subscriptions_path) + .get(); + // remoteHost + if let Some(ref remote_host) = conf.remote_host { + let new_remote_host = input() + .msg(format!("Remote host ? [{}]", remote_host)) + .default(remote_host.to_owned()) + .get(); + if !new_remote_host.is_empty() { + conf.remote_host = Some(new_remote_host); + } + } else { + let new_remote_host: String = input().msg("Remote host ? ").get(); + if !new_remote_host.is_empty() { + conf.remote_host = Some(new_remote_host); + } + } + // remotePort + let res = input() + .msg("Define a remote port? [y/N]") + .default('N') + .get(); + if res == 'y' || res == 'Y' { + let default = conf.remote_port.unwrap_or(443); + conf.remote_port = Some( + input() + .msg(format!("Remote port ? [{}]", default)) + .default(default) + .get(), + ); + } else { + conf.remote_port = None; + } + // remotePath + let res = input() + .msg("Define a remote path? [y/N]") + .default('N') + .get(); + if res == 'y' || res == 'Y' { + conf.remote_path = Some(input().msg("Enter remote path:").get()); + } else { + conf.remote_path = None; + } + // remoteSubscriptionsPath + let res = input() + .msg("Define a remote subscriptions path? [y/N]") + .default('N') + .get(); + if res == 'y' || res == 'Y' { + conf.remote_subscriptions_path = + Some(input().msg("Enter remote subscriptions path:").get()); + } else { + conf.remote_subscriptions_path = None; + } + // whitelist + let mut whitelist: HashSet<_> = conf.whitelist.iter().copied().collect(); + let res = input().msg("Update whitelist? [y/N]").default('N').get(); + if res == 'y' || res == 'Y' { + loop { + println!("1. See whitelist content."); + println!("2. Add an IP to the whitelist."); + println!("3. Removing an IP from the whitelist."); + println!("4. Quit."); + match input().msg("Choose an action: ").default(1).get() { + 2usize => { + whitelist.insert(input().msg("Enter a new IP address: ").get()); + } + 3 => { + whitelist.remove( + &input().msg("Indicate the IP address to be deleted: ").get(), + ); + } + 4 => break, + _ => { + println!("--------------------------------"); + println!("Whitelist content ({} IPs):", whitelist.len()); + whitelist.iter().for_each(|ip| println!("{}", ip)); + println!("--------------------------------"); + } + } + } + } + conf.whitelist = whitelist.iter().copied().collect(); + } + + println!("Configuration successfully updated."); + + conf + } + + fn command( + _conf: Self::Conf, + _opt: Self::Opt, + _data_path: std::path::PathBuf, + ) -> anyhow::Result<()> { + unimplemented!() + } +}