feat: #8 parse store file content and add test
This commit is contained in:
parent
8bf503df14
commit
73059c724f
@ -12,6 +12,9 @@ regex = "1"
|
||||
tokio = { version = "1.21.1", features = ["full"] }
|
||||
async-trait = "0.1.57"
|
||||
|
||||
# useful for tests (embedded files should be delete in release ?)
|
||||
#rust-embed="6.4.1"
|
||||
|
||||
[dependencies.async-std]
|
||||
version = "1.6"
|
||||
features = ["attributes"]
|
||||
|
||||
@ -11,30 +11,65 @@ use super::store::{Credentials, Store};
|
||||
/// FileStore references a `store` file
|
||||
pub struct FileStore {
|
||||
path: String,
|
||||
credentials: Vec<Credentials>,
|
||||
}
|
||||
|
||||
impl FileStore {
|
||||
fn new(path: String) -> Self {
|
||||
FileStore { path }
|
||||
FileStore {
|
||||
path,
|
||||
credentials: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
async fn parse_contents(&self, mut file: File) -> Vec<u8> {
|
||||
let mut contents = vec![];
|
||||
let byte_read = file.read_to_end(&mut contents).await;
|
||||
if byte_read.is_err() {
|
||||
eprintln!(
|
||||
"error occurred while reading store file: {}, err={:?}",
|
||||
self.path,
|
||||
byte_read.err()
|
||||
);
|
||||
/// parse_contents loads and reads the file asynchonously
|
||||
/// parses the file line by line to retrieve the credentials
|
||||
async fn parse_contents(&mut self) {
|
||||
let contents = tokio::fs::read_to_string(&self.path).await;
|
||||
let mut credentials: Vec<Credentials> = vec![];
|
||||
match contents {
|
||||
Ok(c) => {
|
||||
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]
|
||||
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
|
||||
if !Path::new(&self.path).is_file() {
|
||||
eprintln!("{} path referencing file store does not exist", self.path);
|
||||
@ -47,22 +82,22 @@ impl Store for FileStore {
|
||||
return false;
|
||||
}
|
||||
|
||||
let store = File::open(&self.path).await;
|
||||
match store {
|
||||
Ok(f) => {
|
||||
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
|
||||
let contents = self.parse_contents().await;
|
||||
|
||||
self.auth(credentials.username, credentials.password)
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_store() {
|
||||
let store = FileStore::new("/tmp/thegux.pid".to_string());
|
||||
let data = json::parse(r#"{"access_token": "toto", "refresh_token": "tutu"}"#).unwrap();
|
||||
assert_eq!(store.is_auth(&data).await, false);
|
||||
use std::env;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ use json::object::Object;
|
||||
|
||||
#[async_trait]
|
||||
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
|
||||
@ -18,14 +18,14 @@ fn extract_json_value(data: &Object, key: &str) -> String {
|
||||
"".to_string()
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Default, Debug)]
|
||||
pub struct Credentials {
|
||||
pub username: String,
|
||||
pub password: String,
|
||||
}
|
||||
|
||||
impl Credentials {
|
||||
fn new(username: String, password: String) -> Self {
|
||||
pub fn new(username: String, password: String) -> Self {
|
||||
Credentials { username, password }
|
||||
}
|
||||
|
||||
|
||||
4
tests/data/store.txt
Normal file
4
tests/data/store.txt
Normal 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
|
||||
Loading…
x
Reference in New Issue
Block a user