use serde::de::DeserializeOwned;
use std::path::{Path, PathBuf};
use thiserror::Error;
#[derive(Debug, Error)]
pub enum ConfigFileError {
#[error(
"Failed to read configuration file at {path:?} during startup: {source}"
)]
FileRead {
path: PathBuf,
#[source]
source: std::io::Error,
},
#[error("Failed to parse configuration file at {path:?}: {source}")]
Parse {
path: PathBuf,
#[source]
source: toml::de::Error,
},
}
pub fn xdg_config_dir(app_name: &str) -> Option<PathBuf> {
std::env::var_os("XDG_CONFIG_HOME")
.map(PathBuf::from)
.or_else(|| home::home_dir().map(|h| h.join(".config")))
.map(|d| d.join(app_name))
}
pub fn find_config_file(
app_name: &str,
explicit_path: Option<&Path>,
) -> Option<PathBuf> {
if let Some(p) = explicit_path {
return Some(p.to_path_buf());
}
xdg_config_dir(app_name)
.map(|d| d.join("config.toml"))
.filter(|p| p.exists())
}
pub fn load_toml<T: DeserializeOwned>(
path: &Path,
) -> Result<T, ConfigFileError> {
let contents = std::fs::read_to_string(path).map_err(|source| {
ConfigFileError::FileRead {
path: path.to_path_buf(),
source,
}
})?;
toml::from_str(&contents).map_err(|source| ConfigFileError::Parse {
path: path.to_path_buf(),
source,
})
}
#[derive(Debug, serde::Deserialize, Default)]
pub struct CommonConfigFile {
pub log_level: Option<String>,
pub log_format: Option<String>,
}
#[cfg(feature = "server")]
pub fn credential_secret_path() -> Option<PathBuf> {
let dir = std::env::var("CREDENTIALS_DIRECTORY").ok()?;
let path = PathBuf::from(dir).join("oidc-client-secret");
path.exists().then_some(path)
}
pub fn resolve_log_settings(
cli_level: Option<String>,
cli_format: Option<String>,
file: &CommonConfigFile,
) -> Result<(crate::logging::LogLevel, crate::logging::LogFormat), String> {
let level_str = cli_level
.or_else(|| file.log_level.clone())
.unwrap_or_else(|| "info".to_string());
let level = level_str
.parse::<crate::logging::LogLevel>()
.map_err(|e| e.to_string())?;
let format_str = cli_format
.or_else(|| file.log_format.clone())
.unwrap_or_else(|| "text".to_string());
let format = format_str
.parse::<crate::logging::LogFormat>()
.map_err(|e| e.to_string())?;
Ok((level, format))
}