user_password.rs 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. use fancy_regex::Regex;
  2. use lazy_static::lazy_static;
  3. use unicode_segmentation::UnicodeSegmentation;
  4. #[derive(Debug)]
  5. pub struct UserPassword(pub String);
  6. impl UserPassword {
  7. pub fn parse(s: String) -> Result<UserPassword, String> {
  8. if s.trim().is_empty() {
  9. return Err(format!("Password can not be empty or whitespace."));
  10. }
  11. if s.graphemes(true).count() > 100 {
  12. return Err(format!("Password too long."));
  13. }
  14. let forbidden_characters = ['/', '(', ')', '"', '<', '>', '\\', '{', '}'];
  15. let contains_forbidden_characters = s.chars().any(|g| forbidden_characters.contains(&g));
  16. if contains_forbidden_characters {
  17. return Err(format!("Password contains forbidden characters."));
  18. }
  19. if !validate_password(&s) {
  20. return Err(format!("Password should contain a minimum of 6 characters with 1 special 1 letter and 1 numeric"));
  21. }
  22. Ok(Self(s))
  23. }
  24. }
  25. lazy_static! {
  26. // Test it in https://regex101.com/
  27. // https://stackoverflow.com/questions/2370015/regular-expression-for-password-validation/2370045
  28. // Hell1!
  29. // [invalid, greater or equal to 6]
  30. // Hel1!
  31. //
  32. // Hello1!
  33. // [invalid, must include number]
  34. // Hello!
  35. //
  36. // Hello12!
  37. // [invalid must include upper case]
  38. // hello12!
  39. static ref PASSWORD: Regex = Regex::new("((?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[\\W]).{6,20})").unwrap();
  40. }
  41. pub fn validate_password(password: &str) -> bool {
  42. match PASSWORD.is_match(password) {
  43. Ok(is_match) => is_match,
  44. Err(e) => {
  45. log::error!("validate_password fail: {:?}", e);
  46. false
  47. },
  48. }
  49. }