mirror of https://github.com/chipsenkbeil/distant
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
86 lines
3.4 KiB
Rust
86 lines
3.4 KiB
Rust
use distant_net::{AuthChallengeFn, AuthErrorFn, AuthInfoFn, AuthVerifyFn, AuthVerifyKind};
|
|
use log::*;
|
|
use std::io;
|
|
|
|
/// Configuration to use when creating a new [`DistantManagerClient`](super::DistantManagerClient)
|
|
pub struct DistantManagerClientConfig {
|
|
pub on_challenge: Box<AuthChallengeFn>,
|
|
pub on_verify: Box<AuthVerifyFn>,
|
|
pub on_info: Box<AuthInfoFn>,
|
|
pub on_error: Box<AuthErrorFn>,
|
|
}
|
|
|
|
impl DistantManagerClientConfig {
|
|
/// Creates a new config with prompts that return empty strings
|
|
pub fn with_empty_prompts() -> Self {
|
|
Self::with_prompts(|_| Ok("".to_string()), |_| Ok("".to_string()))
|
|
}
|
|
|
|
/// Creates a new config with two prompts
|
|
///
|
|
/// * `password_prompt` - used for prompting for a secret, and should not display what is typed
|
|
/// * `text_prompt` - used for general text, and is okay to display what is typed
|
|
pub fn with_prompts<PP, PT>(password_prompt: PP, text_prompt: PT) -> Self
|
|
where
|
|
PP: Fn(&str) -> io::Result<String> + Send + Sync + 'static,
|
|
PT: Fn(&str) -> io::Result<String> + Send + Sync + 'static,
|
|
{
|
|
Self {
|
|
on_challenge: Box::new(move |questions, _extra| {
|
|
trace!("[manager client] on_challenge({questions:?}, {_extra:?})");
|
|
let mut answers = Vec::new();
|
|
for question in questions.iter() {
|
|
// Contains all prompt lines including same line
|
|
let mut lines = question.text.split('\n').collect::<Vec<_>>();
|
|
|
|
// Line that is prompt on same line as answer
|
|
let line = lines.pop().unwrap();
|
|
|
|
// Go ahead and display all other lines
|
|
for line in lines.into_iter() {
|
|
eprintln!("{}", line);
|
|
}
|
|
|
|
// Get an answer from user input, or use a blank string as an answer
|
|
// if we fail to get input from the user
|
|
let answer = password_prompt(line).unwrap_or_default();
|
|
|
|
answers.push(answer);
|
|
}
|
|
answers
|
|
}),
|
|
on_verify: Box::new(move |kind, text| {
|
|
trace!("[manager client] on_verify({kind}, {text})");
|
|
match kind {
|
|
AuthVerifyKind::Host => {
|
|
eprintln!("{}", text);
|
|
|
|
match text_prompt("Enter [y/N]> ") {
|
|
Ok(answer) => {
|
|
trace!("Verify? Answer = '{answer}'");
|
|
matches!(answer.trim(), "y" | "Y" | "yes" | "YES")
|
|
}
|
|
Err(x) => {
|
|
error!("Failed verification: {x}");
|
|
false
|
|
}
|
|
}
|
|
}
|
|
x => {
|
|
error!("Unsupported verify kind: {x}");
|
|
false
|
|
}
|
|
}
|
|
}),
|
|
on_info: Box::new(|text| {
|
|
trace!("[manager client] on_info({text})");
|
|
println!("{}", text);
|
|
}),
|
|
on_error: Box::new(|kind, text| {
|
|
trace!("[manager client] on_error({kind}, {text})");
|
|
eprintln!("{}: {}", kind, text);
|
|
}),
|
|
}
|
|
}
|
|
}
|