1use crate::error::{CedrosDataError, Result};
2
3#[derive(Debug, Clone)]
4pub struct CedrosDataConfig {
5 pub postgres_uri: String,
6}
7
8impl CedrosDataConfig {
9 pub fn from_env() -> Result<Self> {
10 let postgres_uri =
11 std::env::var("POSTGRES_URI").map_err(|_| CedrosDataError::MissingPostgresUri)?;
12 Ok(Self { postgres_uri })
13 }
14}
15
16#[cfg(feature = "http")]
17#[derive(Debug, Clone)]
18pub struct HttpServerConfig {
19 pub bind_addr: String,
20 pub cors_allowed_origins: Vec<String>,
21 pub enable_cedros_login_profile: bool,
22 pub cedros_login_verify_url: Option<String>,
23 pub allow_unauthenticated_http: bool,
24}
25
26#[cfg(feature = "http")]
27impl Default for HttpServerConfig {
28 fn default() -> Self {
29 Self {
30 bind_addr: "127.0.0.1:8080".to_string(),
31 cors_allowed_origins: Vec::new(),
32 enable_cedros_login_profile: false,
33 cedros_login_verify_url: None,
34 allow_unauthenticated_http: false,
35 }
36 }
37}
38
39#[cfg(feature = "storage")]
40#[derive(Clone)]
41pub struct StorageConfig {
42 pub access_key: String,
43 pub secret_key: String,
44 pub bucket: String,
45 pub region: String,
46 pub endpoint: Option<String>,
47 pub cdn_base_url: Option<String>,
48 pub path_prefix: Option<String>,
49}
50
51#[cfg(feature = "storage")]
52impl std::fmt::Debug for StorageConfig {
53 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54 f.debug_struct("StorageConfig")
55 .field("bucket", &self.bucket)
56 .field("region", &self.region)
57 .field("endpoint", &self.endpoint)
58 .field("access_key", &redact_key(&self.access_key))
59 .field("secret_key", &"[REDACTED]")
60 .finish()
61 }
62}
63
64#[cfg(feature = "storage")]
65impl StorageConfig {
66 pub fn from_env() -> Result<Self> {
67 let access_key = required_env("STORAGE_ACCESS_KEY")?;
68 let secret_key = required_env("STORAGE_SECRET_KEY")?;
69 let bucket = required_env("STORAGE_BUCKET")?;
70 let region = required_env("STORAGE_REGION")?;
71 let endpoint = optional_env("STORAGE_ENDPOINT");
72 let cdn_base_url = optional_env("STORAGE_CDN_BASE_URL");
73 let path_prefix = optional_env("STORAGE_PATH_PREFIX");
74
75 Ok(Self {
76 access_key,
77 secret_key,
78 bucket,
79 region,
80 endpoint,
81 cdn_base_url,
82 path_prefix,
83 })
84 }
85
86 pub fn redacted_summary(&self) -> serde_json::Value {
88 serde_json::json!({
89 "bucket": self.bucket,
90 "region": self.region,
91 "endpoint": self.endpoint,
92 "cdn_base_url": self.cdn_base_url,
93 "path_prefix": self.path_prefix,
94 "access_key": redact_key(&self.access_key),
95 })
96 }
97}
98
99#[cfg(feature = "storage")]
100fn required_env(name: &str) -> Result<String> {
101 std::env::var(name).map_err(|_| {
102 CedrosDataError::InvalidRequest(format!("missing required environment variable {name}"))
103 })
104}
105
106#[cfg(feature = "storage")]
107fn optional_env(name: &str) -> Option<String> {
108 std::env::var(name).ok().filter(|v| !v.is_empty())
109}
110
111#[cfg(feature = "storage")]
112fn redact_key(key: &str) -> String {
113 if key.len() <= 6 {
114 return "***".to_string();
115 }
116 format!("{}***{}", &key[..3], &key[key.len() - 3..])
117}