use actix_web::cookie::SameSite; use crate::config::AppConfig; use crate::error::{AppError, AppResult}; use crate::session::SessionMiddleware; use crate::session::SessionStore; use crate::session::middleware::parse_same_site; /// Pre-validated session configuration, safe to build middleware from. #[derive(Clone)] pub struct SessionConfig { cookie_name: String, cookie_secure: bool, cookie_http_only: bool, cookie_same_site: SameSite, cookie_path: String, cookie_domain: Option, max_age_secs: Option, ttl_secs: u64, } impl SessionConfig { /// Build a `SessionMiddleware` from pre-validated config (infallible). pub fn build_middleware( &self, store: Store, key: actix_web::cookie::Key, ) -> SessionMiddleware { SessionMiddleware::builder(store, key) .cookie_name(self.cookie_name.clone()) .cookie_secure(self.cookie_secure) .cookie_http_only(self.cookie_http_only) .cookie_same_site(self.cookie_same_site) .cookie_path(self.cookie_path.clone()) .cookie_domain(self.cookie_domain.clone()) .cookie_max_age_secs(self.max_age_secs) .state_ttl_secs(self.ttl_secs) .build() } } impl AppConfig { /// Parse and validate all session configuration values. pub fn session_config(&self) -> AppResult { let ttl_secs = self.session_ttl_secs()?; if ttl_secs == 0 { return Err(AppError::Config( "APP_SESSION_TTL_SECS must be greater than 0".into(), )); } let same_site_str = self.session_cookie_same_site()?; let cookie_same_site = parse_same_site(&same_site_str)?; Ok(SessionConfig { cookie_name: self.session_cookie_name()?, cookie_secure: self.session_cookie_secure()?, cookie_http_only: self.session_cookie_http_only()?, cookie_same_site, cookie_path: self.session_cookie_path()?, cookie_domain: self.session_cookie_domain()?, max_age_secs: self.session_max_age_secs()?, ttl_secs, }) } pub fn session_cookie_name(&self) -> AppResult { self.get_env_or("APP_SESSION_COOKIE_NAME", "sid".to_string()) } pub fn session_cookie_secure(&self) -> AppResult { self.get_env_or("APP_SESSION_COOKIE_SECURE", true) } pub fn session_cookie_http_only(&self) -> AppResult { self.get_env_or("APP_SESSION_COOKIE_HTTP_ONLY", true) } pub fn session_cookie_same_site(&self) -> AppResult { self.get_env_or("APP_SESSION_COOKIE_SAME_SITE", "Lax".to_string()) } pub fn session_cookie_path(&self) -> AppResult { self.get_env_or("APP_SESSION_COOKIE_PATH", "/".to_string()) } pub fn session_cookie_domain(&self) -> AppResult> { self.get_env::("APP_SESSION_COOKIE_DOMAIN") } pub fn session_ttl_secs(&self) -> AppResult { self.get_env_or("APP_SESSION_TTL_SECS", 86400) } pub fn session_max_age_secs(&self) -> AppResult> { self.get_env::("APP_SESSION_MAX_AGE_SECS") } }