use std::sync::Arc;
use crate::dao::SaTokenDao;
use crate::error::{SaTokenError, SaTokenResult};
use crate::sso::SsoSession;
pub struct SsoSessionStore {
dao: Arc<SaTokenDao>,
}
impl std::fmt::Debug for SsoSessionStore {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("SsoSessionStore { .. }")
}
}
impl SsoSessionStore {
pub fn new(dao: Arc<SaTokenDao>) -> Self {
Self { dao }
}
pub async fn upsert_client(&self, login_id: &str, service: &str) -> SaTokenResult<()> {
let key = self.dao.keys().sso_session(login_id);
for _ in 0..8 {
let current = self.dao.get_string(&key).await?;
let mut session = match ¤t {
Some(raw) => self.dao.decode::<SsoSession>(raw)?,
None => SsoSession::new(login_id.to_string()),
};
session.add_client(service.to_string());
let new_raw = self.dao.encode(&session)?;
let ok = self
.dao
.cas(&key, current.as_deref(), &new_raw, None)
.await?;
if ok {
return Ok(());
}
}
Err(SaTokenError::InternalError(
"SSO session CAS retries exhausted".into(),
))
}
pub async fn remove(&self, login_id: &str) -> SaTokenResult<Vec<String>> {
let key = self.dao.keys().sso_session(login_id);
let session = self.dao.get_object::<SsoSession>(&key).await?;
let clients = session.map(|s| s.clients).unwrap_or_default();
self.dao.delete(&key).await?;
Ok(clients)
}
pub async fn get(&self, login_id: &str) -> SaTokenResult<Option<SsoSession>> {
let key = self.dao.keys().sso_session(login_id);
self.dao.get_object(&key).await
}
}