Added an interactive cli dialog to kanidm login (#584)

This commit is contained in:
cuberoot74088 2021-10-01 00:35:01 +02:00 committed by GitHub
parent 573e346476
commit ed522fb769
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -12,6 +12,8 @@ use std::io::{self, BufReader, BufWriter, Write};
use std::path::PathBuf; use std::path::PathBuf;
use webauthn_authenticator_rs::{u2fhid::U2FHid, RequestChallengeResponse, WebauthnAuthenticator}; use webauthn_authenticator_rs::{u2fhid::U2FHid, RequestChallengeResponse, WebauthnAuthenticator};
use dialoguer::{theme::ColorfulTheme, Select};
static TOKEN_DIR: &str = "~/.cache"; static TOKEN_DIR: &str = "~/.cache";
static TOKEN_PATH: &str = "~/.cache/kanidm_tokens"; static TOKEN_PATH: &str = "~/.cache/kanidm_tokens";
@ -112,25 +114,25 @@ pub fn write_tokens(tokens: &BTreeMap<String, String>) -> Result<(), ()> {
}) })
} }
fn get_index_choice(len: usize) -> Result<u8, ClientError> { /// An interactive dialog to choose from given options
loop { fn get_index_choice_dialoguer(msg: &str, options: &Vec<String>) -> usize {
let mut buffer = String::new();
if let Err(e) = io::stdin().read_line(&mut buffer) { let user_select = Select::with_theme(&ColorfulTheme::default())
eprintln!("Failed to read from stdin -> {:?}", e); .with_prompt(&msg)
return Err(ClientError::SystemError); .default(0)
}; .items(&options)
let response = buffer.trim(); .interact();
match response.parse::<u8>() {
Ok(i) => { let selection = match user_select {
if (i as usize) < len { Err(error) => {
return Ok(i); eprintln!("Failed to handle user input: {:?}", error);
} else { std::process::exit(1);
eprintln!("Choice must be less than {}", len); }
} Ok(value) => value,
} };
Err(_) => eprintln!("Invalid Number"), debug!("Index of the chosen menu item: {:?}", selection);
};
} selection
} }
impl LoginOpt { impl LoginOpt {
@ -231,18 +233,17 @@ impl LoginOpt {
.get(0) .get(0)
.expect("can not fail - bounds already checked.") .expect("can not fail - bounds already checked.")
} }
len => { _ => {
println!("Please choose how you want to authenticate:"); let mut options = Vec::new();
for (i, val) in mechs.iter().enumerate() { for val in mechs.iter() {
println!("{}: {}", i, val) options.push(val.to_string());
} }
let mech_idx = get_index_choice(len).unwrap_or_else(|e| { let msg = "Please choose how you want to authenticate:";
error!("Error getting index choice -> {:?}", e); let selection = get_index_choice_dialoguer(&msg, &options);
std::process::exit(1);
});
#[allow(clippy::expect_used)] #[allow(clippy::expect_used)]
mechs mechs
.get(mech_idx as usize) .get(selection as usize)
.expect("can not fail - bounds already checked.") .expect("can not fail - bounds already checked.")
} }
}; };
@ -270,18 +271,17 @@ impl LoginOpt {
.get(0) .get(0)
.expect("can not fail - bounds already checked.") .expect("can not fail - bounds already checked.")
} }
len => { _ => {
println!("Please choose what credential to provide:"); let mut options = Vec::new();
for (i, val) in allowed.iter().enumerate() { for val in allowed.iter() {
println!("{}: {}", i, val) options.push(val.to_string());
} }
let idx = get_index_choice(len).unwrap_or_else(|e| { let msg = "Please choose what credential to provide:";
error!("Error getting index choice -> {:?}", e); let selection = get_index_choice_dialoguer(&msg, &options);
std::process::exit(1);
});
#[allow(clippy::expect_used)] #[allow(clippy::expect_used)]
allowed allowed
.get(idx as usize) .get(selection as usize)
.expect("can not fail - bounds already checked.") .expect("can not fail - bounds already checked.")
} }
}; };