cyphr_cli/commands/
init.rs1use cyphr::Principal;
4use cyphr_storage::export_commits;
5
6use super::common::{generate_key, load_key_from_keystore, parse_store};
7use crate::keystore::{JsonKeyStore, KeyStore};
8use crate::{Cli, Error, OutputFormat};
9
10pub fn run(
12 cli: &Cli,
13 algo: &str,
14 key_tmb: Option<&str>,
15 keys_tmb: Option<&[String]>,
16) -> crate::Result<()> {
17 let mut keystore = JsonKeyStore::open(&cli.keystore)?;
18
19 let principal = match (key_tmb, keys_tmb) {
21 (None, Some(tmbs)) if !tmbs.is_empty() => {
23 let keys = tmbs
24 .iter()
25 .map(|tmb| load_key_from_keystore(&keystore, tmb))
26 .collect::<Result<Vec<_>, _>>()?;
27 Principal::explicit(keys)?
28 },
29
30 (Some(tmb), None) => {
32 let key = load_key_from_keystore(&keystore, tmb)?;
33 Principal::implicit(key)?
34 },
35
36 (None, None) => {
38 let (tmb_str, stored, key) = generate_key(algo, None)?;
39 keystore.store(&tmb_str, stored)?;
40 keystore.save()?;
41 Principal::implicit(key)?
42 },
43
44 (Some(_), Some(_)) => {
46 return Err(Error::InvalidArgument(
47 "cannot specify both --key and --keys".into(),
48 ));
49 },
50
51 (None, Some(_)) => {
53 return Err(Error::InvalidArgument(
54 "--keys requires at least one thumbprint".into(),
55 ));
56 },
57 };
58
59 let identity_str = {
61 use coz::base64ct::{Base64UrlUnpadded, Encoding};
62 if let Some(pr) = principal.pg() {
63 pr.as_multihash()
64 .first_variant()
65 .map(Base64UrlUnpadded::encode_string)
66 .map_err(|e| Error::Storage(format!("PR empty: {e}")))?
67 } else {
68 principal
69 .pr()
70 .as_multihash()
71 .first_variant()
72 .map(Base64UrlUnpadded::encode_string)
73 .map_err(|e| Error::Storage(format!("PS empty: {e}")))?
74 }
75 };
76
77 let store = parse_store(&cli.store)?;
79 if let Some(pr_ref) = principal.pg() {
80 let commits = export_commits(&principal)?;
81 for commit in &commits {
82 store.append_commit(pr_ref, commit)?;
83 }
84 }
85
86 match cli.output {
88 OutputFormat::Json => {
89 let keys: Vec<_> = principal.active_keys().map(|k| k.tmb.to_b64()).collect();
90 let output = serde_json::json!({
91 "pr": identity_str,
92 "keys": keys,
93 });
94 println!("{}", serde_json::to_string_pretty(&output)?);
95 },
96 OutputFormat::Table => {
97 println!("Created identity");
98 println!(" pr: {identity_str}");
99 println!(" keys:");
100 for key in principal.active_keys() {
101 let tag_str = key.tag.as_deref().unwrap_or("-");
102 println!(" {} ({}) [{}]", key.tmb.to_b64(), key.alg, tag_str);
103 }
104 println!(" stored: {}", cli.store);
105 },
106 }
107
108 Ok(())
109}