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 Self::get_manager().login_with_options(
141 login_id.to_login_id(),
142 None, None, Some(extra_data),
145 None, None, ).await
148 }
149
150 pub async fn login_with_manager(
152 manager: &SaTokenManager,
153 login_id: impl Into<String>,
154 ) -> SaTokenResult<TokenValue> {
155 manager.login(login_id).await
156 }
157
158 pub async fn logout(token: &TokenValue) -> SaTokenResult<()> {
160 tracing::debug!("开始执行 logout,token: {}", token);
161 let result = Self::get_manager().logout(token).await;
162 match &result {
163 Ok(_) => tracing::debug!("logout 执行成功,token: {}", token),
164 Err(e) => tracing::debug!("logout 执行失败,token: {}, 错误: {}", token, e),
165 }
166 result
167 }
168
169 pub async fn logout_with_manager(
170 manager: &SaTokenManager,
171 token: &TokenValue,
172 ) -> SaTokenResult<()> {
173 manager.logout(token).await
174 }
175
176 pub async fn kick_out(login_id: impl LoginId) -> SaTokenResult<()> {
178 Self::get_manager().kick_out(&login_id.to_login_id()).await
179 }
180
181 pub async fn kick_out_with_manager(
182 manager: &SaTokenManager,
183 login_id: &str,
184 ) -> SaTokenResult<()> {
185 manager.kick_out(login_id).await
186 }
187
188 pub async fn logout_by_login_id(login_id: impl LoginId) -> SaTokenResult<()> {
190 Self::get_manager().logout_by_login_id(&login_id.to_login_id()).await
191 }
192
193 pub async fn logout_by_token(token: &TokenValue) -> SaTokenResult<()> {
195 Self::logout(token).await
196 }
197
198 pub fn get_token_value() -> SaTokenResult<TokenValue> {
208 let ctx = SaTokenContext::try_current().ok_or(SaTokenError::NotLogin)?;
209 ctx.token.ok_or(SaTokenError::NotLogin)
210 }
211
212 pub async fn logout_current() -> SaTokenResult<()> {
220 let token = Self::get_token_value()?;
221 tracing::debug!("成功获取 token: {}", token);
222
223 let result = Self::logout(&token).await;
224 match &result {
225 Ok(_) => tracing::debug!("logout_current 执行成功,token: {}", token),
226 Err(e) => tracing::debug!("logout_current 执行失败,token: {}, 错误: {}", token, e),
227 }
228 result
229 }
230
231 pub fn is_login_current() -> bool {
241 if let Ok(_token) = Self::get_token_value() {
242 true
245 } else {
246 false
247 }
248 }
249
250 pub fn check_login_current() -> SaTokenResult<()> {
258 Self::get_token_value()?;
259 Ok(())
260 }
261
262 pub async fn get_login_id_as_string() -> SaTokenResult<String> {
270 let token = Self::get_token_value()?;
271 Self::get_login_id(&token).await
272 }
273
274 pub async fn get_login_id_as_long() -> SaTokenResult<i64> {
282 let login_id_str = Self::get_login_id_as_string().await?;
283 login_id_str.parse::<i64>()
284 .map_err(|_| SaTokenError::LoginIdNotNumber)
285 }
286
287 pub fn get_token_info_current() -> SaTokenResult<Arc<TokenInfo>> {
296 let ctx = SaTokenContext::try_current().ok_or(SaTokenError::NotLogin)?;
297 ctx.token_info.ok_or(SaTokenError::NotLogin)
298 }
299
300 pub async fn is_login(token: &TokenValue) -> bool {
304 Self::get_manager().is_valid(token).await
305 }
306
307 pub async fn is_login_by_login_id(login_id: impl LoginId) -> bool {
315 match Self::get_token_by_login_id(login_id).await {
316 Ok(token) => Self::is_login(&token).await,
317 Err(_) => false,
318 }
319 }
320
321 pub async fn is_login_with_manager(
322 manager: &SaTokenManager,
323 token: &TokenValue,
324 ) -> bool {
325 manager.is_valid(token).await
326 }
327
328 pub async fn check_login(token: &TokenValue) -> SaTokenResult<()> {
330 if !Self::is_login(token).await {
331 return Err(SaTokenError::NotLogin);
332 }
333 Ok(())
334 }
335
336 pub async fn get_token_info(token: &TokenValue) -> SaTokenResult<TokenInfo> {
338 Self::get_manager().get_token_info(token).await
339 }
340
341 pub async fn get_login_id(token: &TokenValue) -> SaTokenResult<String> {
343 let token_info = Self::get_manager().get_token_info(token).await?;
344 Ok(token_info.login_id)
345 }
346
347 pub async fn get_login_id_or_default(
349 token: &TokenValue,
350 default: impl Into<String>,
351 ) -> String {
352 Self::get_login_id(token)
353 .await
354 .unwrap_or_else(|_| default.into())
355 }
356
357 pub async fn get_token_by_login_id(login_id: impl LoginId) -> SaTokenResult<TokenValue> {
365 let manager = Self::get_manager();
366 let login_id_str = login_id.to_login_id();
367
368 let key = format!("sa:login:token:{}", login_id_str);
370 match manager.storage.get(&key).await {
371 Ok(Some(token_str)) => Ok(TokenValue::new(token_str)),
372 Ok(None) => Err(SaTokenError::NotLogin),
373 Err(e) => Err(SaTokenError::StorageError(e.to_string())),
374 }
375 }
376
377 pub async fn get_all_tokens_by_login_id(login_id: impl LoginId) -> SaTokenResult<Vec<TokenValue>> {
384 let manager = Self::get_manager();
385 let login_id_str = login_id.to_login_id();
386
387 let key = format!("sa:login:tokens:{}", login_id_str);
389 match manager.storage.get(&key).await {
390 Ok(Some(tokens_str)) => {
391 let token_strings: Vec<String> = serde_json::from_str(&tokens_str)
392 .map_err(SaTokenError::SerializationError)?;
393 Ok(token_strings.into_iter().map(TokenValue::new).collect())
394 }
395 Ok(None) => Ok(Vec::new()),
396 Err(e) => Err(SaTokenError::StorageError(e.to_string())),
397 }
398 }
399
400 pub async fn get_session(login_id: impl LoginId) -> SaTokenResult<SaSession> {
404 Self::get_manager().get_session(&login_id.to_login_id()).await
405 }
406
407 pub async fn save_session(session: &SaSession) -> SaTokenResult<()> {
409 Self::get_manager().save_session(session).await
410 }
411
412 pub async fn delete_session(login_id: impl LoginId) -> SaTokenResult<()> {
414 Self::get_manager().delete_session(&login_id.to_login_id()).await
415 }
416
417 pub async fn set_session_value<T: serde::Serialize>(
419 login_id: impl LoginId,
420 key: &str,
421 value: T,
422 ) -> SaTokenResult<()> {
423 let manager = Self::get_manager();
424 let login_id_str = login_id.to_login_id();
425 let mut session = manager.get_session(&login_id_str).await?;
426 session.set(key, value)?;
427 manager.save_session(&session).await
428 }
429
430 pub async fn get_session_value<T: serde::de::DeserializeOwned>(
432 login_id: impl LoginId,
433 key: &str,
434 ) -> SaTokenResult<Option<T>> {
435 let session = Self::get_manager().get_session(&login_id.to_login_id()).await?;
436 Ok(session.get::<T>(key))
437 }
438
439 pub fn create_token(token_value: impl Into<String>) -> TokenValue {
443 TokenValue::new(token_value.into())
444 }
445
446 pub fn is_valid_token_format(token: &str) -> bool {
448 !token.is_empty() && token.len() >= 16
449 }
450}
451
452impl StpUtil {
455 pub async fn set_permissions(
457 login_id: impl LoginId,
458 permissions: Vec<String>,
459 ) -> SaTokenResult<()> {
460 let manager = Self::get_manager();
461 let mut map = manager.user_permissions.write().await;
462 map.insert(login_id.to_login_id(), permissions);
463 Ok(())
464 }
465
466 pub async fn add_permission(
468 login_id: impl LoginId,
469 permission: impl Into<String>,
470 ) -> SaTokenResult<()> {
471 let manager = Self::get_manager();
472 let mut map = manager.user_permissions.write().await;
473 let login_id_str = login_id.to_login_id();
474 let permissions = map.entry(login_id_str).or_insert_with(Vec::new);
475 let perm = permission.into();
476 if !permissions.contains(&perm) {
477 permissions.push(perm);
478 }
479 Ok(())
480 }
481
482 pub async fn remove_permission(
484 login_id: impl LoginId,
485 permission: &str,
486 ) -> SaTokenResult<()> {
487 let manager = Self::get_manager();
488 let mut map = manager.user_permissions.write().await;
489 if let Some(permissions) = map.get_mut(&login_id.to_login_id()) {
490 permissions.retain(|p| p != permission);
491 }
492 Ok(())
493 }
494
495 pub async fn clear_permissions(login_id: impl LoginId) -> SaTokenResult<()> {
497 let manager = Self::get_manager();
498 let mut map = manager.user_permissions.write().await;
499 map.remove(&login_id.to_login_id());
500 Ok(())
501 }
502
503 pub async fn get_permissions(login_id: impl LoginId) -> Vec<String> {
505 let manager = Self::get_manager();
506 let map = manager.user_permissions.read().await;
507 map.get(&login_id.to_login_id()).cloned().unwrap_or_default()
508 }
509
510 pub async fn has_permission(
512 login_id: impl LoginId,
513 permission: &str,
514 ) -> bool {
515 let manager = Self::get_manager();
516 let map = manager.user_permissions.read().await;
517 if let Some(permissions) = map.get(&login_id.to_login_id()) {
518 if permissions.contains(&permission.to_string()) {
520 return true;
521 }
522
523 for perm in permissions {
525 if perm.ends_with(":*") {
526 let prefix = &perm[..perm.len() - 2];
527 if permission.starts_with(prefix) {
528 return true;
529 }
530 }
531 }
532 }
533 false
534 }
535
536 pub async fn has_all_permissions(
538 login_id: impl LoginId,
539 permissions: &[&str],
540 ) -> bool {
541 let login_id_str = login_id.to_login_id();
542 for permission in permissions {
543 if !Self::has_permission(&login_id_str, permission).await {
544 return false;
545 }
546 }
547 true
548 }
549
550 pub async fn has_permissions_and(
552 login_id: impl LoginId,
553 permissions: &[&str],
554 ) -> bool {
555 Self::has_all_permissions(login_id, permissions).await
556 }
557
558 pub async fn has_any_permission(
560 login_id: impl LoginId,
561 permissions: &[&str],
562 ) -> bool {
563 let login_id_str = login_id.to_login_id();
564 for permission in permissions {
565 if Self::has_permission(&login_id_str, permission).await {
566 return true;
567 }
568 }
569 false
570 }
571
572 pub async fn has_permissions_or(
574 login_id: impl LoginId,
575 permissions: &[&str],
576 ) -> bool {
577 Self::has_any_permission(login_id, permissions).await
578 }
579
580 pub async fn check_permission(
582 login_id: impl LoginId,
583 permission: &str,
584 ) -> SaTokenResult<()> {
585 if !Self::has_permission(login_id, permission).await {
586 return Err(SaTokenError::PermissionDeniedDetail(permission.to_string()));
587 }
588 Ok(())
589 }
590}
591
592impl StpUtil {
595 pub async fn set_roles(
597 login_id: impl LoginId,
598 roles: Vec<String>,
599 ) -> SaTokenResult<()> {
600 let manager = Self::get_manager();
601 let mut map = manager.user_roles.write().await;
602 map.insert(login_id.to_login_id(), roles);
603 Ok(())
604 }
605
606 pub async fn add_role(
608 login_id: impl LoginId,
609 role: impl Into<String>,
610 ) -> SaTokenResult<()> {
611 let manager = Self::get_manager();
612 let mut map = manager.user_roles.write().await;
613 let login_id_str = login_id.to_login_id();
614 let roles = map.entry(login_id_str).or_insert_with(Vec::new);
615 let r = role.into();
616 if !roles.contains(&r) {
617 roles.push(r);
618 }
619 Ok(())
620 }
621
622 pub async fn remove_role(
624 login_id: impl LoginId,
625 role: &str,
626 ) -> SaTokenResult<()> {
627 let manager = Self::get_manager();
628 let mut map = manager.user_roles.write().await;
629 if let Some(roles) = map.get_mut(&login_id.to_login_id()) {
630 roles.retain(|r| r != role);
631 }
632 Ok(())
633 }
634
635 pub async fn clear_roles(login_id: impl LoginId) -> SaTokenResult<()> {
637 let manager = Self::get_manager();
638 let mut map = manager.user_roles.write().await;
639 map.remove(&login_id.to_login_id());
640 Ok(())
641 }
642
643 pub async fn get_roles(login_id: impl LoginId) -> Vec<String> {
645 let manager = Self::get_manager();
646 let map = manager.user_roles.read().await;
647 map.get(&login_id.to_login_id()).cloned().unwrap_or_default()
648 }
649
650 pub async fn has_role(
652 login_id: impl LoginId,
653 role: &str,
654 ) -> bool {
655 let manager = Self::get_manager();
656 let map = manager.user_roles.read().await;
657 if let Some(roles) = map.get(&login_id.to_login_id()) {
658 roles.contains(&role.to_string())
659 } else {
660 false
661 }
662 }
663
664 pub async fn has_all_roles(
666 login_id: impl LoginId,
667 roles: &[&str],
668 ) -> bool {
669 let login_id_str = login_id.to_login_id();
670 for role in roles {
671 if !Self::has_role(&login_id_str, role).await {
672 return false;
673 }
674 }
675 true
676 }
677
678 pub async fn has_roles_and(
680 login_id: impl LoginId,
681 roles: &[&str],
682 ) -> bool {
683 Self::has_all_roles(login_id, roles).await
684 }
685
686 pub async fn has_any_role(
688 login_id: impl LoginId,
689 roles: &[&str],
690 ) -> bool {
691 let login_id_str = login_id.to_login_id();
692 for role in roles {
693 if Self::has_role(&login_id_str, role).await {
694 return true;
695 }
696 }
697 false
698 }
699
700 pub async fn has_roles_or(
702 login_id: impl LoginId,
703 roles: &[&str],
704 ) -> bool {
705 Self::has_any_role(login_id, roles).await
706 }
707
708 pub async fn check_role(
710 login_id: impl LoginId,
711 role: &str,
712 ) -> SaTokenResult<()> {
713 if !Self::has_role(login_id, role).await {
714 return Err(SaTokenError::RoleDenied(role.to_string()));
715 }
716 Ok(())
717 }
718}
719
720impl StpUtil {
723 pub async fn kick_out_batch<T: LoginId>(
725 login_ids: &[T],
726 ) -> SaTokenResult<Vec<Result<(), SaTokenError>>> {
727 let manager = Self::get_manager();
728 let mut results = Vec::new();
729 for login_id in login_ids {
730 results.push(manager.kick_out(&login_id.to_login_id()).await);
731 }
732 Ok(results)
733 }
734
735 pub async fn get_token_timeout(token: &TokenValue) -> SaTokenResult<Option<i64>> {
737 let manager = Self::get_manager();
738 let token_info = manager.get_token_info(token).await?;
739
740 if let Some(expire_time) = token_info.expire_time {
741 let now = chrono::Utc::now();
742 let duration = expire_time.signed_duration_since(now);
743 Ok(Some(duration.num_seconds()))
744 } else {
745 Ok(None) }
747 }
748
749 pub async fn renew_timeout(
751 token: &TokenValue,
752 timeout_seconds: i64,
753 ) -> SaTokenResult<()> {
754 let manager = Self::get_manager();
755 let mut token_info = manager.get_token_info(token).await?;
756
757 let new_expire_time = chrono::Utc::now() + chrono::Duration::seconds(timeout_seconds);
759 token_info.expire_time = Some(new_expire_time);
760
761 let key = format!("sa:token:{}", token.as_str());
763 let value = serde_json::to_string(&token_info)
764 .map_err(SaTokenError::SerializationError)?;
765
766 let timeout = std::time::Duration::from_secs(timeout_seconds as u64);
767 manager.storage.set(&key, &value, Some(timeout)).await
768 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
769
770 Ok(())
771 }
772
773 pub async fn set_extra_data(
781 token: &TokenValue,
782 extra_data: serde_json::Value,
783 ) -> SaTokenResult<()> {
784 let manager = Self::get_manager();
785 let mut token_info = manager.get_token_info(token).await?;
786 token_info.extra_data = Some(extra_data);
787
788 let key = format!("sa:token:{}", token.as_str());
789 let value = serde_json::to_string(&token_info)
790 .map_err(SaTokenError::SerializationError)?;
791
792 manager.storage.set(&key, &value, manager.config.timeout_duration()).await
793 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
794
795 Ok(())
796 }
797
798 pub async fn get_extra_data(token: &TokenValue) -> SaTokenResult<Option<serde_json::Value>> {
803 let manager = Self::get_manager();
804 let token_info = manager.get_token_info(token).await?;
805 Ok(token_info.extra_data)
806 }
807
808 pub fn builder(login_id: impl LoginId) -> TokenBuilder {
825 TokenBuilder::new(login_id.to_login_id())
826 }
827}
828
829pub struct TokenBuilder {
831 login_id: String,
832 extra_data: Option<serde_json::Value>,
833 device: Option<String>,
834 login_type: Option<String>,
835}
836
837impl TokenBuilder {
838 pub fn new(login_id: String) -> Self {
840 Self {
841 login_id,
842 extra_data: None,
843 device: None,
844 login_type: None,
845 }
846 }
847
848 pub fn extra_data(mut self, data: serde_json::Value) -> Self {
850 self.extra_data = Some(data);
851 self
852 }
853
854 pub fn device(mut self, device: impl Into<String>) -> Self {
856 self.device = Some(device.into());
857 self
858 }
859
860 pub fn login_type(mut self, login_type: impl Into<String>) -> Self {
862 self.login_type = Some(login_type.into());
863 self
864 }
865
866 pub async fn login<T: LoginId>(self, login_id: Option<T>) -> SaTokenResult<TokenValue> {
870 let manager = StpUtil::get_manager();
871
872 let final_login_id = match login_id {
874 Some(id) => id.to_login_id(),
875 None => self.login_id,
876 };
877 let token = manager.login(final_login_id).await?;
878
879 let mut token_info = manager.get_token_info(&token).await?;
881
882 if let Some(data) = self.extra_data {
884 token_info.extra_data = Some(data);
885 }
886
887 if let Some(device) = self.device {
888 token_info.device = Some(device);
889 }
890
891 if let Some(login_type) = self.login_type {
892 token_info.login_type = login_type;
893 }
894
895 let key = format!("sa:token:{}", token.as_str());
897 let value = serde_json::to_string(&token_info)
898 .map_err(SaTokenError::SerializationError)?;
899
900 manager.storage.set(&key, &value, manager.config.timeout_duration()).await
901 .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
902
903 Ok(token)
904 }
905}
906
907#[cfg(test)]
908mod tests {
909 use super::*;
910
911 #[test]
912 fn test_token_format_validation() {
913 assert!(StpUtil::is_valid_token_format("1234567890abcdef"));
914 assert!(!StpUtil::is_valid_token_format(""));
915 assert!(!StpUtil::is_valid_token_format("short"));
916 }
917
918 #[test]
919 fn test_create_token() {
920 let token = StpUtil::create_token("test-token-123");
921 assert_eq!(token.as_str(), "test-token-123");
922 }
923}