shadow_crypt_shell/encryption/
cli.rs1use clap::{Arg, Command};
2use shadow_crypt_core::profile::SecurityProfile;
3
4use crate::errors::{WorkflowError, WorkflowResult};
5
6#[derive(Debug, Clone)]
8pub struct CliArgs {
9 pub input_files: Vec<String>,
10 pub test_mode: bool, }
12
13pub fn get_cli_args(args: Vec<String>) -> WorkflowResult<CliArgs> {
15 let cmd = || {
16 Command::new("shadow")
17 .about("Encrypt files using shadow format")
18 .arg(
19 Arg::new("files")
20 .help("Input files to encrypt")
21 .required(false)
22 .num_args(1..)
23 .value_name("FILE"),
24 )
25 .arg(
26 Arg::new("test_mode")
27 .long("test-mode")
28 .short('t')
29 .help("Use test security profile for faster key derivation (not recommended for production)")
30 .action(clap::ArgAction::SetTrue),
31 )
32 };
33 let matches = cmd()
34 .try_get_matches_from(&args)
35 .map_err(|e| WorkflowError::UserInput(e.to_string()))?;
36 let input_files: Vec<String> = matches
37 .get_many::<String>("files")
38 .unwrap_or_default()
39 .map(|s| s.to_string())
40 .collect();
41
42 if input_files.is_empty() {
43 return Err(WorkflowError::UserInput(
44 "No input files provided".to_string(),
45 ));
46 }
47
48 Ok(CliArgs {
49 input_files,
50 test_mode: matches.get_flag("test_mode"),
51 })
52}
53
54pub fn get_security_profile(test_mode: bool) -> SecurityProfile {
55 if test_mode {
56 SecurityProfile::Test
57 } else {
58 SecurityProfile::Production
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65
66 #[test]
67 fn test_get_security_profile_test_mode() {
68 match get_security_profile(true) {
69 SecurityProfile::Test => {}
70 _ => panic!("Expected Test profile"),
71 }
72 }
73
74 #[test]
75 fn test_get_security_profile_production() {
76 match get_security_profile(false) {
77 SecurityProfile::Production => {}
78 _ => panic!("Expected Production profile"),
79 }
80 }
81
82 #[test]
83 fn test_parse_cli_args_with_files() {
84 let args = vec![
85 "shadow".to_string(),
86 "file1.txt".to_string(),
87 "file2.txt".to_string(),
88 ];
89 let cli_args = get_cli_args(args).unwrap();
90 assert_eq!(
91 cli_args.input_files,
92 vec!["file1.txt".to_string(), "file2.txt".to_string()]
93 );
94 assert!(!cli_args.test_mode);
95 }
96
97 #[test]
98 fn test_parse_cli_args_with_test_mode() {
99 let args = vec![
100 "shadow".to_string(),
101 "--test-mode".to_string(),
102 "file1.txt".to_string(),
103 ];
104 let cli_args = get_cli_args(args).unwrap();
105 assert_eq!(cli_args.input_files, vec!["file1.txt".to_string()]);
106 assert!(cli_args.test_mode);
107 }
108
109 #[test]
110 fn test_parse_cli_args_no_files() {
111 let args = vec!["shadow".to_string()];
112 let result = get_cli_args(args);
113 assert!(result.is_err());
114 if let Err(WorkflowError::UserInput(msg)) = result {
115 assert_eq!(msg, "No input files provided");
116 } else {
117 panic!("Expected UserInput error");
118 }
119 }
120}