torii_core/session/provider.rs
1//! Session provider trait and implementations
2//!
3//! This module defines the SessionProvider trait which abstracts the creation
4//! and validation of session tokens, allowing for both stateful (database-backed)
5//! and stateless (JWT) session implementations.
6
7use async_trait::async_trait;
8use chrono::Duration;
9
10use crate::{Error, Session, SessionToken, UserId};
11
12/// Trait for session token providers
13///
14/// This trait abstracts the creation and validation of session tokens,
15/// allowing for different implementations such as JWT tokens or
16/// database-backed opaque tokens.
17#[async_trait]
18pub trait SessionProvider: Send + Sync {
19 /// Create a new session token for the given user
20 ///
21 /// # Arguments
22 /// * `user_id` - The ID of the user to create a session for
23 /// * `user_agent` - Optional user agent string
24 /// * `ip_address` - Optional IP address
25 /// * `duration` - How long the session should be valid for
26 ///
27 /// # Returns
28 /// A new Session with an appropriate token
29 async fn create_session(
30 &self,
31 user_id: &UserId,
32 user_agent: Option<String>,
33 ip_address: Option<String>,
34 duration: Duration,
35 ) -> Result<Session, Error>;
36
37 /// Validate and retrieve session information from a token
38 ///
39 /// # Arguments
40 /// * `token` - The session token to validate
41 ///
42 /// # Returns
43 /// The Session if the token is valid, or an error if invalid/expired
44 async fn get_session(&self, token: &SessionToken) -> Result<Session, Error>;
45
46 /// Invalidate a session token
47 ///
48 /// For stateless providers (like JWT), this may be a no-op.
49 /// For stateful providers, this should remove the session from storage.
50 ///
51 /// # Arguments
52 /// * `token` - The session token to invalidate
53 async fn delete_session(&self, token: &SessionToken) -> Result<(), Error>;
54
55 /// Clean up expired sessions
56 ///
57 /// For stateless providers (like JWT), this is typically a no-op.
58 /// For stateful providers, this should remove expired sessions from storage.
59 async fn cleanup_expired_sessions(&self) -> Result<(), Error>;
60
61 /// Invalidate all sessions for a specific user
62 ///
63 /// # Arguments
64 /// * `user_id` - The ID of the user whose sessions should be invalidated
65 ///
66 /// # Note
67 /// For stateless providers like JWT, this may not be fully supported
68 /// without implementing a token blacklist or revocation mechanism.
69 async fn delete_sessions_for_user(&self, user_id: &UserId) -> Result<(), Error>;
70}
71
72/// Implementation of SessionProvider for Box<dyn SessionProvider>
73/// This allows for dynamic dispatch of session providers
74#[async_trait]
75impl SessionProvider for Box<dyn SessionProvider> {
76 async fn create_session(
77 &self,
78 user_id: &UserId,
79 user_agent: Option<String>,
80 ip_address: Option<String>,
81 duration: Duration,
82 ) -> Result<Session, Error> {
83 (**self)
84 .create_session(user_id, user_agent, ip_address, duration)
85 .await
86 }
87
88 async fn get_session(&self, token: &SessionToken) -> Result<Session, Error> {
89 (**self).get_session(token).await
90 }
91
92 async fn delete_session(&self, token: &SessionToken) -> Result<(), Error> {
93 (**self).delete_session(token).await
94 }
95
96 async fn cleanup_expired_sessions(&self) -> Result<(), Error> {
97 (**self).cleanup_expired_sessions().await
98 }
99
100 async fn delete_sessions_for_user(&self, user_id: &UserId) -> Result<(), Error> {
101 (**self).delete_sessions_for_user(user_id).await
102 }
103}