Menu
Public repository / a986cdcc29b5f2c7d03f819e1e5541d4751a1ea2
AkurAI-CRM / crates/crm-api/src/auth/session.rs
Latest change 5a39d9999089a19dada74875fd8c5c7c47f08bac - feat: OIDC auth via AkurAI IDP by Ólafur B. J.
use akurai_json::Value;
use akurai_storage::BTree;
pub struct User {
pub sub: String,
pub email: String,
}
pub fn create(db: &mut BTree, sub: &str, email: &str) -> String {
use std::collections::hash_map::RandomState;
use std::hash::{BuildHasher, Hasher};
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_secs();
let rand = RandomState::new().build_hasher().finish();
let session_id = format!("s_{:x}_{}", rand, now);
let record = Value::Object(vec![
("sub".into(), Value::Str(sub.into())),
("email".into(), Value::Str(email.into())),
("createdAt".into(), Value::Int(now as i64)),
]);
let key = format!("_session:{}", session_id);
let _ = db.insert(key.as_bytes(), record.to_json().as_bytes());
let _ = db.commit();
session_id
}
pub fn extract_session_id(req: &akurai_http::Request) -> Option<String> {
if let Some(auth) = req.header("Authorization") {
if let Some(token) = auth.strip_prefix("Bearer ") {
let t = token.trim();
if !t.is_empty() {
return Some(t.to_string());
}
}
}
if let Some(cookies) = req.header("Cookie") {
for part in cookies.split(';') {
let part = part.trim();
if let Some(value) = part.strip_prefix("crm_session=") {
let v = value.trim();
if !v.is_empty() {
return Some(v.to_string());
}
}
}
}
None
}
pub fn get_user(db: &mut BTree, session_id: &str) -> Option<User> {
let key = format!("_session:{}", session_id);
match db.get(key.as_bytes()) {
Ok(Some(bytes)) => {
let s = String::from_utf8_lossy(&bytes);
if let Ok(val) = akurai_json::parse(&s) {
let sub = val.get("sub").and_then(|v| v.as_str()).unwrap_or("").to_string();
let email = val.get("email").and_then(|v| v.as_str()).unwrap_or("").to_string();
Some(User { sub, email })
} else {
None
}
}
_ => None,
}
}