diff --git a/Cargo.lock b/Cargo.lock index 0e785eb..47d6710 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -699,6 +699,27 @@ dependencies = [ "subtle", ] +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + [[package]] name = "dyn-clone" version = "1.0.17" @@ -1264,6 +1285,16 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags", + "libc", +] + [[package]] name = "linux-raw-sys" version = "0.4.14" @@ -1476,6 +1507,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "p256" version = "0.13.2" @@ -1780,6 +1817,17 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_users" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +dependencies = [ + "getrandom 0.2.15", + "libredox", + "thiserror", +] + [[package]] name = "regex" version = "1.10.4" @@ -2155,6 +2203,7 @@ dependencies = [ "bft-crdt-derive", "bft-json-crdt", "clap", + "dirs", "pem", "serde", "serde_json", diff --git a/side-node/Cargo.toml b/side-node/Cargo.toml index fa1f67f..3df9144 100644 --- a/side-node/Cargo.toml +++ b/side-node/Cargo.toml @@ -10,6 +10,7 @@ base64 = "0.21.7" bft-json-crdt = { path = "../crates/bft-json-crdt" } bft-crdt-derive = { path = "../crates/bft-json-crdt/bft-crdt-derive" } clap = { version = "4.5.4", features = ["derive"] } +dirs = "5.0.1" # serde_cbor = "0.11.2" # move to this once we need to pack things in CBOR serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.117" diff --git a/side-node/src/init.rs b/side-node/src/init.rs index 72d176b..2a28d24 100644 --- a/side-node/src/init.rs +++ b/side-node/src/init.rs @@ -8,29 +8,35 @@ use pem::Pem; use bft_json_crdt::keypair::{make_keypair, KeyPair}; -const KEY_FILE: &str = "side/node/keys.pem"; +const KEY_FILE: &str = "keys.pem"; +const CONFIG_FILE: &str = "config.toml"; -pub(crate) fn init(home: String) -> Result<(), std::io::Error> { - println!("Initializing Side Node at {home}"); - let key_path = key_path(home); +pub(crate) fn init(home: PathBuf) -> Result<(), std::io::Error> { + ensure_directory_exists(&home)?; - ensure_directory_exists(&key_path)?; + let (key_path, config_path) = side_path(home.clone()); let pem = create_pem(); - write(key_path, pem)?; + write_pem(key_path, pem)?; + + let mut file = File::create(config_path)?; Ok(()) } -fn ensure_directory_exists(key_path: &PathBuf) -> Result<(), std::io::Error> { - Ok(if let Some(parent_dir) = key_path.parent() { - println!("Creating parent directory: {:?}", parent_dir); - std::fs::create_dir_all(parent_dir)?; - }) +/// Ensures that the directory at side_dir exists, so we have a place +/// to store our key file and config file. +fn ensure_directory_exists(side_dir: &PathBuf) -> Result<(), std::io::Error> { + if side_dir.exists() { + return Ok(()); + } + println!("Creating side config directory: {:?}", side_dir); + std::fs::create_dir_all(side_dir) } /// Writes a PEM-encoded string to a file at key_path. -fn write(key_path: PathBuf, pem: String) -> Result<(), std::io::Error> { +fn write_pem(key_path: PathBuf, pem: String) -> Result<(), std::io::Error> { + println!("Writing key to: {:?}", key_path); let mut file = File::create(key_path)?; file.write(pem.to_string().as_bytes())?; Ok(()) @@ -46,19 +52,31 @@ fn create_pem() -> String { } /// Returns the path to the key file for this host OS. -fn key_path(home: String) -> PathBuf { - let key_path = format!("{home}/.{KEY_FILE}"); - let path = Path::new(&key_path).to_owned(); - path +fn side_path(prefix: PathBuf) -> (PathBuf, PathBuf) { + let mut key_path = prefix.clone(); + key_path.push(KEY_FILE); + + let mut config_path = prefix.clone(); + config_path.push(CONFIG_FILE); + + (key_path, config_path) } #[cfg(test)] mod tests { + use std::fs; + use super::*; #[test] fn creates_side_node_directory() { - let test_home = format!("/tmp/{KEY_FILE}"); + let mut test_home = PathBuf::new(); + let side_dir = "/tmp/side"; + + // clean up any previous test runs + fs::remove_dir_all(side_dir).expect("couldn't remove side directory during test"); + + test_home.push(side_dir); let node_dir = Path::new(&test_home).parent().unwrap().to_str().unwrap(); let _ = init(test_home.clone()); assert!(std::path::Path::new(node_dir).exists()); @@ -66,12 +84,30 @@ mod tests { #[test] fn creates_key_file() { - let test_home = format!("/tmp/{KEY_FILE}"); - let node_dir = Path::new(&test_home).parent().unwrap().to_str().unwrap(); - let _ = init(test_home.clone()); - assert!(std::path::Path::new(node_dir).exists()); + let mut file_path = PathBuf::new(); + file_path.push("/tmp/side"); + let side_dir = file_path.clone(); + file_path.push(KEY_FILE); + + let _ = init(side_dir.clone()); + assert!(file_path.exists()); + + // check that the pem is readable + let pem = fs::read_to_string(file_path).unwrap(); + assert!(pem.contains("PUBLIC")); + assert!(pem.contains("PRIVATE")); + + assert!(pem::parse_many(&pem).is_ok()); } - // #[test] - // fn creates_config_file() {} + #[test] + fn creates_config_file() { + let mut file_path = PathBuf::new(); + file_path.push("/tmp/side"); + let side_dir = file_path.clone(); + file_path.push(CONFIG_FILE); + + let _ = init(side_dir.clone()); + assert!(file_path.exists()); + } } diff --git a/side-node/src/main.rs b/side-node/src/main.rs index 4872c68..14e43f1 100644 --- a/side-node/src/main.rs +++ b/side-node/src/main.rs @@ -11,8 +11,7 @@ async fn main() { match &args.command { Some(Commands::Init {}) => { - let home = std::env::var("HOME").expect("couldn't read home directory env variable"); - let _ = init::init(home); + let _ = init::init(home()); } Some(Commands::Run {}) => { let (mut bft_crdt, keys) = list_transaction_crdt::new(); @@ -21,3 +20,9 @@ async fn main() { None => println!("No command provided. Exiting. See --help for more information."), } } + +fn home() -> std::path::PathBuf { + let mut path = dirs::home_dir().unwrap(); + path.push(".side"); + path +}