All checks were successful
continuous-integration/drone/push Build is passing
119 lines
3.3 KiB
Rust
119 lines
3.3 KiB
Rust
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<UserID>,
|
|
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<SessionIdentityData> {
|
|
if let Some(id) = self.0 {
|
|
Self::deserialize_session_data(id.id().ok())
|
|
}
|
|
else {
|
|
None
|
|
}
|
|
}
|
|
|
|
pub fn deserialize_session_data(data: Option<String>) -> Option<SessionIdentityData> {
|
|
let res: Option<SessionIdentityData> = 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
|
|
}
|
|
}
|