Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
cli: Register key on first `auth`
Alexis Sellier committed 3 years ago
commit e4b44370d3b4c4a377c8bdd15db62a5d12dd1a55
parent 411c54a604accb05f3b2013a67468bc72f140221
4 files changed +42 -9
modified radicle-cli/examples/rad-auth.md
@@ -7,6 +7,7 @@ $ rad auth
Initializing your 🌱 profile and identity

✓ Creating your 🌱 Ed25519 keypair...
+
! Adding your radicle key to ssh-agent...
✓ Your Radicle ID is did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi. This identifies your device.

👉 To create a radicle project, run `rad init` from a git repository.
modified radicle-cli/src/commands/auth.rs
@@ -4,6 +4,7 @@ use std::ffi::OsString;
use anyhow::anyhow;

use radicle::crypto::ssh;
+
use radicle::crypto::ssh::Passphrase;
use radicle::{profile, Profile};

use crate::terminal as term;
@@ -86,9 +87,16 @@ pub fn init(options: Options) -> anyhow::Result<()> {
        term::passphrase_confirm()
    }?;
    let spinner = term::spinner("Creating your 🌱 Ed25519 keypair...");
-
    let profile = Profile::init(home, passphrase)?;
+
    let profile = Profile::init(home, passphrase.clone())?;
    spinner.finish();

+
    let spinner = term::spinner("Adding your radicle key to ssh-agent...");
+
    if register(&profile, passphrase).is_ok() {
+
        spinner.finish();
+
    } else {
+
        spinner.warn();
+
    }
+

    term::success!(
        "Your Radicle ID is {}. This identifies your device.",
        term::format::highlight(profile.did())
@@ -124,12 +132,7 @@ pub fn authenticate(profile: &Profile, options: Options) -> anyhow::Result<()> {
            term::passphrase()
        }?;
        let spinner = term::spinner("Unlocking...");
-
        let mut agent = ssh::agent::Agent::connect()?;
-
        let secret = profile
-
            .keystore
-
            .secret_key(passphrase)?
-
            .ok_or_else(|| anyhow!("Key not found in {:?}", profile.keystore.path()))?;
-
        agent.register(&secret)?;
+
        register(profile, passphrase)?;
        spinner.finish();

        term::success!("Radicle key added to ssh-agent");
@@ -139,3 +142,16 @@ pub fn authenticate(profile: &Profile, options: Options) -> anyhow::Result<()> {

    Ok(())
}
+

+
/// Register key with ssh-agent.
+
pub fn register(profile: &Profile, passphrase: Passphrase) -> anyhow::Result<()> {
+
    let mut agent = ssh::agent::Agent::connect()?;
+
    let secret = profile
+
        .keystore
+
        .secret_key(passphrase)?
+
        .ok_or_else(|| anyhow!("Key not found in {:?}", profile.keystore.path()))?;
+

+
    agent.register(&secret)?;
+

+
    Ok(())
+
}
modified radicle-cli/src/terminal/io.rs
@@ -19,6 +19,7 @@ use super::Error;
use super::{style, Paint};

pub const ERROR_PREFIX: Paint<&str> = Paint::red("✗");
+
pub const WARNING_PREFIX: Paint<&str> = Paint::yellow("!");
pub const TAB: &str = "    ";

/// Render configuration.
@@ -129,7 +130,7 @@ pub fn subcommand(msg: impl fmt::Display) {
pub fn warning(warning: &str) {
    println!(
        "{} {} {warning}",
-
        Paint::yellow("!"),
+
        WARNING_PREFIX,
        Paint::yellow("Warning:").bold(),
    );
}
modified radicle-cli/src/terminal/spinner.rs
@@ -3,7 +3,7 @@ use std::mem::ManuallyDrop;
use std::sync::{Arc, Mutex};
use std::{fmt, io, thread, time};

-
use crate::terminal::io::ERROR_PREFIX;
+
use crate::terminal::io::{ERROR_PREFIX, WARNING_PREFIX};
use crate::terminal::Paint;

/// How much time to wait between spinner animation updates.
@@ -34,6 +34,7 @@ enum State {
    Running { cursor: usize },
    Canceled,
    Done,
+
    Warn,
    Error,
}

@@ -84,6 +85,13 @@ impl Spinner {
        }
    }

+
    /// Cancel the spinner with a warning sign.
+
    pub fn warn(self) {
+
        if let Ok(mut progress) = self.progress.lock() {
+
            progress.state = State::Warn;
+
        }
+
    }
+

    /// Set the spinner's message.
    pub fn message(&mut self, msg: impl fmt::Display) {
        let msg = msg.to_string();
@@ -151,6 +159,13 @@ pub fn spinner(message: impl ToString) -> Spinner {
                        break;
                    }
                    Progress {
+
                        state: State::Warn,
+
                        message,
+
                    } => {
+
                        writeln!(stdout, "{WARNING_PREFIX} {message}").ok();
+
                        break;
+
                    }
+
                    Progress {
                        state: State::Error,
                        message,
                    } => {