1use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct ModulesConfig {
14 #[serde(default)]
16 pub sapiens: SapiensConfig,
17 #[serde(default)]
19 pub postman: PostmanConfig,
20 #[serde(default)]
22 pub bucket: BucketConfig,
23}
24
25#[allow(clippy::derivable_impls)]
26impl Default for ModulesConfig {
27 fn default() -> Self {
28 Self {
29 sapiens: SapiensConfig::default(),
30 postman: PostmanConfig::default(),
31 bucket: BucketConfig::default(),
32 }
33 }
34}
35
36#[derive(Debug, Clone, Serialize, Deserialize)]
42pub struct SapiensConfig {
43 #[serde(default = "default_true")]
45 pub enabled: bool,
46 #[serde(default)]
48 pub database: Option<String>,
49 #[serde(default)]
51 pub cache: Option<String>,
52 #[serde(default = "default_sapiens_context")]
54 pub bounded_context: String,
55 #[serde(default = "default_domain_version")]
57 pub domain_version: String,
58 #[serde(default)]
60 pub publishes: Vec<String>,
61 #[serde(default)]
63 pub provides: Vec<String>,
64 #[serde(default)]
66 pub auth: Option<SapiensAuthConfig>,
67 #[serde(default)]
69 pub lockout: Option<SapiensLockoutConfig>,
70}
71
72fn default_true() -> bool { true }
73fn default_false() -> bool { false }
74fn default_sapiens_context() -> String { "user-management".to_string() }
75fn default_domain_version() -> String { "1.0.0".to_string() }
76
77impl Default for SapiensConfig {
78 fn default() -> Self {
79 Self {
80 enabled: true,
81 database: Some("default".to_string()),
82 cache: Some("default".to_string()),
83 bounded_context: default_sapiens_context(),
84 domain_version: default_domain_version(),
85 publishes: vec![
86 "sapiens.user.created".to_string(),
87 "sapiens.user.updated".to_string(),
88 "sapiens.user.deleted".to_string(),
89 ],
90 provides: vec![
91 "user.authentication".to_string(),
92 "user.authorization".to_string(),
93 "user.profile".to_string(),
94 ],
95 auth: Some(SapiensAuthConfig::default()),
96 lockout: Some(SapiensLockoutConfig::default()),
97 }
98 }
99}
100
101#[derive(Debug, Clone, Serialize, Deserialize)]
103pub struct SapiensAuthConfig {
104 pub jwt_secret: String,
106 #[serde(default = "default_token_expiration")]
108 pub token_expiration_hours: u64,
109 #[serde(default = "default_refresh_expiration")]
111 pub refresh_token_expiration_days: u64,
112 #[serde(default)]
114 pub password_hasher: PasswordHasherConfig,
115}
116
117fn default_token_expiration() -> u64 { 24 }
118fn default_refresh_expiration() -> u64 { 30 }
119
120impl Default for SapiensAuthConfig {
121 fn default() -> Self {
122 Self {
123 jwt_secret: String::new(), token_expiration_hours: default_token_expiration(),
125 refresh_token_expiration_days: default_refresh_expiration(),
126 password_hasher: PasswordHasherConfig::default(),
127 }
128 }
129}
130
131#[derive(Debug, Clone, Serialize, Deserialize)]
133pub struct PasswordHasherConfig {
134 #[serde(default = "default_iterations")]
136 pub iterations: u32,
137 #[serde(default = "default_memory")]
139 pub memory: u32,
140 #[serde(default = "default_parallelism")]
142 pub parallelism: u32,
143 #[serde(default = "default_hash_length")]
145 pub hash_length: u32,
146}
147
148fn default_iterations() -> u32 { 19456 }
149fn default_memory() -> u32 { 2 }
150fn default_parallelism() -> u32 { 1 }
151fn default_hash_length() -> u32 { 32 }
152
153impl Default for PasswordHasherConfig {
154 fn default() -> Self {
155 Self {
156 iterations: default_iterations(),
157 memory: default_memory(),
158 parallelism: default_parallelism(),
159 hash_length: default_hash_length(),
160 }
161 }
162}
163
164#[derive(Debug, Clone, Serialize, Deserialize)]
166pub struct SapiensLockoutConfig {
167 #[serde(default = "default_max_attempts")]
169 pub max_attempts: u32,
170 #[serde(default = "default_lockout_duration")]
172 pub duration_minutes: u32,
173 #[serde(default)]
175 pub reset_after_hours: Option<u32>,
176}
177
178fn default_max_attempts() -> u32 { 5 }
179fn default_lockout_duration() -> u32 { 15 }
180
181impl Default for SapiensLockoutConfig {
182 fn default() -> Self {
183 Self {
184 max_attempts: default_max_attempts(),
185 duration_minutes: default_lockout_duration(),
186 reset_after_hours: Some(24),
187 }
188 }
189}
190
191#[derive(Debug, Clone, Serialize, Deserialize)]
197pub struct PostmanConfig {
198 #[serde(default = "default_false")]
200 pub enabled: bool,
201 #[serde(default)]
203 pub database: Option<String>,
204 #[serde(default = "default_postman_context")]
206 pub bounded_context: String,
207 #[serde(default = "default_domain_version")]
209 pub domain_version: String,
210 #[serde(default)]
212 pub listens_to: Vec<String>,
213 #[serde(default)]
215 pub smtp: Option<SmtpConfig>,
216 #[serde(default)]
218 pub templates: Option<TemplatesConfig>,
219}
220
221fn default_postman_context() -> String { "email-notification".to_string() }
222
223impl Default for PostmanConfig {
224 fn default() -> Self {
225 Self {
226 enabled: false,
227 database: Some("default".to_string()),
228 bounded_context: default_postman_context(),
229 domain_version: default_domain_version(),
230 listens_to: vec![
231 "sapiens.user.created".to_string(),
232 "sapiens.user.email.changed".to_string(),
233 ],
234 smtp: None,
235 templates: None,
236 }
237 }
238}
239
240#[derive(Debug, Clone, Serialize, Deserialize)]
242pub struct SmtpConfig {
243 pub host: String,
245 #[serde(default = "default_smtp_port")]
247 pub port: u16,
248 #[serde(default)]
250 pub username: Option<String>,
251 #[serde(default)]
253 pub password: Option<String>,
254 #[serde(default = "default_use_tls")]
256 pub use_tls: Option<bool>,
257 pub from_email: String,
259 #[serde(default)]
261 pub from_name: Option<String>,
262}
263
264fn default_use_tls() -> Option<bool> { Some(true) }
265fn default_smtp_port() -> u16 { 587 }
266
267#[derive(Debug, Clone, Serialize, Deserialize, Default)]
269pub struct TemplatesConfig {
270 #[serde(default)]
272 pub welcome_email: Option<String>,
273 #[serde(default)]
275 pub password_reset: Option<String>,
276 #[serde(default)]
278 pub email_verification: Option<String>,
279}
280
281#[derive(Debug, Clone, Serialize, Deserialize)]
287pub struct BucketConfig {
288 #[serde(default = "default_false")]
290 pub enabled: bool,
291 #[serde(default)]
293 pub database: Option<String>,
294 #[serde(default = "default_bucket_context")]
296 pub bounded_context: String,
297 #[serde(default = "default_domain_version")]
299 pub domain_version: String,
300 #[serde(default)]
302 pub storage: Option<StorageConfig>,
303}
304
305fn default_bucket_context() -> String { "file-storage".to_string() }
306
307impl Default for BucketConfig {
308 fn default() -> Self {
309 Self {
310 enabled: false,
311 database: Some("default".to_string()),
312 bounded_context: default_bucket_context(),
313 domain_version: default_domain_version(),
314 storage: None,
315 }
316 }
317}
318
319#[derive(Debug, Clone, Serialize, Deserialize)]
321pub struct StorageConfig {
322 #[serde(default = "default_storage_driver")]
324 pub driver: String,
325 #[serde(default)]
327 pub base_path: Option<String>,
328 #[serde(default)]
330 pub max_file_size: Option<String>,
331 #[serde(default)]
333 pub allowed_extensions: Option<Vec<String>>,
334}
335
336fn default_storage_driver() -> String { "local".to_string() }