pars_core/pgp/
key_management.rs1use std::io::Write;
2use std::process::{Command, Stdio};
3
4use anyhow::{anyhow, Result};
5
6use crate::pgp::utils::wait_child_process;
7use crate::pgp::PGPClient;
8
9fn run_gpg_batched_child(executable: &str, args: &[&str], batch_input: &str) -> Result<()> {
10 let mut cmd = Command::new(executable)
11 .args(args)
12 .stdin(Stdio::piped())
13 .stdout(Stdio::null())
14 .stderr(Stdio::piped())
15 .spawn()?;
16 if let Some(mut input) = cmd.stdin.take() {
17 input.write_all(batch_input.as_bytes())?;
18 input.flush()?;
19 } else {
20 return Err(anyhow!("Failed to open stdin for PGP key generation"));
21 }
22 wait_child_process(&mut cmd)
23}
24
25fn run_gpg_inherited_child(executable: &str, args: &[&str]) -> Result<()> {
26 let status = Command::new(executable)
27 .args(args)
28 .stdin(Stdio::inherit())
29 .stdout(Stdio::inherit())
30 .stderr(Stdio::inherit())
31 .status()?;
32 if status.success() {
33 Ok(())
34 } else {
35 Err(anyhow!(format!("Failed to generate PGP key, code {:?}", status)))
36 }
37}
38
39pub fn key_gen_stdin(pgp_exe: &str) -> Result<()> {
40 let gpg_args = ["--gen-key"];
41 run_gpg_inherited_child(pgp_exe, &gpg_args)
42}
43
44pub fn key_edit_stdin(pgp_exe: &str, key_fpr: &str) -> Result<()> {
45 let gpg_args = ["--edit-key", key_fpr];
46 run_gpg_inherited_child(pgp_exe, &gpg_args)
47}
48pub fn key_gen_batch(pgp_exe: &str, batch_input: &str) -> Result<()> {
49 let gpg_args = ["--batch", "--gen-key"];
50 run_gpg_batched_child(pgp_exe, &gpg_args, batch_input)
51}
52
53impl PGPClient {
54 pub fn key_edit_batch(&self, batch_input: &str) -> Result<()> {
55 for key in &self.keys {
56 let gpg_args =
57 ["--batch", "--command-fd", "0", "--status-fd", "1", "--edit-key", &key.key_fpr];
58 run_gpg_batched_child(&self.executable, &gpg_args, batch_input)?;
59 }
60 Ok(())
61 }
62
63 pub fn list_key_fingerprints(&self) -> Result<Vec<String>> {
64 todo!("impl this")
65 }
66
67 pub fn list_all_user_emails(&self) -> Result<Vec<String>> {
68 todo!("impl this")
69 }
70}
71#[cfg(test)]
72mod tests {
73
74 use serial_test::serial;
75
76 use super::*;
77 use crate::util::test_util::{
78 clean_up_test_key, get_test_email, get_test_executable, gpg_key_edit_example_batch,
79 gpg_key_gen_example_batch,
80 };
81
82 #[test]
92 #[serial]
93 fn pgp_key_gen_batch() {
94 let executable = get_test_executable();
95 key_gen_batch(&executable, &gpg_key_gen_example_batch()).unwrap();
96 let pgp_client = PGPClient::new(executable, &[&get_test_email()]).unwrap();
97 clean_up_test_key(pgp_client.get_executable(), &[&get_test_email()]).unwrap();
98 }
99
100 #[test]
101 #[serial]
102 fn pgp_key_edit_batch() {
103 let executable = get_test_executable();
104 let email = get_test_email();
105 key_gen_batch(&executable, &gpg_key_gen_example_batch()).unwrap();
106 let pgp_client = PGPClient::new(executable, &[&email]).unwrap();
107 pgp_client.key_edit_batch(&gpg_key_edit_example_batch()).unwrap();
108 clean_up_test_key(pgp_client.get_executable(), &[&email]).unwrap();
109 }
110}