use serde::{Deserialize, Serialize};
fn default_true() -> bool { true }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SecurityConfig {
#[serde(default = "default_true")]
pub cors_enabled: bool,
#[serde(default = "default_cors_origins")]
pub cors_origins: Vec<String>,
#[serde(default = "default_cors_methods")]
pub cors_methods: Vec<String>,
#[serde(default = "default_cors_headers")]
pub cors_headers: Vec<String>,
#[serde(default)]
pub csrf: Option<CsrfConfig>,
#[serde(default)]
pub headers: Option<SecurityHeadersConfig>,
}
fn default_cors_origins() -> Vec<String> { vec!["http://localhost:3000".to_string()] }
fn default_cors_methods() -> Vec<String> {
vec!["GET".to_string(), "POST".to_string(), "PUT".to_string(), "DELETE".to_string(), "PATCH".to_string(), "OPTIONS".to_string()]
}
fn default_cors_headers() -> Vec<String> {
vec!["Content-Type".to_string(), "Authorization".to_string()]
}
impl Default for SecurityConfig {
fn default() -> Self {
Self {
cors_enabled: true,
cors_origins: default_cors_origins(),
cors_methods: default_cors_methods(),
cors_headers: default_cors_headers(),
csrf: None,
headers: Some(SecurityHeadersConfig::default()),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CsrfConfig {
#[serde(default = "default_true")]
pub enabled: bool,
#[serde(default = "default_csrf_token_length")]
pub token_length: u32,
#[serde(default = "default_csrf_expires")]
pub expires_in: u64,
}
fn default_csrf_token_length() -> u32 { 32 }
fn default_csrf_expires() -> u64 { 3600 }
impl Default for CsrfConfig {
fn default() -> Self {
Self {
enabled: true,
token_length: default_csrf_token_length(),
expires_in: default_csrf_expires(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SecurityHeadersConfig {
#[serde(default = "default_x_frame_options")]
pub x_frame_options: Option<String>,
#[serde(default = "default_x_content_type_options")]
pub x_content_type_options: Option<String>,
#[serde(default = "default_x_xss_protection")]
pub x_xss_protection: Option<String>,
#[serde(default = "default_hsts")]
pub strict_transport_security: Option<String>,
}
fn default_x_frame_options() -> Option<String> { Some("DENY".to_string()) }
fn default_x_content_type_options() -> Option<String> { Some("nosniff".to_string()) }
fn default_x_xss_protection() -> Option<String> { Some("1; mode=block".to_string()) }
fn default_hsts() -> Option<String> { Some("max-age=31536000; includeSubDomains".to_string()) }
impl Default for SecurityHeadersConfig {
fn default() -> Self {
Self {
x_frame_options: default_x_frame_options(),
x_content_type_options: default_x_content_type_options(),
x_xss_protection: default_x_xss_protection(),
strict_transport_security: default_hsts(),
}
}
}