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;
14
15#[derive(Clone)]
17pub struct SaTokenManager {
18 pub(crate) storage: Arc<dyn SaStorage>,
19 pub config: SaTokenConfig,
20 pub(crate) user_permissions: Arc<RwLock<HashMap<String, Vec<String>>>>,
22 pub(crate) user_roles: Arc<RwLock<HashMap<String, Vec<String>>>>,
24}
25
26impl SaTokenManager {
27 pub fn new(storage: Arc<dyn SaStorage>, config: SaTokenConfig) -> Self {
29 Self {
30 storage,
31 config,
32 user_permissions: Arc::new(RwLock::new(HashMap::new())),
33 user_roles: Arc::new(RwLock::new(HashMap::new())),
34 }
35 }
36
37 pub async fn login(&self, login_id: impl Into<String>) -> SaTokenResult<TokenValue> {
39 let login_id = login_id.into();
40
41 let token = TokenGenerator::generate(&self.config);
43
44 let mut token_info = TokenInfo::new(token.clone(), login_id.clone());
46 token_info.login_type = "default".to_string();
47
48 if let Some(timeout) = self.config.timeout_duration() {
50 token_info.expire_time = Some(Utc::now() + Duration::from_std(timeout).unwrap());
51 }
52
53 let key = format!("sa:token:{}", token.as_str());
55 let value = serde_json::to_string(&token_info)
56 .map_err(|e| SaTokenError::SerializationError(e))?;
57
58 self.storage.set(&key, &value, self.config.timeout_duration()).await
59 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
60
61 let login_token_key = format!("sa:login:token:{}", login_id);
63 self.storage.set(&login_token_key, token.as_str(), self.config.timeout_duration()).await
64 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
65
66 if !self.config.is_concurrent {
68 self.logout_by_login_id(&login_id).await?;
69 }
70
71 Ok(token)
72 }
73
74 pub async fn logout(&self, token: &TokenValue) -> SaTokenResult<()> {
76 let key = format!("sa:token:{}", token.as_str());
77 self.storage.delete(&key).await
78 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
79 Ok(())
80 }
81
82 pub async fn logout_by_login_id(&self, _login_id: &str) -> SaTokenResult<()> {
84 Ok(())
87 }
88
89 pub async fn get_token_info(&self, token: &TokenValue) -> SaTokenResult<TokenInfo> {
91 let key = format!("sa:token:{}", token.as_str());
92 let value = self.storage.get(&key).await
93 .map_err(|e| SaTokenError::StorageError(e.to_string()))?
94 .ok_or(SaTokenError::TokenNotFound)?;
95
96 let token_info: TokenInfo = serde_json::from_str(&value)
97 .map_err(|e| SaTokenError::SerializationError(e))?;
98
99 if token_info.is_expired() {
101 self.logout(token).await?;
103 return Err(SaTokenError::TokenExpired);
104 }
105
106 if self.config.auto_renew {
109 let renew_timeout = if self.config.active_timeout > 0 {
110 self.config.active_timeout
111 } else {
112 self.config.timeout
113 };
114
115 let _ = self.renew_timeout_internal(token, renew_timeout, &token_info).await;
117 }
118
119 Ok(token_info)
120 }
121
122 pub async fn is_valid(&self, token: &TokenValue) -> bool {
124 self.get_token_info(token).await.is_ok()
125 }
126
127 pub async fn get_session(&self, login_id: &str) -> SaTokenResult<SaSession> {
129 let key = format!("sa:session:{}", login_id);
130 let value = self.storage.get(&key).await
131 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
132
133 if let Some(value) = value {
134 let session: SaSession = serde_json::from_str(&value)
135 .map_err(|e| SaTokenError::SerializationError(e))?;
136 Ok(session)
137 } else {
138 Ok(SaSession::new(login_id))
139 }
140 }
141
142 pub async fn save_session(&self, session: &SaSession) -> SaTokenResult<()> {
144 let key = format!("sa:session:{}", session.id);
145 let value = serde_json::to_string(session)
146 .map_err(|e| SaTokenError::SerializationError(e))?;
147
148 self.storage.set(&key, &value, None).await
149 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
150
151 Ok(())
152 }
153
154 pub async fn delete_session(&self, login_id: &str) -> SaTokenResult<()> {
156 let key = format!("sa:session:{}", login_id);
157 self.storage.delete(&key).await
158 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
159 Ok(())
160 }
161
162 pub async fn renew_timeout(
164 &self,
165 token: &TokenValue,
166 timeout_seconds: i64,
167 ) -> SaTokenResult<()> {
168 let token_info = self.get_token_info(token).await?;
169 self.renew_timeout_internal(token, timeout_seconds, &token_info).await
170 }
171
172 async fn renew_timeout_internal(
174 &self,
175 token: &TokenValue,
176 timeout_seconds: i64,
177 token_info: &TokenInfo,
178 ) -> SaTokenResult<()> {
179 let mut new_token_info = token_info.clone();
180
181 use chrono::{Utc, Duration};
183 let new_expire_time = Utc::now() + Duration::seconds(timeout_seconds);
184 new_token_info.expire_time = Some(new_expire_time);
185
186 let key = format!("sa:token:{}", token.as_str());
188 let value = serde_json::to_string(&new_token_info)
189 .map_err(|e| SaTokenError::SerializationError(e))?;
190
191 let timeout = std::time::Duration::from_secs(timeout_seconds as u64);
192 self.storage.set(&key, &value, Some(timeout)).await
193 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
194
195 Ok(())
196 }
197
198 pub async fn kick_out(&self, login_id: &str) -> SaTokenResult<()> {
200 self.logout_by_login_id(login_id).await?;
201 self.delete_session(login_id).await?;
202 Ok(())
203 }
204}