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"] } | 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"] | ||||||
|  | |||||||
| @ -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); | ||||||
| } | } | ||||||
|  | |||||||
| @ -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
									
								
							
							
						
						
									
										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