mod config;
mod csrf;
mod extractors;
mod flash;
pub use config::{CsrfConfig, SessionConfig, SessionStorage};
pub use csrf::{csrf_middleware, CsrfLayer, CsrfMiddleware, CsrfToken};
pub use extractors::{AuthSession, SessionAuth, SessionData, TypedSession};
pub use flash::{FlashKind, FlashMessage, FlashMessages};
pub use tower_sessions::{Expiry, Session, SessionManagerLayer};
#[cfg(feature = "session-memory")]
pub use tower_sessions_memory_store::MemoryStore;
#[cfg(feature = "session-redis")]
pub use tower_sessions_redis_store::RedisStore;
#[cfg(feature = "session-redis")]
pub use tower_sessions_redis_store::fred;
#[cfg(feature = "session-memory")]
use time::Duration;
#[cfg(feature = "session-redis")]
use crate::error::Result;
#[cfg(feature = "session-memory")]
pub fn create_memory_session_layer(config: &SessionConfig) -> SessionManagerLayer<MemoryStore> {
use tower_sessions::cookie::SameSite;
let store = MemoryStore::default();
let expiry = if config.expiry_secs == 0 {
Expiry::OnSessionEnd
} else if let Some(inactivity) = config.inactivity_timeout_secs {
Expiry::OnInactivity(Duration::seconds(inactivity as i64))
} else {
Expiry::OnInactivity(Duration::seconds(config.expiry_secs as i64))
};
let same_site = match config.same_site.to_lowercase().as_str() {
"strict" => SameSite::Strict,
"none" => SameSite::None,
_ => SameSite::Lax,
};
let cookie_name = config.cookie_name.clone();
let cookie_path = config.cookie_path.clone();
let cookie_domain = config.cookie_domain.clone();
let mut layer = SessionManagerLayer::new(store)
.with_name(cookie_name)
.with_expiry(expiry)
.with_secure(config.secure)
.with_http_only(config.http_only)
.with_same_site(same_site)
.with_path(cookie_path);
if let Some(domain) = cookie_domain {
layer = layer.with_domain(domain);
}
layer
}
#[cfg(feature = "session-redis")]
pub async fn create_redis_session_layer(
config: &SessionConfig,
redis_url: &str,
) -> Result<SessionManagerLayer<RedisStore<tower_sessions_redis_store::fred::clients::Pool>>> {
use crate::error::Error;
use tower_sessions::cookie::SameSite;
use tower_sessions_redis_store::fred::prelude::*;
let redis_config = Config::from_url(redis_url)
.map_err(|e| Error::Internal(format!("Invalid Redis URL for sessions: {e}")))?;
let pool = Builder::from_config(redis_config)
.build_pool(6)
.map_err(|e| Error::Internal(format!("Failed to create session Redis pool: {e}")))?;
pool.init()
.await
.map_err(|e| Error::Internal(format!("Failed to connect to Redis for sessions: {e}")))?;
let store = RedisStore::new(pool);
let expiry = if config.expiry_secs == 0 {
Expiry::OnSessionEnd
} else if let Some(inactivity) = config.inactivity_timeout_secs {
Expiry::OnInactivity(Duration::seconds(inactivity as i64))
} else {
Expiry::OnInactivity(Duration::seconds(config.expiry_secs as i64))
};
let same_site = match config.same_site.to_lowercase().as_str() {
"strict" => SameSite::Strict,
"none" => SameSite::None,
_ => SameSite::Lax,
};
let cookie_name = config.cookie_name.clone();
let cookie_path = config.cookie_path.clone();
let cookie_domain = config.cookie_domain.clone();
let mut layer = SessionManagerLayer::new(store)
.with_name(cookie_name)
.with_expiry(expiry)
.with_secure(config.secure)
.with_http_only(config.http_only)
.with_same_site(same_site)
.with_path(cookie_path);
if let Some(domain) = cookie_domain {
layer = layer.with_domain(domain);
}
Ok(layer)
}