1use 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
32static GLOBAL_MANAGER: OnceCell<Arc<SaTokenManager>> = OnceCell::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(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 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 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 pub async fn logout(token: &TokenValue) -> SaTokenResult<()> {
155 tracing::debug!("开始执行 logout,token: {}", token);
156 let result = Self::get_manager().logout(token).await;
157 match &result {
158 Ok(_) => tracing::debug!("logout 执行成功,token: {}", token),
159 Err(e) => tracing::debug!("logout 执行失败,token: {}, 错误: {}", token, e),
160 }
161 result
162 }
163
164 pub async fn logout_with_manager(
165 manager: &SaTokenManager,
166 token: &TokenValue,
167 ) -> SaTokenResult<()> {
168 manager.logout(token).await
169 }
170
171 pub async fn kick_out(login_id: impl LoginId) -> SaTokenResult<()> {
173 Self::get_manager().kick_out(&login_id.to_login_id()).await
174 }
175
176 pub async fn kick_out_with_manager(
177 manager: &SaTokenManager,
178 login_id: &str,
179 ) -> SaTokenResult<()> {
180 manager.kick_out(login_id).await
181 }
182
183 pub async fn logout_by_login_id(login_id: impl LoginId) -> SaTokenResult<()> {
185 Self::get_manager().logout_by_login_id(&login_id.to_login_id()).await
186 }
187
188 pub async fn logout_by_token(token: &TokenValue) -> SaTokenResult<()> {
190 Self::logout(token).await
191 }
192
193 pub fn get_token_value() -> SaTokenResult<TokenValue> {
203 let ctx = SaTokenContext::get_current()
204 .ok_or(SaTokenError::NotLogin)?;
205 ctx.token.ok_or(SaTokenError::NotLogin)
206 }
207
208 pub async fn logout_current() -> SaTokenResult<()> {
216 let token = Self::get_token_value()?;
217 tracing::debug!("成功获取 token: {}", token);
218
219 let result = Self::logout(&token).await;
220 match &result {
221 Ok(_) => tracing::debug!("logout_current 执行成功,token: {}", token),
222 Err(e) => tracing::debug!("logout_current 执行失败,token: {}, 错误: {}", token, e),
223 }
224 result
225 }
226
227 pub fn is_login_current() -> bool {
237 if let Ok(_token) = Self::get_token_value() {
238 true
241 } else {
242 false
243 }
244 }
245
246 pub fn check_login_current() -> SaTokenResult<()> {
254 Self::get_token_value()?;
255 Ok(())
256 }
257
258 pub async fn get_login_id_as_string() -> SaTokenResult<String> {
266 let token = Self::get_token_value()?;
267 Self::get_login_id(&token).await
268 }
269
270 pub async fn get_login_id_as_long() -> SaTokenResult<i64> {
278 let login_id_str = Self::get_login_id_as_string().await?;
279 login_id_str.parse::<i64>()
280 .map_err(|_| SaTokenError::LoginIdNotNumber)
281 }
282
283 pub fn get_token_info_current() -> SaTokenResult<Arc<TokenInfo>> {
292 let ctx = SaTokenContext::get_current()
293 .ok_or(SaTokenError::NotLogin)?;
294 ctx.token_info.ok_or(SaTokenError::NotLogin)
295 }
296
297 pub async fn is_login(token: &TokenValue) -> bool {
301 Self::get_manager().is_valid(token).await
302 }
303
304 pub async fn is_login_by_login_id(login_id: impl LoginId) -> bool {
312 match Self::get_token_by_login_id(login_id).await {
313 Ok(token) => Self::is_login(&token).await,
314 Err(_) => false,
315 }
316 }
317
318 pub async fn is_login_with_manager(
319 manager: &SaTokenManager,
320 token: &TokenValue,
321 ) -> bool {
322 manager.is_valid(token).await
323 }
324
325 pub async fn check_login(token: &TokenValue) -> SaTokenResult<()> {
327 if !Self::is_login(token).await {
328 return Err(SaTokenError::NotLogin);
329 }
330 Ok(())
331 }
332
333 pub async fn get_token_info(token: &TokenValue) -> SaTokenResult<TokenInfo> {
335 Self::get_manager().get_token_info(token).await
336 }
337
338 pub async fn get_login_id(token: &TokenValue) -> SaTokenResult<String> {
340 let token_info = Self::get_manager().get_token_info(token).await?;
341 Ok(token_info.login_id)
342 }
343
344 pub async fn get_login_id_or_default(
346 token: &TokenValue,
347 default: impl Into<String>,
348 ) -> String {
349 Self::get_login_id(token)
350 .await
351 .unwrap_or_else(|_| default.into())
352 }
353
354 pub async fn get_token_by_login_id(login_id: impl LoginId) -> SaTokenResult<TokenValue> {
362 let manager = Self::get_manager();
363 let login_id_str = login_id.to_login_id();
364
365 let key = format!("sa:login:token:{}", login_id_str);
367 match manager.storage.get(&key).await {
368 Ok(Some(token_str)) => Ok(TokenValue::new(token_str)),
369 Ok(None) => Err(SaTokenError::NotLogin),
370 Err(e) => Err(SaTokenError::StorageError(e.to_string())),
371 }
372 }
373
374 pub async fn get_all_tokens_by_login_id(login_id: impl LoginId) -> SaTokenResult<Vec<TokenValue>> {
381 let manager = Self::get_manager();
382 let login_id_str = login_id.to_login_id();
383
384 let key = format!("sa:login:tokens:{}", login_id_str);
386 match manager.storage.get(&key).await {
387 Ok(Some(tokens_str)) => {
388 let token_strings: Vec<String> = serde_json::from_str(&tokens_str)
389 .map_err(|e| SaTokenError::SerializationError(e))?;
390 Ok(token_strings.into_iter().map(TokenValue::new).collect())
391 }
392 Ok(None) => Ok(Vec::new()),
393 Err(e) => Err(SaTokenError::StorageError(e.to_string())),
394 }
395 }
396
397 pub async fn get_session(login_id: impl LoginId) -> SaTokenResult<SaSession> {
401 Self::get_manager().get_session(&login_id.to_login_id()).await
402 }
403
404 pub async fn save_session(session: &SaSession) -> SaTokenResult<()> {
406 Self::get_manager().save_session(session).await
407 }
408
409 pub async fn delete_session(login_id: impl LoginId) -> SaTokenResult<()> {
411 Self::get_manager().delete_session(&login_id.to_login_id()).await
412 }
413
414 pub async fn set_session_value<T: serde::Serialize>(
416 login_id: impl LoginId,
417 key: &str,
418 value: T,
419 ) -> SaTokenResult<()> {
420 let manager = Self::get_manager();
421 let login_id_str = login_id.to_login_id();
422 let mut session = manager.get_session(&login_id_str).await?;
423 session.set(key, value)?;
424 manager.save_session(&session).await
425 }
426
427 pub async fn get_session_value<T: serde::de::DeserializeOwned>(
429 login_id: impl LoginId,
430 key: &str,
431 ) -> SaTokenResult<Option<T>> {
432 let session = Self::get_manager().get_session(&login_id.to_login_id()).await?;
433 Ok(session.get::<T>(key))
434 }
435
436 pub fn create_token(token_value: impl Into<String>) -> TokenValue {
440 TokenValue::new(token_value.into())
441 }
442
443 pub fn is_valid_token_format(token: &str) -> bool {
445 !token.is_empty() && token.len() >= 16
446 }
447}
448
449impl StpUtil {
452 pub async fn set_permissions(
454 login_id: impl LoginId,
455 permissions: Vec<String>,
456 ) -> SaTokenResult<()> {
457 let manager = Self::get_manager();
458 let mut map = manager.user_permissions.write().await;
459 map.insert(login_id.to_login_id(), permissions);
460 Ok(())
461 }
462
463 pub async fn add_permission(
465 login_id: impl LoginId,
466 permission: impl Into<String>,
467 ) -> SaTokenResult<()> {
468 let manager = Self::get_manager();
469 let mut map = manager.user_permissions.write().await;
470 let login_id_str = login_id.to_login_id();
471 let permissions = map.entry(login_id_str).or_insert_with(Vec::new);
472 let perm = permission.into();
473 if !permissions.contains(&perm) {
474 permissions.push(perm);
475 }
476 Ok(())
477 }
478
479 pub async fn remove_permission(
481 login_id: impl LoginId,
482 permission: &str,
483 ) -> SaTokenResult<()> {
484 let manager = Self::get_manager();
485 let mut map = manager.user_permissions.write().await;
486 if let Some(permissions) = map.get_mut(&login_id.to_login_id()) {
487 permissions.retain(|p| p != permission);
488 }
489 Ok(())
490 }
491
492 pub async fn clear_permissions(login_id: impl LoginId) -> SaTokenResult<()> {
494 let manager = Self::get_manager();
495 let mut map = manager.user_permissions.write().await;
496 map.remove(&login_id.to_login_id());
497 Ok(())
498 }
499
500 pub async fn get_permissions(login_id: impl LoginId) -> Vec<String> {
502 let manager = Self::get_manager();
503 let map = manager.user_permissions.read().await;
504 map.get(&login_id.to_login_id()).cloned().unwrap_or_default()
505 }
506
507 pub async fn has_permission(
509 login_id: impl LoginId,
510 permission: &str,
511 ) -> bool {
512 let manager = Self::get_manager();
513 let map = manager.user_permissions.read().await;
514 if let Some(permissions) = map.get(&login_id.to_login_id()) {
515 if permissions.contains(&permission.to_string()) {
517 return true;
518 }
519
520 for perm in permissions {
522 if perm.ends_with(":*") {
523 let prefix = &perm[..perm.len() - 2];
524 if permission.starts_with(prefix) {
525 return true;
526 }
527 }
528 }
529 }
530 false
531 }
532
533 pub async fn has_all_permissions(
535 login_id: impl LoginId,
536 permissions: &[&str],
537 ) -> bool {
538 let login_id_str = login_id.to_login_id();
539 for permission in permissions {
540 if !Self::has_permission(&login_id_str, permission).await {
541 return false;
542 }
543 }
544 true
545 }
546
547 pub async fn has_permissions_and(
549 login_id: impl LoginId,
550 permissions: &[&str],
551 ) -> bool {
552 Self::has_all_permissions(login_id, permissions).await
553 }
554
555 pub async fn has_any_permission(
557 login_id: impl LoginId,
558 permissions: &[&str],
559 ) -> bool {
560 let login_id_str = login_id.to_login_id();
561 for permission in permissions {
562 if Self::has_permission(&login_id_str, permission).await {
563 return true;
564 }
565 }
566 false
567 }
568
569 pub async fn has_permissions_or(
571 login_id: impl LoginId,
572 permissions: &[&str],
573 ) -> bool {
574 Self::has_any_permission(login_id, permissions).await
575 }
576
577 pub async fn check_permission(
579 login_id: impl LoginId,
580 permission: &str,
581 ) -> SaTokenResult<()> {
582 if !Self::has_permission(login_id, permission).await {
583 return Err(SaTokenError::PermissionDeniedDetail(permission.to_string()));
584 }
585 Ok(())
586 }
587}
588
589impl StpUtil {
592 pub async fn set_roles(
594 login_id: impl LoginId,
595 roles: Vec<String>,
596 ) -> SaTokenResult<()> {
597 let manager = Self::get_manager();
598 let mut map = manager.user_roles.write().await;
599 map.insert(login_id.to_login_id(), roles);
600 Ok(())
601 }
602
603 pub async fn add_role(
605 login_id: impl LoginId,
606 role: impl Into<String>,
607 ) -> SaTokenResult<()> {
608 let manager = Self::get_manager();
609 let mut map = manager.user_roles.write().await;
610 let login_id_str = login_id.to_login_id();
611 let roles = map.entry(login_id_str).or_insert_with(Vec::new);
612 let r = role.into();
613 if !roles.contains(&r) {
614 roles.push(r);
615 }
616 Ok(())
617 }
618
619 pub async fn remove_role(
621 login_id: impl LoginId,
622 role: &str,
623 ) -> SaTokenResult<()> {
624 let manager = Self::get_manager();
625 let mut map = manager.user_roles.write().await;
626 if let Some(roles) = map.get_mut(&login_id.to_login_id()) {
627 roles.retain(|r| r != role);
628 }
629 Ok(())
630 }
631
632 pub async fn clear_roles(login_id: impl LoginId) -> SaTokenResult<()> {
634 let manager = Self::get_manager();
635 let mut map = manager.user_roles.write().await;
636 map.remove(&login_id.to_login_id());
637 Ok(())
638 }
639
640 pub async fn get_roles(login_id: impl LoginId) -> Vec<String> {
642 let manager = Self::get_manager();
643 let map = manager.user_roles.read().await;
644 map.get(&login_id.to_login_id()).cloned().unwrap_or_default()
645 }
646
647 pub async fn has_role(
649 login_id: impl LoginId,
650 role: &str,
651 ) -> bool {
652 let manager = Self::get_manager();
653 let map = manager.user_roles.read().await;
654 if let Some(roles) = map.get(&login_id.to_login_id()) {
655 roles.contains(&role.to_string())
656 } else {
657 false
658 }
659 }
660
661 pub async fn has_all_roles(
663 login_id: impl LoginId,
664 roles: &[&str],
665 ) -> bool {
666 let login_id_str = login_id.to_login_id();
667 for role in roles {
668 if !Self::has_role(&login_id_str, role).await {
669 return false;
670 }
671 }
672 true
673 }
674
675 pub async fn has_roles_and(
677 login_id: impl LoginId,
678 roles: &[&str],
679 ) -> bool {
680 Self::has_all_roles(login_id, roles).await
681 }
682
683 pub async fn has_any_role(
685 login_id: impl LoginId,
686 roles: &[&str],
687 ) -> bool {
688 let login_id_str = login_id.to_login_id();
689 for role in roles {
690 if Self::has_role(&login_id_str, role).await {
691 return true;
692 }
693 }
694 false
695 }
696
697 pub async fn has_roles_or(
699 login_id: impl LoginId,
700 roles: &[&str],
701 ) -> bool {
702 Self::has_any_role(login_id, roles).await
703 }
704
705 pub async fn check_role(
707 login_id: impl LoginId,
708 role: &str,
709 ) -> SaTokenResult<()> {
710 if !Self::has_role(login_id, role).await {
711 return Err(SaTokenError::RoleDenied(role.to_string()));
712 }
713 Ok(())
714 }
715}
716
717impl StpUtil {
720 pub async fn kick_out_batch<T: LoginId>(
722 login_ids: &[T],
723 ) -> SaTokenResult<Vec<Result<(), SaTokenError>>> {
724 let manager = Self::get_manager();
725 let mut results = Vec::new();
726 for login_id in login_ids {
727 results.push(manager.kick_out(&login_id.to_login_id()).await);
728 }
729 Ok(results)
730 }
731
732 pub async fn get_token_timeout(token: &TokenValue) -> SaTokenResult<Option<i64>> {
734 let manager = Self::get_manager();
735 let token_info = manager.get_token_info(token).await?;
736
737 if let Some(expire_time) = token_info.expire_time {
738 let now = chrono::Utc::now();
739 let duration = expire_time.signed_duration_since(now);
740 Ok(Some(duration.num_seconds()))
741 } else {
742 Ok(None) }
744 }
745
746 pub async fn renew_timeout(
748 token: &TokenValue,
749 timeout_seconds: i64,
750 ) -> SaTokenResult<()> {
751 let manager = Self::get_manager();
752 let mut token_info = manager.get_token_info(token).await?;
753
754 let new_expire_time = chrono::Utc::now() + chrono::Duration::seconds(timeout_seconds);
756 token_info.expire_time = Some(new_expire_time);
757
758 let key = format!("sa:token:{}", token.as_str());
760 let value = serde_json::to_string(&token_info)
761 .map_err(|e| SaTokenError::SerializationError(e))?;
762
763 let timeout = std::time::Duration::from_secs(timeout_seconds as u64);
764 manager.storage.set(&key, &value, Some(timeout)).await
765 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
766
767 Ok(())
768 }
769
770 pub async fn set_extra_data(
778 token: &TokenValue,
779 extra_data: serde_json::Value,
780 ) -> SaTokenResult<()> {
781 let manager = Self::get_manager();
782 let mut token_info = manager.get_token_info(token).await?;
783 token_info.extra_data = Some(extra_data);
784
785 let key = format!("sa:token:{}", token.as_str());
786 let value = serde_json::to_string(&token_info)
787 .map_err(|e| SaTokenError::SerializationError(e))?;
788
789 manager.storage.set(&key, &value, manager.config.timeout_duration()).await
790 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
791
792 Ok(())
793 }
794
795 pub async fn get_extra_data(token: &TokenValue) -> SaTokenResult<Option<serde_json::Value>> {
800 let manager = Self::get_manager();
801 let token_info = manager.get_token_info(token).await?;
802 Ok(token_info.extra_data)
803 }
804
805 pub fn builder(login_id: impl LoginId) -> TokenBuilder {
822 TokenBuilder::new(login_id.to_login_id())
823 }
824}
825
826pub struct TokenBuilder {
828 login_id: String,
829 extra_data: Option<serde_json::Value>,
830 device: Option<String>,
831 login_type: Option<String>,
832}
833
834impl TokenBuilder {
835 pub fn new(login_id: String) -> Self {
837 Self {
838 login_id,
839 extra_data: None,
840 device: None,
841 login_type: None,
842 }
843 }
844
845 pub fn extra_data(mut self, data: serde_json::Value) -> Self {
847 self.extra_data = Some(data);
848 self
849 }
850
851 pub fn device(mut self, device: impl Into<String>) -> Self {
853 self.device = Some(device.into());
854 self
855 }
856
857 pub fn login_type(mut self, login_type: impl Into<String>) -> Self {
859 self.login_type = Some(login_type.into());
860 self
861 }
862
863 pub async fn login<T: LoginId>(self, login_id: Option<T>) -> SaTokenResult<TokenValue> {
867 let manager = StpUtil::get_manager();
868
869 let final_login_id = match login_id {
871 Some(id) => id.to_login_id(),
872 None => self.login_id,
873 };
874 let token = manager.login(final_login_id).await?;
875
876 let mut token_info = manager.get_token_info(&token).await?;
878
879 if let Some(data) = self.extra_data {
881 token_info.extra_data = Some(data);
882 }
883
884 if let Some(device) = self.device {
885 token_info.device = Some(device);
886 }
887
888 if let Some(login_type) = self.login_type {
889 token_info.login_type = login_type;
890 }
891
892 let key = format!("sa:token:{}", token.as_str());
894 let value = serde_json::to_string(&token_info)
895 .map_err(|e| SaTokenError::SerializationError(e))?;
896
897 manager.storage.set(&key, &value, manager.config.timeout_duration()).await
898 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
899
900 Ok(token)
901 }
902}
903
904#[cfg(test)]
905mod tests {
906 use super::*;
907
908 #[test]
909 fn test_token_format_validation() {
910 assert!(StpUtil::is_valid_token_format("1234567890abcdef"));
911 assert!(!StpUtil::is_valid_token_format(""));
912 assert!(!StpUtil::is_valid_token_format("short"));
913 }
914
915 #[test]
916 fn test_create_token() {
917 let token = StpUtil::create_token("test-token-123");
918 assert_eq!(token.as_str(), "test-token-123");
919 }
920}