pub trait AppSession: Sized {
// Required methods
fn from_db<'life0, 'async_trait>(
pool: &'life0 PgPool,
session_id: Uuid,
) -> Pin<Box<dyn Future<Output = Result<Self>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn create<'life0, 'async_trait>(
pool: &'life0 PgPool,
) -> Pin<Box<dyn Future<Output = Result<Self>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn from_inner(inner: CJASession) -> Self;
fn inner(&self) -> &CJASession;
// Provided methods
fn session_id(&self) -> &Uuid { ... }
fn created_at(&self) -> &DateTime<Utc> { ... }
fn updated_at(&self) -> &DateTime<Utc> { ... }
}Expand description
A trait for implementing custom session types that integrate with the framework’s session management.
Sessions are automatically created when needed and persisted across requests using secure cookies.
Your session type must include the CJASession as an inner field and can add any additional
fields needed by your application.
§Example
use cja::server::session::{AppSession, CJASession};
use serde::{Serialize, Deserialize};
#[derive(Debug, Clone)]
struct UserSession {
inner: CJASession,
user_id: Option<i32>,
preferences: serde_json::Value,
}
#[async_trait::async_trait]
impl AppSession for UserSession {
async fn from_db(pool: &sqlx::PgPool, session_id: uuid::Uuid) -> cja::Result<Self> {
// Query your session data including any custom fields
// In a real app, you'd have extended the sessions table with these columns
let row = sqlx::query_as::<_, CJASession>(
"SELECT session_id, created_at, updated_at FROM sessions WHERE session_id = $1"
)
.bind(session_id)
.fetch_one(pool)
.await?;
// For this example, we're just using default values for custom fields
// In a real app, you'd query your extended session data here
Ok(Self {
inner: row,
user_id: None,
preferences: serde_json::json!({}),
})
}
async fn create(pool: &sqlx::PgPool) -> cja::Result<Self> {
let row = sqlx::query_as::<_, CJASession>(
"INSERT INTO sessions DEFAULT VALUES RETURNING session_id, created_at, updated_at"
)
.fetch_one(pool)
.await?;
Ok(Self {
inner: row,
user_id: None,
preferences: serde_json::json!({}),
})
}
fn from_inner(inner: CJASession) -> Self {
Self {
inner,
user_id: None,
preferences: serde_json::json!({}),
}
}
fn inner(&self) -> &CJASession {
&self.inner
}
}§Using Sessions in Handlers
use axum::response::IntoResponse;
use cja::server::session::Session;
async fn handler(
Session(session): Session<UserSession>
) -> impl IntoResponse {
format!("Session ID: {}, User: {:?}",
session.session_id(),
session.user_id)
}Required Methods§
Sourcefn from_db<'life0, 'async_trait>(
pool: &'life0 PgPool,
session_id: Uuid,
) -> Pin<Box<dyn Future<Output = Result<Self>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn from_db<'life0, 'async_trait>(
pool: &'life0 PgPool,
session_id: Uuid,
) -> Pin<Box<dyn Future<Output = Result<Self>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Load a session from the database by its ID.
This method should fetch the session record and any associated data from your sessions table.
Sourcefn create<'life0, 'async_trait>(
pool: &'life0 PgPool,
) -> Pin<Box<dyn Future<Output = Result<Self>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn create<'life0, 'async_trait>(
pool: &'life0 PgPool,
) -> Pin<Box<dyn Future<Output = Result<Self>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Create a new session in the database.
This method should insert a new session record with default values and return the created session.
Sourcefn from_inner(inner: CJASession) -> Self
fn from_inner(inner: CJASession) -> Self
Create a session instance from the inner CJASession.
This is used internally when reconstructing sessions. Custom fields should be initialized with default values.
Sourcefn inner(&self) -> &CJASession
fn inner(&self) -> &CJASession
Get a reference to the inner CJASession.
This provides access to the core session fields like ID and timestamps.
Provided Methods§
fn session_id(&self) -> &Uuid
fn created_at(&self) -> &DateTime<Utc>
fn updated_at(&self) -> &DateTime<Utc>
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.