sa_token_core/
util.rs

1// Author: 金书记
2//
3//! StpUtil - sa-token 便捷工具类
4//! 
5//! 提供类似 Java 版 StpUtil 的静态方法,方便进行认证和权限操作
6//! 
7//! ## 使用示例
8//! 
9//! ```rust,ignore
10//! use sa_token_core::StpUtil;
11//! 
12//! // 初始化全局 Manager(应用启动时调用一次)
13//! StpUtil::init_manager(manager);
14//! 
15//! // 之后就可以直接使用,支持多种 ID 类型
16//! let token = StpUtil::login("user_123").await?;  // 字符串 ID
17//! let token = StpUtil::login(10001).await?;       // 数字 ID (i32)
18//! let token = StpUtil::login(10001_i64).await?;   // 数字 ID (i64)
19//! 
20//! StpUtil::set_permissions(10001, vec!["user:list".to_string()]).await?;
21//! ```
22
23use std::sync::Arc;
24use std::fmt::Display;
25use once_cell::sync::OnceCell;
26use crate::{SaTokenManager, SaTokenResult, SaTokenError};
27use crate::token::{TokenValue, TokenInfo};
28use crate::session::SaSession;
29use crate::context::SaTokenContext;
30use crate::event::{SaTokenEventBus, SaTokenListener};
31
32/// 全局 SaTokenManager 实例
33static GLOBAL_MANAGER: OnceCell<Arc<SaTokenManager>> = OnceCell::new();
34
35/// LoginId trait - 支持任何可以转换为字符串的类型作为登录 ID
36/// 
37/// 自动实现了 String, &str, i32, i64, u32, u64 等常用类型
38pub trait LoginId {
39    fn to_login_id(&self) -> String;
40}
41
42// 为所有实现了 Display 的类型自动实现 LoginId
43impl<T: Display> LoginId for T {
44    fn to_login_id(&self) -> String {
45        self.to_string()
46    }
47}
48
49/// StpUtil - 权限认证工具类
50/// 
51/// 提供便捷的认证和授权操作方法,类似于 Java 版 sa-token 的 StpUtil
52pub struct StpUtil;
53
54impl StpUtil {
55    // ==================== 初始化 ====================
56    
57    /// 初始化全局 SaTokenManager(应用启动时调用一次)
58    /// 
59    /// # 示例
60    /// ```rust,ignore
61    /// let manager = SaTokenConfig::builder()
62    ///     .storage(Arc::new(MemoryStorage::new()))
63    ///     .build();
64    /// StpUtil::init_manager(manager);
65    /// ```
66    pub fn init_manager(manager: SaTokenManager) {
67        GLOBAL_MANAGER.set(Arc::new(manager))
68            .unwrap_or_else(|_| panic!("StpUtil manager already initialized"));
69    }
70    
71    /// 获取全局 Manager
72    fn get_manager() -> &'static Arc<SaTokenManager> {
73        GLOBAL_MANAGER.get()
74            .expect("StpUtil not initialized. Call StpUtil::init_manager() first.")
75    }
76    
77    /// 获取事件总线,用于注册监听器
78    /// 
79    /// # 示例
80    /// ```rust,ignore
81    /// use sa_token_core::{StpUtil, SaTokenListener};
82    /// use async_trait::async_trait;
83    /// 
84    /// struct MyListener;
85    /// 
86    /// #[async_trait]
87    /// impl SaTokenListener for MyListener {
88    ///     async fn on_login(&self, login_id: &str, token: &str, login_type: &str) {
89    ///         println!("用户 {} 登录了", login_id);
90    ///     }
91    /// }
92    /// 
93    /// // 注册监听器
94    /// StpUtil::event_bus().register(Arc::new(MyListener)).await;
95    /// ```
96    pub fn event_bus() -> &'static SaTokenEventBus {
97        &Self::get_manager().event_bus
98    }
99    
100    /// 注册事件监听器(便捷方法)
101    /// 
102    /// # 示例
103    /// ```rust,ignore
104    /// StpUtil::register_listener(Arc::new(MyListener)).await;
105    /// ```
106    pub fn register_listener(listener: Arc<dyn SaTokenListener>) {
107        Self::event_bus().register(listener);
108    }
109    
110    // ==================== 登录相关 ====================
111    
112    /// 会话登录
113    /// 
114    /// # 示例
115    /// ```rust,ignore
116    /// // 支持字符串 ID
117    /// let token = StpUtil::login("user_123").await?;
118    /// 
119    /// // 支持数字 ID
120    /// let token = StpUtil::login(10001).await?;
121    /// let token = StpUtil::login(10001_i64).await?;
122    /// ```
123    pub async fn login(login_id: impl LoginId) -> SaTokenResult<TokenValue> {
124        Self::get_manager().login(login_id.to_login_id()).await
125    }
126
127    pub async fn login_with_type(login_id: impl LoginId, _login_type: impl Into<String>) -> SaTokenResult<TokenValue> {
128        Self::get_manager().login(login_id.to_login_id()).await
129    }
130    
131    /// 登录并设置额外数据 | Login with extra data
132    /// 
133    /// # 参数 | Arguments
134    /// * `login_id` - 登录ID | Login ID
135    /// * `extra_data` - 额外数据 | Extra data
136    pub async fn login_with_extra(
137        login_id: impl LoginId,
138        extra_data: serde_json::Value,
139    ) -> SaTokenResult<TokenValue> {
140        let token = Self::get_manager().login(login_id.to_login_id()).await?;
141        Self::set_extra_data(&token, extra_data).await?;
142        Ok(token)
143    }
144    
145    /// 会话登录(带 manager 参数的版本,向后兼容)
146    pub async fn login_with_manager(
147        manager: &SaTokenManager,
148        login_id: impl Into<String>,
149    ) -> SaTokenResult<TokenValue> {
150        manager.login(login_id).await
151    }
152    
153    /// 会话登出
154    pub async fn logout(token: &TokenValue) -> SaTokenResult<()> {
155        Self::get_manager().logout(token).await
156    }
157    
158    pub async fn logout_with_manager(
159        manager: &SaTokenManager,
160        token: &TokenValue,
161    ) -> SaTokenResult<()> {
162        manager.logout(token).await
163    }
164    
165    /// 踢人下线(根据登录ID)
166    pub async fn kick_out(login_id: impl LoginId) -> SaTokenResult<()> {
167        Self::get_manager().kick_out(&login_id.to_login_id()).await
168    }
169    
170    pub async fn kick_out_with_manager(
171        manager: &SaTokenManager,
172        login_id: &str,
173    ) -> SaTokenResult<()> {
174        manager.kick_out(login_id).await
175    }
176    
177    /// 强制登出(根据登录ID)
178    pub async fn logout_by_login_id(login_id: impl LoginId) -> SaTokenResult<()> {
179        Self::get_manager().logout_by_login_id(&login_id.to_login_id()).await
180    }
181    
182    /// 根据 token 登出(别名方法,更直观)
183    pub async fn logout_by_token(token: &TokenValue) -> SaTokenResult<()> {
184        Self::logout(token).await
185    }
186    
187    // ==================== 当前会话操作(无参数,从上下文获取)====================
188    
189    /// 获取当前请求的 token(无参数,从上下文获取)
190    /// 
191    /// # 示例
192    /// ```rust,ignore
193    /// // 在请求处理函数中
194    /// let token = StpUtil::get_token_value()?;
195    /// ```
196    pub fn get_token_value() -> SaTokenResult<TokenValue> {
197        let ctx = SaTokenContext::get_current()
198            .ok_or(SaTokenError::NotLogin)?;
199        ctx.token.ok_or(SaTokenError::NotLogin)
200    }
201    
202    /// 当前会话登出(无参数,从上下文获取 token)
203    /// 
204    /// # 示例
205    /// ```rust,ignore
206    /// // 在请求处理函数中
207    /// StpUtil::logout_current().await?;
208    /// ```
209    pub async fn logout_current() -> SaTokenResult<()> {
210        let token = Self::get_token_value()?;
211        Self::logout(&token).await
212    }
213    
214    /// 检查当前会话是否登录(无参数,返回 bool)
215    /// 
216    /// # 示例
217    /// ```rust,ignore
218    /// // 在请求处理函数中
219    /// if StpUtil::is_login_current() {
220    ///     println!("当前用户已登录");
221    /// }
222    /// ```
223    pub fn is_login_current() -> bool {
224        if let Ok(_token) = Self::get_token_value() {
225            // 注意:这里使用同步检查,只检查上下文中是否有 token
226            // 如果需要异步验证,需要使用 is_login(&token).await
227            true
228        } else {
229            false
230        }
231    }
232    
233    /// 检查当前会话登录状态,未登录则抛出异常(无参数)
234    /// 
235    /// # 示例
236    /// ```rust,ignore
237    /// // 在请求处理函数中
238    /// StpUtil::check_login_current()?;
239    /// ```
240    pub fn check_login_current() -> SaTokenResult<()> {
241        Self::get_token_value()?;
242        Ok(())
243    }
244    
245    /// 获取当前会话的 login_id(String 类型,无参数)
246    /// 
247    /// # 示例
248    /// ```rust,ignore
249    /// // 在请求处理函数中
250    /// let login_id = StpUtil::get_login_id_as_string().await?;
251    /// ```
252    pub async fn get_login_id_as_string() -> SaTokenResult<String> {
253        let token = Self::get_token_value()?;
254        Self::get_login_id(&token).await
255    }
256    
257    /// 获取当前会话的 login_id(i64 类型,无参数)
258    /// 
259    /// # 示例
260    /// ```rust,ignore
261    /// // 在请求处理函数中
262    /// let user_id = StpUtil::get_login_id_as_long().await?;
263    /// ```
264    pub async fn get_login_id_as_long() -> SaTokenResult<i64> {
265        let login_id_str = Self::get_login_id_as_string().await?;
266        login_id_str.parse::<i64>()
267            .map_err(|_| SaTokenError::LoginIdNotNumber)
268    }
269    
270    /// 获取当前会话的 token 信息(无参数)
271    /// 
272    /// # 示例
273    /// ```rust,ignore
274    /// // 在请求处理函数中
275    /// let token_info = StpUtil::get_token_info_current()?;
276    /// println!("Token 创建时间: {:?}", token_info.create_time);
277    /// ```
278    pub fn get_token_info_current() -> SaTokenResult<Arc<TokenInfo>> {
279        let ctx = SaTokenContext::get_current()
280            .ok_or(SaTokenError::NotLogin)?;
281        ctx.token_info.ok_or(SaTokenError::NotLogin)
282    }
283    
284    // ==================== Token 验证 ====================
285    
286    /// 检查当前 token 是否已登录
287    pub async fn is_login(token: &TokenValue) -> bool {
288        Self::get_manager().is_valid(token).await
289    }
290    
291    /// 根据登录 ID 检查是否已登录
292    /// 
293    /// # 示例
294    /// ```rust,ignore
295    /// let is_logged_in = StpUtil::is_login_by_login_id("user_123").await;
296    /// let is_logged_in = StpUtil::is_login_by_login_id(10001).await;
297    /// ```
298    pub async fn is_login_by_login_id(login_id: impl LoginId) -> bool {
299        match Self::get_token_by_login_id(login_id).await {
300            Ok(token) => Self::is_login(&token).await,
301            Err(_) => false,
302        }
303    }
304    
305    pub async fn is_login_with_manager(
306        manager: &SaTokenManager,
307        token: &TokenValue,
308    ) -> bool {
309        manager.is_valid(token).await
310    }
311    
312    /// 检查当前 token 是否已登录,如果未登录则抛出异常
313    pub async fn check_login(token: &TokenValue) -> SaTokenResult<()> {
314        if !Self::is_login(token).await {
315            return Err(SaTokenError::NotLogin);
316        }
317        Ok(())
318    }
319    
320    /// 获取 token 信息
321    pub async fn get_token_info(token: &TokenValue) -> SaTokenResult<TokenInfo> {
322        Self::get_manager().get_token_info(token).await
323    }
324    
325    /// 获取当前 token 的登录ID
326    pub async fn get_login_id(token: &TokenValue) -> SaTokenResult<String> {
327        let token_info = Self::get_manager().get_token_info(token).await?;
328        Ok(token_info.login_id)
329    }
330    
331    /// 获取当前 token 的登录ID,如果未登录则返回默认值
332    pub async fn get_login_id_or_default(
333        token: &TokenValue,
334        default: impl Into<String>,
335    ) -> String {
336        Self::get_login_id(token)
337            .await
338            .unwrap_or_else(|_| default.into())
339    }
340    
341    /// 根据登录 ID 获取当前用户的 token
342    /// 
343    /// # 示例
344    /// ```rust,ignore
345    /// let token = StpUtil::get_token_by_login_id("user_123").await?;
346    /// let token = StpUtil::get_token_by_login_id(10001).await?;
347    /// ```
348    pub async fn get_token_by_login_id(login_id: impl LoginId) -> SaTokenResult<TokenValue> {
349        let manager = Self::get_manager();
350        let login_id_str = login_id.to_login_id();
351        
352        // 从存储中获取该用户的 token
353        let key = format!("sa:login:token:{}", login_id_str);
354        match manager.storage.get(&key).await {
355            Ok(Some(token_str)) => Ok(TokenValue::new(token_str)),
356            Ok(None) => Err(SaTokenError::NotLogin),
357            Err(e) => Err(SaTokenError::StorageError(e.to_string())),
358        }
359    }
360    
361    /// 根据登录 ID 获取所有在线的 token 列表(支持多设备登录)
362    /// 
363    /// # 示例
364    /// ```rust,ignore
365    /// let tokens = StpUtil::get_all_tokens_by_login_id("user_123").await?;
366    /// ```
367    pub async fn get_all_tokens_by_login_id(login_id: impl LoginId) -> SaTokenResult<Vec<TokenValue>> {
368        let manager = Self::get_manager();
369        let login_id_str = login_id.to_login_id();
370        
371        // 从存储中获取该用户的所有 token
372        let key = format!("sa:login:tokens:{}", login_id_str);
373        match manager.storage.get(&key).await {
374            Ok(Some(tokens_str)) => {
375                let token_strings: Vec<String> = serde_json::from_str(&tokens_str)
376                    .map_err(|e| SaTokenError::SerializationError(e))?;
377                Ok(token_strings.into_iter().map(TokenValue::new).collect())
378            }
379            Ok(None) => Ok(Vec::new()),
380            Err(e) => Err(SaTokenError::StorageError(e.to_string())),
381        }
382    }
383    
384    // ==================== Session 会话 ====================
385    
386    /// 获取当前登录账号的 Session
387    pub async fn get_session(login_id: impl LoginId) -> SaTokenResult<SaSession> {
388        Self::get_manager().get_session(&login_id.to_login_id()).await
389    }
390    
391    /// 保存 Session
392    pub async fn save_session(session: &SaSession) -> SaTokenResult<()> {
393        Self::get_manager().save_session(session).await
394    }
395    
396    /// 删除 Session
397    pub async fn delete_session(login_id: impl LoginId) -> SaTokenResult<()> {
398        Self::get_manager().delete_session(&login_id.to_login_id()).await
399    }
400    
401    /// 在 Session 中设置值
402    pub async fn set_session_value<T: serde::Serialize>(
403        login_id: impl LoginId,
404        key: &str,
405        value: T,
406    ) -> SaTokenResult<()> {
407        let manager = Self::get_manager();
408        let login_id_str = login_id.to_login_id();
409        let mut session = manager.get_session(&login_id_str).await?;
410        session.set(key, value)?;
411        manager.save_session(&session).await
412    }
413    
414    /// 从 Session 中获取值
415    pub async fn get_session_value<T: serde::de::DeserializeOwned>(
416        login_id: impl LoginId,
417        key: &str,
418    ) -> SaTokenResult<Option<T>> {
419        let session = Self::get_manager().get_session(&login_id.to_login_id()).await?;
420        Ok(session.get::<T>(key))
421    }
422    
423    // ==================== Token 相关 ====================
424    
425    /// 创建一个新的 token(但不登录)
426    pub fn create_token(token_value: impl Into<String>) -> TokenValue {
427        TokenValue::new(token_value.into())
428    }
429    
430    /// 检查 token 格式是否有效(仅检查格式,不检查是否存在于存储中)
431    pub fn is_valid_token_format(token: &str) -> bool {
432        !token.is_empty() && token.len() >= 16
433    }
434}
435
436// ==================== 权限管理 ====================
437
438impl StpUtil {
439    /// 为用户添加权限
440    pub async fn set_permissions(
441        login_id: impl LoginId,
442        permissions: Vec<String>,
443    ) -> SaTokenResult<()> {
444        let manager = Self::get_manager();
445        let mut map = manager.user_permissions.write().await;
446        map.insert(login_id.to_login_id(), permissions);
447        Ok(())
448    }
449    
450    /// 为用户添加单个权限
451    pub async fn add_permission(
452        login_id: impl LoginId,
453        permission: impl Into<String>,
454    ) -> SaTokenResult<()> {
455        let manager = Self::get_manager();
456        let mut map = manager.user_permissions.write().await;
457        let login_id_str = login_id.to_login_id();
458        let permissions = map.entry(login_id_str).or_insert_with(Vec::new);
459        let perm = permission.into();
460        if !permissions.contains(&perm) {
461            permissions.push(perm);
462        }
463        Ok(())
464    }
465    
466    /// 移除用户的某个权限
467    pub async fn remove_permission(
468        login_id: impl LoginId,
469        permission: &str,
470    ) -> SaTokenResult<()> {
471        let manager = Self::get_manager();
472        let mut map = manager.user_permissions.write().await;
473        if let Some(permissions) = map.get_mut(&login_id.to_login_id()) {
474            permissions.retain(|p| p != permission);
475        }
476        Ok(())
477    }
478    
479    /// 清除用户的所有权限
480    pub async fn clear_permissions(login_id: impl LoginId) -> SaTokenResult<()> {
481        let manager = Self::get_manager();
482        let mut map = manager.user_permissions.write().await;
483        map.remove(&login_id.to_login_id());
484        Ok(())
485    }
486    
487    /// 获取用户的所有权限
488    pub async fn get_permissions(login_id: impl LoginId) -> Vec<String> {
489        let manager = Self::get_manager();
490        let map = manager.user_permissions.read().await;
491        map.get(&login_id.to_login_id()).cloned().unwrap_or_default()
492    }
493    
494    /// 检查用户是否拥有指定权限
495    pub async fn has_permission(
496        login_id: impl LoginId,
497        permission: &str,
498    ) -> bool {
499        let manager = Self::get_manager();
500        let map = manager.user_permissions.read().await;
501        if let Some(permissions) = map.get(&login_id.to_login_id()) {
502            // 精确匹配
503            if permissions.contains(&permission.to_string()) {
504                return true;
505            }
506            
507            // 通配符匹配(例如 admin:* 匹配 admin:read)
508            for perm in permissions {
509                if perm.ends_with(":*") {
510                    let prefix = &perm[..perm.len() - 2];
511                    if permission.starts_with(prefix) {
512                        return true;
513                    }
514                }
515            }
516        }
517        false
518    }
519    
520    /// 检查用户是否拥有所有指定权限(AND 逻辑)
521    pub async fn has_all_permissions(
522        login_id: impl LoginId,
523        permissions: &[&str],
524    ) -> bool {
525        let login_id_str = login_id.to_login_id();
526        for permission in permissions {
527            if !Self::has_permission(&login_id_str, permission).await {
528                return false;
529            }
530        }
531        true
532    }
533    
534    /// 检查用户是否拥有所有指定权限(别名,AND 逻辑)
535    pub async fn has_permissions_and(
536        login_id: impl LoginId,
537        permissions: &[&str],
538    ) -> bool {
539        Self::has_all_permissions(login_id, permissions).await
540    }
541    
542    /// 检查用户是否拥有任一指定权限(OR 逻辑)
543    pub async fn has_any_permission(
544        login_id: impl LoginId,
545        permissions: &[&str],
546    ) -> bool {
547        let login_id_str = login_id.to_login_id();
548        for permission in permissions {
549            if Self::has_permission(&login_id_str, permission).await {
550                return true;
551            }
552        }
553        false
554    }
555    
556    /// 检查用户是否拥有任一指定权限(别名,OR 逻辑)
557    pub async fn has_permissions_or(
558        login_id: impl LoginId,
559        permissions: &[&str],
560    ) -> bool {
561        Self::has_any_permission(login_id, permissions).await
562    }
563    
564    /// 检查权限,如果没有则抛出异常
565    pub async fn check_permission(
566        login_id: impl LoginId,
567        permission: &str,
568    ) -> SaTokenResult<()> {
569        if !Self::has_permission(login_id, permission).await {
570            return Err(SaTokenError::PermissionDeniedDetail(permission.to_string()));
571        }
572        Ok(())
573    }
574}
575
576// ==================== 角色管理 ====================
577
578impl StpUtil {
579    /// 为用户设置角色
580    pub async fn set_roles(
581        login_id: impl LoginId,
582        roles: Vec<String>,
583    ) -> SaTokenResult<()> {
584        let manager = Self::get_manager();
585        let mut map = manager.user_roles.write().await;
586        map.insert(login_id.to_login_id(), roles);
587        Ok(())
588    }
589    
590    /// 为用户添加单个角色
591    pub async fn add_role(
592        login_id: impl LoginId,
593        role: impl Into<String>,
594    ) -> SaTokenResult<()> {
595        let manager = Self::get_manager();
596        let mut map = manager.user_roles.write().await;
597        let login_id_str = login_id.to_login_id();
598        let roles = map.entry(login_id_str).or_insert_with(Vec::new);
599        let r = role.into();
600        if !roles.contains(&r) {
601            roles.push(r);
602        }
603        Ok(())
604    }
605    
606    /// 移除用户的某个角色
607    pub async fn remove_role(
608        login_id: impl LoginId,
609        role: &str,
610    ) -> SaTokenResult<()> {
611        let manager = Self::get_manager();
612        let mut map = manager.user_roles.write().await;
613        if let Some(roles) = map.get_mut(&login_id.to_login_id()) {
614            roles.retain(|r| r != role);
615        }
616        Ok(())
617    }
618    
619    /// 清除用户的所有角色
620    pub async fn clear_roles(login_id: impl LoginId) -> SaTokenResult<()> {
621        let manager = Self::get_manager();
622        let mut map = manager.user_roles.write().await;
623        map.remove(&login_id.to_login_id());
624        Ok(())
625    }
626    
627    /// 获取用户的所有角色
628    pub async fn get_roles(login_id: impl LoginId) -> Vec<String> {
629        let manager = Self::get_manager();
630        let map = manager.user_roles.read().await;
631        map.get(&login_id.to_login_id()).cloned().unwrap_or_default()
632    }
633    
634    /// 检查用户是否拥有指定角色
635    pub async fn has_role(
636        login_id: impl LoginId,
637        role: &str,
638    ) -> bool {
639        let manager = Self::get_manager();
640        let map = manager.user_roles.read().await;
641        if let Some(roles) = map.get(&login_id.to_login_id()) {
642            roles.contains(&role.to_string())
643        } else {
644            false
645        }
646    }
647    
648    /// 检查用户是否拥有所有指定角色(AND 逻辑)
649    pub async fn has_all_roles(
650        login_id: impl LoginId,
651        roles: &[&str],
652    ) -> bool {
653        let login_id_str = login_id.to_login_id();
654        for role in roles {
655            if !Self::has_role(&login_id_str, role).await {
656                return false;
657            }
658        }
659        true
660    }
661    
662    /// 检查用户是否拥有所有指定角色(别名,AND 逻辑)
663    pub async fn has_roles_and(
664        login_id: impl LoginId,
665        roles: &[&str],
666    ) -> bool {
667        Self::has_all_roles(login_id, roles).await
668    }
669    
670    /// 检查用户是否拥有任一指定角色(OR 逻辑)
671    pub async fn has_any_role(
672        login_id: impl LoginId,
673        roles: &[&str],
674    ) -> bool {
675        let login_id_str = login_id.to_login_id();
676        for role in roles {
677            if Self::has_role(&login_id_str, role).await {
678                return true;
679            }
680        }
681        false
682    }
683    
684    /// 检查用户是否拥有任一指定角色(别名,OR 逻辑)
685    pub async fn has_roles_or(
686        login_id: impl LoginId,
687        roles: &[&str],
688    ) -> bool {
689        Self::has_any_role(login_id, roles).await
690    }
691    
692    /// 检查角色,如果没有则抛出异常
693    pub async fn check_role(
694        login_id: impl LoginId,
695        role: &str,
696    ) -> SaTokenResult<()> {
697        if !Self::has_role(login_id, role).await {
698            return Err(SaTokenError::RoleDenied(role.to_string()));
699        }
700        Ok(())
701    }
702}
703
704// ==================== 扩展工具方法 ====================
705
706impl StpUtil {
707    /// 批量踢人下线
708    pub async fn kick_out_batch<T: LoginId>(
709        login_ids: &[T],
710    ) -> SaTokenResult<Vec<Result<(), SaTokenError>>> {
711        let manager = Self::get_manager();
712        let mut results = Vec::new();
713        for login_id in login_ids {
714            results.push(manager.kick_out(&login_id.to_login_id()).await);
715        }
716        Ok(results)
717    }
718    
719    /// 获取 token 剩余有效时间(秒)
720    pub async fn get_token_timeout(token: &TokenValue) -> SaTokenResult<Option<i64>> {
721        let manager = Self::get_manager();
722        let token_info = manager.get_token_info(token).await?;
723        
724        if let Some(expire_time) = token_info.expire_time {
725            let now = chrono::Utc::now();
726            let duration = expire_time.signed_duration_since(now);
727            Ok(Some(duration.num_seconds()))
728        } else {
729            Ok(None) // 永久有效
730        }
731    }
732    
733    /// 续期 token(重置过期时间)
734    pub async fn renew_timeout(
735        token: &TokenValue,
736        timeout_seconds: i64,
737    ) -> SaTokenResult<()> {
738        let manager = Self::get_manager();
739        let mut token_info = manager.get_token_info(token).await?;
740        
741        // 设置新的过期时间
742        let new_expire_time = chrono::Utc::now() + chrono::Duration::seconds(timeout_seconds);
743        token_info.expire_time = Some(new_expire_time);
744        
745        // 保存更新后的 token 信息
746        let key = format!("sa:token:{}", token.as_str());
747        let value = serde_json::to_string(&token_info)
748            .map_err(|e| SaTokenError::SerializationError(e))?;
749        
750        let timeout = std::time::Duration::from_secs(timeout_seconds as u64);
751        manager.storage.set(&key, &value, Some(timeout)).await
752            .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
753        
754        Ok(())
755    }
756    
757    // ==================== 额外数据操作 | Extra Data Operations ====================
758    
759    /// 设置 Token 的额外数据 | Set extra data for token
760    /// 
761    /// # 参数 | Arguments
762    /// * `token` - Token值 | Token value
763    /// * `extra_data` - 额外数据 | Extra data
764    pub async fn set_extra_data(
765        token: &TokenValue,
766        extra_data: serde_json::Value,
767    ) -> SaTokenResult<()> {
768        let manager = Self::get_manager();
769        let mut token_info = manager.get_token_info(token).await?;
770        token_info.extra_data = Some(extra_data);
771        
772        let key = format!("sa:token:{}", token.as_str());
773        let value = serde_json::to_string(&token_info)
774            .map_err(|e| SaTokenError::SerializationError(e))?;
775        
776        manager.storage.set(&key, &value, manager.config.timeout_duration()).await
777            .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
778        
779        Ok(())
780    }
781    
782    /// 获取 Token 的额外数据 | Get extra data from token
783    /// 
784    /// # 参数 | Arguments
785    /// * `token` - Token值 | Token value
786    pub async fn get_extra_data(token: &TokenValue) -> SaTokenResult<Option<serde_json::Value>> {
787        let manager = Self::get_manager();
788        let token_info = manager.get_token_info(token).await?;
789        Ok(token_info.extra_data)
790    }
791    
792    // ==================== 链式调用 | Chain Call ====================
793    
794    /// 创建 Token 构建器,用于链式调用 | Create token builder for chain calls
795    /// 
796    /// # 示例 | Example
797    /// ```rust,ignore
798    /// use serde_json::json;
799    /// 
800    /// // 链式调用示例
801    /// let token = StpUtil::builder("user_123")
802    ///     .extra_data(json!({"ip": "192.168.1.1"}))
803    ///     .device("pc")
804    ///     .login_type("admin")
805    ///     .login()
806    ///     .await?;
807    /// ```
808    pub fn builder(login_id: impl LoginId) -> TokenBuilder {
809        TokenBuilder::new(login_id.to_login_id())
810    }
811}
812
813/// Token 构建器 - 支持链式调用 | Token Builder - Supports chain calls
814pub struct TokenBuilder {
815    login_id: String,
816    extra_data: Option<serde_json::Value>,
817    device: Option<String>,
818    login_type: Option<String>,
819}
820
821impl TokenBuilder {
822    /// 创建新的 Token 构建器 | Create new token builder
823    pub fn new(login_id: String) -> Self {
824        Self {
825            login_id,
826            extra_data: None,
827            device: None,
828            login_type: None,
829        }
830    }
831    
832    /// 设置额外数据 | Set extra data
833    pub fn extra_data(mut self, data: serde_json::Value) -> Self {
834        self.extra_data = Some(data);
835        self
836    }
837    
838    /// 设置设备信息 | Set device info
839    pub fn device(mut self, device: impl Into<String>) -> Self {
840        self.device = Some(device.into());
841        self
842    }
843    
844    /// 设置登录类型 | Set login type
845    pub fn login_type(mut self, login_type: impl Into<String>) -> Self {
846        self.login_type = Some(login_type.into());
847        self
848    }
849    
850    /// 执行登录操作 | Execute login
851    /// 
852    /// 如果不提供 login_id 参数,则使用构建器中的 login_id
853    pub async fn login<T: LoginId>(self, login_id: Option<T>) -> SaTokenResult<TokenValue> {
854        let manager = StpUtil::get_manager();
855        
856        // 登录获取 token,使用传入的 login_id 或构建器中的 login_id
857        let final_login_id = match login_id {
858            Some(id) => id.to_login_id(),
859            None => self.login_id,
860        };
861        let token = manager.login(final_login_id).await?;
862        
863        // 获取 token 信息并修改
864        let mut token_info = manager.get_token_info(&token).await?;
865        
866        // 设置额外属性
867        if let Some(data) = self.extra_data {
868            token_info.extra_data = Some(data);
869        }
870        
871        if let Some(device) = self.device {
872            token_info.device = Some(device);
873        }
874        
875        if let Some(login_type) = self.login_type {
876            token_info.login_type = login_type;
877        }
878        
879        // 保存更新后的 token 信息
880        let key = format!("sa:token:{}", token.as_str());
881        let value = serde_json::to_string(&token_info)
882            .map_err(|e| SaTokenError::SerializationError(e))?;
883        
884        manager.storage.set(&key, &value, manager.config.timeout_duration()).await
885            .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
886        
887        Ok(token)
888    }
889}
890
891#[cfg(test)]
892mod tests {
893    use super::*;
894    
895    #[test]
896    fn test_token_format_validation() {
897        assert!(StpUtil::is_valid_token_format("1234567890abcdef"));
898        assert!(!StpUtil::is_valid_token_format(""));
899        assert!(!StpUtil::is_valid_token_format("short"));
900    }
901    
902    #[test]
903    fn test_create_token() {
904        let token = StpUtil::create_token("test-token-123");
905        assert_eq!(token.as_str(), "test-token-123");
906    }
907}