Skip to content
Clone
f0a1552
110 lines 3.5 KB Rust
use std::net::IpAddr;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(default)]
pub struct AdminConfig {
pub enabled: Option<bool>,
pub bind_addr: Option<String>,
pub port: Option<u16>,
pub seed_username: Option<String>,
pub seed_password: Option<String>,
pub session_cookie_name: Option<String>,
pub session_table_name: Option<String>,
pub cors_allow_origins: Vec<String>,
pub cors_allow_credentials: Option<bool>,
}
impl AdminConfig {
pub fn enabled(&self) -> bool {
self.enabled.unwrap_or(true)
}
pub fn bind_addr(&self) -> &str {
self.bind_addr.as_deref().unwrap_or("0.0.0.0")
}
pub fn port(&self) -> u16 {
self.port.unwrap_or(3004)
}
pub fn seed_username(&self) -> Option<&str> {
self.seed_username
.as_deref()
.map(str::trim)
.filter(|value| !value.is_empty())
}
pub fn seed_password(&self) -> Option<&str> {
self.seed_password
.as_deref()
.filter(|value| !value.is_empty())
}
pub fn session_cookie_name(&self) -> &str {
self.session_cookie_name
.as_deref()
.unwrap_or("gitdata_admin_session")
}
pub fn session_table_name(&self) -> &str {
self.session_table_name
.as_deref()
.unwrap_or("admin_session")
}
pub fn cors_allow_credentials(&self) -> bool {
self.cors_allow_credentials.unwrap_or(false)
}
pub fn is_valid(&self) -> Result<(), String> {
if !self.enabled() {
return Ok(());
}
let bind = self.bind_addr();
if bind.parse::<IpAddr>().is_err() {
return Err(format!("admin.bind_addr is not a valid IP: {bind:?}"));
}
if self.port == Some(0) {
return Err("admin.port must be greater than 0".to_string());
}
if self.session_cookie_name().trim().is_empty() {
return Err("admin.session_cookie_name must not be empty".to_string());
}
let table = self.session_table_name();
if table.trim().is_empty() {
return Err("admin.session_table_name must not be empty".to_string());
}
if table.contains(['*', '?', '[', ']', '\\']) {
return Err(format!(
"admin.session_table_name must not contain glob characters: {table:?}"
));
}
match (self.seed_username(), self.seed_password()) {
(Some(username), Some(password)) => {
if username.len() < 3 {
return Err("admin.seed_username must be at least 3 characters".to_string());
}
if password.len() < 8 {
return Err("admin.seed_password must be at least 8 characters".to_string());
}
}
(Some(_), None) => {
return Err("admin.seed_username requires admin.seed_password".to_string());
}
(None, Some(_)) => {
return Err("admin.seed_password requires admin.seed_username".to_string());
}
(None, None) => {}
}
for origin in &self.cors_allow_origins {
if !origin.starts_with("http://") && !origin.starts_with("https://") {
return Err(format!(
"admin.cors_allow_origins entry must be an origin URL: {origin:?}"
));
}
}
Ok(())
}
}