107 lines
2.9 KiB
Rust
107 lines
2.9 KiB
Rust
//! Radicle node profile.
|
|
//!
|
|
//! $RAD_HOME/ # Radicle home
|
|
//! storage/ # Storage root
|
|
//! zEQNunJUqkNahQ8VvQYuWZZV7EJB/ # Project git repository
|
|
//! ... # More projects...
|
|
//! keys/
|
|
//! radicle # Secret key (PKCS 8)
|
|
//! radicle.pub # Public key (PKCS 8)
|
|
//! node/
|
|
//! radicle.sock # Node control socket
|
|
//!
|
|
use std::path::PathBuf;
|
|
use std::{env, io};
|
|
|
|
use crate::crypto::{KeyPair, PublicKey, SecretKey, Signature, Signer};
|
|
use crate::keystore::UnsafeKeystore;
|
|
use crate::node;
|
|
use crate::storage::git::Storage;
|
|
|
|
#[derive(Debug)]
|
|
pub struct UnsafeSigner {
|
|
public: PublicKey,
|
|
secret: SecretKey,
|
|
}
|
|
|
|
impl Signer for UnsafeSigner {
|
|
fn public_key(&self) -> &PublicKey {
|
|
&self.public
|
|
}
|
|
|
|
fn sign(&self, msg: &[u8]) -> Signature {
|
|
Signature(self.secret.sign(msg, None))
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct Profile {
|
|
pub home: PathBuf,
|
|
pub signer: UnsafeSigner,
|
|
pub storage: Storage,
|
|
}
|
|
|
|
impl Profile {
|
|
pub fn init(keypair: KeyPair) -> Result<Self, io::Error> {
|
|
let home = self::home()?;
|
|
let mut keystore = UnsafeKeystore::new(&home.join("keys"));
|
|
let public = keypair.pk.into();
|
|
let signer = UnsafeSigner {
|
|
public,
|
|
secret: keypair.sk,
|
|
};
|
|
let storage = Storage::open(&home.join("storage"))?;
|
|
|
|
keystore.put(&signer.public, &signer.secret)?;
|
|
|
|
Ok(Profile {
|
|
home,
|
|
signer,
|
|
storage,
|
|
})
|
|
}
|
|
|
|
pub fn load() -> Result<Self, io::Error> {
|
|
let home = self::home()?;
|
|
let (public, secret) = UnsafeKeystore::new(&home.join("keys")).get()?;
|
|
let signer = UnsafeSigner { public, secret };
|
|
let storage = Storage::open(&home.join("storage"))?;
|
|
|
|
Ok(Profile {
|
|
home,
|
|
signer,
|
|
storage,
|
|
})
|
|
}
|
|
|
|
/// Return a connection to the locally running node.
|
|
pub fn node(&self) -> Result<node::Connection, io::Error> {
|
|
node::Connection::connect(self.socket())
|
|
}
|
|
|
|
pub fn id(&self) -> &PublicKey {
|
|
self.signer.public_key()
|
|
}
|
|
|
|
/// Get the path to the radicle node socket.
|
|
fn socket(&self) -> PathBuf {
|
|
env::var_os("RAD_SOCKET")
|
|
.map(PathBuf::from)
|
|
.unwrap_or_else(|| self.home.join("node").join(node::DEFAULT_SOCKET_NAME))
|
|
}
|
|
}
|
|
|
|
/// Get the path to the radicle home folder.
|
|
pub fn home() -> Result<PathBuf, io::Error> {
|
|
if let Some(home) = env::var_os("RAD_HOME") {
|
|
Ok(PathBuf::from(home))
|
|
} else if let Some(home) = env::var_os("HOME") {
|
|
Ok(PathBuf::from(home).join(".radicle"))
|
|
} else {
|
|
Err(io::Error::new(
|
|
io::ErrorKind::NotFound,
|
|
"Neither `RAD_HOME` nor `HOME` are set",
|
|
))
|
|
}
|
|
}
|