BasicOIDC/src/data/session_identity.rs

135 lines
3.7 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 last_2fa_auth: Option<u64>,
pub status: SessionStatus,
}
pub struct SessionIdentity<'a>(pub Option<&'a Identity>);
impl SessionIdentity<'_> {
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, status: SessionStatus) {
self.set_session_data(
req,
&SessionIdentityData {
id: Some(user.uid.clone()),
is_admin: user.admin,
last_2fa_auth: None,
auth_time: time(),
status,
},
);
}
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 record_2fa_auth(&self, req: &HttpRequest) {
let mut sess = self.get_session_data().unwrap_or_default();
sess.last_2fa_auth = Some(time());
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
}
pub fn last_2fa_auth(&self) -> Option<u64> {
self.get_session_data().unwrap_or_default().last_2fa_auth
}
}