From bc190051db93c4eab5348e69a148020f21bd28a8 Mon Sep 17 00:00:00 2001 From: notplants Date: Mon, 26 May 2025 17:56:04 -0400 Subject: [PATCH] bundle change-password cli with peach-web --- Cargo.lock | 1 + peach-web/Cargo.toml | 1 + peach-web/src/cli/change_password.rs | 34 ++++++++++++++++++++++++++++ peach-web/src/cli/mod.rs | 1 + peach-web/src/error.rs | 6 +++++ peach-web/src/main.rs | 29 ++++++++++++++++++------ tilde-client/src/lib.rs | 1 + 7 files changed, 66 insertions(+), 7 deletions(-) create mode 100644 peach-web/src/cli/change_password.rs create mode 100644 peach-web/src/cli/mod.rs diff --git a/Cargo.lock b/Cargo.lock index ee6e509..788c448 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2575,6 +2575,7 @@ dependencies = [ "peach-stats", "reqwest", "rouille", + "rpassword", "temporary", "urlencoding", "vnstat_parse", diff --git a/peach-web/Cargo.toml b/peach-web/Cargo.toml index dc495c5..9616bc6 100644 --- a/peach-web/Cargo.toml +++ b/peach-web/Cargo.toml @@ -52,3 +52,4 @@ xdg = "2.2" jsonrpc_client = { version = "0.7", features = ["macros", "reqwest"] } reqwest = "0.11.24" urlencoding = "2.1.3" +rpassword = "5.0" diff --git a/peach-web/src/cli/change_password.rs b/peach-web/src/cli/change_password.rs new file mode 100644 index 0000000..c776a0b --- /dev/null +++ b/peach-web/src/cli/change_password.rs @@ -0,0 +1,34 @@ +use peach_lib::password_utils::set_new_password; +use crate::error::PeachWebError; + +/// Utility function to set the admin password for peach-web from the command-line. +pub fn set_peach_web_password(password: Option) -> Result<(), PeachWebError> { + match password { + // read password from CLI arg + Some(password) => { + set_new_password(&password) + .map_err(|err| PeachWebError::PeachLib { source: err, msg: "Error setting password via cli".to_string() })?; + println!( + "Your new password has been set for peach-web. You can login through the \ + web interface with username admin." + ); + Ok(()) + } + // read password from tty + None => { + let pass1 = rpassword::read_password_from_tty(Some("New password: "))?; + let pass2 = rpassword::read_password_from_tty(Some("Confirm password: "))?; + if pass1 != pass2 { + Err(PeachWebError::InvalidPassword) + } else { + set_new_password(&pass1) + .map_err(|err| PeachWebError::PeachLib { source: err, msg: "Passwords did not match".to_string() })?; + println!( + "Your new password has been set for peach-web. You can login through the \ + web interface with username admin." + ); + Ok(()) + } + } + } +} \ No newline at end of file diff --git a/peach-web/src/cli/mod.rs b/peach-web/src/cli/mod.rs new file mode 100644 index 0000000..68d8a82 --- /dev/null +++ b/peach-web/src/cli/mod.rs @@ -0,0 +1 @@ +pub mod change_password; \ No newline at end of file diff --git a/peach-web/src/error.rs b/peach-web/src/error.rs index dfe7ec6..007eb54 100644 --- a/peach-web/src/error.rs +++ b/peach-web/src/error.rs @@ -19,6 +19,7 @@ pub enum PeachWebError { PeachLib { source: PeachError, msg: String }, Yaml(YamlError), Tilde(TildeError), + InvalidPassword, NotYetImplemented, } @@ -27,6 +28,7 @@ impl std::error::Error for PeachWebError { match *self { PeachWebError::FailedToRegisterDynDomain(_) => None, PeachWebError::HomeDir => None, + PeachWebError::InvalidPassword => None, PeachWebError::Io(ref source) => Some(source), PeachWebError::Json(ref source) => Some(source), PeachWebError::OsString => None, @@ -48,6 +50,10 @@ impl std::fmt::Display for PeachWebError { f, "Filesystem error: failed to determine home directory path" ), + PeachWebError::InvalidPassword => write!( + f, + "Failed to change password via CLI" + ), PeachWebError::Io(ref source) => write!(f, "IO error: {}", source), PeachWebError::Json(ref source) => write!(f, "Serde JSON error: {}", source), PeachWebError::OsString => write!( diff --git a/peach-web/src/main.rs b/peach-web/src/main.rs index 01ccc73..9c7fa78 100644 --- a/peach-web/src/main.rs +++ b/peach-web/src/main.rs @@ -19,11 +19,9 @@ mod public_router; mod routes; mod templates; pub mod utils; +mod cli; -use std::{ - collections::HashMap, - sync::{Mutex, RwLock}, -}; +use std::{collections::HashMap, env, sync::{Mutex, RwLock}}; use lazy_static::lazy_static; use log::info; @@ -52,9 +50,7 @@ pub struct SessionData { } /// Launch the peach-web server. -fn main() { - // initialize logger - env_logger::init(); +fn run_webserver() { // set ip address / hostname and port for the webserver // defaults to "127.0.0.1:8000" @@ -121,3 +117,22 @@ fn main() { }) }); } + +/// cli entry point +fn main() { + env_logger::init(); + + let mut args = env::args(); + let _program = args.next(); // skip program name + + match args.next().as_deref() { + Some("run") => run_webserver(), + Some("change-password") => { + cli::change_password::set_peach_web_password(args.next()); + } + _ => { + eprintln!("Usage: peach-web "); + std::process::exit(1); + } + } +} \ No newline at end of file diff --git a/tilde-client/src/lib.rs b/tilde-client/src/lib.rs index 1b2d86f..1c0829e 100644 --- a/tilde-client/src/lib.rs +++ b/tilde-client/src/lib.rs @@ -38,6 +38,7 @@ impl TildeClient { } let result = String::from_utf8_lossy(&output.stdout).to_string(); + println!("Command: {:?}", command); println!("Command output: {}", result); Ok(result)