feat: #8 parse store file content and add test

This commit is contained in:
landrigun 2022-09-29 16:27:45 +00:00
parent 8bf503df14
commit 73059c724f
4 changed files with 70 additions and 28 deletions

View File

@ -12,6 +12,9 @@ regex = "1"
tokio = { version = "1.21.1", features = ["full"] } tokio = { version = "1.21.1", features = ["full"] }
async-trait = "0.1.57" async-trait = "0.1.57"
# useful for tests (embedded files should be delete in release ?)
#rust-embed="6.4.1"
[dependencies.async-std] [dependencies.async-std]
version = "1.6" version = "1.6"
features = ["attributes"] features = ["attributes"]

View File

@ -11,30 +11,65 @@ use super::store::{Credentials, Store};
/// FileStore references a `store` file /// FileStore references a `store` file
pub struct FileStore { pub struct FileStore {
path: String, path: String,
credentials: Vec<Credentials>,
} }
impl FileStore { impl FileStore {
fn new(path: String) -> Self { fn new(path: String) -> Self {
FileStore { path } FileStore {
path,
credentials: vec![],
}
} }
async fn parse_contents(&self, mut file: File) -> Vec<u8> { /// parse_contents loads and reads the file asynchonously
let mut contents = vec![]; /// parses the file line by line to retrieve the credentials
let byte_read = file.read_to_end(&mut contents).await; async fn parse_contents(&mut self) {
if byte_read.is_err() { let contents = tokio::fs::read_to_string(&self.path).await;
eprintln!( let mut credentials: Vec<Credentials> = vec![];
"error occurred while reading store file: {}, err={:?}", match contents {
self.path, Ok(c) => {
byte_read.err() let lines: Vec<&str> = c.split("\n").collect();
); for line in lines {
if line.starts_with("#") {
continue;
}
let line_split: Vec<&str> = line.split(":").collect();
if line_split.len() != 2 {
continue;
}
credentials.push(Credentials::new(
line_split[0].to_string(),
line_split[1].to_string(),
));
}
}
Err(e) => {
eprintln!(
"error occurred while reading store file: {}, err={:?}",
self.path, e
);
}
} }
contents self.credentials = credentials;
}
fn auth(&self, username: String, password: String) -> bool {
let credentials: Vec<&Credentials> = self
.credentials
.iter()
.filter(|x| x.username == username && x.password == password)
.collect();
if credentials.len() == 1 {
return true;
}
false
} }
} }
#[async_trait] #[async_trait]
impl Store for FileStore { impl Store for FileStore {
async fn is_auth(&self, data: &json::JsonValue) -> bool { async fn is_auth(&mut self, data: &json::JsonValue) -> bool {
// ensure that the store file already exists even after its instanciation // ensure that the store file already exists even after its instanciation
if !Path::new(&self.path).is_file() { if !Path::new(&self.path).is_file() {
eprintln!("{} path referencing file store does not exist", self.path); eprintln!("{} path referencing file store does not exist", self.path);
@ -47,22 +82,22 @@ impl Store for FileStore {
return false; return false;
} }
let store = File::open(&self.path).await; let contents = self.parse_contents().await;
match store {
Ok(f) => { self.auth(credentials.username, credentials.password)
let contents = self.parse_contents(f).await;
println!("file contents : {:?}", contents.len());
return true;
}
Err(e) => eprintln!("error while opening the file {}, err={:?}", self.path, e),
}
false
} }
} }
#[tokio::test] #[tokio::test]
async fn test_store() { async fn test_store() {
let store = FileStore::new("/tmp/thegux.pid".to_string()); use std::env;
let data = json::parse(r#"{"access_token": "toto", "refresh_token": "tutu"}"#).unwrap();
assert_eq!(store.is_auth(&data).await, false); let root_path = env::var("CARGO_MANIFEST_DIR").unwrap();
// TODO: path::Path should be better
let store_path = format!("{}/{}/{}/{}", root_path, "tests", "data", "store.txt");
let mut store = FileStore::new(store_path);
let data = json::parse(r#"{"username": "toto", "password": "tata"}"#).unwrap();
assert_eq!(store.is_auth(&data).await, true);
} }

View File

@ -4,7 +4,7 @@ use json::object::Object;
#[async_trait] #[async_trait]
pub trait Store { pub trait Store {
async fn is_auth(&self, data: &json::JsonValue) -> bool; async fn is_auth(&mut self, data: &json::JsonValue) -> bool;
} }
/// extract_json_value extracts String json value from a key /// extract_json_value extracts String json value from a key
@ -18,14 +18,14 @@ fn extract_json_value(data: &Object, key: &str) -> String {
"".to_string() "".to_string()
} }
#[derive(Default)] #[derive(Default, Debug)]
pub struct Credentials { pub struct Credentials {
pub username: String, pub username: String,
pub password: String, pub password: String,
} }
impl Credentials { impl Credentials {
fn new(username: String, password: String) -> Self { pub fn new(username: String, password: String) -> Self {
Credentials { username, password } Credentials { username, password }
} }

4
tests/data/store.txt Normal file
View File

@ -0,0 +1,4 @@
# this a test password storage with password in clear
# need to be updated in the future to encrypt or hash the password
# <username>:<password>
toto:tata