use crate::db::Database; use crate::identity::{IdKeyData, Identity}; use age::secrecy::ExposeSecret; use regex::Regex; use std::path::Path; use std::process::exit; pub fn create_id(db_path: &Path, name: String, email: String) -> anyhow::Result<()> { let mut db = Database::load_or_create(db_path)?; // sanity check to ensure this id does not already exist for key in &db.keys { if key.name == name && key.email == email { eprintln!( "key '{:?}' (keyid {}) already exists in database", key, key.keys.keyid()? ); eprintln!("if you want to recreate it, remove it first"); exit(1); } } // Email is a fucking nightmare // RFC5322, I hate you let email_re = Regex::new( r#"(?x) ^(?P[^@\s]+)@ ([[:word:]]+\.)* [[:word:]]+$ "#, ) .unwrap(); if !email_re.is_match(&email) { eprintln!("`{email}` is not a valid RFC5322 email address"); exit(1); } let key = age::x25519::Identity::generate(); let ss = key.to_string(); let ss = ss.expose_secret(); let identity = Identity { name, email, keys: IdKeyData::Local(ss.to_string()), }; db.keys.push(identity.clone()); // save database db.write(db_path)?; println!( "wrote new key {:?} (keyid {}) to database", identity, identity.keys.keyid()? ); Ok(()) }