Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
cli: `rad self` improvements
Alexis Sellier committed 2 years ago
commit 0f3212a1b2d35e848672d8543b9ae721437b5476
parent 613e3e526937188a7323354b145b602693073339
6 files changed +62 -28
modified radicle-cli/examples/rad-auth.md
@@ -7,7 +7,7 @@ $ rad auth
Initializing your radicle 👾 identity

✓ Creating your Ed25519 keypair...
-
✓ Your Radicle ID is did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi. This identifies your device.
+
✓ Your Radicle DID is did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi. This identifies your device.

To create a radicle project, run `rad init` from a git repository.
```
@@ -15,12 +15,6 @@ To create a radicle project, run `rad init` from a git repository.
You can get the above information at all times using the `self` command:

```
-
$ rad self
-
DID            did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
-
Node ID (NID)  z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
-
Key (hash)     SHA256:UIedaL6Cxm6OUErh9GQUzzglSk7VpQlVTI1TAFB/HWA
-
Key (full)     ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHahWSBEpuT1ESZbynOmBNkLBSnR32Ar4woZqSV2YNH1
-
Storage (git)  [..]/storage
-
Storage (keys) [..]/keys
-
Node (socket)  [..]/node/control.sock
+
$ rad self --did
+
did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
```
modified radicle-cli/examples/rad-self.md
@@ -3,13 +3,15 @@ device and node.

```
$ rad self
-
DID            did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
-
Node ID (NID)  z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
-
Key (hash)     SHA256:UIedaL6Cxm6OUErh9GQUzzglSk7VpQlVTI1TAFB/HWA
-
Key (full)     ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHahWSBEpuT1ESZbynOmBNkLBSnR32Ar4woZqSV2YNH1
-
Storage (git)  [..]
-
Storage (keys) [..]
-
Node (socket)  [..]
+
DID             did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+
└╴Node ID (NID) z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+
SSH             not running
+
├╴Key (hash)    SHA256:UIedaL6Cxm6OUErh9GQUzzglSk7VpQlVTI1TAFB/HWA
+
└╴Key (full)    ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHahWSBEpuT1ESZbynOmBNkLBSnR32Ar4woZqSV2YNH1
+
Home            [..]/home/alice/.radicle
+
├╴Storage       [..]/home/alice/.radicle/storage
+
├╴Keys          [..]/home/alice/.radicle/keys
+
└╴Node          [..]/home/alice/.radicle/node
```

If you need to display only your DID, Node ID, or SSH Public Key, you can use
@@ -29,3 +31,8 @@ z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
$ rad self --ssh-key
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHahWSBEpuT1ESZbynOmBNkLBSnR32Ar4woZqSV2YNH1
```
+

+
```
+
$ rad self --home
+
[..]/home/alice/.radicle
+
```
modified radicle-cli/src/commands/auth.rs
@@ -106,7 +106,7 @@ pub fn init(options: Options) -> anyhow::Result<()> {
    }

    term::success!(
-
        "Your Radicle ID is {}. This identifies your device.",
+
        "Your Radicle DID is {}. This identifies your device.",
        term::format::highlight(profile.did())
    );

modified radicle-cli/src/commands/self.rs
@@ -20,6 +20,7 @@ Options

    --nid                Show your Node ID (NID)
    --did                Show your DID
+
    --home               Show your Radicle home
    --ssh-key            Show your public key in OpenSSH format
    --ssh-fingerprint    Show your public key fingerprint in OpenSSH format
    --help               Show help
