use axum_extra::extract::cookie::{Cookie, CookieJar}; use uuid::Uuid; use std::sync::{Arc, RwLock}; use crate::db::User; pub const COOKIE_NAME: &str = "lldap_session"; #[derive(Clone, Debug)] pub struct HttpSessionManager { inner: Arc>>, } impl HttpSessionManager { pub fn new() -> Self { Self { inner: Arc::new(RwLock::new(vec![])), } } pub fn add_session(&self, user: User, cookies: CookieJar) -> CookieJar { let uuid = Uuid::new_v4(); let mut cookie = Cookie::new(COOKIE_NAME, uuid.to_string()); cookie.set_path("/"); let session = HttpSession { user, uuid }; { self.inner.write().unwrap().push(session); } cookies.add(cookie) } pub fn get_session(&self, cookies: &CookieJar) -> Option { let cookie = cookies.get(COOKIE_NAME)?; let previous_uuid = Uuid::parse_str(cookie.value()).ok()?; self.inner .read() .unwrap() .iter() .find(|session| session.uuid == previous_uuid) .cloned() } pub fn remove_session(&self, session: &HttpSession, cookies: CookieJar) -> CookieJar { let mut cookie = Cookie::new(COOKIE_NAME, String::new()); cookie.set_path("/"); let idx = { let Some(idx) = self.inner.read().unwrap().iter().position(|s| s == session) else { return cookies; }; idx }; { self.inner.write().unwrap().remove(idx); } cookies.remove(cookie) } } #[derive(Clone, Debug)] pub struct HttpSession { // TODO: by storing the session here, it means // it needs to be updated every time we change the user. pub user: User, pub uuid: Uuid, } impl PartialEq for HttpSession { fn eq(&self, other: &Self) -> bool { self.uuid == other.uuid } }