use serde::{Deserialize, Serialize};
use crate::errors::OrionError;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct AdminAuthConfig {
pub enabled: bool,
pub api_keys: Vec<String>,
pub header: String,
}
impl AdminAuthConfig {
pub fn effective_keys(&self) -> Vec<&str> {
self.api_keys
.iter()
.filter(|k| !k.is_empty())
.map(String::as_str)
.collect()
}
pub(crate) fn validate(&self, is_production: bool) -> Result<(), OrionError> {
if self.enabled && self.effective_keys().is_empty() {
return Err(OrionError::Config {
message:
"At least one admin API key must be configured when admin auth is enabled. \
Set admin_auth.api_keys"
.to_string(),
});
}
if !self.enabled {
if is_production {
return Err(OrionError::Config {
message: "admin_auth must be enabled when environment starts with 'prod'. \
Set admin_auth.enabled = true and configure admin_auth.api_keys"
.to_string(),
});
}
tracing::warn!(
"Admin auth is disabled. For production, enable admin_auth with a strong API key"
);
}
Ok(())
}
}
impl Default for AdminAuthConfig {
fn default() -> Self {
Self {
enabled: false,
api_keys: Vec::new(),
header: "Authorization".to_string(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_admin_auth_config_default() {
let config = AdminAuthConfig::default();
assert!(!config.enabled);
assert!(config.api_keys.is_empty());
assert_eq!(config.header, "Authorization");
}
#[test]
fn test_effective_keys_returns_configured_keys() {
let config = AdminAuthConfig {
enabled: true,
api_keys: vec!["key-a".to_string(), "key-b".to_string()],
header: "Authorization".to_string(),
};
assert_eq!(config.effective_keys(), vec!["key-a", "key-b"]);
}
#[test]
fn test_effective_keys_filters_empty_strings() {
let config = AdminAuthConfig {
enabled: true,
api_keys: vec!["".to_string(), "key-a".to_string(), "".to_string()],
header: "Authorization".to_string(),
};
assert_eq!(config.effective_keys(), vec!["key-a"]);
}
#[test]
fn test_effective_keys_empty() {
let config = AdminAuthConfig::default();
assert!(config.effective_keys().is_empty());
}
}