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};
15
16#[derive(Clone)]
18pub struct SaTokenManager {
19 pub(crate) storage: Arc<dyn SaStorage>,
20 pub config: SaTokenConfig,
21 pub(crate) user_permissions: Arc<RwLock<HashMap<String, Vec<String>>>>,
23 pub(crate) user_roles: Arc<RwLock<HashMap<String, Vec<String>>>>,
25 pub(crate) event_bus: SaTokenEventBus,
27}
28
29impl SaTokenManager {
30 pub fn new(storage: Arc<dyn SaStorage>, config: SaTokenConfig) -> Self {
32 Self {
33 storage,
34 config,
35 user_permissions: Arc::new(RwLock::new(HashMap::new())),
36 user_roles: Arc::new(RwLock::new(HashMap::new())),
37 event_bus: SaTokenEventBus::new(),
38 }
39 }
40
41 pub fn event_bus(&self) -> &SaTokenEventBus {
43 &self.event_bus
44 }
45
46 pub async fn login(&self, login_id: impl Into<String>) -> SaTokenResult<TokenValue> {
48 let login_id = login_id.into();
49
50 let token = TokenGenerator::generate_with_login_id(&self.config, &login_id);
52
53 let mut token_info = TokenInfo::new(token.clone(), login_id.clone());
55 token_info.login_type = "default".to_string();
56
57 if let Some(timeout) = self.config.timeout_duration() {
59 token_info.expire_time = Some(Utc::now() + Duration::from_std(timeout).unwrap());
60 }
61
62 let key = format!("sa:token:{}", token.as_str());
64 let value = serde_json::to_string(&token_info)
65 .map_err(|e| SaTokenError::SerializationError(e))?;
66
67 self.storage.set(&key, &value, self.config.timeout_duration()).await
68 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
69
70 let login_token_key = format!("sa:login:token:{}", login_id);
72 self.storage.set(&login_token_key, token.as_str(), self.config.timeout_duration()).await
73 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
74
75 if !self.config.is_concurrent {
77 self.logout_by_login_id(&login_id).await?;
78 }
79
80 let event = SaTokenEvent::login(login_id.clone(), token.as_str())
82 .with_login_type(&token_info.login_type);
83 self.event_bus.publish(event).await;
84
85 Ok(token)
86 }
87
88 pub async fn logout(&self, token: &TokenValue) -> SaTokenResult<()> {
90 let key = format!("sa:token:{}", token.as_str());
92 let token_info_str = self.storage.get(&key).await
93 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
94
95 let token_info = if let Some(value) = token_info_str {
96 serde_json::from_str::<TokenInfo>(&value).ok()
97 } else {
98 None
99 };
100
101 self.storage.delete(&key).await
103 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
104
105 if let Some(info) = token_info {
107 let event = SaTokenEvent::logout(info.login_id, token.as_str())
108 .with_login_type(&info.login_type);
109 self.event_bus.publish(event).await;
110 }
111
112 Ok(())
113 }
114
115 pub async fn logout_by_login_id(&self, _login_id: &str) -> SaTokenResult<()> {
117 Ok(())
120 }
121
122 pub async fn get_token_info(&self, token: &TokenValue) -> SaTokenResult<TokenInfo> {
124 let key = format!("sa:token:{}", token.as_str());
125 let value = self.storage.get(&key).await
126 .map_err(|e| SaTokenError::StorageError(e.to_string()))?
127 .ok_or(SaTokenError::TokenNotFound)?;
128
129 let token_info: TokenInfo = serde_json::from_str(&value)
130 .map_err(|e| SaTokenError::SerializationError(e))?;
131
132 if token_info.is_expired() {
134 self.logout(token).await?;
136 return Err(SaTokenError::TokenExpired);
137 }
138
139 if self.config.auto_renew {
142 let renew_timeout = if self.config.active_timeout > 0 {
143 self.config.active_timeout
144 } else {
145 self.config.timeout
146 };
147
148 let _ = self.renew_timeout_internal(token, renew_timeout, &token_info).await;
150 }
151
152 Ok(token_info)
153 }
154
155 pub async fn is_valid(&self, token: &TokenValue) -> bool {
157 self.get_token_info(token).await.is_ok()
158 }
159
160 pub async fn get_session(&self, login_id: &str) -> SaTokenResult<SaSession> {
162 let key = format!("sa:session:{}", login_id);
163 let value = self.storage.get(&key).await
164 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
165
166 if let Some(value) = value {
167 let session: SaSession = serde_json::from_str(&value)
168 .map_err(|e| SaTokenError::SerializationError(e))?;
169 Ok(session)
170 } else {
171 Ok(SaSession::new(login_id))
172 }
173 }
174
175 pub async fn save_session(&self, session: &SaSession) -> SaTokenResult<()> {
177 let key = format!("sa:session:{}", session.id);
178 let value = serde_json::to_string(session)
179 .map_err(|e| SaTokenError::SerializationError(e))?;
180
181 self.storage.set(&key, &value, None).await
182 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
183
184 Ok(())
185 }
186
187 pub async fn delete_session(&self, login_id: &str) -> SaTokenResult<()> {
189 let key = format!("sa:session:{}", login_id);
190 self.storage.delete(&key).await
191 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
192 Ok(())
193 }
194
195 pub async fn renew_timeout(
197 &self,
198 token: &TokenValue,
199 timeout_seconds: i64,
200 ) -> SaTokenResult<()> {
201 let token_info = self.get_token_info(token).await?;
202 self.renew_timeout_internal(token, timeout_seconds, &token_info).await
203 }
204
205 async fn renew_timeout_internal(
207 &self,
208 token: &TokenValue,
209 timeout_seconds: i64,
210 token_info: &TokenInfo,
211 ) -> SaTokenResult<()> {
212 let mut new_token_info = token_info.clone();
213
214 use chrono::{Utc, Duration};
216 let new_expire_time = Utc::now() + Duration::seconds(timeout_seconds);
217 new_token_info.expire_time = Some(new_expire_time);
218
219 let key = format!("sa:token:{}", token.as_str());
221 let value = serde_json::to_string(&new_token_info)
222 .map_err(|e| SaTokenError::SerializationError(e))?;
223
224 let timeout = std::time::Duration::from_secs(timeout_seconds as u64);
225 self.storage.set(&key, &value, Some(timeout)).await
226 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
227
228 Ok(())
229 }
230
231 pub async fn kick_out(&self, login_id: &str) -> SaTokenResult<()> {
233 let token_result = self.storage.get(&format!("sa:login:token:{}", login_id)).await;
235
236 self.logout_by_login_id(login_id).await?;
237 self.delete_session(login_id).await?;
238
239 if let Ok(Some(token_str)) = token_result {
241 let event = SaTokenEvent::kick_out(login_id, token_str);
242 self.event_bus.publish(event).await;
243 }
244
245 Ok(())
246 }
247}