263 lines
9.9 KiB
Rust
263 lines
9.9 KiB
Rust
|
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<Self> {
|
||
|
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<Vec<String>, Box<dyn std::error::Error>> {
|
||
|
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())
|
||
|
}
|
||
|
}
|