1use super::error::CredentialsError;
2use secure_types::SecureString;
3
4#[derive(Clone)]
10pub struct Credentials {
11 pub username: SecureString,
12 pub password: SecureString,
13 pub confirm_password: SecureString,
14}
15
16impl Credentials {
17 pub fn new(
18 username: SecureString,
19 password: SecureString,
20 confirm_password: SecureString,
21 ) -> Self {
22 Self {
23 username,
24 password,
25 confirm_password,
26 }
27 }
28
29 pub fn new_with_capacity(capacity: usize) -> Result<Self, CredentialsError> {
31 let username = SecureString::new_with_capacity(capacity)
32 .map_err(|e| CredentialsError::Custom(e.to_string()))?;
33
34 let password = SecureString::new_with_capacity(capacity)
35 .map_err(|e| CredentialsError::Custom(e.to_string()))?;
36
37 let confirm_password = SecureString::new_with_capacity(capacity)
38 .map_err(|e| CredentialsError::Custom(e.to_string()))?;
39 Ok(Self {
40 username,
41 password,
42 confirm_password,
43 })
44 }
45
46 pub fn erase(&mut self) {
50 self.username.erase();
51 self.password.erase();
52 self.confirm_password.erase();
53 }
54
55 pub fn copy_passwd_to_confirm(&mut self) {
57 self.password.unlock_str(|str| {
58 self.confirm_password.erase();
59 self.confirm_password.push_str(str);
60 });
61 }
62
63 pub fn is_valid(&self) -> Result<(), CredentialsError> {
64 if self.username.char_len() == 0 {
65 return Err(CredentialsError::UsernameEmpty);
66 }
67
68 if self.password.char_len() == 0 {
69 return Err(CredentialsError::PasswordEmpty);
70 }
71
72 if self.confirm_password.char_len() == 0 {
73 return Err(CredentialsError::ConfirmPasswordEmpty);
74 }
75
76 let res = self.password.unlock_str(|password| {
77 self.confirm_password.unlock_str(|confirm_password| {
78 if password != confirm_password {
79 return Err(CredentialsError::PasswordsDoNotMatch);
80 } else {
81 Ok(())
82 }
83 })
84 });
85 res
86 }
87}
88
89impl Default for Credentials {
90 fn default() -> Self {
91 Self::new(
92 SecureString::from(""),
93 SecureString::from(""),
94 SecureString::from(""),
95 )
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102
103 #[test]
104 fn test_copy_passwd_to_confirm() {
105 let mut credentials = Credentials::new(
106 SecureString::from("username"),
107 SecureString::from("password"),
108 SecureString::from("something_else"),
109 );
110
111 credentials.copy_passwd_to_confirm();
112 assert!(credentials.is_valid().is_ok());
113 }
114}