1use serde::{Deserialize, Serialize};
2use zxcvbn::zxcvbn;
3
4#[derive(Debug, Serialize, Deserialize)]
5pub struct StrengthResult {
6 pub score: u8,
8 pub crack_time_seconds: f64,
10 pub warning: Option<String>,
12 pub suggestions: Vec<String>,
14}
15
16pub fn check_strength(password: &str) -> StrengthResult {
18 let result = zxcvbn(password, &[]);
19
20 let feedback = result.feedback();
24
25 let warning = if let Some(feedback) = feedback {
26 if feedback.warning().is_some() {
27 feedback.warning().map(|w| w.to_string())
28 } else {
29 None
30 }
31 } else {
32 None
33 };
34
35 let suggestions = if let Some(feedback) = feedback {
36 feedback
37 .suggestions()
38 .iter()
39 .map(|s| s.to_string())
40 .collect()
41 } else {
42 Vec::new()
43 };
44
45 let crack_time_seconds = 0.0; StrengthResult {
51 score: result.score().try_into().unwrap_or(0),
52 crack_time_seconds,
53 warning,
54 suggestions,
55 }
56}
57
58#[cfg(test)]
59mod tests {
60 use super::*;
61
62 #[test]
63 fn test_weak_password() {
64 let result = check_strength("password");
65 assert_eq!(result.score, 0);
66 }
67
68 #[test]
69 fn test_strong_password() {
70 let result = check_strength("correct horse battery staple");
72 assert!(result.score >= 3);
73 }
74}