tower_sessions_seaorm_store/lib.rs
1//! # Tower Sessions Store for Sea-ORM with PostgreSQL
2//!
3//! A robust and efficient session store implementation for [`tower-sessions`](https://crates.io/crates/tower-sessions)
4//! using [Sea-ORM](https://crates.io/crates/sea-orm) as the database abstraction layer.
5//!
6//! This crate provides a PostgreSQL backend implementation for session storage in web applications
7//! built with Tower-compatible frameworks like Axum, Hyper, or any Tower-based service.
8//!
9//! ## Features
10//!
11//! - Persistent session storage in PostgreSQL databases
12//! - Sea-ORM integration for type-safe database operations
13//! - Automatic session expiration and cleanup
14//! - Automatic database migration support (with `migration` feature)
15//! - Optimized upsert operations for better performance
16//! - Comprehensive error handling with dedicated error types
17//! - Serialization of session data using MessagePack for compact storage
18//!
19//! ## Quick Start
20//!
21//! ```no_run
22//! use sea_orm::{Database, DbConn};
23//! use time::Duration;
24//! use tower_sessions::Expiry;
25//! use tower_sessions_seaorm_store::PostgresStore;
26//!
27//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
28//! // Connect to the database
29//! let conn = Database::connect("postgres://postgres:postgres@localhost:5432/sessions").await?;
30//!
31//! // Create a new PostgresStore
32//! let store = PostgresStore::new(conn);
33//!
34//! // Run migrations to set up the database schema (requires "migration" feature)
35//! store.migrate().await?;
36//!
37//! // Use the store with tower-sessions
38//! let session_layer = tower_sessions::SessionManagerLayer::new(store)
39//! .with_expiry(Expiry::OnInactivity(Duration::days(7)));
40//! # Ok(())
41//! # }
42//! ```
43//!
44//! ## Axum Integration Example
45//!
46//! ```no_run
47//! use axum::{Router, routing::get};
48//! use sea_orm::{Database, DbConn};
49//! use time::Duration;
50//! use tower_sessions::{Expiry, Session, SessionManagerLayer};
51//! use tower_sessions_seaorm_store::PostgresStore;
52//!
53//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
54//! // Connect to the database
55//! let conn = Database::connect("postgres://postgres:postgres@localhost:5432/sessions").await?;
56//!
57//! // Create the store
58//! let store = PostgresStore::new(conn);
59//!
60//! // Run migrations to set up the database schema
61//! store.migrate().await?;
62//!
63//! // Configure session layer
64//! let session_layer = SessionManagerLayer::new(store)
65//! .with_expiry(Expiry::OnInactivity(Duration::days(1)))
66//! .with_secure(true);
67//!
68//! // Build your Axum application with session support
69//! let app = Router::new()
70//! .route("/", get(|| async { "Hello, world!" }))
71//! .layer(session_layer);
72//! # Ok(())
73//! # }
74//! ```
75//!
76//! ## Session Management
77//!
78//! Once your application is set up with the session layer, you can use the session in your handlers:
79//!
80//! ```no_run
81//! use axum::extract::State;
82//! use tower_sessions::Session;
83//!
84//! # async fn example(session: Session) -> Result<String, &'static str> {
85//! // Set a value
86//! session.insert("user_id", 123).await.map_err(|_| "Failed to insert")?;
87//!
88//! // Get a value
89//! let user_id: Option<u32> = session.get("user_id").await.map_err(|_| "Failed to get")?;
90//!
91//! // Remove a value
92//! session.remove("user_id").await.map_err(|_| "Failed to remove")?;
93//!
94//! // Clear the entire session
95//! session.flush().await.map_err(|_| "Failed to flush")?;
96//! # Ok("Success".to_string())
97//! # }
98//! ```
99
100pub mod entity;
101#[cfg(feature = "migration")]
102pub mod migration;
103mod postgres_store;
104
105pub use sea_orm;
106
107/// An error type for SeaORM stores.
108#[derive(thiserror::Error, Debug)]
109pub enum SeaOrmStoreError {
110 /// A variant to map Sea-ORM errors.
111 #[error(transparent)]
112 SeaOrm(#[from] sea_orm::DbErr),
113
114 /// A variant to map `rmp_serde` encode errors.
115 #[error(transparent)]
116 Encode(#[from] rmp_serde::encode::Error),
117
118 /// A variant to map `rmp_serde` decode errors.
119 #[error(transparent)]
120 Decode(#[from] rmp_serde::decode::Error),
121}
122
123impl From<SeaOrmStoreError> for tower_sessions::session_store::Error {
124 fn from(err: SeaOrmStoreError) -> Self {
125 match err {
126 SeaOrmStoreError::SeaOrm(inner) => tower_sessions::session_store::Error::Backend(inner.to_string()),
127 SeaOrmStoreError::Decode(inner) => tower_sessions::session_store::Error::Decode(inner.to_string()),
128 SeaOrmStoreError::Encode(inner) => tower_sessions::session_store::Error::Encode(inner.to_string()),
129 }
130 }
131}
132
133// Re-export our PostgreSQL store implementation
134/// The main PostgreSQL store implementation for tower-sessions
135///
136/// This is the primary type you'll use from this crate.
137/// See [`PostgresStore`] documentation for usage details.
138pub use postgres_store::PostgresStore;
139
140// Re-export necessary types from tower-sessions for convenience
141/// Session storage error types and results
142///
143/// These are re-exported from the `tower-sessions` crate for convenience.
144pub use tower_sessions::session_store;
145
146/// Trait for implementing session store expiration cleanup
147///
148/// Implementation provided by `PostgresStore` allows for efficient deletion of
149/// expired sessions from the database.
150pub use tower_sessions::ExpiredDeletion;
151
152/// Session identifier type
153///
154/// Re-exported from `tower-sessions` for convenience.
155pub use tower_sessions::session::Id;
156
157/// Session record type
158///
159/// Contains the session data and metadata that gets stored in the database.
160pub use tower_sessions::session::Record;
161
162/// Session type for manipulating the current session
163///
164/// This is the type you'll use in your request handlers to access session data.
165pub use tower_sessions::Session;
166
167/// Trait for implementing session storage backends
168///
169/// Implemented by `PostgresStore` to provide the required storage functionality.
170pub use tower_sessions::SessionStore;
171