use std::{ io::Write, // sync::Arc, fmt::Debug, fs, path::{Path, PathBuf}, io::{Error, ErrorKind}, }; use log::error; // use async_session::{MemoryStore, Session, SessionStore}; use serde::{Deserialize, Serialize}; //use tiitls_utils::logs::file; use uuid::Uuid; use crate::defs::{ FILE_SCHEME, SID_SETTINGS_FILE, SID_REQUESTS_FILE, SID_TRACE_FILE, // SID_UI_FILE, // UI_SETTINGS_FILE, // SidSettings, Config as SessionsConfig, TraceData, UserAction, }; #[derive(Serialize, Deserialize, Debug, Clone, Copy)] pub struct UserId(Uuid); impl UserId { #[allow(dead_code)] pub fn new() -> Self { Self(Uuid::new_v4()) } pub fn from(data: &str) -> Option { match Uuid::parse_str(data) { Ok(uuid) => Some(Self(uuid)), Err(_) => None, } } } impl std::fmt::Display for UserId { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0) } } impl UserId { /// Log user actions to config.user_store_access|reqs_store_file/user_id/config.user_store_access path /// Add a line with timestamp /// It also get ReqHeaderMap to add more data ? #[allow(dead_code)] pub fn log_user_id_action(&self, action: UserAction, sessions_config: &SessionsConfig) -> std::io::Result<()> { let id_path = format!("{}/{}", sessions_config.users_store_uri.replace(FILE_SCHEME, ""), self); if ! Path::new(&id_path).exists() { fs::create_dir(&id_path)?; } let now = chrono::Utc::now().timestamp().to_string(); let (log_data, file_path) = match action { UserAction::Access => ( format!("{}\n",now), format!("{}/{}",&id_path,sessions_config.user_store_access) ), UserAction::Log(info) => ( format!("notity:{}:{}\n",now,info), format!("{}/{}",&id_path,sessions_config.user_store_access) ), UserAction::Request(info) => ( format!("req:{}:{}\n",now,info), format!("{}/{}",&id_path,sessions_config.user_store_access) ), UserAction::View(info) => ( format!("view:{}:{}\n",now,info), format!("{}/{}",&id_path,sessions_config.user_store_access) ), UserAction::List(info) => ( format!("list:{}:{}\n",now,info), format!("{}/{}",&id_path,sessions_config.user_store_access) ), UserAction::Profile(info) => ( format!("profile:{}:{}\n",now,info), format!("{}/{}",&id_path,sessions_config.user_store_access) ), UserAction::Other => ( format!("other:{}::\n",now), format!("{}/{}",&id_path,sessions_config.user_store_access) ), }; self.write_data(&file_path, &log_data, false) // if ! Path::new(&file_path).exists() { // fs::write(&file_path, log_data)?; // } else { // let access_id_file = fs::OpenOptions::new() // .write(true) // .append(true) // This is needed to append to file // .open(&file_path); // if let Ok(mut file) = access_id_file { // let _ = file.write_all(log_data.as_bytes())?; // } // } // Ok(()) } fn id_path(&self, file: &str, sessions_config: &SessionsConfig) -> String { format!("{}/{}/{}", sessions_config.users_store_uri.replace(FILE_SCHEME, ""), self,file) } #[allow(dead_code)] fn write_data(&self, file_path: &str, data: &str, overwrite: bool) -> std::io::Result<()> { let check_path = |path: &Path| -> std::io::Result<()> { if ! Path::new(&path).exists() { if let Err(e) = std::fs::create_dir(&path) { return Err(Error::new( ErrorKind::InvalidInput, format!("Error create path {}: {}",&path.display(), e) )); // std::process::exit(2) } } Ok(()) }; if file_path.is_empty() || data.is_empty() { return Err(Error::new( ErrorKind::InvalidInput, format!("Error save {}",&file_path) )); } if ! Path::new(&file_path).exists() { let path = PathBuf::from(&file_path); if let Some(dir_path) = path.parent() { if ! Path::new(&dir_path).exists() { if let Some(parent_dir_path) = dir_path.parent() { if ! Path::new(&parent_dir_path).exists() { let res = check_path(&parent_dir_path); if res.is_err() { return res; } } } let res = check_path(&dir_path); if res.is_err() { return res; } } } } if overwrite || ! Path::new(&file_path).exists() { fs::write(&file_path, data)?; println!("Overwrite: {}",&file_path); } else { let sid_settings_file = fs::OpenOptions::new() .write(true) .append(true) // This is needed to append to file .open(&file_path); if let Ok(mut file) = sid_settings_file { file.write_all(data.as_bytes())?; } println!("write: {}",&file_path); } Ok(()) } #[allow(dead_code)] pub fn sid_settings_path(&self, sessions_config: &SessionsConfig) -> String { self.id_path(SID_SETTINGS_FILE, sessions_config) } #[allow(dead_code)] pub fn sid_settings_content(&self, sessions_config: &SessionsConfig) -> String { let file_path = self.sid_settings_path(sessions_config); if ! Path::new(&file_path).exists() { String::from("") } else { match std::fs::read_to_string(&file_path) { Ok(content) => content, Err(e) => { error!("Error read {}: {}",&file_path,e); String::from("") } } } } // pub fn sid_settings(&self, sessions_config: &SessionsConfig) -> SidSettings { // let file_path = self.id_path(SID_SETTINGS_FILE, sessions_config); // if Path::new(&file_path).exists() { // match std::fs::read_to_string(&file_path) { // Ok(content) => sessions_config.sid_settings.from_json(&content,&file_path), // Err(e) => { // error!("Error read {}: {}",&file_path,e); // sessions_config.sid_settings.to_owned() // } // } // } else { // //dbg!(&sessions_config.sid_settings); // sessions_config.sid_settings.to_owned() // } // } // pub fn save_sid_settings(&self, sid_settings: SidSettings, sessions_config: &SessionsConfig) -> std::io::Result<()> { // let file_path = self.id_path(SID_SETTINGS_FILE, sessions_config); // let data = sid_settings.to_json(); // self.write_data(&file_path, &data, true) // } #[allow(dead_code)] pub fn save_trace_data(&self, trace_data: TraceData, sessions_config: &SessionsConfig) -> std::io::Result<()> { // let file_curenv_path = self.id_path(&format!("{}/{}",trace_data.server,SID_CURENV_FILE), sessions_config); // let res_curenv = self.write_data(&file_curenv_path, &trace_data.curenv, true); // let _ = res_curenv.as_ref().unwrap_or_else(|e|{ // println!("Error save trace curenv: {}",&e); // &() // }); // if res_curenv.is_err() { // return res_curenv; // } // if trace_data.ui.len() > 0 { // let file_ui_path = self.id_path(&format!("{}/{}",trace_data.server,SID_UI_FILE), sessions_config); // let res_ui = self.write_data(&file_ui_path, &trace_data.ui, true); // let _ = res_ui.as_ref().unwrap_or_else(|e|{ // println!("Error save trace ui: {}",&e); // &() // }); // if res_ui.is_err() { return res_ui; } // } let file_trace_path = self.id_path(&format!("{}/{}",trace_data.server,SID_TRACE_FILE), sessions_config); let contents = trace_data.contents_to_json(); let mut result = Ok(()); let lines = contents.len() - 1; for (idx, line) in contents.iter().enumerate() { let prfx = if idx == 0 && Path::new(&file_trace_path).exists() { ",\n" } else { "" }; let sfx = if idx == lines { "" } else { ",\n" }; result = self.write_data( &file_trace_path, format!("{}{}{}",&prfx,&line,&sfx).as_str(), false ); let _ = result.as_ref().unwrap_or_else(|e|{ println!("Error save trace contets: {} line {}",&e, &idx); &() }); if result.is_err() { break; } } result } #[allow(dead_code)] pub fn save_sid_request(&self, data: &str, sessions_config: &SessionsConfig) -> std::io::Result<()> { let file_path = self.id_path(SID_REQUESTS_FILE, sessions_config); println!("---- {}",&file_path); self.write_data(&file_path, &data, false) } #[allow(dead_code)] pub fn read_sid_requests(&self, sessions_config: &SessionsConfig) -> Result, Box> { let file_path = self.id_path(SID_REQUESTS_FILE, sessions_config); let data = fs::read_to_string(file_path)?; Ok(data.split("\n").map(|s| s.to_string()).collect()) } }