use actix_identity::Identity; use serde::{Deserialize, Serialize}; use crate::constants::{MAX_SESSION_DURATION, MIN_ACTIVITY_RECORD_TIME}; use crate::data::user::User; use crate::utils::time::time; #[derive(Debug, Serialize, Deserialize, Eq, PartialEq)] enum SessionStatus { SignedIn, NeedNewPassword, NeedMFA, } #[derive(Debug, Serialize, Deserialize)] struct SessionIdentityData { pub id: String, pub is_admin: bool, last_access: u64, pub status: SessionStatus, } pub struct SessionIdentity<'a>(pub &'a Identity); impl<'a> SessionIdentity<'a> { pub fn set_user(&self, user: &User) { self.set_session_data(&SessionIdentityData { id: user.uid.clone(), is_admin: user.admin, last_access: time(), status: SessionStatus::SignedIn, }); } fn get_session_data(&self) -> Option { let mut res: Option = self.0.identity() .as_ref() .map(String::as_str) .map(serde_json::from_str) .map(|f| f.expect("Failed to deserialize session data!")); if let Some(session) = res.as_mut() { if session.last_access + MAX_SESSION_DURATION < time() { log::info!("Session is expired for {}", session.id); self.0.forget(); return None; } if session.last_access + MIN_ACTIVITY_RECORD_TIME < time() { log::debug!("Refresh last access for session"); session.last_access = time(); self.set_session_data(session); } } res } fn set_session_data(&self, data: &SessionIdentityData) { let s = serde_json::to_string(data) .expect("Failed to serialize session data!"); self.0.remember(s); } pub fn is_authenticated(&self) -> bool { self.get_session_data() .map(|s| s.status == SessionStatus::SignedIn) .unwrap_or(false) } }