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 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 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 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 pub async fn logout_by_token(token: &TokenValue) -> SaTokenResult<()> {
184 Self::logout(token).await
185 }
186
187 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 pub async fn logout_current() -> SaTokenResult<()> {
210 let token = Self::get_token_value()?;
211 Self::logout(&token).await
212 }
213
214 pub fn is_login_current() -> bool {
224 if let Ok(_token) = Self::get_token_value() {
225 true
228 } else {
229 false
230 }
231 }
232
233 pub fn check_login_current() -> SaTokenResult<()> {
241 Self::get_token_value()?;
242 Ok(())
243 }
244
245 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 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 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 pub async fn is_login(token: &TokenValue) -> bool {
288 Self::get_manager().is_valid(token).await
289 }
290
291 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 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 pub async fn get_token_info(token: &TokenValue) -> SaTokenResult<TokenInfo> {
322 Self::get_manager().get_token_info(token).await
323 }
324
325 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 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 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 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 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 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 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 pub async fn save_session(session: &SaSession) -> SaTokenResult<()> {
393 Self::get_manager().save_session(session).await
394 }
395
396 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 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 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 pub fn create_token(token_value: impl Into<String>) -> TokenValue {
427 TokenValue::new(token_value.into())
428 }
429
430 pub fn is_valid_token_format(token: &str) -> bool {
432 !token.is_empty() && token.len() >= 16
433 }
434}
435
436impl StpUtil {
439 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 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 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 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 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 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 if permissions.contains(&permission.to_string()) {
504 return true;
505 }
506
507 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 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 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 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 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 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
576impl StpUtil {
579 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 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 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 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 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 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 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 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 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 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 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
704impl StpUtil {
707 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 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) }
731 }
732
733 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 let new_expire_time = chrono::Utc::now() + chrono::Duration::seconds(timeout_seconds);
743 token_info.expire_time = Some(new_expire_time);
744
745 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 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 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 pub fn builder(login_id: impl LoginId) -> TokenBuilder {
809 TokenBuilder::new(login_id.to_login_id())
810 }
811}
812
813pub 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 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 pub fn extra_data(mut self, data: serde_json::Value) -> Self {
834 self.extra_data = Some(data);
835 self
836 }
837
838 pub fn device(mut self, device: impl Into<String>) -> Self {
840 self.device = Some(device.into());
841 self
842 }
843
844 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 pub async fn login<T: LoginId>(self, login_id: Option<T>) -> SaTokenResult<TokenValue> {
854 let manager = StpUtil::get_manager();
855
856 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 let mut token_info = manager.get_token_info(&token).await?;
865
866 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 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}