@@ -30,6 +31,7 @@ Options
enum Show {
    NodeId,
    Did,
+
    Home,
    SshKey,
    SshFingerprint,
    All,
@@ -55,6 +57,9 @@ impl Args for Options {
                Long("did") if show.is_none() => {
                    show = Some(Show::Did);
                }
+
                Long("home") if show.is_none() => {
+
                    show = Some(Show::Home);
+
                }
                Long("ssh-key") if show.is_none() => {
                    show = Some(Show::SshKey);
                }
@@ -87,6 +92,9 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
        Show::Did => {
            term::print(profile.did());
        }
+
        Show::Home => {
+
            term::print(profile.home().display());
+
        }
        Show::SshKey => {
            term::print(ssh::fmt::key(profile.id()));
        }
@@ -110,38 +118,56 @@ fn all(profile: &Profile) -> anyhow::Result<()> {

    let node_id = profile.id();
    table.push([
-
        term::format::style("Node ID (NID)").to_string(),
+
        term::format::style("└╴Node ID (NID)").to_string(),
        term::format::tertiary(node_id).to_string(),
    ]);

+
    let ssh_agent = match ssh::agent::Agent::connect() {
+
        Ok(c) => term::format::positive(format!(
+
            "running ({})",
+
            c.pid().map(|p| p.to_string()).unwrap_or(String::from("?"))
+
        )),
+
        Err(e) if e.is_not_running() => term::format::yellow(String::from("not running")),
+
        Err(e) => term::format::negative(format!("error: {e}")),
+
    };
+
    table.push([
+
        term::format::style("SSH").to_string(),
+
        ssh_agent.to_string(),
+
    ]);
+

    let ssh_short = ssh::fmt::fingerprint(node_id);
    table.push([
-
        term::format::style("Key (hash)").to_string(),
+
        term::format::style("├╴Key (hash)").to_string(),
        term::format::tertiary(ssh_short).to_string(),
    ]);

    let ssh_long = ssh::fmt::key(node_id);
    table.push([
-
        term::format::style("Key (full)").to_string(),
+
        term::format::style("└╴Key (full)").to_string(),
        term::format::tertiary(ssh_long).to_string(),
    ]);

+
    let home = profile.home();
+
    table.push([
+
        term::format::style("Home").to_string(),
+
        term::format::tertiary(home.display()).to_string(),
+
    ]);
+

    let storage_path = profile.home.storage();
    table.push([
-
        term::format::style("Storage (git)").to_string(),
+
        term::format::style("├╴Storage").to_string(),
        term::format::tertiary(storage_path.display()).to_string(),
    ]);

    let keys_path = profile.home.keys();
    table.push([
-
        term::format::style("Storage (keys)").to_string(),
+
        term::format::style("├╴Keys").to_string(),
        term::format::tertiary(keys_path.display()).to_string(),
    ]);

-
    let socket_path = profile.socket();
    table.push([
-
        term::format::style("Node (socket)").to_string(),
-
        term::format::tertiary(socket_path.display()).to_string(),
+
        term::format::style("└╴Node").to_string(),
+
        term::format::tertiary(profile.home.node().display()).to_string(),
    ]);

    table.print();
modified radicle-node/src/test/environment.rs
@@ -90,7 +90,7 @@ impl Environment {
    /// Create a new profile in this environment.
    /// This should be used when a running node is not required.
    pub fn profile(&mut self, name: &str) -> Profile {
-
        let home = Home::new(self.tmp().join("home").join(name)).unwrap();
+
        let home = Home::new(self.tmp().join("home").join(name).join(".radicle")).unwrap();
        let storage = Storage::open(home.storage()).unwrap();
        let keystore = Keystore::new(&home.keys());
        let keypair = KeyPair::from_seed(Seed::from([!(self.users as u8); 32]));
modified radicle-ssh/src/agent/client.rs
@@ -3,6 +3,7 @@ use std::io::{Read, Write};
use std::ops::DerefMut;
use std::os::unix::net::UnixStream;
use std::path::Path;
+
use std::str::FromStr;

use byteorder::{BigEndian, ByteOrder, WriteBytesExt};
use log::*;
@@ -51,12 +52,18 @@ pub struct AgentClient<S> {
    stream: S,
}

-
// https://tools.ietf.org/html/draft-miller-ssh-agent-00#section-4.1
impl<S> AgentClient<S> {
    /// Connect to an SSH agent via the provided stream (on Unix, usually a Unix-domain socket).
    pub fn connect(stream: S) -> Self {
        AgentClient { stream }
    }
+

+
    /// Get the agent PID.
+
    pub fn pid(&self) -> Option<u32> {
+
        std::env::var("SSH_AGENT_PID")
+
            .ok()
+
            .and_then(|v| u32::from_str(&v).ok())
+
    }
}

pub trait ClientStream: Sized + Send + Sync {
@@ -76,7 +83,7 @@ pub trait ClientStream: Sized + Send + Sync {
            Err(Error::Io(io_err)) if io_err.kind() == std::io::ErrorKind::NotFound => {
                Err(Error::BadAuthSock)
            }
-
            err => err,
+
            other => other,
        }
    }
}