Allow executing program to retrieve credentials
* config / authentication: permit to call external program for getting credentials You can add into your ncspot/config.toml like this: ``` creds_username = "mylogin" creds_passeval = "pass my_pass_path_to_spot_password" ``` Or using any password manager who send your password.to stdout. If a newline is detected it will be automatically removed * Move credential commands into separate structure Also add an option for a username command * Document credential commands --------- Co-authored-by: Henrik Friedrichsen <henrik@affekt.org>
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
use std::process::Command;
|
||||
|
||||
use cursive::traits::Resizable;
|
||||
use cursive::view::Nameable;
|
||||
use cursive::views::*;
|
||||
@@ -60,6 +62,38 @@ pub fn create_credentials() -> Result<RespotCredentials, String> {
|
||||
.unwrap_or_else(|| Err("Didn't obtain any credentials".to_string()))
|
||||
}
|
||||
|
||||
pub fn credentials_eval(
|
||||
username_cmd: &str,
|
||||
password_cmd: &str,
|
||||
) -> Result<RespotCredentials, String> {
|
||||
fn eval(cmd: &str) -> Result<Vec<u8>, String> {
|
||||
println!("Executing \"{}\"", cmd);
|
||||
let mut result = Command::new("sh")
|
||||
.args(["-c", cmd])
|
||||
.output()
|
||||
.map_err(|e| e.to_string())?
|
||||
.stdout;
|
||||
if let Some(&last_byte) = result.last() {
|
||||
if last_byte == 10 {
|
||||
result.pop();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
println!("Retrieving username");
|
||||
let username = String::from_utf8_lossy(&eval(username_cmd)?).into();
|
||||
println!("Retrieving password");
|
||||
let password = eval(password_cmd)?;
|
||||
|
||||
Ok(RespotCredentials {
|
||||
username,
|
||||
auth_type: AuthenticationType::AUTHENTICATION_USER_PASS,
|
||||
auth_data: password,
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct AuthResponse {
|
||||
pub credentials: RespotCredentials,
|
||||
|
||||
@@ -93,6 +93,13 @@ pub struct ConfigValues {
|
||||
pub statusbar_format: Option<String>,
|
||||
pub library_tabs: Option<Vec<LibraryTab>>,
|
||||
pub hide_display_names: Option<bool>,
|
||||
pub credentials: Option<Credentials>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
|
||||
pub struct Credentials {
|
||||
pub username_cmd: Option<String>,
|
||||
pub password_cmd: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
|
||||
|
||||
12
src/main.rs
12
src/main.rs
@@ -191,7 +191,17 @@ fn main() -> Result<(), String> {
|
||||
info!("Using cached credentials");
|
||||
c
|
||||
}
|
||||
None => credentials_prompt(None)?,
|
||||
None => {
|
||||
info!("Attempting to resolve credentials via username/password commands");
|
||||
let creds = cfg.values().credentials.clone().unwrap_or_default();
|
||||
|
||||
match (creds.username_cmd, creds.password_cmd) {
|
||||
(Some(username_cmd), Some(password_cmd)) => {
|
||||
authentication::credentials_eval(&username_cmd, &password_cmd)?
|
||||
}
|
||||
_ => credentials_prompt(None)?,
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user