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;
30
31/// 全局 SaTokenManager 实例
32static GLOBAL_MANAGER: OnceCell<Arc<SaTokenManager>> = OnceCell::new();
33
34/// LoginId trait - 支持任何可以转换为字符串的类型作为登录 ID
35/// 
36/// 自动实现了 String, &str, i32, i64, u32, u64 等常用类型
37pub trait LoginId {
38    fn to_login_id(&self) -> String;
39}
40
41// 为所有实现了 Display 的类型自动实现 LoginId
42impl<T: Display> LoginId for T {
43    fn to_login_id(&self) -> String {
44        self.to_string()
45    }
46}
47
48/// StpUtil - 权限认证工具类
49/// 
50/// 提供便捷的认证和授权操作方法,类似于 Java 版 sa-token 的 StpUtil
51pub struct StpUtil;
52
53impl StpUtil {
54    // ==================== 初始化 ====================
55    
56    /// 初始化全局 SaTokenManager(应用启动时调用一次)
57    /// 
58    /// # 示例
59    /// ```rust,ignore
60    /// let manager = SaTokenConfig::builder()
61    ///     .storage(Arc::new(MemoryStorage::new()))
62    ///     .build();
63    /// StpUtil::init_manager(manager);
64    /// ```
65    pub fn init_manager(manager: SaTokenManager) {
66        GLOBAL_MANAGER.set(Arc::new(manager))
67            .unwrap_or_else(|_| panic!("StpUtil manager already initialized"));
68    }
69    
70    /// 获取全局 Manager
71    fn get_manager() -> &'static Arc<SaTokenManager> {
72        GLOBAL_MANAGER.get()
73            .expect("StpUtil not initialized. Call StpUtil::init_manager() first.")
74    }
75    
76    // ==================== 登录相关 ====================
77    
78    /// 会话登录
79    /// 
80    /// # 示例
81    /// ```rust,ignore
82    /// // 支持字符串 ID
83    /// let token = StpUtil::login("user_123").await?;
84    /// 
85    /// // 支持数字 ID
86    /// let token = StpUtil::login(10001).await?;
87    /// let token = StpUtil::login(10001_i64).await?;
88    /// ```
89    pub async fn login(login_id: impl LoginId) -> SaTokenResult<TokenValue> {
90        Self::get_manager().login(login_id.to_login_id()).await
91    }
92    
93    /// 会话登录(带 manager 参数的版本,向后兼容)
94    pub async fn login_with_manager(
95        manager: &SaTokenManager,
96        login_id: impl Into<String>,
97    ) -> SaTokenResult<TokenValue> {
98        manager.login(login_id).await
99    }
100    
101    /// 会话登出
102    pub async fn logout(token: &TokenValue) -> SaTokenResult<()> {
103        Self::get_manager().logout(token).await
104    }
105    
106    pub async fn logout_with_manager(
107        manager: &SaTokenManager,
108        token: &TokenValue,
109    ) -> SaTokenResult<()> {
110        manager.logout(token).await
111    }
112    
113    /// 踢人下线(根据登录ID)
114    pub async fn kick_out(login_id: impl LoginId) -> SaTokenResult<()> {
115        Self::get_manager().kick_out(&login_id.to_login_id()).await
116    }
117    
118    pub async fn kick_out_with_manager(
119        manager: &SaTokenManager,
120        login_id: &str,
121    ) -> SaTokenResult<()> {
122        manager.kick_out(login_id).await
123    }
124    
125    /// 强制登出(根据登录ID)
126    pub async fn logout_by_login_id(login_id: impl LoginId) -> SaTokenResult<()> {
127        Self::get_manager().logout_by_login_id(&login_id.to_login_id()).await
128    }
129    
130    /// 根据 token 登出(别名方法,更直观)
131    pub async fn logout_by_token(token: &TokenValue) -> SaTokenResult<()> {
132        Self::logout(token).await
133    }
134    
135    // ==================== 当前会话操作(无参数,从上下文获取)====================
136    
137    /// 获取当前请求的 token(无参数,从上下文获取)
138    /// 
139    /// # 示例
140    /// ```rust,ignore
141    /// // 在请求处理函数中
142    /// let token = StpUtil::get_token_value()?;
143    /// ```
144    pub fn get_token_value() -> SaTokenResult<TokenValue> {
145        let ctx = SaTokenContext::get_current()
146            .ok_or(SaTokenError::NotLogin)?;
147        ctx.token.ok_or(SaTokenError::NotLogin)
148    }
149    
150    /// 当前会话登出(无参数,从上下文获取 token)
151    /// 
152    /// # 示例
153    /// ```rust,ignore
154    /// // 在请求处理函数中
155    /// StpUtil::logout_current().await?;
156    /// ```
157    pub async fn logout_current() -> SaTokenResult<()> {
158        let token = Self::get_token_value()?;
159        Self::logout(&token).await
160    }
161    
162    /// 检查当前会话是否登录(无参数,返回 bool)
163    /// 
164    /// # 示例
165    /// ```rust,ignore
166    /// // 在请求处理函数中
167    /// if StpUtil::is_login_current() {
168    ///     println!("当前用户已登录");
169    /// }
170    /// ```
171    pub fn is_login_current() -> bool {
172        if let Ok(_token) = Self::get_token_value() {
173            // 注意:这里使用同步检查,只检查上下文中是否有 token
174            // 如果需要异步验证,需要使用 is_login(&token).await
175            true
176        } else {
177            false
178        }
179    }
180    
181    /// 检查当前会话登录状态,未登录则抛出异常(无参数)
182    /// 
183    /// # 示例
184    /// ```rust,ignore
185    /// // 在请求处理函数中
186    /// StpUtil::check_login_current()?;
187    /// ```
188    pub fn check_login_current() -> SaTokenResult<()> {
189        Self::get_token_value()?;
190        Ok(())
191    }
192    
193    /// 获取当前会话的 login_id(String 类型,无参数)
194    /// 
195    /// # 示例
196    /// ```rust,ignore
197    /// // 在请求处理函数中
198    /// let login_id = StpUtil::get_login_id_as_string()?;
199    /// ```
200    pub fn get_login_id_as_string() -> SaTokenResult<String> {
201        let ctx = SaTokenContext::get_current()
202            .ok_or(SaTokenError::NotLogin)?;
203        ctx.login_id.ok_or(SaTokenError::NotLogin)
204    }
205    
206    /// 获取当前会话的 login_id(i64 类型,无参数)
207    /// 
208    /// # 示例
209    /// ```rust,ignore
210    /// // 在请求处理函数中
211    /// let user_id = StpUtil::get_login_id_as_long()?;
212    /// ```
213    pub fn get_login_id_as_long() -> SaTokenResult<i64> {
214        let login_id_str = Self::get_login_id_as_string()?;
215        login_id_str.parse::<i64>()
216            .map_err(|_| SaTokenError::InvalidToken("Login ID is not a valid number".to_string()))
217    }
218    
219    /// 获取当前会话的 token 信息(无参数)
220    /// 
221    /// # 示例
222    /// ```rust,ignore
223    /// // 在请求处理函数中
224    /// let token_info = StpUtil::get_token_info_current()?;
225    /// println!("Token 创建时间: {:?}", token_info.create_time);
226    /// ```
227    pub fn get_token_info_current() -> SaTokenResult<Arc<TokenInfo>> {
228        let ctx = SaTokenContext::get_current()
229            .ok_or(SaTokenError::NotLogin)?;
230        ctx.token_info.ok_or(SaTokenError::NotLogin)
231    }
232    
233    // ==================== Token 验证 ====================
234    
235    /// 检查当前 token 是否已登录
236    pub async fn is_login(token: &TokenValue) -> bool {
237        Self::get_manager().is_valid(token).await
238    }
239    
240    /// 根据登录 ID 检查是否已登录
241    /// 
242    /// # 示例
243    /// ```rust,ignore
244    /// let is_logged_in = StpUtil::is_login_by_login_id("user_123").await;
245    /// let is_logged_in = StpUtil::is_login_by_login_id(10001).await;
246    /// ```
247    pub async fn is_login_by_login_id(login_id: impl LoginId) -> bool {
248        match Self::get_token_by_login_id(login_id).await {
249            Ok(token) => Self::is_login(&token).await,
250            Err(_) => false,
251        }
252    }
253    
254    pub async fn is_login_with_manager(
255        manager: &SaTokenManager,
256        token: &TokenValue,
257    ) -> bool {
258        manager.is_valid(token).await
259    }
260    
261    /// 检查当前 token 是否已登录,如果未登录则抛出异常
262    pub async fn check_login(token: &TokenValue) -> SaTokenResult<()> {
263        if !Self::is_login(token).await {
264            return Err(SaTokenError::NotLogin);
265        }
266        Ok(())
267    }
268    
269    /// 获取 token 信息
270    pub async fn get_token_info(token: &TokenValue) -> SaTokenResult<TokenInfo> {
271        Self::get_manager().get_token_info(token).await
272    }
273    
274    /// 获取当前 token 的登录ID
275    pub async fn get_login_id(token: &TokenValue) -> SaTokenResult<String> {
276        let token_info = Self::get_manager().get_token_info(token).await?;
277        Ok(token_info.login_id)
278    }
279    
280    /// 获取当前 token 的登录ID,如果未登录则返回默认值
281    pub async fn get_login_id_or_default(
282        token: &TokenValue,
283        default: impl Into<String>,
284    ) -> String {
285        Self::get_login_id(token)
286            .await
287            .unwrap_or_else(|_| default.into())
288    }
289    
290    /// 根据登录 ID 获取当前用户的 token
291    /// 
292    /// # 示例
293    /// ```rust,ignore
294    /// let token = StpUtil::get_token_by_login_id("user_123").await?;
295    /// let token = StpUtil::get_token_by_login_id(10001).await?;
296    /// ```
297    pub async fn get_token_by_login_id(login_id: impl LoginId) -> SaTokenResult<TokenValue> {
298        let manager = Self::get_manager();
299        let login_id_str = login_id.to_login_id();
300        
301        // 从存储中获取该用户的 token
302        let key = format!("sa:login:token:{}", login_id_str);
303        match manager.storage.get(&key).await {
304            Ok(Some(token_str)) => Ok(TokenValue::new(token_str)),
305            Ok(None) => Err(SaTokenError::NotLogin),
306            Err(e) => Err(SaTokenError::StorageError(e.to_string())),
307        }
308    }
309    
310    /// 根据登录 ID 获取所有在线的 token 列表(支持多设备登录)
311    /// 
312    /// # 示例
313    /// ```rust,ignore
314    /// let tokens = StpUtil::get_all_tokens_by_login_id("user_123").await?;
315    /// ```
316    pub async fn get_all_tokens_by_login_id(login_id: impl LoginId) -> SaTokenResult<Vec<TokenValue>> {
317        let manager = Self::get_manager();
318        let login_id_str = login_id.to_login_id();
319        
320        // 从存储中获取该用户的所有 token
321        let key = format!("sa:login:tokens:{}", login_id_str);
322        match manager.storage.get(&key).await {
323            Ok(Some(tokens_str)) => {
324                let token_strings: Vec<String> = serde_json::from_str(&tokens_str)
325                    .map_err(|e| SaTokenError::SerializationError(e))?;
326                Ok(token_strings.into_iter().map(TokenValue::new).collect())
327            }
328            Ok(None) => Ok(Vec::new()),
329            Err(e) => Err(SaTokenError::StorageError(e.to_string())),
330        }
331    }
332    
333    // ==================== Session 会话 ====================
334    
335    /// 获取当前登录账号的 Session
336    pub async fn get_session(login_id: impl LoginId) -> SaTokenResult<SaSession> {
337        Self::get_manager().get_session(&login_id.to_login_id()).await
338    }
339    
340    /// 保存 Session
341    pub async fn save_session(session: &SaSession) -> SaTokenResult<()> {
342        Self::get_manager().save_session(session).await
343    }
344    
345    /// 删除 Session
346    pub async fn delete_session(login_id: impl LoginId) -> SaTokenResult<()> {
347        Self::get_manager().delete_session(&login_id.to_login_id()).await
348    }
349    
350    /// 在 Session 中设置值
351    pub async fn set_session_value<T: serde::Serialize>(
352        login_id: impl LoginId,
353        key: &str,
354        value: T,
355    ) -> SaTokenResult<()> {
356        let manager = Self::get_manager();
357        let login_id_str = login_id.to_login_id();
358        let mut session = manager.get_session(&login_id_str).await?;
359        session.set(key, value)?;
360        manager.save_session(&session).await
361    }
362    
363    /// 从 Session 中获取值
364    pub async fn get_session_value<T: serde::de::DeserializeOwned>(
365        login_id: impl LoginId,
366        key: &str,
367    ) -> SaTokenResult<Option<T>> {
368        let session = Self::get_manager().get_session(&login_id.to_login_id()).await?;
369        Ok(session.get::<T>(key))
370    }
371    
372    // ==================== Token 相关 ====================
373    
374    /// 创建一个新的 token(但不登录)
375    pub fn create_token(token_value: impl Into<String>) -> TokenValue {
376        TokenValue::new(token_value.into())
377    }
378    
379    /// 检查 token 格式是否有效(仅检查格式,不检查是否存在于存储中)
380    pub fn is_valid_token_format(token: &str) -> bool {
381        !token.is_empty() && token.len() >= 16
382    }
383}
384
385// ==================== 权限管理 ====================
386
387impl StpUtil {
388    /// 为用户添加权限
389    pub async fn set_permissions(
390        login_id: impl LoginId,
391        permissions: Vec<String>,
392    ) -> SaTokenResult<()> {
393        let manager = Self::get_manager();
394        let mut map = manager.user_permissions.write().await;
395        map.insert(login_id.to_login_id(), permissions);
396        Ok(())
397    }
398    
399    /// 为用户添加单个权限
400    pub async fn add_permission(
401        login_id: impl LoginId,
402        permission: impl Into<String>,
403    ) -> SaTokenResult<()> {
404        let manager = Self::get_manager();
405        let mut map = manager.user_permissions.write().await;
406        let login_id_str = login_id.to_login_id();
407        let permissions = map.entry(login_id_str).or_insert_with(Vec::new);
408        let perm = permission.into();
409        if !permissions.contains(&perm) {
410            permissions.push(perm);
411        }
412        Ok(())
413    }
414    
415    /// 移除用户的某个权限
416    pub async fn remove_permission(
417        login_id: impl LoginId,
418        permission: &str,
419    ) -> SaTokenResult<()> {
420        let manager = Self::get_manager();
421        let mut map = manager.user_permissions.write().await;
422        if let Some(permissions) = map.get_mut(&login_id.to_login_id()) {
423            permissions.retain(|p| p != permission);
424        }
425        Ok(())
426    }
427    
428    /// 清除用户的所有权限
429    pub async fn clear_permissions(login_id: impl LoginId) -> SaTokenResult<()> {
430        let manager = Self::get_manager();
431        let mut map = manager.user_permissions.write().await;
432        map.remove(&login_id.to_login_id());
433        Ok(())
434    }
435    
436    /// 获取用户的所有权限
437    pub async fn get_permissions(login_id: impl LoginId) -> Vec<String> {
438        let manager = Self::get_manager();
439        let map = manager.user_permissions.read().await;
440        map.get(&login_id.to_login_id()).cloned().unwrap_or_default()
441    }
442    
443    /// 检查用户是否拥有指定权限
444    pub async fn has_permission(
445        login_id: impl LoginId,
446        permission: &str,
447    ) -> bool {
448        let manager = Self::get_manager();
449        let map = manager.user_permissions.read().await;
450        if let Some(permissions) = map.get(&login_id.to_login_id()) {
451            // 精确匹配
452            if permissions.contains(&permission.to_string()) {
453                return true;
454            }
455            
456            // 通配符匹配(例如 admin:* 匹配 admin:read)
457            for perm in permissions {
458                if perm.ends_with(":*") {
459                    let prefix = &perm[..perm.len() - 2];
460                    if permission.starts_with(prefix) {
461                        return true;
462                    }
463                }
464            }
465        }
466        false
467    }
468    
469    /// 检查用户是否拥有所有指定权限(AND 逻辑)
470    pub async fn has_all_permissions(
471        login_id: impl LoginId,
472        permissions: &[&str],
473    ) -> bool {
474        let login_id_str = login_id.to_login_id();
475        for permission in permissions {
476            if !Self::has_permission(&login_id_str, permission).await {
477                return false;
478            }
479        }
480        true
481    }
482    
483    /// 检查用户是否拥有所有指定权限(别名,AND 逻辑)
484    pub async fn has_permissions_and(
485        login_id: impl LoginId,
486        permissions: &[&str],
487    ) -> bool {
488        Self::has_all_permissions(login_id, permissions).await
489    }
490    
491    /// 检查用户是否拥有任一指定权限(OR 逻辑)
492    pub async fn has_any_permission(
493        login_id: impl LoginId,
494        permissions: &[&str],
495    ) -> bool {
496        let login_id_str = login_id.to_login_id();
497        for permission in permissions {
498            if Self::has_permission(&login_id_str, permission).await {
499                return true;
500            }
501        }
502        false
503    }
504    
505    /// 检查用户是否拥有任一指定权限(别名,OR 逻辑)
506    pub async fn has_permissions_or(
507        login_id: impl LoginId,
508        permissions: &[&str],
509    ) -> bool {
510        Self::has_any_permission(login_id, permissions).await
511    }
512    
513    /// 检查权限,如果没有则抛出异常
514    pub async fn check_permission(
515        login_id: impl LoginId,
516        permission: &str,
517    ) -> SaTokenResult<()> {
518        if !Self::has_permission(login_id, permission).await {
519            return Err(SaTokenError::PermissionDenied(permission.to_string()));
520        }
521        Ok(())
522    }
523}
524
525// ==================== 角色管理 ====================
526
527impl StpUtil {
528    /// 为用户设置角色
529    pub async fn set_roles(
530        login_id: impl LoginId,
531        roles: Vec<String>,
532    ) -> SaTokenResult<()> {
533        let manager = Self::get_manager();
534        let mut map = manager.user_roles.write().await;
535        map.insert(login_id.to_login_id(), roles);
536        Ok(())
537    }
538    
539    /// 为用户添加单个角色
540    pub async fn add_role(
541        login_id: impl LoginId,
542        role: impl Into<String>,
543    ) -> SaTokenResult<()> {
544        let manager = Self::get_manager();
545        let mut map = manager.user_roles.write().await;
546        let login_id_str = login_id.to_login_id();
547        let roles = map.entry(login_id_str).or_insert_with(Vec::new);
548        let r = role.into();
549        if !roles.contains(&r) {
550            roles.push(r);
551        }
552        Ok(())
553    }
554    
555    /// 移除用户的某个角色
556    pub async fn remove_role(
557        login_id: impl LoginId,
558        role: &str,
559    ) -> SaTokenResult<()> {
560        let manager = Self::get_manager();
561        let mut map = manager.user_roles.write().await;
562        if let Some(roles) = map.get_mut(&login_id.to_login_id()) {
563            roles.retain(|r| r != role);
564        }
565        Ok(())
566    }
567    
568    /// 清除用户的所有角色
569    pub async fn clear_roles(login_id: impl LoginId) -> SaTokenResult<()> {
570        let manager = Self::get_manager();
571        let mut map = manager.user_roles.write().await;
572        map.remove(&login_id.to_login_id());
573        Ok(())
574    }
575    
576    /// 获取用户的所有角色
577    pub async fn get_roles(login_id: impl LoginId) -> Vec<String> {
578        let manager = Self::get_manager();
579        let map = manager.user_roles.read().await;
580        map.get(&login_id.to_login_id()).cloned().unwrap_or_default()
581    }
582    
583    /// 检查用户是否拥有指定角色
584    pub async fn has_role(
585        login_id: impl LoginId,
586        role: &str,
587    ) -> bool {
588        let manager = Self::get_manager();
589        let map = manager.user_roles.read().await;
590        if let Some(roles) = map.get(&login_id.to_login_id()) {
591            roles.contains(&role.to_string())
592        } else {
593            false
594        }
595    }
596    
597    /// 检查用户是否拥有所有指定角色(AND 逻辑)
598    pub async fn has_all_roles(
599        login_id: impl LoginId,
600        roles: &[&str],
601    ) -> bool {
602        let login_id_str = login_id.to_login_id();
603        for role in roles {
604            if !Self::has_role(&login_id_str, role).await {
605                return false;
606            }
607        }
608        true
609    }
610    
611    /// 检查用户是否拥有所有指定角色(别名,AND 逻辑)
612    pub async fn has_roles_and(
613        login_id: impl LoginId,
614        roles: &[&str],
615    ) -> bool {
616        Self::has_all_roles(login_id, roles).await
617    }
618    
619    /// 检查用户是否拥有任一指定角色(OR 逻辑)
620    pub async fn has_any_role(
621        login_id: impl LoginId,
622        roles: &[&str],
623    ) -> bool {
624        let login_id_str = login_id.to_login_id();
625        for role in roles {
626            if Self::has_role(&login_id_str, role).await {
627                return true;
628            }
629        }
630        false
631    }
632    
633    /// 检查用户是否拥有任一指定角色(别名,OR 逻辑)
634    pub async fn has_roles_or(
635        login_id: impl LoginId,
636        roles: &[&str],
637    ) -> bool {
638        Self::has_any_role(login_id, roles).await
639    }
640    
641    /// 检查角色,如果没有则抛出异常
642    pub async fn check_role(
643        login_id: impl LoginId,
644        role: &str,
645    ) -> SaTokenResult<()> {
646        if !Self::has_role(login_id, role).await {
647            return Err(SaTokenError::RoleDenied(role.to_string()));
648        }
649        Ok(())
650    }
651}
652
653// ==================== 扩展工具方法 ====================
654
655impl StpUtil {
656    /// 批量踢人下线
657    pub async fn kick_out_batch<T: LoginId>(
658        login_ids: &[T],
659    ) -> SaTokenResult<Vec<Result<(), SaTokenError>>> {
660        let manager = Self::get_manager();
661        let mut results = Vec::new();
662        for login_id in login_ids {
663            results.push(manager.kick_out(&login_id.to_login_id()).await);
664        }
665        Ok(results)
666    }
667    
668    /// 获取 token 剩余有效时间(秒)
669    pub async fn get_token_timeout(token: &TokenValue) -> SaTokenResult<Option<i64>> {
670        let manager = Self::get_manager();
671        let token_info = manager.get_token_info(token).await?;
672        
673        if let Some(expire_time) = token_info.expire_time {
674            let now = chrono::Utc::now();
675            let duration = expire_time.signed_duration_since(now);
676            Ok(Some(duration.num_seconds()))
677        } else {
678            Ok(None) // 永久有效
679        }
680    }
681    
682    /// 续期 token(重置过期时间)
683    pub async fn renew_timeout(
684        token: &TokenValue,
685        timeout_seconds: i64,
686    ) -> SaTokenResult<()> {
687        let manager = Self::get_manager();
688        let mut token_info = manager.get_token_info(token).await?;
689        
690        // 设置新的过期时间
691        let new_expire_time = chrono::Utc::now() + chrono::Duration::seconds(timeout_seconds);
692        token_info.expire_time = Some(new_expire_time);
693        
694        // 保存更新后的 token 信息
695        let key = format!("sa:token:{}", token.as_str());
696        let value = serde_json::to_string(&token_info)
697            .map_err(|e| SaTokenError::SerializationError(e))?;
698        
699        let timeout = std::time::Duration::from_secs(timeout_seconds as u64);
700        manager.storage.set(&key, &value, Some(timeout)).await
701            .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
702        
703        Ok(())
704    }
705}
706
707#[cfg(test)]
708mod tests {
709    use super::*;
710    
711    #[test]
712    fn test_token_format_validation() {
713        assert!(StpUtil::is_valid_token_format("1234567890abcdef"));
714        assert!(!StpUtil::is_valid_token_format(""));
715        assert!(!StpUtil::is_valid_token_format("short"));
716    }
717    
718    #[test]
719    fn test_create_token() {
720        let token = StpUtil::create_token("test-token-123");
721        assert_eq!(token.as_str(), "test-token-123");
722    }
723}