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}