//! Defines the `Credentials` struct, for use when logging in to a server. use crypto::digest::Digest; use crypto::md5::Md5; use crate::server::{LoginRequest, Version}; /// Credentials for logging in a client to a server. #[derive(Debug, Eq, PartialEq)] pub struct Credentials { user_name: String, password: String, digest: String, } impl Credentials { /// Attempts to build credentials. /// /// Returns `None` if `password` is empty, `Some(credentials)` otherwise. pub fn new(user_name: String, password: String) -> Option { if password.is_empty() { return None; } let mut hasher = Md5::new(); hasher.input_str(&user_name); hasher.input_str(&password); let digest = hasher.result_str(); Some(Credentials { user_name, password, digest, }) } /// The user name to log in as. pub fn user_name(&self) -> &str { &self.user_name } /// The password to log in with. pub fn password(&self) -> &str { &self.password } /// Returns md5(user_name + password). pub fn digest(&self) -> &str { &self.digest } pub fn into_login_request(self, version: Version) -> LoginRequest { LoginRequest { user_name: self.user_name, password: self.password, digest: self.digest, major: version.major, minor: version.minor, } } } #[cfg(test)] mod tests { use crate::server::{LoginRequest, Version}; use super::Credentials; #[test] fn empty_password() { assert_eq!(Credentials::new("alice".to_string(), String::new()), None); } #[test] fn new_success() { let user_name = "alice".to_string(); let password = "sekrit".to_string(); let credentials = Credentials::new(user_name, password).unwrap(); assert_eq!(credentials.user_name(), "alice"); assert_eq!(credentials.password(), "sekrit"); } #[test] fn digest() { let user_name = "alice".to_string(); let password = "sekrit".to_string(); let credentials = Credentials::new(user_name, password).unwrap(); // To generate the expected value on the command line; // // ```sh // $ user_name="alice" // $ password="sekrit" // $ echo -e "${user_name}${password}" | md5sum // ``` assert_eq!(credentials.digest(), "286da88eb442032bdd3913979af76e8a"); } #[test] fn into_login_request() { let user_name = "alice".to_string(); let password = "sekrit".to_string(); let credentials = Credentials::new(user_name.clone(), password.clone()).unwrap(); let digest = credentials.digest().to_string(); let version = Version { major: 13, minor: 37, }; assert_eq!( credentials.into_login_request(version), LoginRequest { user_name, password, digest, major: 13, minor: 37, } ); } }