use std::convert::identity; use std::path::Path; use std::process::exit; use crate::db::Database; use crate::identity::{unescape, IdKeyData, Identity}; pub fn import_key(db_path: &Path, key: String, insert_anyway: bool) -> anyhow::Result<()> { // decode the key let components = key.split("/").collect::>(); if components.len() != 4 || components[0] != "sage" { eprintln!("not a sage key (looks like sage/key/name/email"); eprintln!("to import a raw age key without an identity, add it to the database manually"); exit(1); } let [_sentinel, key, name, email] = components.as_slice() else { unreachable!() }; let name = unescape(name.to_string())?; let email = unescape(email.to_string())?; let keys = match &key[0..3] { "age" => { IdKeyData::Peer(key.to_string()) }, "AGE" => { IdKeyData::Local(key.to_string()) }, _ => { eprintln!("unsupported age key type; is this a sage key?"); exit(1); } }; let identity = Identity { name, email, keys }; let mut db = Database::load_or_create(db_path)?; for key in &db.keys { if key.keys.keyid()? == identity.keys.keyid()? { println!("key {} already exists in database, skipping", key.keys.keyid()?); return Ok(()); } if key.name == identity.name && key.email == identity.email && !insert_anyway { eprintln!("database already has a key for {:?}", identity); eprintln!("to import anyway, run again with --import-anyway"); exit(1); } } db.keys.push(identity.clone()); db.write(db_path)?; println!("imported {:?} (keyid {}) successfully", identity, identity.keys.keyid()?); Ok(()) }