1use std::sync::Arc;
6use std::collections::HashMap;
7use chrono::{Duration, Utc};
8use tokio::sync::RwLock;
9use sa_token_adapter::storage::SaStorage;
10use crate::config::SaTokenConfig;
11use crate::error::{SaTokenError, SaTokenResult};
12use crate::token::{TokenInfo, TokenValue, TokenGenerator};
13use crate::session::SaSession;
14use crate::event::{SaTokenEventBus, SaTokenEvent};
15use crate::online::OnlineManager;
16use crate::distributed::DistributedSessionManager;
17
18#[derive(Clone)]
20pub struct SaTokenManager {
21 pub(crate) storage: Arc<dyn SaStorage>,
22 pub config: SaTokenConfig,
23 pub(crate) user_permissions: Arc<RwLock<HashMap<String, Vec<String>>>>,
25 pub(crate) user_roles: Arc<RwLock<HashMap<String, Vec<String>>>>,
27 pub(crate) event_bus: SaTokenEventBus,
29 online_manager: Option<Arc<OnlineManager>>,
31 distributed_manager: Option<Arc<DistributedSessionManager>>,
33}
34
35impl SaTokenManager {
36 pub fn new(storage: Arc<dyn SaStorage>, config: SaTokenConfig) -> Self {
38 Self {
39 storage,
40 config,
41 user_permissions: Arc::new(RwLock::new(HashMap::new())),
42 user_roles: Arc::new(RwLock::new(HashMap::new())),
43 event_bus: SaTokenEventBus::new(),
44 online_manager: None,
45 distributed_manager: None,
46 }
47 }
48
49 pub fn with_online_manager(mut self, manager: Arc<OnlineManager>) -> Self {
50 self.online_manager = Some(manager);
51 self
52 }
53
54 pub fn with_distributed_manager(mut self, manager: Arc<DistributedSessionManager>) -> Self {
55 self.distributed_manager = Some(manager);
56 self
57 }
58
59 pub fn online_manager(&self) -> Option<&Arc<OnlineManager>> {
60 self.online_manager.as_ref()
61 }
62
63 pub fn distributed_manager(&self) -> Option<&Arc<DistributedSessionManager>> {
64 self.distributed_manager.as_ref()
65 }
66
67 pub fn event_bus(&self) -> &SaTokenEventBus {
69 &self.event_bus
70 }
71
72 pub async fn login(&self, login_id: impl Into<String>) -> SaTokenResult<TokenValue> {
74 let login_id = login_id.into();
75
76 let token = TokenGenerator::generate_with_login_id(&self.config, &login_id);
78
79 let mut token_info = TokenInfo::new(token.clone(), login_id.clone());
81 token_info.login_type = "default".to_string();
82
83 if let Some(timeout) = self.config.timeout_duration() {
85 token_info.expire_time = Some(Utc::now() + Duration::from_std(timeout).unwrap());
86 }
87
88 let key = format!("sa:token:{}", token.as_str());
90 let value = serde_json::to_string(&token_info)
91 .map_err(|e| SaTokenError::SerializationError(e))?;
92
93 self.storage.set(&key, &value, self.config.timeout_duration()).await
94 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
95
96 let login_token_key = format!("sa:login:token:{}", login_id);
98 self.storage.set(&login_token_key, token.as_str(), self.config.timeout_duration()).await
99 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
100
101 if !self.config.is_concurrent {
103 self.logout_by_login_id(&login_id).await?;
104 }
105
106 let event = SaTokenEvent::login(login_id.clone(), token.as_str())
108 .with_login_type(&token_info.login_type);
109 self.event_bus.publish(event).await;
110
111 Ok(token)
112 }
113
114 pub async fn logout(&self, token: &TokenValue) -> SaTokenResult<()> {
116 let key = format!("sa:token:{}", token.as_str());
118 let token_info_str = self.storage.get(&key).await
119 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
120
121 let token_info = if let Some(value) = token_info_str {
122 serde_json::from_str::<TokenInfo>(&value).ok()
123 } else {
124 None
125 };
126
127 self.storage.delete(&key).await
129 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
130
131 if let Some(info) = token_info {
133 let event = SaTokenEvent::logout(info.login_id, token.as_str())
134 .with_login_type(&info.login_type);
135 self.event_bus.publish(event).await;
136 }
137
138 Ok(())
139 }
140
141 pub async fn logout_by_login_id(&self, _login_id: &str) -> SaTokenResult<()> {
143 Ok(())
146 }
147
148 pub async fn get_token_info(&self, token: &TokenValue) -> SaTokenResult<TokenInfo> {
150 let key = format!("sa:token:{}", token.as_str());
151 let value = self.storage.get(&key).await
152 .map_err(|e| SaTokenError::StorageError(e.to_string()))?
153 .ok_or(SaTokenError::TokenNotFound)?;
154
155 let token_info: TokenInfo = serde_json::from_str(&value)
156 .map_err(|e| SaTokenError::SerializationError(e))?;
157
158 if token_info.is_expired() {
160 self.logout(token).await?;
162 return Err(SaTokenError::TokenExpired);
163 }
164
165 if self.config.auto_renew {
168 let renew_timeout = if self.config.active_timeout > 0 {
169 self.config.active_timeout
170 } else {
171 self.config.timeout
172 };
173
174 let _ = self.renew_timeout_internal(token, renew_timeout, &token_info).await;
176 }
177
178 Ok(token_info)
179 }
180
181 pub async fn is_valid(&self, token: &TokenValue) -> bool {
183 self.get_token_info(token).await.is_ok()
184 }
185
186 pub async fn get_session(&self, login_id: &str) -> SaTokenResult<SaSession> {
188 let key = format!("sa:session:{}", login_id);
189 let value = self.storage.get(&key).await
190 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
191
192 if let Some(value) = value {
193 let session: SaSession = serde_json::from_str(&value)
194 .map_err(|e| SaTokenError::SerializationError(e))?;
195 Ok(session)
196 } else {
197 Ok(SaSession::new(login_id))
198 }
199 }
200
201 pub async fn save_session(&self, session: &SaSession) -> SaTokenResult<()> {
203 let key = format!("sa:session:{}", session.id);
204 let value = serde_json::to_string(session)
205 .map_err(|e| SaTokenError::SerializationError(e))?;
206
207 self.storage.set(&key, &value, None).await
208 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
209
210 Ok(())
211 }
212
213 pub async fn delete_session(&self, login_id: &str) -> SaTokenResult<()> {
215 let key = format!("sa:session:{}", login_id);
216 self.storage.delete(&key).await
217 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
218 Ok(())
219 }
220
221 pub async fn renew_timeout(
223 &self,
224 token: &TokenValue,
225 timeout_seconds: i64,
226 ) -> SaTokenResult<()> {
227 let token_info = self.get_token_info(token).await?;
228 self.renew_timeout_internal(token, timeout_seconds, &token_info).await
229 }
230
231 async fn renew_timeout_internal(
233 &self,
234 token: &TokenValue,
235 timeout_seconds: i64,
236 token_info: &TokenInfo,
237 ) -> SaTokenResult<()> {
238 let mut new_token_info = token_info.clone();
239
240 use chrono::{Utc, Duration};
242 let new_expire_time = Utc::now() + Duration::seconds(timeout_seconds);
243 new_token_info.expire_time = Some(new_expire_time);
244
245 let key = format!("sa:token:{}", token.as_str());
247 let value = serde_json::to_string(&new_token_info)
248 .map_err(|e| SaTokenError::SerializationError(e))?;
249
250 let timeout = std::time::Duration::from_secs(timeout_seconds as u64);
251 self.storage.set(&key, &value, Some(timeout)).await
252 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
253
254 Ok(())
255 }
256
257 pub async fn kick_out(&self, login_id: &str) -> SaTokenResult<()> {
259 let token_result = self.storage.get(&format!("sa:login:token:{}", login_id)).await;
260
261 if let Some(online_mgr) = &self.online_manager {
262 let _ = online_mgr.kick_out_notify(login_id, "Account kicked out".to_string()).await;
263 }
264
265 self.logout_by_login_id(login_id).await?;
266 self.delete_session(login_id).await?;
267
268 if let Ok(Some(token_str)) = token_result {
269 let event = SaTokenEvent::kick_out(login_id, token_str);
270 self.event_bus.publish(event).await;
271 }
272
273 Ok(())
274 }
275}