use std::time::Duration;
#[derive(Debug, Clone)]
pub struct SessionConfig {
pub cookie_name: String,
pub cookie_domain: Option<String>,
pub cookie_path: String,
pub cookie_secure: bool,
pub cookie_http_only: bool,
pub cookie_same_site: SameSite,
pub ttl: Duration,
pub id_length: usize,
pub secret_key: Option<String>,
pub signed: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SameSite {
Strict,
Lax,
None,
}
impl Default for SessionConfig {
fn default() -> Self {
Self {
cookie_name: "session".to_string(),
cookie_domain: None,
cookie_path: "/".to_string(),
cookie_secure: false,
cookie_http_only: true,
cookie_same_site: SameSite::Lax,
ttl: Duration::from_secs(3600),
id_length: 32,
secret_key: None,
signed: false,
}
}
}
impl SessionConfig {
pub fn new() -> Self {
Self::default()
}
pub fn with_cookie_name(mut self, name: impl Into<String>) -> Self {
self.cookie_name = name.into();
self
}
pub fn with_cookie_domain(mut self, domain: impl Into<String>) -> Self {
self.cookie_domain = Some(domain.into());
self
}
pub fn with_cookie_path(mut self, path: impl Into<String>) -> Self {
self.cookie_path = path.into();
self
}
pub fn with_secure(mut self, secure: bool) -> Self {
self.cookie_secure = secure;
self
}
pub fn with_http_only(mut self, http_only: bool) -> Self {
self.cookie_http_only = http_only;
self
}
pub fn with_same_site(mut self, same_site: SameSite) -> Self {
self.cookie_same_site = same_site;
self
}
pub fn with_ttl(mut self, ttl: Duration) -> Self {
self.ttl = ttl;
self
}
pub fn with_id_length(mut self, length: usize) -> Self {
self.id_length = length;
self
}
pub fn with_secret_key(mut self, key: impl Into<String>) -> Self {
self.secret_key = Some(key.into());
self.signed = true;
self
}
pub fn signed(mut self, key: impl Into<String>) -> Self {
self.secret_key = Some(key.into());
self.signed = true;
self
}
pub fn unsigned(mut self) -> Self {
self.secret_key = None;
self.signed = false;
self
}
pub fn build_cookie_header(&self, session_id: &str) -> String {
let mut parts = vec![format!("{}={}", self.cookie_name, session_id)];
if let Some(ref domain) = self.cookie_domain {
parts.push(format!("Domain={}", domain));
}
parts.push(format!("Path={}", self.cookie_path));
if self.cookie_secure {
parts.push("Secure".to_string());
}
if self.cookie_http_only {
parts.push("HttpOnly".to_string());
}
let same_site = match self.cookie_same_site {
SameSite::Strict => "Strict",
SameSite::Lax => "Lax",
SameSite::None => "None",
};
parts.push(format!("SameSite={}", same_site));
let max_age = self.ttl.as_secs();
parts.push(format!("Max-Age={}", max_age));
parts.join("; ")
}
}