diff options
Diffstat (limited to 'src/authenticate.rs')
| -rw-r--r-- | src/authenticate.rs | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/src/authenticate.rs b/src/authenticate.rs new file mode 100644 index 0000000..fab33a2 --- /dev/null +++ b/src/authenticate.rs @@ -0,0 +1,93 @@ +use std::path::Path; + +use auth_git2::Prompter; +use inquire::{InquireError, PasswordDisplayMode}; + +use crate::Config; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Inquirer<'a>(pub &'a Config); + +fn config_value(git_config: &git2::Config, name: &str) -> Option<String> { + git_config + .get_entry(name) + .ok() + .and_then(|entry| entry.value().map(|entry| entry.to_string())) +} + +fn prompt_secret(message: &str) -> Result<String, InquireError> { + inquire::Password::new(message) + .without_confirmation() + .with_display_mode(PasswordDisplayMode::Masked) + .prompt() +} + +impl Prompter for Inquirer<'_> { + fn prompt_username_password( + &mut self, + url: &str, + git_config: &git2::Config, + ) -> Option<(String, String)> { + let username = self + .0 + .username_for_url(url) + .cloned() + .or_else(|| config_value(git_config, "autosave.username")); + let password = self + .0 + .password_for_url(url) + .cloned() + .or_else(|| config_value(git_config, "autosave.password")); + if let Some(username) = username + && let Some(password) = password + { + return Some((username, password)); + } + + println!("Authenticating to {url}"); + let username = inquire::prompt_text("Username:").ok()?; + let password = prompt_secret("Password:").ok()?; + + Some((username, password)) + } + + fn prompt_password( + &mut self, + username: &str, + url: &str, + git_config: &git2::Config, + ) -> Option<String> { + let password = self + .0 + .password_for_url(url) + .cloned() + .or_else(|| config_value(git_config, "autosave.password")); + if let Some(password) = password { + return Some(password); + } + + println!("Authenticating to {url}"); + prompt_secret(&format!("Password for {username}:")).ok() + } + + fn prompt_ssh_key_passphrase( + &mut self, + private_key_path: &Path, + git_config: &git2::Config, + ) -> Option<String> { + let password = self + .0 + .passphrase_for_key(private_key_path) + .cloned() + .or_else(|| config_value(git_config, "autosave.password")); + if let Some(password) = password { + return Some(password); + } + + prompt_secret(&format!( + "Passphrase for {}:", + private_key_path.to_string_lossy() + )) + .ok() + } +} |
