sa_token_core/
distributed.rs

1//! Distributed Session Management Module | 分布式 Session 管理模块
2//!
3//! # Code Flow Logic | 代码流程逻辑
4//!
5//! ## English
6//! 
7//! ### Overview
8//! This module provides distributed session management for microservices architecture.
9//! It enables session sharing across multiple services with service authentication,
10//! session attributes management, and automatic timeout handling.
11//! 
12//! ### Service Registration Flow
13//! ```text
14//! 1. Create ServiceCredential
15//!    ├─→ service_id: Unique service identifier
16//!    ├─→ service_name: Human-readable name
17//!    ├─→ secret_key: Service authentication secret
18//!    ├─→ permissions: List of permissions
19//!    └─→ created_at: Registration timestamp
20//!    ↓
21//! 2. DistributedSessionManager.register_service(credential)
22//!    └─→ Store in service_credentials HashMap
23//!    ↓
24//! 3. Service Registered Successfully
25//! ```
26//! 
27//! ### Service Authentication Flow
28//! ```text
29//! 1. Service Requests Access
30//!    ├─→ Provide service_id
31//!    └─→ Provide secret_key
32//!    ↓
33//! 2. DistributedSessionManager.verify_service(service_id, secret)
34//!    ├─→ Look up service in credentials map
35//!    ├─→ Compare secret_key
36//!    └─→ Return ServiceCredential if valid
37//!    ↓
38//! 3. Authentication Result
39//!    ├─→ Success: Return ServiceCredential
40//!    └─→ Failure: Return PermissionDenied error
41//! ```
42//! 
43//! ### Session Creation Flow
44//! ```text
45//! 1. User Logs In on Any Service
46//!    ↓
47//! 2. create_session(login_id, token)
48//!    ├─→ Generate unique session_id (UUID)
49//!    ├─→ Record service_id (which service created it)
50//!    ├─→ Set timestamps (create_time, last_access)
51//!    └─→ Initialize empty attributes HashMap
52//!    ↓
53//! 3. Save to Distributed Storage
54//!    ├─→ storage.save_session(session, ttl)
55//!    └─→ TTL: session_timeout duration
56//!    ↓
57//! 4. Return DistributedSession
58//! ```
59//! 
60//! ### Cross-Service Session Access Flow
61//! ```text
62//! 1. Service A Creates Session
63//!    session_id: "uuid-123"
64//!    service_id: "service-a"
65//!    login_id: "user123"
66//!    ↓
67//! 2. Service B Accesses Session
68//!    get_session("uuid-123")
69//!    ↓
70//! 3. Retrieve from Distributed Storage
71//!    ├─→ storage.get_session(session_id)
72//!    └─→ Returns full session data
73//!    ↓
74//! 4. Service B Reads/Modifies Session
75//!    ├─→ Access attributes
76//!    ├─→ Update last_access time
77//!    └─→ Save back to storage
78//! ```
79//! 
80//! ### Session Attributes Flow
81//! ```text
82//! 1. set_attribute(session_id, key, value)
83//!    ├─→ Get current session
84//!    ├─→ session.attributes.insert(key, value)
85//!    ├─→ Update last_access timestamp
86//!    └─→ Save updated session
87//!    ↓
88//! 2. get_attribute(session_id, key)
89//!    ├─→ Get session from storage
90//!    └─→ Return attributes.get(key)
91//!    ↓
92//! 3. remove_attribute(session_id, key)
93//!    ├─→ Get current session
94//!    ├─→ session.attributes.remove(key)
95//!    └─→ Save updated session
96//! ```
97//! 
98//! ### Session Cleanup Flow
99//! ```text
100//! 1. delete_session(session_id)
101//!    └─→ storage.delete_session(session_id)
102//!    ↓
103//! 2. delete_all_sessions(login_id)
104//!    ├─→ get_sessions_by_login_id(login_id)
105//!    └─→ For each session: delete_session(id)
106//!    ↓
107//! 3. Automatic Cleanup (TTL-based)
108//!    └─→ Storage backend expires sessions after timeout
109//! ```
110//! 
111//! ### Multi-Session Management
112//! ```text
113//! One user can have multiple sessions:
114//! 
115//! user123:
116//!   ├─→ Session 1 (created by service-a, web device)
117//!   ├─→ Session 2 (created by service-b, mobile device)
118//!   └─→ Session 3 (created by service-c, desktop app)
119//! 
120//! All sessions share the same login_id but have unique session_ids
121//! Each service can access any session via distributed storage
122//! ```
123//!
124//! ## 中文
125//! 
126//! ### 概述
127//! 本模块为微服务架构提供分布式 Session 管理。
128//! 它支持多个服务之间的 Session 共享,包括服务认证、Session 属性管理和自动超时处理。
129//! 
130//! ### 服务注册流程
131//! ```text
132//! 1. 创建 ServiceCredential
133//!    ├─→ service_id: 唯一服务标识符
134//!    ├─→ service_name: 可读服务名称
135//!    ├─→ secret_key: 服务认证密钥
136//!    ├─→ permissions: 权限列表
137//!    └─→ created_at: 注册时间戳
138//!    ↓
139//! 2. DistributedSessionManager.register_service(credential)
140//!    └─→ 存储到 service_credentials HashMap
141//!    ↓
142//! 3. 服务注册成功
143//! ```
144//! 
145//! ### 服务认证流程
146//! ```text
147//! 1. 服务请求访问
148//!    ├─→ 提供 service_id
149//!    └─→ 提供 secret_key
150//!    ↓
151//! 2. DistributedSessionManager.verify_service(service_id, secret)
152//!    ├─→ 在凭证映射中查找服务
153//!    ├─→ 比较 secret_key
154//!    └─→ 如果有效则返回 ServiceCredential
155//!    ↓
156//! 3. 认证结果
157//!    ├─→ 成功: 返回 ServiceCredential
158//!    └─→ 失败: 返回 PermissionDenied 错误
159//! ```
160//! 
161//! ### Session 创建流程
162//! ```text
163//! 1. 用户在任意服务上登录
164//!    ↓
165//! 2. create_session(login_id, token)
166//!    ├─→ 生成唯一 session_id (UUID)
167//!    ├─→ 记录 service_id (创建它的服务)
168//!    ├─→ 设置时间戳 (create_time, last_access)
169//!    └─→ 初始化空的 attributes HashMap
170//!    ↓
171//! 3. 保存到分布式存储
172//!    ├─→ storage.save_session(session, ttl)
173//!    └─→ TTL: session_timeout 持续时间
174//!    ↓
175//! 4. 返回 DistributedSession
176//! ```
177//! 
178//! ### 跨服务 Session 访问流程
179//! ```text
180//! 1. 服务 A 创建 Session
181//!    session_id: "uuid-123"
182//!    service_id: "service-a"
183//!    login_id: "user123"
184//!    ↓
185//! 2. 服务 B 访问 Session
186//!    get_session("uuid-123")
187//!    ↓
188//! 3. 从分布式存储获取
189//!    ├─→ storage.get_session(session_id)
190//!    └─→ 返回完整 session 数据
191//!    ↓
192//! 4. 服务 B 读取/修改 Session
193//!    ├─→ 访问属性
194//!    ├─→ 更新 last_access 时间
195//!    └─→ 保存回存储
196//! ```
197//! 
198//! ### Session 属性流程
199//! ```text
200//! 1. set_attribute(session_id, key, value)
201//!    ├─→ 获取当前 session
202//!    ├─→ session.attributes.insert(key, value)
203//!    ├─→ 更新 last_access 时间戳
204//!    └─→ 保存更新后的 session
205//!    ↓
206//! 2. get_attribute(session_id, key)
207//!    ├─→ 从存储获取 session
208//!    └─→ 返回 attributes.get(key)
209//!    ↓
210//! 3. remove_attribute(session_id, key)
211//!    ├─→ 获取当前 session
212//!    ├─→ session.attributes.remove(key)
213//!    └─→ 保存更新后的 session
214//! ```
215//! 
216//! ### Session 清理流程
217//! ```text
218//! 1. delete_session(session_id)
219//!    └─→ storage.delete_session(session_id)
220//!    ↓
221//! 2. delete_all_sessions(login_id)
222//!    ├─→ get_sessions_by_login_id(login_id)
223//!    └─→ 对每个 session: delete_session(id)
224//!    ↓
225//! 3. 自动清理 (基于 TTL)
226//!    └─→ 存储后端在超时后自动过期 sessions
227//! ```
228//! 
229//! ### 多 Session 管理
230//! ```text
231//! 一个用户可以有多个 sessions:
232//! 
233//! user123:
234//!   ├─→ Session 1 (service-a 创建, web 设备)
235//!   ├─→ Session 2 (service-b 创建, 移动设备)
236//!   └─→ Session 3 (service-c 创建, 桌面应用)
237//! 
238//! 所有 sessions 共享相同的 login_id 但有唯一的 session_ids
239//! 每个服务都可以通过分布式存储访问任何 session
240//! ```
241
242use crate::error::SaTokenError;
243use async_trait::async_trait;
244use serde::{Deserialize, Serialize};
245use std::collections::HashMap;
246use std::sync::Arc;
247use std::time::Duration;
248use chrono::{DateTime, Utc};
249use tokio::sync::RwLock;
250
251/// Distributed session data structure
252/// 分布式 Session 数据结构
253///
254/// Represents a session that can be shared across multiple services
255/// 表示可以在多个服务之间共享的 Session
256#[derive(Debug, Clone, Serialize, Deserialize)]
257pub struct DistributedSession {
258    /// Unique session identifier | 唯一 Session 标识符
259    pub session_id: String,
260    
261    /// User login ID | 用户登录 ID
262    pub login_id: String,
263    
264    /// Authentication token | 认证 Token
265    pub token: String,
266    
267    /// ID of the service that created this session | 创建此 Session 的服务 ID
268    pub service_id: String,
269    
270    /// Session creation time | Session 创建时间
271    pub create_time: DateTime<Utc>,
272    
273    /// Last access time | 最后访问时间
274    pub last_access: DateTime<Utc>,
275    
276    /// Session attributes (key-value pairs) | Session 属性(键值对)
277    pub attributes: HashMap<String, String>,
278}
279
280/// Service credential for inter-service authentication
281/// 服务间认证的服务凭证
282///
283/// Contains service identification and permission information
284/// 包含服务标识和权限信息
285#[derive(Debug, Clone, Serialize, Deserialize)]
286pub struct ServiceCredential {
287    /// Unique service identifier | 唯一服务标识符
288    pub service_id: String,
289    
290    /// Human-readable service name | 可读的服务名称
291    pub service_name: String,
292    
293    /// Service authentication secret key | 服务认证密钥
294    pub secret_key: String,
295    
296    /// Service registration time | 服务注册时间
297    pub created_at: DateTime<Utc>,
298    
299    /// List of permissions this service has | 该服务拥有的权限列表
300    pub permissions: Vec<String>,
301}
302
303/// Distributed session storage trait
304/// 分布式 Session 存储 trait
305///
306/// Implement this trait to provide custom storage backends
307/// 实现此 trait 以提供自定义存储后端
308#[async_trait]
309pub trait DistributedSessionStorage: Send + Sync {
310    /// Save a session to storage with optional TTL
311    /// 保存 Session 到存储,可选 TTL
312    ///
313    /// # Arguments | 参数
314    /// * `session` - Session to save | 要保存的 Session
315    /// * `ttl` - Time-to-live duration | 生存时间
316    async fn save_session(&self, session: DistributedSession, ttl: Option<Duration>) -> Result<(), SaTokenError>;
317    
318    /// Get a session from storage
319    /// 从存储获取 Session
320    ///
321    /// # Arguments | 参数
322    /// * `session_id` - Session identifier | Session 标识符
323    async fn get_session(&self, session_id: &str) -> Result<Option<DistributedSession>, SaTokenError>;
324    
325    /// Delete a session from storage
326    /// 从存储删除 Session
327    ///
328    /// # Arguments | 参数
329    /// * `session_id` - Session identifier | Session 标识符
330    async fn delete_session(&self, session_id: &str) -> Result<(), SaTokenError>;
331    
332    /// Get all sessions for a specific user
333    /// 获取特定用户的所有 Sessions
334    ///
335    /// # Arguments | 参数
336    /// * `login_id` - User login ID | 用户登录 ID
337    async fn get_sessions_by_login_id(&self, login_id: &str) -> Result<Vec<DistributedSession>, SaTokenError>;
338}
339
340/// Distributed session manager
341/// 分布式 Session 管理器
342///
343/// Manages distributed sessions and service authentication
344/// 管理分布式 Sessions 和服务认证
345pub struct DistributedSessionManager {
346    /// Session storage backend | Session 存储后端
347    storage: Arc<dyn DistributedSessionStorage>,
348    
349    /// Current service ID | 当前服务 ID
350    service_id: String,
351    
352    /// Default session timeout | 默认 Session 超时时间
353    session_timeout: Duration,
354    
355    /// Registered service credentials | 已注册的服务凭证
356    service_credentials: Arc<RwLock<HashMap<String, ServiceCredential>>>,
357}
358
359impl DistributedSessionManager {
360    /// Create a new distributed session manager
361    /// 创建新的分布式 Session 管理器
362    ///
363    /// # Arguments | 参数
364    /// * `storage` - Session storage implementation | Session 存储实现
365    /// * `service_id` - ID of this service | 此服务的 ID
366    /// * `session_timeout` - Default session timeout | 默认 Session 超时时间
367    ///
368    /// # Example | 示例
369    /// ```rust,ignore
370    /// let storage = Arc::new(MyDistributedStorage::new());
371    /// let manager = DistributedSessionManager::new(
372    ///     storage,
373    ///     "my-service".to_string(),
374    ///     Duration::from_secs(3600),
375    /// );
376    /// ```
377    pub fn new(
378        storage: Arc<dyn DistributedSessionStorage>,
379        service_id: String,
380        session_timeout: Duration,
381    ) -> Self {
382        Self {
383            storage,
384            service_id,
385            session_timeout,
386            service_credentials: Arc::new(RwLock::new(HashMap::new())),
387        }
388    }
389
390    /// Register a service for inter-service authentication
391    /// 注册服务以进行服务间认证
392    ///
393    /// # Arguments | 参数
394    /// * `credential` - Service credential information | 服务凭证信息
395    ///
396    /// # Example | 示例
397    /// ```rust,ignore
398    /// let credential = ServiceCredential {
399    ///     service_id: "api-gateway".to_string(),
400    ///     service_name: "API Gateway".to_string(),
401    ///     secret_key: "secret123".to_string(),
402    ///     created_at: Utc::now(),
403    ///     permissions: vec!["read".to_string(), "write".to_string()],
404    /// };
405    /// manager.register_service(credential).await;
406    /// ```
407    pub async fn register_service(&self, credential: ServiceCredential) {
408        let mut credentials = self.service_credentials.write().await;
409        credentials.insert(credential.service_id.clone(), credential);
410    }
411
412    /// Verify a service's credentials
413    /// 验证服务的凭证
414    ///
415    /// # Arguments | 参数
416    /// * `service_id` - Service identifier | 服务标识符
417    /// * `secret` - Service secret key | 服务密钥
418    ///
419    /// # Returns | 返回值
420    /// * `Ok(ServiceCredential)` - Service authenticated | 服务已认证
421    /// * `Err(PermissionDenied)` - Invalid credentials | 凭证无效
422    ///
423    /// # Example | 示例
424    /// ```rust,ignore
425    /// match manager.verify_service("api-gateway", "secret123").await {
426    ///     Ok(cred) => println!("Service {} verified", cred.service_name),
427    ///     Err(e) => println!("Verification failed: {}", e),
428    /// }
429    /// ```
430    pub async fn verify_service(&self, service_id: &str, secret: &str) -> Result<ServiceCredential, SaTokenError> {
431        let credentials = self.service_credentials.read().await;
432        if let Some(cred) = credentials.get(service_id) {
433            if cred.secret_key == secret {
434                return Ok(cred.clone());
435            }
436        }
437        Err(SaTokenError::PermissionDenied)
438    }
439
440    /// Create a new distributed session
441    /// 创建新的分布式 Session
442    ///
443    /// # Arguments | 参数
444    /// * `login_id` - User login ID | 用户登录 ID
445    /// * `token` - Authentication token | 认证 Token
446    ///
447    /// # Returns | 返回值
448    /// * `Ok(DistributedSession)` - Session created | Session 已创建
449    /// * `Err(SaTokenError)` - Creation failed | 创建失败
450    ///
451    /// # Example | 示例
452    /// ```rust,ignore
453    /// let session = manager.create_session(
454    ///     "user123".to_string(),
455    ///     "token456".to_string(),
456    /// ).await?;
457    /// println!("Session created: {}", session.session_id);
458    /// ```
459    pub async fn create_session(
460        &self,
461        login_id: String,
462        token: String,
463    ) -> Result<DistributedSession, SaTokenError> {
464        let session = DistributedSession {
465            session_id: uuid::Uuid::new_v4().to_string(),
466            login_id,
467            token,
468            service_id: self.service_id.clone(),
469            create_time: Utc::now(),
470            last_access: Utc::now(),
471            attributes: HashMap::new(),
472        };
473
474        self.storage.save_session(session.clone(), Some(self.session_timeout)).await?;
475        Ok(session)
476    }
477
478    /// Get a session by ID
479    /// 通过 ID 获取 Session
480    ///
481    /// # Arguments | 参数
482    /// * `session_id` - Session identifier | Session 标识符
483    ///
484    /// # Returns | 返回值
485    /// * `Ok(DistributedSession)` - Session found | 找到 Session
486    /// * `Err(SessionNotFound)` - Session not found | 未找到 Session
487    ///
488    /// # Example | 示例
489    /// ```rust,ignore
490    /// let session = manager.get_session("session-id-123").await?;
491    /// println!("User: {}", session.login_id);
492    /// ```
493    pub async fn get_session(&self, session_id: &str) -> Result<DistributedSession, SaTokenError> {
494        self.storage.get_session(session_id).await?
495            .ok_or(SaTokenError::SessionNotFound)
496    }
497
498    /// Update an existing session
499    /// 更新现有 Session
500    ///
501    /// # Arguments | 参数
502    /// * `session` - Updated session data | 更新后的 Session 数据
503    ///
504    /// # Example | 示例
505    /// ```rust,ignore
506    /// let mut session = manager.get_session("session-id").await?;
507    /// session.attributes.insert("role".to_string(), "admin".to_string());
508    /// manager.update_session(session).await?;
509    /// ```
510    pub async fn update_session(&self, session: DistributedSession) -> Result<(), SaTokenError> {
511        self.storage.save_session(session, Some(self.session_timeout)).await
512    }
513
514    /// Delete a session
515    /// 删除 Session
516    ///
517    /// # Arguments | 参数
518    /// * `session_id` - Session identifier | Session 标识符
519    ///
520    /// # Example | 示例
521    /// ```rust,ignore
522    /// manager.delete_session("session-id-123").await?;
523    /// ```
524    pub async fn delete_session(&self, session_id: &str) -> Result<(), SaTokenError> {
525        self.storage.delete_session(session_id).await
526    }
527
528    /// Refresh a session (update last access time)
529    /// 刷新 Session(更新最后访问时间)
530    ///
531    /// # Arguments | 参数
532    /// * `session_id` - Session identifier | Session 标识符
533    ///
534    /// # Example | 示例
535    /// ```rust,ignore
536    /// manager.refresh_session("session-id-123").await?;
537    /// ```
538    pub async fn refresh_session(&self, session_id: &str) -> Result<(), SaTokenError> {
539        let mut session = self.get_session(session_id).await?;
540        session.last_access = Utc::now();
541        self.update_session(session).await
542    }
543
544    /// Set a session attribute
545    /// 设置 Session 属性
546    ///
547    /// # Arguments | 参数
548    /// * `session_id` - Session identifier | Session 标识符
549    /// * `key` - Attribute key | 属性键
550    /// * `value` - Attribute value | 属性值
551    ///
552    /// # Example | 示例
553    /// ```rust,ignore
554    /// manager.set_attribute("session-id", "theme".to_string(), "dark".to_string()).await?;
555    /// ```
556    pub async fn set_attribute(
557        &self,
558        session_id: &str,
559        key: String,
560        value: String,
561    ) -> Result<(), SaTokenError> {
562        let mut session = self.get_session(session_id).await?;
563        session.attributes.insert(key, value);
564        session.last_access = Utc::now();
565        self.update_session(session).await
566    }
567
568    /// Get a session attribute
569    /// 获取 Session 属性
570    ///
571    /// # Arguments | 参数
572    /// * `session_id` - Session identifier | Session 标识符
573    /// * `key` - Attribute key | 属性键
574    ///
575    /// # Returns | 返回值
576    /// * `Some(value)` - Attribute found | 找到属性
577    /// * `None` - Attribute not found | 未找到属性
578    ///
579    /// # Example | 示例
580    /// ```rust,ignore
581    /// if let Some(theme) = manager.get_attribute("session-id", "theme").await? {
582    ///     println!("Theme: {}", theme);
583    /// }
584    /// ```
585    pub async fn get_attribute(
586        &self,
587        session_id: &str,
588        key: &str,
589    ) -> Result<Option<String>, SaTokenError> {
590        let session = self.get_session(session_id).await?;
591        Ok(session.attributes.get(key).cloned())
592    }
593
594    /// Remove a session attribute
595    /// 移除 Session 属性
596    ///
597    /// # Arguments | 参数
598    /// * `session_id` - Session identifier | Session 标识符
599    /// * `key` - Attribute key | 属性键
600    ///
601    /// # Example | 示例
602    /// ```rust,ignore
603    /// manager.remove_attribute("session-id", "temp_data").await?;
604    /// ```
605    pub async fn remove_attribute(
606        &self,
607        session_id: &str,
608        key: &str,
609    ) -> Result<(), SaTokenError> {
610        let mut session = self.get_session(session_id).await?;
611        session.attributes.remove(key);
612        session.last_access = Utc::now();
613        self.update_session(session).await
614    }
615
616    /// Get all sessions for a specific user
617    /// 获取特定用户的所有 Sessions
618    ///
619    /// # Arguments | 参数
620    /// * `login_id` - User login ID | 用户登录 ID
621    ///
622    /// # Returns | 返回值
623    /// Vector of sessions | Sessions 向量
624    ///
625    /// # Example | 示例
626    /// ```rust,ignore
627    /// let sessions = manager.get_sessions_by_login_id("user123").await?;
628    /// println!("User has {} active sessions", sessions.len());
629    /// ```
630    pub async fn get_sessions_by_login_id(&self, login_id: &str) -> Result<Vec<DistributedSession>, SaTokenError> {
631        self.storage.get_sessions_by_login_id(login_id).await
632    }
633
634    /// Delete all sessions for a specific user
635    /// 删除特定用户的所有 Sessions
636    ///
637    /// # Arguments | 参数
638    /// * `login_id` - User login ID | 用户登录 ID
639    ///
640    /// # Example | 示例
641    /// ```rust,ignore
642    /// manager.delete_all_sessions("user123").await?;
643    /// ```
644    pub async fn delete_all_sessions(&self, login_id: &str) -> Result<(), SaTokenError> {
645        let sessions = self.get_sessions_by_login_id(login_id).await?;
646        for session in sessions {
647            self.delete_session(&session.session_id).await?;
648        }
649        Ok(())
650    }
651}
652
653/// In-memory distributed session storage implementation
654/// 内存分布式 Session 存储实现
655///
656/// For testing and development purposes
657/// 用于测试和开发目的
658pub struct InMemoryDistributedStorage {
659    /// Sessions storage: session_id -> DistributedSession
660    /// Sessions 存储: session_id -> DistributedSession
661    sessions: Arc<RwLock<HashMap<String, DistributedSession>>>,
662    
663    /// Login index: login_id -> Vec<session_id>
664    /// 登录索引: login_id -> Vec<session_id>
665    login_index: Arc<RwLock<HashMap<String, Vec<String>>>>,
666}
667
668impl InMemoryDistributedStorage {
669    /// Create a new in-memory storage
670    /// 创建新的内存存储
671    pub fn new() -> Self {
672        Self {
673            sessions: Arc::new(RwLock::new(HashMap::new())),
674            login_index: Arc::new(RwLock::new(HashMap::new())),
675        }
676    }
677}
678
679impl Default for InMemoryDistributedStorage {
680    fn default() -> Self {
681        Self::new()
682    }
683}
684
685#[async_trait]
686impl DistributedSessionStorage for InMemoryDistributedStorage {
687    async fn save_session(&self, session: DistributedSession, _ttl: Option<Duration>) -> Result<(), SaTokenError> {
688        let session_id = session.session_id.clone();
689        let login_id = session.login_id.clone();
690        
691        let mut sessions = self.sessions.write().await;
692        sessions.insert(session_id.clone(), session);
693        
694        let mut index = self.login_index.write().await;
695        index.entry(login_id)
696            .or_insert_with(Vec::new)
697            .push(session_id);
698        
699        Ok(())
700    }
701
702    async fn get_session(&self, session_id: &str) -> Result<Option<DistributedSession>, SaTokenError> {
703        let sessions = self.sessions.read().await;
704        Ok(sessions.get(session_id).cloned())
705    }
706
707    async fn delete_session(&self, session_id: &str) -> Result<(), SaTokenError> {
708        let mut sessions = self.sessions.write().await;
709        if let Some(session) = sessions.remove(session_id) {
710            let mut index = self.login_index.write().await;
711            if let Some(session_ids) = index.get_mut(&session.login_id) {
712                session_ids.retain(|id| id != session_id);
713                if session_ids.is_empty() {
714                    index.remove(&session.login_id);
715                }
716            }
717        }
718        Ok(())
719    }
720
721    async fn get_sessions_by_login_id(&self, login_id: &str) -> Result<Vec<DistributedSession>, SaTokenError> {
722        let index = self.login_index.read().await;
723        let session_ids = index.get(login_id).cloned().unwrap_or_default();
724        
725        let sessions = self.sessions.read().await;
726        let mut result = Vec::new();
727        for session_id in session_ids {
728            if let Some(session) = sessions.get(&session_id) {
729                result.push(session.clone());
730            }
731        }
732        
733        Ok(result)
734    }
735}
736
737#[cfg(test)]
738mod tests {
739    use super::*;
740
741    #[tokio::test]
742    async fn test_distributed_session_manager() {
743        let storage = Arc::new(InMemoryDistributedStorage::new());
744        let manager = DistributedSessionManager::new(
745            storage,
746            "service1".to_string(),
747            Duration::from_secs(3600),
748        );
749
750        let session = manager.create_session(
751            "user1".to_string(),
752            "token1".to_string(),
753        ).await.unwrap();
754
755        let retrieved = manager.get_session(&session.session_id).await.unwrap();
756        assert_eq!(retrieved.login_id, "user1");
757    }
758
759    #[tokio::test]
760    async fn test_session_attributes() {
761        let storage = Arc::new(InMemoryDistributedStorage::new());
762        let manager = DistributedSessionManager::new(
763            storage,
764            "service1".to_string(),
765            Duration::from_secs(3600),
766        );
767
768        let session = manager.create_session(
769            "user2".to_string(),
770            "token2".to_string(),
771        ).await.unwrap();
772
773        manager.set_attribute(
774            &session.session_id,
775            "key1".to_string(),
776            "value1".to_string(),
777        ).await.unwrap();
778
779        let value = manager.get_attribute(&session.session_id, "key1").await.unwrap();
780        assert_eq!(value, Some("value1".to_string()));
781    }
782
783    #[tokio::test]
784    async fn test_service_verification() {
785        let storage = Arc::new(InMemoryDistributedStorage::new());
786        let manager = DistributedSessionManager::new(
787            storage,
788            "service1".to_string(),
789            Duration::from_secs(3600),
790        );
791
792        let credential = ServiceCredential {
793            service_id: "service2".to_string(),
794            service_name: "Service 2".to_string(),
795            secret_key: "secret123".to_string(),
796            created_at: Utc::now(),
797            permissions: vec!["read".to_string(), "write".to_string()],
798        };
799
800        manager.register_service(credential.clone()).await;
801
802        let verified = manager.verify_service("service2", "secret123").await.unwrap();
803        assert_eq!(verified.service_id, "service2");
804
805        let result = manager.verify_service("service2", "wrong_secret").await;
806        assert!(result.is_err());
807    }
808
809    #[tokio::test]
810    async fn test_delete_all_sessions() {
811        let storage = Arc::new(InMemoryDistributedStorage::new());
812        let manager = DistributedSessionManager::new(
813            storage,
814            "service1".to_string(),
815            Duration::from_secs(3600),
816        );
817
818        manager.create_session("user3".to_string(), "token1".to_string()).await.unwrap();
819        manager.create_session("user3".to_string(), "token2".to_string()).await.unwrap();
820
821        let sessions = manager.get_sessions_by_login_id("user3").await.unwrap();
822        assert_eq!(sessions.len(), 2);
823
824        manager.delete_all_sessions("user3").await.unwrap();
825
826        let sessions = manager.get_sessions_by_login_id("user3").await.unwrap();
827        assert_eq!(sessions.len(), 0);
828    }
829}