diff options
Diffstat (limited to 'console/src/utils.rs')
| -rw-r--r-- | console/src/utils.rs | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/console/src/utils.rs b/console/src/utils.rs new file mode 100644 index 0000000..1e65f0e --- /dev/null +++ b/console/src/utils.rs @@ -0,0 +1,107 @@ +use std::io::{self, Read, Write}; +use crossterm::terminal; +use tokio::task; + +pub fn read_password(prompt: &str) -> Option<String> { + print!("{}", prompt); + io::stdout().flush().unwrap(); + + let raw_mode_enabled = terminal::enable_raw_mode().is_ok(); + if !raw_mode_enabled { + eprintln!("Warning: Password will be displayed in plain text"); + } + + let mut buffer = Vec::new(); + loop { + let mut byte = [0]; + if io::stdin().read(&mut byte).is_err() || byte[0] == b'\n' || byte[0] == b'\r' { + break; + } + + match byte[0] { + 8 | 127 => { + if buffer.pop().is_some() { + print!("\x08 \x08"); + io::stdout().flush().unwrap(); + } + } + 3 => { + println!(); + return None; + } + _ => { + buffer.push(byte[0]); + print!("*"); + io::stdout().flush().unwrap(); + } + } + } + + if raw_mode_enabled { + terminal::disable_raw_mode().unwrap(); + } + println!(); + + Some(String::from_utf8_lossy(&buffer).into_owned()) +} + +pub fn read_password_and_confirm( + prompt: &str, + confirm_prompt: &str +) -> Option<String> { + loop { + let pw1 = read_password(prompt).unwrap(); + let pw2 = read_password(confirm_prompt).unwrap(); + + if pw1 == pw2 { + return Some(pw1); + } + eprintln!("The passwords entered twice do not match, please try again."); + } +} + +pub fn confirm(prompt: &str) -> bool { + let prompt = format!("{} [Y/n]: ", prompt); + loop { + let input = read_password(&prompt).unwrap_or_default(); + match input.to_lowercase().as_str() { + "y" | "yes" | "" => return true, + "n" | "no" => return false, + _ => eprintln!("Invalid input, please enter Y or n."), + } + } +} + +pub async fn read_password_async(prompt: &str) -> Option<String> { + let prompt = prompt.to_owned(); + task::spawn_blocking(move || read_password(&prompt)) + .await + .unwrap_or_else(|_| None) +} + +pub async fn read_password_and_confirm_async( + prompt: &str, + confirm_prompt: &str +) -> Option<String> { + loop { + let pw1 = read_password_async(prompt).await.unwrap(); + let pw2 = read_password_async(confirm_prompt).await.unwrap(); + + if pw1 == pw2 { + return Some(pw1); + } + eprintln!("The passwords entered twice do not match, please try again."); + } +} + +pub async fn confirm_async(prompt: &str) -> bool { + let prompt = format!("{} [Y/n]: ", prompt); + loop { + let input = read_password_async(&prompt).await.unwrap_or_default(); + match input.to_lowercase().as_str() { + "y" | "yes" | "" => return true, + "n" | "no" => return false, + _ => eprintln!("Invalid input, please enter Y or n."), + } + } +}
\ No newline at end of file |
