1use serde::{Deserialize, Serialize};
8use std::path::PathBuf;
9
10#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
12#[serde(tag = "backend", rename_all = "lowercase")]
13pub enum StorageBackend {
14 Sqlite {
16 path: PathBuf,
18 },
19 Json {
21 path: PathBuf,
23 },
24 Memory,
26}
27
28impl Default for StorageBackend {
29 fn default() -> Self {
30 StorageBackend::Sqlite {
31 path: PathBuf::from("./data/vbr.db"),
32 }
33 }
34}
35
36#[derive(Debug, Clone, Serialize, Deserialize)]
38pub struct SessionConfig {
39 #[serde(default = "default_true")]
41 pub enabled: bool,
42
43 #[serde(default = "default_session_timeout")]
45 pub timeout: u64,
46
47 #[serde(default)]
49 pub scoped_data: bool,
50}
51
52fn default_true() -> bool {
53 true
54}
55
56fn default_session_timeout() -> u64 {
57 3600 }
59
60impl Default for SessionConfig {
61 fn default() -> Self {
62 Self {
63 enabled: true,
64 timeout: default_session_timeout(),
65 scoped_data: false,
66 }
67 }
68}
69
70#[derive(Debug, Clone, Serialize, Deserialize)]
72pub struct AgingConfig {
73 #[serde(default)]
75 pub enabled: bool,
76
77 #[serde(default = "default_cleanup_interval")]
79 pub cleanup_interval: u64,
80
81 #[serde(default = "default_true")]
83 pub auto_update_timestamps: bool,
84}
85
86fn default_cleanup_interval() -> u64 {
87 3600 }
89
90impl Default for AgingConfig {
91 fn default() -> Self {
92 Self {
93 enabled: false,
94 cleanup_interval: default_cleanup_interval(),
95 auto_update_timestamps: true,
96 }
97 }
98}
99
100#[derive(Debug, Clone, Serialize, Deserialize)]
102pub struct AuthConfig {
103 #[serde(default)]
105 pub enabled: bool,
106
107 #[serde(default)]
109 pub jwt_secret: Option<String>,
110
111 #[serde(default = "default_token_expiration")]
113 pub token_expiration: u64,
114}
115
116fn default_token_expiration() -> u64 {
117 86400 }
119
120impl Default for AuthConfig {
121 fn default() -> Self {
122 Self {
123 enabled: false,
124 jwt_secret: None,
125 token_expiration: default_token_expiration(),
126 }
127 }
128}
129
130#[derive(Debug, Clone, Serialize, Deserialize)]
132pub struct VbrConfig {
133 #[serde(default)]
135 pub storage: StorageBackend,
136
137 #[serde(default)]
139 pub sessions: SessionConfig,
140
141 #[serde(default)]
143 pub aging: AgingConfig,
144
145 #[serde(default)]
147 pub auth: AuthConfig,
148
149 #[serde(default = "default_api_prefix")]
151 pub api_prefix: String,
152}
153
154fn default_api_prefix() -> String {
155 "/api".to_string()
156}
157
158impl Default for VbrConfig {
159 fn default() -> Self {
160 Self {
161 storage: StorageBackend::default(),
162 sessions: SessionConfig::default(),
163 aging: AgingConfig::default(),
164 auth: AuthConfig::default(),
165 api_prefix: default_api_prefix(),
166 }
167 }
168}
169
170impl VbrConfig {
171 pub fn new() -> Self {
173 Self::default()
174 }
175
176 pub fn with_storage_backend(mut self, backend: StorageBackend) -> Self {
178 self.storage = backend;
179 self
180 }
181
182 pub fn with_sessions(mut self, config: SessionConfig) -> Self {
184 self.sessions = config;
185 self
186 }
187
188 pub fn with_aging(mut self, config: AgingConfig) -> Self {
190 self.aging = config;
191 self
192 }
193
194 pub fn with_auth(mut self, config: AuthConfig) -> Self {
196 self.auth = config;
197 self
198 }
199
200 pub fn with_api_prefix(mut self, prefix: String) -> Self {
202 self.api_prefix = prefix;
203 self
204 }
205}
206
207#[cfg(test)]
208mod tests {
209 use super::*;
210
211 #[test]
212 fn test_storage_backend_default() {
213 let backend = StorageBackend::default();
214 assert!(matches!(backend, StorageBackend::Sqlite { .. }));
215 }
216
217 #[test]
218 fn test_vbr_config_default() {
219 let config = VbrConfig::default();
220 assert!(config.sessions.enabled);
221 assert_eq!(config.sessions.timeout, 3600);
222 assert!(!config.aging.enabled);
223 assert!(!config.auth.enabled);
224 assert_eq!(config.api_prefix, "/api");
225 }
226
227 #[test]
228 fn test_vbr_config_builder() {
229 let config = VbrConfig::new()
230 .with_api_prefix("/v1/api".to_string())
231 .with_storage_backend(StorageBackend::Memory);
232
233 assert_eq!(config.api_prefix, "/v1/api");
234 assert!(matches!(config.storage, StorageBackend::Memory));
235 }
236}