diff --git a/radicle-cli/src/commands/auth.rs b/radicle-cli/src/commands/auth.rs index 0fb5f894..30da2dc5 100644 --- a/radicle-cli/src/commands/auth.rs +++ b/radicle-cli/src/commands/auth.rs @@ -171,12 +171,12 @@ pub fn authenticate(options: Options, profile: &Profile) -> anyhow::Result<()> { term::success!("Radicle key already in ssh-agent"); return Ok(()); } - - let validator = term::io::PassphraseValidator::new(profile.keystore.clone()); - let passphrase = if options.stdin { + let passphrase = if let Some(phrase) = profile::env::passphrase() { + phrase + } else if options.stdin { term::passphrase_stdin()? } else { - term::passphrase(RAD_PASSPHRASE, validator)? + term::io::passphrase(term::io::PassphraseValidator::new(profile.keystore.clone()))? }; register(&mut agent, profile, passphrase)?; @@ -191,7 +191,7 @@ pub fn authenticate(options: Options, profile: &Profile) -> anyhow::Result<()> { // Try RAD_PASSPHRASE fallback. if let Some(passphrase) = profile::env::passphrase() { ssh::keystore::MemorySigner::load(&profile.keystore, Some(passphrase)) - .map_err(|_| anyhow!("RAD_PASSPHRASE failed"))?; + .map_err(|_| anyhow!("`{RAD_PASSPHRASE}` is invalid"))?; return Ok(()); }; diff --git a/radicle-cli/src/commands/node/control.rs b/radicle-cli/src/commands/node/control.rs index edc4e8f9..78e56fe9 100644 --- a/radicle-cli/src/commands/node/control.rs +++ b/radicle-cli/src/commands/node/control.rs @@ -31,7 +31,11 @@ pub fn start( // Ask passphrase here, otherwise it'll be a fatal error when running the daemon // without `RAD_PASSPHRASE`. let validator = term::io::PassphraseValidator::new(profile.keystore.clone()); - let Ok(passphrase) = term::io::passphrase(profile::env::RAD_PASSPHRASE, validator) else { + let passphrase = if let Some(phrase) = profile::env::passphrase() { + phrase + } else if let Ok(phrase) = term::io::passphrase(validator) { + phrase + } else { anyhow::bail!("your radicle passphrase is required to start your node"); }; Some((profile::env::RAD_PASSPHRASE, passphrase)) diff --git a/radicle-cli/src/terminal/io.rs b/radicle-cli/src/terminal/io.rs index 11dacbb9..9dce1497 100644 --- a/radicle-cli/src/terminal/io.rs +++ b/radicle-cli/src/terminal/io.rs @@ -39,13 +39,22 @@ impl inquire::validator::StringValidator for PassphraseValidator { } } -/// Get the signer. First we try getting it from ssh-agent, otherwise we prompt the user. +/// Get the signer. First we try getting it from ssh-agent, otherwise we prompt the user, +/// if we're connected to a TTY. pub fn signer(profile: &Profile) -> anyhow::Result> { if let Ok(signer) = profile.signer() { return Ok(signer); } let validator = PassphraseValidator::new(profile.keystore.clone()); - let passphrase = passphrase(RAD_PASSPHRASE, validator)?; + let passphrase = match passphrase(validator) { + Ok(p) => p, + Err(inquire::InquireError::NotTTY) => { + return Err(anyhow::anyhow!( + "running in non-interactive mode, please set `{RAD_PASSPHRASE}` to unseal your key", + )); + } + Err(e) => return Err(e.into()), + }; let spinner = spinner("Unsealing key..."); let signer = MemorySigner::load(&profile.keystore, Some(passphrase))?; diff --git a/radicle-term/src/io.rs b/radicle-term/src/io.rs index 1998a953..7629e71a 100644 --- a/radicle-term/src/io.rs +++ b/radicle-term/src/io.rs @@ -214,22 +214,17 @@ where Ok(value) } -pub fn passphrase, V: validator::StringValidator + 'static>( - var: K, +pub fn passphrase( validate: V, ) -> Result { - if let Ok(p) = env::var(var) { - Ok(Passphrase::from(p)) - } else { - Ok(Passphrase::from( - Password::new("Passphrase:") - .with_render_config(*CONFIG) - .with_display_mode(inquire::PasswordDisplayMode::Masked) - .without_confirmation() - .with_validator(validate) - .prompt()?, - )) - } + Ok(Passphrase::from( + Password::new("Passphrase:") + .with_render_config(*CONFIG) + .with_display_mode(inquire::PasswordDisplayMode::Masked) + .without_confirmation() + .with_validator(validate) + .prompt()?, + )) } pub fn passphrase_confirm>(