passgenlib/
lib.rs

1mod gen_engine;
2
3/// Main [Passgen] structure.
4///
5/// # Examples
6///
7/// You can create a token that includes lowercase letters and numbers up to 30 characters long:
8///
9/// ```
10/// use passgenlib::Passgen;
11/// let result = Passgen::new().set_enabled_letters(true).set_enabled_numbers(true).generate(30);
12/// ```
13///
14/// You can create a default strong password including all literals, numbers and symbols:
15///
16/// ```
17/// use passgenlib::Passgen;
18/// let result = Passgen::default().generate(12);
19/// ```
20///
21/// You can create a strong and usability password.
22/// Including all characters, but
23/// the first position in the password is a capital or small letter,
24/// the last position is the symbol.
25/// 🔸 Excluded ambiguous characters `"0oOiIlL1"`.
26///
27/// ```
28/// use passgenlib::Passgen;
29/// let result = Passgen::default_strong_and_usab().generate(8);
30/// ```
31/// You can create a set from your custom charset:
32///
33/// ```
34/// use passgenlib::Passgen;
35/// let result = Passgen::new().set_custom_charset("bla@.321").generate(8);
36/// ```
37pub struct Passgen {
38    /// Presence of letters.
39    pub enab_letters: bool,
40
41    /// Presence of a capital letters.
42    pub enab_u_letters: bool,
43
44    /// Presence of numeric characters.
45    pub enab_num: bool,
46
47    /// Presence of special characters.
48    pub enab_spec_symbs: bool,
49
50    /// Including all characters, but
51    /// the first position in the password is a capital or small letter,
52    /// the last position is the symbol. Excluded ambiguous characters `"0oOiIlL1"`.
53    ///
54    /// ⚠️ If this rule is enabled, the other consistency rules of the generating are not taken,
55    /// except for a rule `custom_charset`.
56    pub enab_strong_usab: bool,
57
58    /// User defined character set.
59    ///
60    /// ⚠️This set of characters will exclude all other rules except for a rule `"enab_strong_usab"`.
61    ///
62    /// ⚙️If `"enab_strong_usab"` on too then you can generate combined strong and usability result with custom charset.
63    pub custom_charset: &'static str,
64}
65
66impl Passgen {
67    /// Get an instance of `Passgen` without any rules.
68    pub fn new() -> Passgen {
69        Passgen {
70            enab_letters: false,
71            enab_u_letters: false,
72            enab_num: false,
73            enab_spec_symbs: false,
74            enab_strong_usab: false,
75            custom_charset: "",
76        }
77    }
78
79    /// Set default ruleset of `Passgen` to *"all simple rules are enabled"*.
80    pub fn default() -> Passgen {
81        Passgen {
82            enab_letters: true,
83            enab_u_letters: true,
84            enab_num: true,
85            enab_spec_symbs: true,
86            enab_strong_usab: false,
87            custom_charset: "",
88        }
89    }
90
91    /// Set default ruleset of `Passgen` to *"Strong & usability"*.
92    ///
93    /// Including all characters, but
94    /// the first position in the password is a capital or small letter,
95    /// the last position is the symbol. Excluded ambiguous characters `"0oOiIlL1"`.
96    ///
97    /// ⚠️ If this rule is enabled, the other consistency rules of the generating are not taken,
98    /// except for a rule `custom_charset`.
99    pub fn default_strong_and_usab() -> Passgen {
100        Passgen {
101            enab_letters: false,
102            enab_u_letters: false,
103            enab_num: false,
104            enab_spec_symbs: false,
105            custom_charset: "",
106            enab_strong_usab: true,
107        }
108    }
109
110    /// Set value of the field `enab_letters` for `Passgen`.
111    pub fn set_enabled_letters(&mut self, value: bool) -> &mut Passgen {
112        self.enab_letters = value;
113        self
114    }
115
116    /// Set value of the field `enab_u_letters` for `Passgen`.
117    pub fn set_enabled_uppercase_letters(&mut self, value: bool) -> &mut Passgen {
118        self.enab_u_letters = value;
119        self
120    }
121
122    /// Set value of the field `enab_num` for `Passgen`.
123    pub fn set_enabled_numbers(&mut self, value: bool) -> &mut Passgen {
124        self.enab_num = value;
125        self
126    }
127
128    /// Set value of the field `enab_spec_symbs` for `Passgen`.
129    pub fn set_enabled_spec_symbols(&mut self, value: bool) -> &mut Passgen {
130        self.enab_spec_symbs = value;
131        self
132    }
133
134    /// Set value of the field `enab_strong_usab` for `Passgen`.
135    ///
136    /// Including all characters, but
137    /// the first position in the password is a capital or small letter,
138    /// the last position is the symbol. Excluded ambiguous characters `"0oOiIlL1"`.
139    ///
140    /// ⚠️ If this rule is enabled, the other consistency rules of the generating are not taken,
141    /// except for a rule `custom_charset`.
142    pub fn set_enabled_strong_usab(&mut self, value: bool) -> &mut Passgen {
143        self.enab_strong_usab = value;
144        self
145    }
146
147    /// Set user defined character set.
148    /// You can use any Unicode characters and emoji. For example: abcABC123⭕➖❎⚫⬛n₼⁂🙂
149    ///
150    /// ⚠️This set of characters will exclude all other rules except for a rule `"enab_strong_usab"`.
151    ///
152    /// ⚙️If `"enab_strong_usab"` on too then you can generate combined strong and usability result with custom charset.
153    pub fn set_custom_charset(&mut self, value: &'static str) -> &mut Passgen {
154        self.custom_charset = value;
155        self
156    }
157
158    /// Generate result. Argument "length" will not be less than 4
159    pub fn generate(&mut self, length: u32) -> String {
160        if !self.is_ruleset_clean() {
161            let res_len = if length < 4 { 4 } else { length };
162
163            let mut pwd = self.generate_pass(res_len);
164
165            if self.custom_charset.len() == 0 {
166                while !self.is_valid_pwd_by_consist(pwd.clone()) {
167                    pwd = self.generate_pass(res_len);
168                }
169            }
170            pwd
171        } else {
172            "".to_string()
173        }
174    }
175
176    fn is_ruleset_clean(&self) -> bool {
177        !self.enab_letters
178            && !self.enab_u_letters
179            && !self.enab_num
180            && !self.enab_spec_symbs
181            && !self.enab_strong_usab
182            && self.custom_charset.len() == 0
183    }
184}
185
186#[cfg(test)]
187mod tests {
188    use crate::Passgen;
189
190    #[test]
191    fn it_works() {
192        assert_eq!(Passgen::new().generate(4).len(), 0);
193        assert_ne!(
194            Passgen::new().set_enabled_letters(true).generate(4).len(),
195            0
196        );
197        assert_ne!(
198            Passgen::default()
199                .set_custom_charset("abcABC123⭕➖❎⚫⬛п₼⁂🙂")
200                .generate(4)
201                .len(),
202            0
203        );
204
205        assert_ne!(Passgen::default_strong_and_usab().generate(4).len(), 0);
206    }
207}