2022-04-01 16:59:17 +00:00
|
|
|
use actix_identity::Identity;
|
2022-04-01 20:51:33 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
2022-04-01 16:59:17 +00:00
|
|
|
|
2022-04-01 20:51:33 +00:00
|
|
|
use crate::constants::{MAX_SESSION_DURATION, MIN_ACTIVITY_RECORD_TIME};
|
2022-04-01 16:59:17 +00:00
|
|
|
use crate::data::user::User;
|
2022-04-01 20:51:33 +00:00
|
|
|
use crate::utils::time::time;
|
|
|
|
|
|
|
|
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
|
2022-04-02 06:30:01 +00:00
|
|
|
pub enum SessionStatus {
|
|
|
|
Invalid,
|
2022-04-01 20:51:33 +00:00
|
|
|
SignedIn,
|
|
|
|
NeedNewPassword,
|
|
|
|
NeedMFA,
|
|
|
|
}
|
2022-04-01 16:59:17 +00:00
|
|
|
|
2022-04-02 06:30:01 +00:00
|
|
|
impl Default for SessionStatus {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self::Invalid
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Serialize, Deserialize, Default)]
|
2022-04-01 20:51:33 +00:00
|
|
|
struct SessionIdentityData {
|
2022-04-01 16:59:17 +00:00
|
|
|
pub id: String,
|
|
|
|
pub is_admin: bool,
|
2022-04-01 20:51:33 +00:00
|
|
|
last_access: u64,
|
|
|
|
pub status: SessionStatus,
|
2022-04-02 06:30:01 +00:00
|
|
|
|
|
|
|
// TODO : add session max duration (1 day)
|
2022-04-01 16:59:17 +00:00
|
|
|
}
|
|
|
|
|
2022-04-01 20:51:33 +00:00
|
|
|
pub struct SessionIdentity<'a>(pub &'a Identity);
|
|
|
|
|
|
|
|
impl<'a> SessionIdentity<'a> {
|
|
|
|
pub fn set_user(&self, user: &User) {
|
|
|
|
self.set_session_data(&SessionIdentityData {
|
2022-04-01 16:59:17 +00:00
|
|
|
id: user.uid.clone(),
|
|
|
|
is_admin: user.admin,
|
2022-04-01 20:51:33 +00:00
|
|
|
last_access: time(),
|
|
|
|
status: SessionStatus::SignedIn,
|
|
|
|
});
|
2022-04-01 16:59:17 +00:00
|
|
|
}
|
|
|
|
|
2022-04-01 20:51:33 +00:00
|
|
|
fn get_session_data(&self) -> Option<SessionIdentityData> {
|
|
|
|
let mut res: Option<SessionIdentityData> = self.0.identity()
|
|
|
|
.as_ref()
|
|
|
|
.map(String::as_str)
|
|
|
|
.map(serde_json::from_str)
|
|
|
|
.map(|f| f.expect("Failed to deserialize session data!"));
|
|
|
|
|
2022-04-02 06:30:01 +00:00
|
|
|
// Check if session is valid
|
|
|
|
if let Some(sess) = &res {
|
|
|
|
if sess.id.is_empty() {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-01 20:51:33 +00:00
|
|
|
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);
|
|
|
|
}
|
2022-04-01 16:59:17 +00:00
|
|
|
}
|
2022-04-01 20:51:33 +00:00
|
|
|
|
|
|
|
res
|
2022-04-01 16:59:17 +00:00
|
|
|
}
|
|
|
|
|
2022-04-01 20:51:33 +00:00
|
|
|
fn set_session_data(&self, data: &SessionIdentityData) {
|
|
|
|
let s = serde_json::to_string(data)
|
|
|
|
.expect("Failed to serialize session data!");
|
|
|
|
|
|
|
|
self.0.remember(s);
|
2022-04-01 16:59:17 +00:00
|
|
|
}
|
|
|
|
|
2022-04-02 06:30:01 +00:00
|
|
|
pub fn set_status(&self, status: SessionStatus) {
|
|
|
|
let mut sess = self.get_session_data().unwrap_or_default();
|
|
|
|
sess.status = status;
|
|
|
|
self.set_session_data(&sess);
|
|
|
|
}
|
|
|
|
|
2022-04-01 20:51:33 +00:00
|
|
|
pub fn is_authenticated(&self) -> bool {
|
|
|
|
self.get_session_data()
|
|
|
|
.map(|s| s.status == SessionStatus::SignedIn)
|
2022-04-01 16:59:17 +00:00
|
|
|
.unwrap_or(false)
|
|
|
|
}
|
2022-04-02 06:30:01 +00:00
|
|
|
|
|
|
|
pub fn need_new_password(&self) -> bool {
|
|
|
|
self.get_session_data()
|
|
|
|
.map(|s| s.status == SessionStatus::NeedNewPassword)
|
|
|
|
.unwrap_or(false)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn user_id(&self) -> String {
|
|
|
|
self.get_session_data()
|
|
|
|
.unwrap_or_default()
|
|
|
|
.id
|
|
|
|
}
|
2022-04-01 16:59:17 +00:00
|
|
|
}
|