1use std::sync::Arc;
24use std::fmt::Display;
25use std::sync::OnceLock;
26use crate::{SaTokenManager, SaTokenResult, SaTokenError};
27use crate::token::{TokenValue, TokenInfo};
28use crate::session::SaSession;
29use crate::context::SaTokenContext;
30use crate::event::{SaTokenEventBus, SaTokenListener};
31
32static GLOBAL_MANAGER: OnceLock<Arc<SaTokenManager>> = OnceLock::new();
34
35pub trait LoginId {
39 fn to_login_id(&self) -> String;
40}
41
42impl<T: Display> LoginId for T {
44 fn to_login_id(&self) -> String {
45 self.to_string()
46 }
47}
48
49pub struct StpUtil;
53
54impl StpUtil {
55 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 fn get_manager() -> &'static Arc<SaTokenManager> {
73 GLOBAL_MANAGER.get()
74 .expect("StpUtil not initialized. Call StpUtil::init_manager() first.")
75 }
76
77 pub fn event_bus() -> &'static SaTokenEventBus {
97 &Self::get_manager().event_bus
98 }
99
100 pub fn register_listener(listener: Arc<dyn SaTokenListener>) {
107 Self::event_bus().register(listener);
108 }
109
110 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(
128 login_id: impl LoginId,
129 login_type: impl Into<String>,
130 ) -> SaTokenResult<TokenValue> {
131 Self::get_manager()
132 .login_with_options(
133 login_id.to_login_id(),
134 Some(login_type.into()),
135 None,
136 None,
137 None,
138 None,
139 )
140 .await
141 }
142
143 pub async fn login_with_extra(
149 login_id: impl LoginId,
150 extra_data: serde_json::Value,
151 ) -> SaTokenResult<TokenValue> {
152 Self::get_manager().login_with_options(
153 login_id.to_login_id(),
154 None, None, Some(extra_data),
157 None, None, ).await
160 }
161
162 pub async fn login_with_manager(
164 manager: &SaTokenManager,
165 login_id: impl Into<String>,
166 ) -> SaTokenResult<TokenValue> {
167 manager.login(login_id).await
168 }
169
170 pub async fn logout(token: &TokenValue) -> SaTokenResult<()> {
172 tracing::debug!("开始执行 logout,token: {}", token);
173 let result = Self::get_manager().logout(token).await;
174 match &result {
175 Ok(_) => tracing::debug!("logout 执行成功,token: {}", token),
176 Err(e) => tracing::debug!("logout 执行失败,token: {}, 错误: {}", token, e),
177 }
178 result
179 }
180
181 pub async fn logout_with_manager(
182 manager: &SaTokenManager,
183 token: &TokenValue,
184 ) -> SaTokenResult<()> {
185 manager.logout(token).await
186 }
187
188 pub async fn kick_out(login_id: impl LoginId) -> SaTokenResult<()> {
190 Self::get_manager().kick_out(&login_id.to_login_id()).await
191 }
192
193 pub async fn kick_out_with_manager(
194 manager: &SaTokenManager,
195 login_id: &str,
196 ) -> SaTokenResult<()> {
197 manager.kick_out(login_id).await
198 }
199
200 pub async fn logout_by_login_id(login_id: impl LoginId) -> SaTokenResult<()> {
202 Self::get_manager().logout_by_login_id(&login_id.to_login_id()).await
203 }
204
205 pub async fn logout_by_token(token: &TokenValue) -> SaTokenResult<()> {
207 Self::logout(token).await
208 }
209
210 pub fn get_token_value() -> SaTokenResult<TokenValue> {
220 let ctx = SaTokenContext::try_current().ok_or(SaTokenError::NotLogin)?;
221 ctx.token.ok_or(SaTokenError::NotLogin)
222 }
223
224 pub async fn logout_current() -> SaTokenResult<()> {
232 let token = Self::get_token_value()?;
233 tracing::debug!("成功获取 token: {}", token);
234
235 let result = Self::logout(&token).await;
236 match &result {
237 Ok(_) => tracing::debug!("logout_current 执行成功,token: {}", token),
238 Err(e) => tracing::debug!("logout_current 执行失败,token: {}, 错误: {}", token, e),
239 }
240 result
241 }
242
243 pub fn is_login_current() -> bool {
253 if let Ok(_token) = Self::get_token_value() {
254 true
257 } else {
258 false
259 }
260 }
261
262 pub fn check_login_current() -> SaTokenResult<()> {
270 Self::get_token_value()?;
271 Ok(())
272 }
273
274 pub async fn get_login_id_as_string() -> SaTokenResult<String> {
282 if let Some(ctx) = SaTokenContext::get_current()
283 && let Some(switch_id) = ctx.switch_login_id {
284 return Ok(switch_id);
285 }
286 let token = Self::get_token_value()?;
287 Self::get_login_id(&token).await
288 }
289
290 pub async fn get_login_id_as_long() -> SaTokenResult<i64> {
298 let login_id_str = Self::get_login_id_as_string().await?;
299 login_id_str.parse::<i64>()
300 .map_err(|_| SaTokenError::LoginIdNotNumber)
301 }
302
303 pub fn get_token_info_current() -> SaTokenResult<Arc<TokenInfo>> {
312 let ctx = SaTokenContext::try_current().ok_or(SaTokenError::NotLogin)?;
313 ctx.token_info.ok_or(SaTokenError::NotLogin)
314 }
315
316 pub async fn is_login(token: &TokenValue) -> bool {
320 Self::get_manager().is_valid(token).await
321 }
322
323 pub async fn is_login_by_login_id(login_id: impl LoginId) -> bool {
331 match Self::get_token_by_login_id(login_id).await {
332 Ok(token) => Self::is_login(&token).await,
333 Err(_) => false,
334 }
335 }
336
337 pub async fn is_login_with_manager(
338 manager: &SaTokenManager,
339 token: &TokenValue,
340 ) -> bool {
341 manager.is_valid(token).await
342 }
343
344 pub async fn check_login(token: &TokenValue) -> SaTokenResult<()> {
346 if !Self::is_login(token).await {
347 return Err(SaTokenError::NotLogin);
348 }
349 Ok(())
350 }
351
352 pub async fn get_token_info(token: &TokenValue) -> SaTokenResult<TokenInfo> {
354 Self::get_manager().get_token_info(token).await
355 }
356
357 pub async fn get_login_id(token: &TokenValue) -> SaTokenResult<String> {
359 let token_info = Self::get_manager().get_token_info(token).await?;
360 Ok(token_info.login_id)
361 }
362
363 pub async fn get_login_id_or_default(
365 token: &TokenValue,
366 default: impl Into<String>,
367 ) -> String {
368 Self::get_login_id(token)
369 .await
370 .unwrap_or_else(|_| default.into())
371 }
372
373 pub async fn get_token_by_login_id(login_id: impl LoginId) -> SaTokenResult<TokenValue> {
381 let manager = Self::get_manager();
382 let login_id_str = login_id.to_login_id();
383
384 let key = manager.config.make_key("login:token:", &login_id_str);
386 match manager.storage.get(&key).await {
387 Ok(Some(token_str)) => Ok(TokenValue::new(token_str)),
388 Ok(None) => Err(SaTokenError::NotLogin),
389 Err(e) => Err(SaTokenError::StorageError(e.to_string())),
390 }
391 }
392
393 pub async fn get_all_tokens_by_login_id(login_id: impl LoginId) -> SaTokenResult<Vec<TokenValue>> {
400 let manager = Self::get_manager();
401 let login_id_str = login_id.to_login_id();
402
403 let key = manager.config.make_key("login:tokens:", &login_id_str);
405 match manager.storage.get(&key).await {
406 Ok(Some(tokens_str)) => {
407 let token_strings: Vec<String> = serde_json::from_str(&tokens_str)
408 .map_err(SaTokenError::SerializationError)?;
409 Ok(token_strings.into_iter().map(TokenValue::new).collect())
410 }
411 Ok(None) => Ok(Vec::new()),
412 Err(e) => Err(SaTokenError::StorageError(e.to_string())),
413 }
414 }
415
416 pub async fn get_session(login_id: impl LoginId) -> SaTokenResult<SaSession> {
420 Self::get_manager().get_session(&login_id.to_login_id()).await
421 }
422
423 pub async fn save_session(session: &SaSession) -> SaTokenResult<()> {
425 Self::get_manager().save_session(session).await
426 }
427
428 pub async fn delete_session(login_id: impl LoginId) -> SaTokenResult<()> {
430 Self::get_manager().delete_session(&login_id.to_login_id()).await
431 }
432
433 pub async fn set_session_value<T: serde::Serialize>(
435 login_id: impl LoginId,
436 key: &str,
437 value: T,
438 ) -> SaTokenResult<()> {
439 let manager = Self::get_manager();
440 let login_id_str = login_id.to_login_id();
441 let mut session = manager.get_session(&login_id_str).await?;
442 session.set(key, value)?;
443 manager.save_session(&session).await
444 }
445
446 pub async fn get_session_value<T: serde::de::DeserializeOwned>(
448 login_id: impl LoginId,
449 key: &str,
450 ) -> SaTokenResult<Option<T>> {
451 let session = Self::get_manager().get_session(&login_id.to_login_id()).await?;
452 Ok(session.get::<T>(key))
453 }
454
455 pub fn create_token(token_value: impl Into<String>) -> TokenValue {
459 TokenValue::new(token_value.into())
460 }
461
462 pub fn is_valid_token_format(token: &str) -> bool {
464 !token.is_empty() && token.len() >= 16
465 }
466}
467
468impl StpUtil {
471 pub async fn set_permissions(
474 login_id: impl LoginId,
475 permissions: Vec<String>,
476 ) -> SaTokenResult<()> {
477 Self::get_manager()
478 .set_permissions(&login_id.to_login_id(), permissions)
479 .await
480 }
481
482 pub async fn add_permission(
484 login_id: impl LoginId,
485 permission: impl Into<String>,
486 ) -> SaTokenResult<()> {
487 Self::get_manager()
488 .add_permission(&login_id.to_login_id(), permission.into())
489 .await
490 }
491
492 pub async fn remove_permission(
494 login_id: impl LoginId,
495 permission: &str,
496 ) -> SaTokenResult<()> {
497 Self::get_manager()
498 .remove_permission(&login_id.to_login_id(), permission)
499 .await
500 }
501
502 pub async fn clear_permissions(login_id: impl LoginId) -> SaTokenResult<()> {
504 Self::get_manager()
505 .clear_permissions(&login_id.to_login_id())
506 .await
507 }
508
509 pub async fn get_permissions(login_id: impl LoginId) -> Vec<String> {
512 Self::get_manager()
513 .get_permissions(&login_id.to_login_id())
514 .await
515 .unwrap_or_default()
516 }
517
518 pub async fn has_permission(
522 login_id: impl LoginId,
523 permission: &str,
524 ) -> bool {
525 let permissions = match Self::get_manager()
526 .get_permissions(&login_id.to_login_id())
527 .await
528 {
529 Ok(list) => list,
530 Err(_) => return false,
531 };
532
533 if permissions.iter().any(|p| p == permission) {
535 return true;
536 }
537 if permissions.iter().any(|p| p == "*") {
539 return true;
540 }
541 permissions.iter().any(|perm| {
543 perm.strip_suffix(":*")
544 .is_some_and(|prefix| permission.starts_with(prefix))
545 })
546 }
547
548 pub async fn has_all_permissions(
550 login_id: impl LoginId,
551 permissions: &[&str],
552 ) -> bool {
553 let login_id_str = login_id.to_login_id();
554 for permission in permissions {
555 if !Self::has_permission(&login_id_str, permission).await {
556 return false;
557 }
558 }
559 true
560 }
561
562 pub async fn has_permissions_and(
564 login_id: impl LoginId,
565 permissions: &[&str],
566 ) -> bool {
567 Self::has_all_permissions(login_id, permissions).await
568 }
569
570 pub async fn has_any_permission(
572 login_id: impl LoginId,
573 permissions: &[&str],
574 ) -> bool {
575 let login_id_str = login_id.to_login_id();
576 for permission in permissions {
577 if Self::has_permission(&login_id_str, permission).await {
578 return true;
579 }
580 }
581 false
582 }
583
584 pub async fn has_permissions_or(
586 login_id: impl LoginId,
587 permissions: &[&str],
588 ) -> bool {
589 Self::has_any_permission(login_id, permissions).await
590 }
591
592 pub async fn check_permission(
594 login_id: impl LoginId,
595 permission: &str,
596 ) -> SaTokenResult<()> {
597 if !Self::has_permission(login_id, permission).await {
598 return Err(SaTokenError::PermissionDeniedDetail(permission.to_string()));
599 }
600 Ok(())
601 }
602}
603
604impl StpUtil {
607 pub async fn set_roles(
610 login_id: impl LoginId,
611 roles: Vec<String>,
612 ) -> SaTokenResult<()> {
613 Self::get_manager()
614 .set_roles(&login_id.to_login_id(), roles)
615 .await
616 }
617
618 pub async fn add_role(
620 login_id: impl LoginId,
621 role: impl Into<String>,
622 ) -> SaTokenResult<()> {
623 Self::get_manager()
624 .add_role(&login_id.to_login_id(), role.into())
625 .await
626 }
627
628 pub async fn remove_role(
630 login_id: impl LoginId,
631 role: &str,
632 ) -> SaTokenResult<()> {
633 Self::get_manager()
634 .remove_role(&login_id.to_login_id(), role)
635 .await
636 }
637
638 pub async fn clear_roles(login_id: impl LoginId) -> SaTokenResult<()> {
640 Self::get_manager()
641 .clear_roles(&login_id.to_login_id())
642 .await
643 }
644
645 pub async fn get_roles(login_id: impl LoginId) -> Vec<String> {
648 Self::get_manager()
649 .get_roles(&login_id.to_login_id())
650 .await
651 .unwrap_or_default()
652 }
653
654 pub async fn has_role(
657 login_id: impl LoginId,
658 role: &str,
659 ) -> bool {
660 match Self::get_manager().get_roles(&login_id.to_login_id()).await {
661 Ok(roles) => roles.iter().any(|r| r == role),
662 Err(_) => false,
663 }
664 }
665
666 pub async fn has_all_roles(
668 login_id: impl LoginId,
669 roles: &[&str],
670 ) -> bool {
671 let login_id_str = login_id.to_login_id();
672 for role in roles {
673 if !Self::has_role(&login_id_str, role).await {
674 return false;
675 }
676 }
677 true
678 }
679
680 pub async fn has_roles_and(
682 login_id: impl LoginId,
683 roles: &[&str],
684 ) -> bool {
685 Self::has_all_roles(login_id, roles).await
686 }
687
688 pub async fn has_any_role(
690 login_id: impl LoginId,
691 roles: &[&str],
692 ) -> bool {
693 let login_id_str = login_id.to_login_id();
694 for role in roles {
695 if Self::has_role(&login_id_str, role).await {
696 return true;
697 }
698 }
699 false
700 }
701
702 pub async fn has_roles_or(
704 login_id: impl LoginId,
705 roles: &[&str],
706 ) -> bool {
707 Self::has_any_role(login_id, roles).await
708 }
709
710 pub async fn check_role(
712 login_id: impl LoginId,
713 role: &str,
714 ) -> SaTokenResult<()> {
715 if !Self::has_role(login_id, role).await {
716 return Err(SaTokenError::RoleDenied(role.to_string()));
717 }
718 Ok(())
719 }
720}
721
722impl StpUtil {
725 pub async fn disable(login_id: impl LoginId, time: i64) -> SaTokenResult<()> {
727 Self::get_manager()
728 .disable(&login_id.to_login_id(), time)
729 .await
730 }
731
732 pub async fn disable_level(
734 login_id: impl LoginId,
735 service: &str,
736 level: i32,
737 time: i64,
738 ) -> SaTokenResult<()> {
739 Self::get_manager()
740 .disable_level(&login_id.to_login_id(), service, level, time)
741 .await
742 }
743
744 pub async fn check_disable(login_id: impl LoginId) -> SaTokenResult<()> {
746 Self::check_disable_level(login_id, crate::disable::DEFAULT_DISABLE_SERVICE, crate::disable::MIN_DISABLE_LEVEL).await
747 }
748
749 pub async fn check_disable_service(
751 login_id: impl LoginId,
752 service: &str,
753 ) -> SaTokenResult<()> {
754 Self::check_disable_level(login_id, service, crate::disable::MIN_DISABLE_LEVEL).await
755 }
756
757 pub async fn check_disable_services(
759 login_id: impl LoginId,
760 services: &[&str],
761 ) -> SaTokenResult<()> {
762 Self::get_manager()
763 .check_disable_services(
764 &login_id.to_login_id(),
765 services,
766 crate::disable::MIN_DISABLE_LEVEL,
767 )
768 .await
769 }
770
771 pub async fn check_disable_level(
773 login_id: impl LoginId,
774 service: &str,
775 level: i32,
776 ) -> SaTokenResult<()> {
777 Self::get_manager()
778 .check_disable_level(&login_id.to_login_id(), service, level)
779 .await
780 }
781
782 pub async fn untie_disable(login_id: impl LoginId, service: &str) -> SaTokenResult<()> {
784 Self::get_manager()
785 .untie_disable(&login_id.to_login_id(), service)
786 .await
787 }
788}
789
790impl StpUtil {
793 pub async fn open_safe(service: &str, safe_time: i64) -> SaTokenResult<()> {
795 let token = Self::get_token_value()?;
796 Self::get_manager().open_safe(&token, service, safe_time).await
797 }
798
799 pub async fn is_safe(service: &str) -> SaTokenResult<bool> {
801 let token = Self::get_token_value()?;
802 Self::get_manager().is_safe(&token, service).await
803 }
804
805 pub async fn check_safe(service: &str) -> SaTokenResult<()> {
807 Self::check_login_current()?;
808 let token = Self::get_token_value()?;
809 Self::get_manager().check_safe(&token, service).await
810 }
811
812 pub async fn close_safe(service: &str) -> SaTokenResult<()> {
814 let token = Self::get_token_value()?;
815 Self::get_manager().close_safe(&token, service).await
816 }
817}
818
819impl StpUtil {
822 pub fn switch_to(login_id: impl LoginId) {
824 let mut ctx = SaTokenContext::get_current().unwrap_or_default();
825 ctx.switch_login_id = Some(login_id.to_login_id());
826 SaTokenContext::set_current(ctx);
827 }
828
829 pub fn end_switch() {
831 if let Some(mut ctx) = SaTokenContext::get_current() {
832 ctx.switch_login_id = None;
833 SaTokenContext::set_current(ctx);
834 }
835 }
836
837 pub fn is_switch() -> bool {
839 SaTokenContext::get_current()
840 .and_then(|c| c.switch_login_id)
841 .is_some()
842 }
843
844 pub fn get_switch_login_id() -> Option<String> {
846 SaTokenContext::get_current().and_then(|c| c.switch_login_id)
847 }
848}
849
850impl StpUtil {
853 pub async fn kick_out_batch<T: LoginId>(
855 login_ids: &[T],
856 ) -> SaTokenResult<Vec<Result<(), SaTokenError>>> {
857 let manager = Self::get_manager();
858 let mut results = Vec::new();
859 for login_id in login_ids {
860 results.push(manager.kick_out(&login_id.to_login_id()).await);
861 }
862 Ok(results)
863 }
864
865 pub async fn get_token_timeout(token: &TokenValue) -> SaTokenResult<Option<i64>> {
867 let manager = Self::get_manager();
868 let token_info = manager.get_token_info(token).await?;
869
870 if let Some(expire_time) = token_info.expire_time {
871 let now = chrono::Utc::now();
872 let duration = expire_time.signed_duration_since(now);
873 Ok(Some(duration.num_seconds()))
874 } else {
875 Ok(None) }
877 }
878
879 pub async fn renew_timeout(
881 token: &TokenValue,
882 timeout_seconds: i64,
883 ) -> SaTokenResult<()> {
884 let manager = Self::get_manager();
885 let mut token_info = manager.get_token_info(token).await?;
886
887 let new_expire_time = chrono::Utc::now() + chrono::Duration::seconds(timeout_seconds);
889 token_info.expire_time = Some(new_expire_time);
890
891 let key = manager.config.make_key("token:", token.as_str());
893 let value = serde_json::to_string(&token_info)
894 .map_err(SaTokenError::SerializationError)?;
895
896 let timeout = std::time::Duration::from_secs(timeout_seconds as u64);
897 manager.storage.set(&key, &value, Some(timeout)).await
898 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
899
900 Ok(())
901 }
902
903 pub async fn set_extra_data(
911 token: &TokenValue,
912 extra_data: serde_json::Value,
913 ) -> SaTokenResult<()> {
914 let manager = Self::get_manager();
915 let mut token_info = manager.get_token_info(token).await?;
916 token_info.extra_data = Some(extra_data);
917
918 let key = manager.config.make_key("token:", token.as_str());
919 let value = serde_json::to_string(&token_info)
920 .map_err(SaTokenError::SerializationError)?;
921
922 manager.storage.set(&key, &value, manager.config.timeout_duration()).await
923 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
924
925 Ok(())
926 }
927
928 pub async fn get_extra_data(token: &TokenValue) -> SaTokenResult<Option<serde_json::Value>> {
933 let manager = Self::get_manager();
934 let token_info = manager.get_token_info(token).await?;
935 Ok(token_info.extra_data)
936 }
937
938 pub async fn get_terminal_list(
941 login_id: &str,
942 device_type: Option<&str>,
943 ) -> SaTokenResult<Vec<crate::session::SaTerminalInfo>> {
944 Self::get_manager()
945 .get_terminal_list("default", login_id, device_type)
946 .await
947 }
948
949 pub async fn get_token_value_list_by_login_id(
950 login_id: &str,
951 device_type: Option<&str>,
952 ) -> SaTokenResult<Vec<String>> {
953 Self::get_manager()
954 .get_token_value_list_by_login_id("default", login_id, device_type)
955 .await
956 }
957
958 pub async fn get_terminal_info_by_token(
959 token: &TokenValue,
960 ) -> SaTokenResult<Option<crate::session::SaTerminalInfo>> {
961 Self::get_manager()
962 .get_terminal_info_by_token(token)
963 .await
964 }
965
966 pub fn stp_logic(login_type: &str) -> Arc<crate::stp_logic::SaLogic> {
969 crate::stp_logic::get_or_create_stp_logic(login_type, Self::get_manager().clone())
970 }
971
972 pub fn put_stp_logic(logic: Arc<crate::stp_logic::SaLogic>) {
973 crate::stp_logic::put_stp_logic(logic);
974 }
975
976 pub fn remove_stp_logic(login_type: &str) {
977 crate::stp_logic::remove_stp_logic(login_type);
978 }
979
980 pub fn builder(login_id: impl LoginId) -> TokenBuilder {
997 TokenBuilder::new(login_id.to_login_id())
998 }
999}
1000
1001pub struct TokenBuilder {
1003 login_id: String,
1004 extra_data: Option<serde_json::Value>,
1005 device: Option<String>,
1006 login_type: Option<String>,
1007}
1008
1009impl TokenBuilder {
1010 pub fn new(login_id: String) -> Self {
1012 Self {
1013 login_id,
1014 extra_data: None,
1015 device: None,
1016 login_type: None,
1017 }
1018 }
1019
1020 pub fn extra_data(mut self, data: serde_json::Value) -> Self {
1022 self.extra_data = Some(data);
1023 self
1024 }
1025
1026 pub fn device(mut self, device: impl Into<String>) -> Self {
1028 self.device = Some(device.into());
1029 self
1030 }
1031
1032 pub fn login_type(mut self, login_type: impl Into<String>) -> Self {
1034 self.login_type = Some(login_type.into());
1035 self
1036 }
1037
1038 pub async fn login<T: LoginId>(self, login_id: Option<T>) -> SaTokenResult<TokenValue> {
1042 let manager = StpUtil::get_manager();
1043
1044 let final_login_id = match login_id {
1046 Some(id) => id.to_login_id(),
1047 None => self.login_id,
1048 };
1049 let token = manager.login(final_login_id).await?;
1050
1051 let mut token_info = manager.get_token_info(&token).await?;
1053
1054 if let Some(data) = self.extra_data {
1056 token_info.extra_data = Some(data);
1057 }
1058
1059 if let Some(device) = self.device {
1060 token_info.device = Some(device);
1061 }
1062
1063 if let Some(login_type) = self.login_type {
1064 token_info.login_type = login_type;
1065 }
1066
1067 let key = manager.config.make_key("token:", token.as_str());
1069 let value = serde_json::to_string(&token_info)
1070 .map_err(SaTokenError::SerializationError)?;
1071
1072 manager.storage.set(&key, &value, manager.config.timeout_duration()).await
1073 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
1074
1075 Ok(token)
1076 }
1077}
1078
1079#[cfg(test)]
1080mod tests {
1081 use super::*;
1082
1083 #[test]
1084 fn test_token_format_validation() {
1085 assert!(StpUtil::is_valid_token_format("1234567890abcdef"));
1086 assert!(!StpUtil::is_valid_token_format(""));
1087 assert!(!StpUtil::is_valid_token_format("short"));
1088 }
1089
1090 #[test]
1091 fn test_create_token() {
1092 let token = StpUtil::create_token("test-token-123");
1093 assert_eq!(token.as_str(), "test-token-123");
1094 }
1095}