use crate::error::KvError;
#[derive(Clone)]
pub struct KvConfig {
pub vault_url: String,
}
fn akv_url_from_env() -> Result<String, KvError> {
let raw = std::env::var("TSAFE_AKV_URL").map_err(|_| {
KvError::Config("TSAFE_AKV_URL is not set — e.g. https://myvault.vault.azure.net".into())
})?;
let url = raw.trim_end_matches('/').to_string();
if !url.starts_with("https://") {
return Err(KvError::Config(
"TSAFE_AKV_URL must start with https:// — plain HTTP is not allowed".into(),
));
}
Ok(url)
}
impl KvConfig {
pub fn from_env() -> Result<Self, KvError> {
Ok(Self {
vault_url: akv_url_from_env()?,
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn from_env_missing_url_returns_config_error() {
let result = temp_env::with_var("TSAFE_AKV_URL", None::<&str>, KvConfig::from_env);
assert!(matches!(result, Err(KvError::Config(_))));
}
#[test]
fn from_env_http_url_rejected() {
let result = temp_env::with_var(
"TSAFE_AKV_URL",
Some("http://myvault.vault.azure.net"),
KvConfig::from_env,
);
assert!(matches!(result, Err(KvError::Config(_))));
}
#[test]
fn from_env_https_url_accepted() {
let result = temp_env::with_var(
"TSAFE_AKV_URL",
Some("https://myvault.vault.azure.net"),
KvConfig::from_env,
);
assert!(result.is_ok());
assert_eq!(result.unwrap().vault_url, "https://myvault.vault.azure.net");
}
#[test]
fn from_env_trailing_slash_trimmed() {
let result = temp_env::with_var(
"TSAFE_AKV_URL",
Some("https://myvault.vault.azure.net/"),
KvConfig::from_env,
);
assert!(result.is_ok());
assert_eq!(result.unwrap().vault_url, "https://myvault.vault.azure.net");
}
}