1use bitwarden_generators::{PassphraseGeneratorRequest, PasswordGeneratorRequest};
2use bitwarden_pm::PasswordManagerClient;
3use clap::Args;
4
5use crate::render::CommandResult;
6
7#[derive(Args, Clone)]
8pub struct GenerateArgs {
9 #[arg(short = 'u', long, action, help = "Include uppercase characters (A-Z)")]
11 pub uppercase: bool,
12
13 #[arg(short = 'l', long, action, help = "Include lowercase characters (a-z)")]
14 pub lowercase: bool,
15
16 #[arg(short = 'n', long, action, help = "Include numbers (0-9)")]
17 pub number: bool,
18
19 #[arg(
20 short = 's',
21 long,
22 action,
23 help = "Include special characters (!@#$%^&*)"
24 )]
25 pub special: bool,
26
27 #[arg(long, default_value = "16", help = "Length of generated password")]
28 pub length: u8,
29
30 #[arg(long, help = "Minimum number of numeric characters")]
31 pub min_numbers: Option<u8>,
32
33 #[arg(long, help = "Minimum number of special characters")]
34 pub min_special: Option<u8>,
35
36 #[arg(long, action, help = "Avoid ambiguous characters")]
37 pub ambiguous: bool,
38
39 #[arg(short = 'p', long, action, help = "Generate a passphrase")]
41 pub passphrase: bool,
42
43 #[arg(long, default_value = "5", help = "Number of words in the passphrase")]
44 pub words: u8,
45
46 #[arg(long, default_value = "-", help = "Separator between words")]
47 pub separator: char,
48
49 #[arg(long, action, help = "Capitalize the first letter of each word")]
50 pub capitalize: bool,
51
52 #[arg(long, action, help = "Include a number in one of the words")]
53 pub include_number: bool,
54}
55
56impl GenerateArgs {
57 pub fn run(mut self, client: &PasswordManagerClient) -> CommandResult {
58 let result = if self.passphrase {
59 client.generator().passphrase(PassphraseGeneratorRequest {
60 num_words: self.words,
61 word_separator: self.separator.to_string(),
62 capitalize: self.capitalize,
63 include_number: self.include_number,
64 })?
65 } else {
66 if !self.lowercase && !self.uppercase && !self.number && !self.special {
68 self.lowercase = true;
69 self.uppercase = true;
70 self.number = true;
71 }
72
73 client.generator().password(PasswordGeneratorRequest {
74 lowercase: self.lowercase,
75 uppercase: self.uppercase,
76 numbers: self.number,
77 special: self.special,
78 length: self.length,
79 min_number: self.min_numbers,
80 min_special: self.min_special,
81 avoid_ambiguous: self.ambiguous,
82 ..Default::default()
83 })?
84 };
85
86 Ok(result.into())
87 }
88}