//use async_trait::async_trait; use async_session::{Session, SessionStore,MemoryStore}; use async_sqlx_session::SqliteSessionStore; // use axum::{ // http::{ // StatusCode, // request::Parts, // }, // extract::FromRequestParts, // }; // use tower_cookies::Cookies; use std::sync::{Arc,Mutex}; use rand_chacha::ChaCha8Rng; pub type Random = Arc>; use crate::{ // SESSION_COOKIE_NAME, defs::{ FileStore, AppDBs, SESSION_ID, USER_DATA, }, users::{ User, UserStatus, }, }; #[derive(Clone)] pub enum SessionStoreDB { Files(FileStore), SqlLite(SqliteSessionStore), Memory(MemoryStore), None, } /// In `SessionStoreDB` creation match the corresponding store to return it as item argument impl SessionStoreDB { pub fn connect_file_store(store: FileStore) -> Self{ SessionStoreDB::Files(store) } pub fn connect_memory_store() -> Self{ SessionStoreDB::Memory(MemoryStore::new()) } pub fn connect_sqlite_store(store: SqliteSessionStore) -> Self{ SessionStoreDB::SqlLite(store) } pub async fn store_session_data(id: &str, user_data: &str, expire: u64, app_dbs: &AppDBs) -> String { // dbg!("user_data: {}",&user_data); let mut session = Session::new(); if ! id.is_empty() { session.insert(SESSION_ID, id).unwrap_or_else(|e|{ println!("Error insert session {}",e); }); } if ! user_data.is_empty() { session.insert(USER_DATA, user_data).unwrap_or_else(|e|{ println!("Error insert session {}",e); }); } if expire > 0 { session.expire_in(std::time::Duration::from_secs(expire)); } else if app_dbs.config.session_expire > 0 { session.expire_in(std::time::Duration::from_secs(app_dbs.config.session_expire)); } //session.into_cookie_value().unwrap_or_default() match app_dbs.sessions_store_db.to_owned() { SessionStoreDB::Files(store) => { store.store_session(session).await.unwrap_or_else(|e|{ println!("Error store session {}",e); None }).unwrap_or_default() }, SessionStoreDB::SqlLite(store) => { store.store_session(session).await.unwrap_or_else(|e|{ println!("Error store session {}",e); None }).unwrap_or_default() }, SessionStoreDB::Memory(store) => { store.store_session(session).await.unwrap_or_else(|e|{ println!("Error store session {}",e); None }).unwrap_or_default() }, SessionStoreDB::None => { String::from("") }, } } pub async fn update_session_data(session: Session, app_dbs: &AppDBs) -> String { //session.into_cookie_value().unwrap_or_default() let cur_session = session.clone(); match app_dbs.sessions_store_db.to_owned() { SessionStoreDB::Files(store) => { store.store_session(session).await.unwrap_or_else(|e|{ println!("Error store session {}",e); None }).unwrap_or_default() }, SessionStoreDB::SqlLite(store) => { let _ = store.destroy_session(session).await; store.store_session(cur_session).await.unwrap_or_else(|e|{ println!("Error store session {}",e); None }).unwrap_or_default() }, SessionStoreDB::Memory(store) => { store.store_session(session).await.unwrap_or_else(|e|{ println!("Error store session {}",e); None }).unwrap_or_default() }, SessionStoreDB::None => { String::from("") }, } } pub async fn cleanup_data(app_dbs: &AppDBs) { //session.into_cookie_value().unwrap_or_default() match app_dbs.sessions_store_db.to_owned() { SessionStoreDB::Files(store) => { let _ = store.cleanup().await; }, SessionStoreDB::SqlLite(store) => { let _ = store.cleanup().await; }, SessionStoreDB::Memory(store) => { let _ = store.cleanup().await; }, SessionStoreDB::None => { }, } } } #[derive(Clone, Default, Debug)] pub struct AuthState{ pub session: Option, pub user: Option, } impl AuthState { // pub fn new(session: Session, user: User) -> Self { // let sid = session.get("sid").unwrap_or_default(); // let user_store = &app_dbs.user_store; // let user = User::select("id", sid, user_store).await.unwrap_or_default(); // //let user = User::from_id(sid, app_dbs); // Self { // session, // user // } // } // pub fn sid(&self) -> String { // if let Some(session) = &self.session { // session.get("sid").unwrap_or_default() // } else { // String::from("") // } // } pub fn id(&self) -> String { if let Some(session) = &self.session { session.id().to_owned() } else { String::from("") } } #[allow(dead_code)] pub fn ses_expired(&self) -> bool { if let Some(session) = &self.session { session.is_expired() } else { true } } pub fn ses_destroyed(&self) -> bool { if let Some(session) = &self.session { session.is_destroyed() } else { true } } pub fn destroy(&self) -> bool { if let Some(mut session) = self.session.to_owned() { session.destroy(); self.ses_destroyed() } else { true } } #[allow(dead_code)] pub fn ses_validate(&self) -> bool { if let Some(session) = &self.session { session.clone().validate().is_some() } else { false } } pub fn user_data(&self) -> Vec { if let Some(session) = &self.session { let user_data: String = session.get(USER_DATA).unwrap_or_default(); user_data.split("|").map(|s| s.to_string()).collect() } else { Vec::new() } } pub fn user_id(&self) -> String { let user_data = self.user_data(); if user_data.len() > 0 && user_data[0] != "0" { user_data[0].to_owned() } else { String::from("") } } pub fn user_name(&self) -> String { let user_data = self.user_data(); if user_data.len() > 1 && user_data[1] != "" { user_data[1].to_owned() } else { String::from("") } } pub fn user_email(&self) -> String { let user_data = self.user_data(); if user_data.len() > 2 && user_data[2] != "" { user_data[2].to_owned() } else { String::from("") } } pub fn user_roles(&self) -> String { let user_data = self.user_data(); if user_data.len() > 3 && user_data[3] != "" { user_data[3].to_owned() } else { String::from("") } } pub fn user_items(&self) -> String { let user_data = self.user_data(); if user_data.len() > 4 && user_data[4] != "" { user_data[4].to_owned() } else { String::from("") } } pub fn is_admin(&self) -> bool { let user_data = self.user_data(); if user_data.len() > 5 && user_data[5] != "" { user_data[5] == "true" || user_data[5] == "1" } else { false } } #[allow(dead_code)] pub fn user_status(&self) -> UserStatus { let user_data = self.user_data(); if user_data.len() > 6 && user_data[6] != "" { UserStatus::from_str(&user_data[6]) } else { UserStatus::Unknown } } pub fn has_auth_role(&self, auth_roles: &Vec) -> bool { let roles = self.user_roles(); for role in auth_roles.to_owned() { if roles.contains(&role) { return true; } } return false; } pub async fn expire_in(&mut self, expire_secs: u64, app_dbs: &AppDBs ) -> Self { if let Some(mut session) = self.session.to_owned() { session.expire_in(std::time::Duration::from_secs(expire_secs)); let _ = SessionStoreDB::update_session_data(session.to_owned(),&app_dbs).await; Self { session: Some(session), user: self.user.to_owned(), } } else { self.to_owned() } } #[allow(dead_code)] pub async fn from_data(&self, app_dbs: &AppDBs) -> Self { let user_id = self.user_id(); let user = if !user_id.is_empty() { // dbg!(&user_id); match User::select("id", &user_id, false, &app_dbs.user_store).await { Ok(user) => Some(user), Err(e) => { println!("Error user {}: {:#}",&user_id,e); None } } } else { None }; // dbg!(&user); Self { session: self.session.to_owned(), user, } } pub async fn from_cookie(session_cookie: String, app_dbs: &AppDBs) -> Self { let result_session = match app_dbs.sessions_store_db.to_owned() { SessionStoreDB::Files(store) => store .load_session(session_cookie) .await , SessionStoreDB::SqlLite(store) => store .load_session(session_cookie) .await , SessionStoreDB::Memory(store) => store .load_session(session_cookie.to_string()) .await , SessionStoreDB::None => { dbg!("No store"); return AuthState::default(); }, }; // dbg!(&result_session); match result_session { Ok(op_session) => if let Some(session) = op_session { if let Some(sid) = session.get::("sid") { // dbg!( // "UserDataFromSession: session decoded success, user_data={}", // &session // ); let user_store = &app_dbs.user_store; let user = User::select("id", &sid, false, user_store).await.unwrap_or_default(); return AuthState { session: Some(session), user: Some(user) }; } else { println!("No `sid` found in session"); } }, Err(e) => { println!("Error session {}", e); } } AuthState::default() } } /* #[async_trait] impl FromRequestParts for AuthState where S: Send + Sync, { type Rejection = (StatusCode, &'static str); async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result { // let h = parts.headers.to_owned(); // dbg!(&h); /* if let Some(app_dbs) = parts.extensions.get::>() { if let Some(cookies) = parts.extensions.get::() { if let Some(s_cookie) = cookies.get(SESSION_COOKIE_NAME) { let session_cookie = s_cookie.to_string().replace(&format!("{}=",SESSION_COOKIE_NAME),""); println!("From request parts cookie: {}",session_cookie); // continue to decode the session cookie // return Ok( // AuthState::from_cookie(session_cookie, app_dbs).await // ); } } } */ Ok(AuthState::default()) // Err(( // StatusCode::INTERNAL_SERVER_ERROR, // "No `user_data` found in session", // )) // let cookie = Option::::g(parts, state); // let cookie = Cookies::get(parts, state); // if let Some(_user_agent) = parts.headers.get(USER_AGENT) { // Ok(AuthState(None)) // } else { // Err((StatusCode::BAD_REQUEST, "`User-Agent` header is missing")) // } // let cookie = Option::>::from_request_parts(req, state) //let cookies = Cookies::from(pa, state).await?; // let info: String = cookies // .get(SESSION_COOKIE_NAME) // // .and_then(|c| c.value().parse().ok()) // .unwrap_or_default() // ; // dbg!(&info); // //cookies.add(Cookie::new(COOKIE_NAME, visited.to_string())); } } */