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<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(())
}