use std::path::Path;
use std::process::exit;
use age::secrecy::ExposeSecret;
use regex::Regex;
use crate::db::Database;
use crate::identity::{IdKeyData, Identity};
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<login>[^@\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(())
}