use std::sync::Arc;
use std::time::Duration;
use crate::config::SaTokenConfig;
use crate::dao::SaTokenDao;
use crate::error::{SaTokenError, SaTokenResult};
use crate::keys::{AccountNs, LoginId, SaKeys};
use crate::session::{SaSession, SaTerminalInfo};
use crate::token::TokenValue;
pub struct SessionRepo {
dao: Arc<SaTokenDao>,
config: Arc<SaTokenConfig>,
}
impl std::fmt::Debug for SessionRepo {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("SessionRepo { .. }")
}
}
impl SessionRepo {
pub fn new(dao: Arc<SaTokenDao>, config: Arc<SaTokenConfig>) -> Self {
Self { dao, config }
}
fn session_ttl(&self) -> Option<Duration> {
self.dao.default_ttl()
}
fn ns(login_type: &str, login_id: &str) -> SaTokenResult<AccountNs> {
let id =
LoginId::try_new(login_id).map_err(|e| SaTokenError::ConfigError(e.to_string()))?;
Ok(SaKeys::account_ns(login_type, &id))
}
fn account_session_key(&self, ns: &AccountNs) -> SaTokenResult<String> {
self.dao
.keys()
.session_by_ns(ns)
.map_err(|e| SaTokenError::ConfigError(e.to_string()))
}
pub async fn get_by_ns(&self, ns: &AccountNs) -> SaTokenResult<SaSession> {
let key = self.account_session_key(ns)?;
if let Some(session) = self.dao.get_object::<SaSession>(&key).await? {
return Ok(session);
}
Ok(SaSession::new(ns.as_str()))
}
pub async fn get_account_session(
&self,
login_type: &str,
login_id: &str,
) -> SaTokenResult<SaSession> {
let ns = Self::ns(login_type, login_id)?;
self.get_by_ns(&ns).await
}
pub async fn snapshot_account_session(&self, ns: &AccountNs) -> SaTokenResult<Option<String>> {
let key = self.account_session_key(ns)?;
self.dao.get_string(&key).await
}
pub async fn save_by_ns(&self, ns: &AccountNs, session: &SaSession) -> SaTokenResult<()> {
let key = self.account_session_key(ns)?;
self.dao.set_object(&key, session, self.session_ttl()).await
}
pub async fn save_account_session(
&self,
login_type: &str,
login_id: &str,
session: &SaSession,
) -> SaTokenResult<()> {
let ns = Self::ns(login_type, login_id)?;
self.save_by_ns(&ns, session).await
}
pub async fn save_session_object(&self, session: &SaSession) -> SaTokenResult<()> {
let ns = AccountNs::from_trusted(session.id.clone());
self.save_by_ns(&ns, session).await
}
pub async fn delete_by_ns(&self, ns: &AccountNs) -> SaTokenResult<()> {
let key = self.account_session_key(ns)?;
self.dao.delete(&key).await
}
pub async fn delete_account_session(
&self,
login_type: &str,
login_id: &str,
) -> SaTokenResult<()> {
let ns = Self::ns(login_type, login_id)?;
self.delete_by_ns(&ns).await
}
pub async fn add_terminal(
&self,
ns: &AccountNs,
terminal: SaTerminalInfo,
) -> SaTokenResult<()> {
let mut session = self.get_by_ns(ns).await?;
session.add_terminal(terminal);
self.save_by_ns(ns, &session).await
}
pub async fn remove_terminal(&self, ns: &AccountNs, token: &str) -> SaTokenResult<bool> {
let mut session = self.get_by_ns(ns).await?;
if session.remove_terminal(token).is_none() {
return Ok(false);
}
self.save_by_ns(ns, &session).await?;
Ok(true)
}
pub async fn terminal_count(&self, ns: &AccountNs) -> SaTokenResult<usize> {
Ok(self.get_by_ns(ns).await?.terminal_count())
}
pub async fn get_terminal_list(
&self,
ns: &AccountNs,
device_type: Option<&str>,
) -> SaTokenResult<Vec<SaTerminalInfo>> {
Ok(self
.get_by_ns(ns)
.await?
.get_terminal_list_by_device_type(device_type))
}
pub async fn get_token_list(
&self,
ns: &AccountNs,
device_type: Option<&str>,
) -> SaTokenResult<Vec<String>> {
Ok(self
.get_by_ns(ns)
.await?
.get_token_value_list_by_device_type(device_type))
}
pub async fn get_terminal(
&self,
ns: &AccountNs,
token: &str,
) -> SaTokenResult<Option<SaTerminalInfo>> {
Ok(self.get_by_ns(ns).await?.get_terminal(token).cloned())
}
fn token_session_ttl(&self) -> Option<Duration> {
self.dao.default_ttl()
}
pub async fn create_token_session(&self, token: &TokenValue) -> SaTokenResult<()> {
let session = SaSession::new(format!("token-session:{}", token.as_str()));
self.save_token_session(token, &session).await
}
pub async fn save_token_session(
&self,
token: &TokenValue,
session: &SaSession,
) -> SaTokenResult<()> {
let key = self.dao.keys().token_session(token.as_str());
self.dao
.set_object(&key, session, self.token_session_ttl())
.await
}
pub async fn get_token_session(&self, token: &TokenValue) -> SaTokenResult<Option<SaSession>> {
let key = self.dao.keys().token_session(token.as_str());
self.dao.get_object(&key).await
}
pub async fn delete_token_session(&self, token: &TokenValue) -> SaTokenResult<()> {
self.dao
.delete(&self.dao.keys().token_session(token.as_str()))
.await
}
pub fn token_session_key(&self, token: &str) -> String {
self.dao.keys().token_session(token)
}
pub fn config(&self) -> &Arc<SaTokenConfig> {
&self.config
}
}