pinakes: import in parallel; various UI improvements

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I1eb47cd79cd4145c56af966f6756fe1d6a6a6964
This commit is contained in:
raf 2026-02-03 10:31:20 +03:00
commit 116fe7b059
Signed by: NotAShelf
GPG key ID: 29D95B64378DB4BF
42 changed files with 4316 additions and 316 deletions

View file

@ -484,6 +484,85 @@ pub struct ServerConfig {
/// If set, all requests (except /health) must include `Authorization: Bearer <key>`.
/// Can also be set via `PINAKES_API_KEY` environment variable.
pub api_key: Option<String>,
/// TLS/HTTPS configuration
#[serde(default)]
pub tls: TlsConfig,
}
/// TLS/HTTPS configuration for secure connections
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TlsConfig {
/// Enable TLS (HTTPS)
#[serde(default)]
pub enabled: bool,
/// Path to the TLS certificate file (PEM format)
#[serde(default)]
pub cert_path: Option<PathBuf>,
/// Path to the TLS private key file (PEM format)
#[serde(default)]
pub key_path: Option<PathBuf>,
/// Enable HTTP to HTTPS redirect (starts a second listener on http_port)
#[serde(default)]
pub redirect_http: bool,
/// Port for HTTP redirect listener (default: 80)
#[serde(default = "default_http_port")]
pub http_port: u16,
/// Enable HSTS (HTTP Strict Transport Security) header
#[serde(default = "default_true")]
pub hsts_enabled: bool,
/// HSTS max-age in seconds (default: 1 year)
#[serde(default = "default_hsts_max_age")]
pub hsts_max_age: u64,
}
fn default_http_port() -> u16 {
80
}
fn default_hsts_max_age() -> u64 {
31536000 // 1 year in seconds
}
impl Default for TlsConfig {
fn default() -> Self {
Self {
enabled: false,
cert_path: None,
key_path: None,
redirect_http: false,
http_port: default_http_port(),
hsts_enabled: true,
hsts_max_age: default_hsts_max_age(),
}
}
}
impl TlsConfig {
/// Validate TLS configuration
pub fn validate(&self) -> Result<(), String> {
if self.enabled {
if self.cert_path.is_none() {
return Err("TLS enabled but cert_path not specified".into());
}
if self.key_path.is_none() {
return Err("TLS enabled but key_path not specified".into());
}
if let Some(ref cert_path) = self.cert_path {
if !cert_path.exists() {
return Err(format!(
"TLS certificate file not found: {}",
cert_path.display()
));
}
}
if let Some(ref key_path) = self.key_path {
if !key_path.exists() {
return Err(format!("TLS key file not found: {}", key_path.display()));
}
}
}
Ok(())
}
}
impl Config {
@ -564,6 +643,8 @@ impl Config {
if self.scanning.import_concurrency == 0 || self.scanning.import_concurrency > 256 {
return Err("import_concurrency must be between 1 and 256".into());
}
// Validate TLS configuration
self.server.tls.validate()?;
Ok(())
}
@ -609,6 +690,7 @@ impl Default for Config {
host: "127.0.0.1".to_string(),
port: 3000,
api_key: None,
tls: TlsConfig::default(),
},
ui: UiConfig::default(),
accounts: AccountsConfig::default(),