algae_cli/cli/
protect.rs

1use std::{fmt::Debug, path::PathBuf};
2
3use clap::Parser;
4use miette::{IntoDiagnostic, Result, WrapErr};
5use tokio::fs::remove_file;
6
7use crate::{
8	files::{append_age_ext, encrypt_file},
9	passphrases::PassphraseArgs,
10};
11
12/// Encrypt a file using a passphrase.
13///
14/// Whenever possible, prefer to use `encrypt` and `decrypt` with identity files
15/// (public key cryptography).
16///
17/// This utility may also be used to convert a plaintext identity file into a
18/// passphrase-protected one.
19#[derive(Debug, Clone, Parser)]
20pub struct ProtectArgs {
21	/// File to be encrypted.
22	pub input: PathBuf,
23
24	/// Path or filename to write the encrypted file to.
25	///
26	/// By default this is the input file, with `.age` appended.
27	#[arg(short, long)]
28	pub output: Option<PathBuf>,
29
30	/// Delete input file after encrypting.
31	#[arg(long = "rm")]
32	pub remove: bool,
33
34	#[command(flatten)]
35	#[allow(missing_docs, reason = "don't interfere with clap")]
36	pub key: PassphraseArgs,
37}
38
39/// CLI command for the `protect` operation (passphrase encryption).
40pub async fn run(
41	ProtectArgs {
42		ref input,
43		output,
44		key,
45		remove,
46	}: ProtectArgs,
47) -> Result<()> {
48	let key = key.require_with_confirmation().await?;
49	let output = output.unwrap_or_else(|| append_age_ext(input));
50
51	encrypt_file(input, output, Box::new(key)).await?;
52
53	if remove {
54		remove_file(input)
55			.await
56			.into_diagnostic()
57			.wrap_err("deleting input file")?;
58	}
59
60	Ok(())
61}