use super::auth_config::{AuthConfig, PublicKeyError, PUBLIC_KEY_DECODING_ERR_MSG};
use crate::config::{
cache_config::CacheConfig, log_config::LoggingConfig, otlp_config::TracingConfig,
};
use config::{Config, ConfigError, File};
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
#[cfg(feature = "search")]
use crate::config::index_config::IndexConfig;
use crate::config::otlp_config::TracingLevel;
#[derive(Debug, Default, Deserialize, PartialEq, Clone, Serialize)]
pub struct AppConfig {
pub logging: LoggingConfig,
pub cache: CacheConfig,
pub tracing: TracingConfig,
pub auth: AuthConfig,
pub public_dir: Option<PathBuf>,
#[cfg(feature = "search")]
pub index: IndexConfig,
}
pub struct AppConfigBuilder {
logging: LoggingConfig,
cache: CacheConfig,
tracing: TracingConfig,
auth: AuthConfig,
public_dir: Option<PathBuf>,
#[cfg(feature = "search")]
index: IndexConfig,
}
impl From<AppConfig> for AppConfigBuilder {
fn from(config: AppConfig) -> Self {
Self {
logging: config.logging,
cache: config.cache,
tracing: config.tracing,
auth: config.auth,
public_dir: config.public_dir,
#[cfg(feature = "search")]
index: config.index,
}
}
}
impl Default for AppConfigBuilder {
fn default() -> Self {
Self::new()
}
}
impl AppConfigBuilder {
pub fn new() -> Self {
AppConfig::default().into()
}
pub fn with_log_level(mut self, log_level: String) -> Self {
self.logging.log_level = log_level;
self
}
pub fn with_tracing(mut self, tracing: bool) -> Self {
self.tracing.tracing_enabled = tracing;
self
}
pub fn with_tracing_level(mut self, tracing_level: TracingLevel) -> Self {
self.tracing.tracing_level = tracing_level;
self
}
pub fn with_otlp_agent_host(mut self, otlp_agent_host: String) -> Self {
self.tracing.otlp_agent_host = otlp_agent_host;
self
}
pub fn with_otlp_agent_port(mut self, otlp_agent_port: String) -> Self {
self.tracing.otlp_agent_port = otlp_agent_port;
self
}
pub fn with_otlp_tracing_service_name(mut self, otlp_tracing_service_name: String) -> Self {
self.tracing.otlp_tracing_service_name = otlp_tracing_service_name;
self
}
pub fn with_cache_capacity(mut self, cache_capacity: u64) -> Self {
self.cache.capacity = cache_capacity;
self
}
pub fn with_cache_tti_seconds(mut self, tti_seconds: u64) -> Self {
self.cache.tti_seconds = tti_seconds;
self
}
pub fn with_auth_public_key(
mut self,
public_key: Option<String>,
) -> Result<Self, PublicKeyError> {
if let Some(public_key) = public_key {
self.auth.public_key = Some(public_key.try_into()?);
}
Ok(self)
}
pub fn with_auth_enabled_for_reads(mut self, enabled_for_reads: bool) -> Self {
self.auth.enabled_for_reads = enabled_for_reads;
self
}
pub fn with_public_dir(mut self, public_dir: Option<PathBuf>) -> Self {
self.public_dir = public_dir;
self
}
#[cfg(feature = "search")]
pub fn with_create_index(mut self, create_index: bool) -> Self {
self.index.create_index = create_index;
self
}
pub fn build(self) -> AppConfig {
AppConfig {
logging: self.logging,
cache: self.cache,
tracing: self.tracing,
auth: self.auth,
public_dir: self.public_dir,
#[cfg(feature = "search")]
index: self.index,
}
}
}
pub fn load_config(
app_config: Option<AppConfig>,
config_path: Option<PathBuf>,
) -> Result<AppConfig, ConfigError> {
let mut settings_config_builder = Config::builder();
if let Some(config_path) = config_path {
settings_config_builder = settings_config_builder.add_source(File::from(config_path));
}
let settings = settings_config_builder.build()?;
let mut app_config_builder = if let Some(app_config) = app_config {
AppConfigBuilder::from(app_config)
} else {
AppConfigBuilder::new()
};
if let Ok(log_level) = settings.get::<String>("logging.log_level") {
app_config_builder = app_config_builder.with_log_level(log_level);
}
if let Ok(tracing) = settings.get::<bool>("tracing.tracing_enabled") {
app_config_builder = app_config_builder.with_tracing(tracing);
}
if let Ok(tracing_level) = settings.get::<TracingLevel>("tracing.tracing_level") {
app_config_builder = app_config_builder.with_tracing_level(tracing_level);
}
if let Ok(otlp_agent_host) = settings.get::<String>("tracing.otlp_agent_host") {
app_config_builder = app_config_builder.with_otlp_agent_host(otlp_agent_host);
}
if let Ok(otlp_agent_port) = settings.get::<String>("tracing.otlp_agent_port") {
app_config_builder = app_config_builder.with_otlp_agent_port(otlp_agent_port);
}
if let Ok(otlp_tracing_service_name) =
settings.get::<String>("tracing.otlp_tracing_service_name")
{
app_config_builder =
app_config_builder.with_otlp_tracing_service_name(otlp_tracing_service_name);
}
if let Ok(cache_capacity) = settings.get::<u64>("cache.capacity") {
app_config_builder = app_config_builder.with_cache_capacity(cache_capacity);
}
if let Ok(cache_tti_seconds) = settings.get::<u64>("cache.tti_seconds") {
app_config_builder = app_config_builder.with_cache_tti_seconds(cache_tti_seconds);
}
if let Ok(public_key) = settings.get::<Option<String>>("auth.public_key") {
app_config_builder = app_config_builder
.with_auth_public_key(public_key)
.map_err(|_| ConfigError::Message(PUBLIC_KEY_DECODING_ERR_MSG.to_owned()))?;
}
if let Ok(enabled_for_reads) = settings.get::<bool>("auth.enabled_for_reads") {
app_config_builder = app_config_builder.with_auth_enabled_for_reads(enabled_for_reads);
}
if let Ok(public_dir) = settings.get::<Option<PathBuf>>("public_dir") {
app_config_builder = app_config_builder.with_public_dir(public_dir);
}
#[cfg(feature = "search")]
if let Ok(create_index) = settings.get::<bool>("index.create_index") {
app_config_builder = app_config_builder.with_create_index(create_index);
}
Ok(app_config_builder.build())
}