use common::request::Request; use std::fs::File; use std::io::{BufRead, BufReader}; use std::path::PathBuf; #[derive(Clone)] pub struct PasswordDirectory { dir_path: PathBuf, } impl PasswordDirectory { pub fn new(path: &str) -> PasswordDirectory { PasswordDirectory { dir_path: PathBuf::from(path), } } pub fn check_auth(&self, request: &Request) -> bool { // Don't allow empty userids or test_passwords // if request.userid.is_empty() || request.userid.contains('/') || request.password.is_empty() { return false; } let mut file_name = self.dir_path.clone(); file_name.push(&request.userid); if let Ok(file) = File::open(file_name) { for line in BufReader::new(file).lines().map_while(Result::ok) { if !line.starts_with('#') && line.trim() == request.password { return true; } } } false } } #[cfg(test)] mod tests { use crate::repository::PasswordDirectory; use common::request::Request; const TEST_PATH: &str = "../test_passwords"; #[test] fn it_checks_good_password() { let repository = PasswordDirectory::new(TEST_PATH); let request = Request::new("bp", "some-rad-password", "ignore-this", "also-ignore-this"); assert_eq!(repository.check_auth(&request), true); } #[test] fn it_fails_bad_password() { let repository = PasswordDirectory::new(TEST_PATH); let request = Request::new("bp", "not-correct", "ignore-this", "also-ignore-this"); assert_eq!(repository.check_auth(&request), false); } #[test] fn it_fails_bad_userid() { let repository = PasswordDirectory::new(TEST_PATH); let request = Request::new( "bp-xxx", "some-rad-password", "ignore-this", "also-ignore-this", ); assert_eq!(repository.check_auth(&request), false); } #[test] fn it_ignores_comments() { let repository = PasswordDirectory::new(TEST_PATH); let request = Request::new("bp-xxx", "commented-out", "ignore-this", "also-ignore-this"); assert_eq!(repository.check_auth(&request), false); } }