use actix_identity::Identity; use actix_web::{HttpMessage, HttpRequest}; use serde::{Deserialize, Serialize}; use crate::data::user::{User, UserID}; use crate::utils::time::time; #[derive(Debug, Serialize, Deserialize, Eq, PartialEq)] pub enum SessionStatus { Invalid, SignedIn, NeedNewPassword, Need2FA, } impl Default for SessionStatus { fn default() -> Self { Self::Invalid } } #[derive(Debug, Serialize, Deserialize, Default)] pub struct SessionIdentityData { pub id: Option, pub is_admin: bool, pub auth_time: u64, pub status: SessionStatus, } pub struct SessionIdentity<'a>(pub Option<&'a Identity>); impl<'a> SessionIdentity<'a> { fn get_session_data(&self) -> Option { if let Some(id) = self.0 { Self::deserialize_session_data(id.id().ok()) } else { None } } pub fn deserialize_session_data(data: Option) -> Option { let res: Option = data .as_deref() .map(serde_json::from_str) .map(|f| match f { Ok(d) => Some(d), Err(e) => { log::warn!("Failed to deserialize session data! {:?}", e); None } }) .unwrap_or(None); // Check if session is valid if let Some(sess) = &res { sess.id.as_ref()?; } res } fn set_session_data(&self, req: &HttpRequest, data: &SessionIdentityData) { let s = serde_json::to_string(data).expect("Failed to serialize session data!"); log::debug!("Will set user session data."); if let Err(e) = Identity::login(&req.extensions(), s) { log::error!("Failed to set session data! {}", e); } log::debug!("Did set user session data."); } pub fn set_user(&self, req: &HttpRequest, user: &User) { self.set_session_data(req, &SessionIdentityData { id: Some(user.uid.clone()), is_admin: user.admin, auth_time: time(), status: SessionStatus::SignedIn, }); } pub fn set_status(&self, req: &HttpRequest, status: SessionStatus) { let mut sess = self.get_session_data().unwrap_or_default(); sess.status = status; self.set_session_data(req, &sess); } pub fn is_authenticated(&self) -> bool { self.get_session_data() .map(|s| s.status == SessionStatus::SignedIn) .unwrap_or(false) } pub fn need_new_password(&self) -> bool { self.get_session_data() .map(|s| s.status == SessionStatus::NeedNewPassword) .unwrap_or(false) } pub fn need_2fa_auth(&self) -> bool { self.get_session_data() .map(|s| s.status == SessionStatus::Need2FA) .unwrap_or(false) } pub fn is_admin(&self) -> bool { self.get_session_data().unwrap_or_default().is_admin } pub fn user_id(&self) -> UserID { self.get_session_data().unwrap_or_default().id .expect("UserID should never be null here!") } pub fn auth_time(&self) -> u64 { self.get_session_data().unwrap_or_default().auth_time } }