1use rand::Rng;
8use schemars::JsonSchema;
9use serde::{Deserialize, Serialize};
10
11mod account;
12mod branding;
13mod captcha;
14mod clients;
15mod database;
16mod email;
17mod experimental;
18mod http;
19mod matrix;
20mod passwords;
21mod policy;
22mod rate_limiting;
23mod secrets;
24mod telemetry;
25mod templates;
26mod upstream_oauth2;
27
28pub use self::{
29 account::AccountConfig,
30 branding::BrandingConfig,
31 captcha::{CaptchaConfig, CaptchaServiceKind},
32 clients::{ClientAuthMethodConfig, ClientConfig, ClientsConfig},
33 database::{DatabaseConfig, PgSslMode},
34 email::{EmailConfig, EmailSmtpMode, EmailTransportKind},
35 experimental::ExperimentalConfig,
36 http::{
37 BindConfig as HttpBindConfig, HttpConfig, ListenerConfig as HttpListenerConfig,
38 Resource as HttpResource, TlsConfig as HttpTlsConfig, UnixOrTcp,
39 },
40 matrix::{HomeserverKind, MatrixConfig},
41 passwords::{Algorithm as PasswordAlgorithm, PasswordsConfig},
42 policy::PolicyConfig,
43 rate_limiting::RateLimitingConfig,
44 secrets::SecretsConfig,
45 telemetry::{
46 MetricsConfig, MetricsExporterKind, Propagator, TelemetryConfig, TracingConfig,
47 TracingExporterKind,
48 },
49 templates::TemplatesConfig,
50 upstream_oauth2::{
51 ClaimsImports as UpstreamOAuth2ClaimsImports, DiscoveryMode as UpstreamOAuth2DiscoveryMode,
52 EmailImportPreference as UpstreamOAuth2EmailImportPreference,
53 ImportAction as UpstreamOAuth2ImportAction, PkceMethod as UpstreamOAuth2PkceMethod,
54 Provider as UpstreamOAuth2Provider, ResponseMode as UpstreamOAuth2ResponseMode,
55 TokenAuthMethod as UpstreamOAuth2TokenAuthMethod, UpstreamOAuth2Config,
56 },
57};
58use crate::util::ConfigurationSection;
59
60#[derive(Debug, Serialize, Deserialize, JsonSchema)]
62pub struct RootConfig {
63 #[serde(default, skip_serializing_if = "ClientsConfig::is_default")]
65 pub clients: ClientsConfig,
66
67 #[serde(default)]
69 pub http: HttpConfig,
70
71 #[serde(default)]
73 pub database: DatabaseConfig,
74
75 #[serde(default, skip_serializing_if = "TelemetryConfig::is_default")]
77 pub telemetry: TelemetryConfig,
78
79 #[serde(default, skip_serializing_if = "TemplatesConfig::is_default")]
81 pub templates: TemplatesConfig,
82
83 #[serde(default)]
85 pub email: EmailConfig,
86
87 pub secrets: SecretsConfig,
89
90 #[serde(default)]
92 pub passwords: PasswordsConfig,
93
94 pub matrix: MatrixConfig,
96
97 #[serde(default, skip_serializing_if = "PolicyConfig::is_default")]
99 pub policy: PolicyConfig,
100
101 #[serde(default, skip_serializing_if = "RateLimitingConfig::is_default")]
104 pub rate_limiting: RateLimitingConfig,
105
106 #[serde(default, skip_serializing_if = "UpstreamOAuth2Config::is_default")]
108 pub upstream_oauth2: UpstreamOAuth2Config,
109
110 #[serde(default, skip_serializing_if = "BrandingConfig::is_default")]
112 pub branding: BrandingConfig,
113
114 #[serde(default, skip_serializing_if = "CaptchaConfig::is_default")]
116 pub captcha: CaptchaConfig,
117
118 #[serde(default, skip_serializing_if = "AccountConfig::is_default")]
121 pub account: AccountConfig,
122
123 #[serde(default, skip_serializing_if = "ExperimentalConfig::is_default")]
125 pub experimental: ExperimentalConfig,
126}
127
128impl ConfigurationSection for RootConfig {
129 fn validate(&self, figment: &figment::Figment) -> Result<(), figment::Error> {
130 self.clients.validate(figment)?;
131 self.http.validate(figment)?;
132 self.database.validate(figment)?;
133 self.telemetry.validate(figment)?;
134 self.templates.validate(figment)?;
135 self.email.validate(figment)?;
136 self.passwords.validate(figment)?;
137 self.secrets.validate(figment)?;
138 self.matrix.validate(figment)?;
139 self.policy.validate(figment)?;
140 self.rate_limiting.validate(figment)?;
141 self.upstream_oauth2.validate(figment)?;
142 self.branding.validate(figment)?;
143 self.captcha.validate(figment)?;
144 self.account.validate(figment)?;
145 self.experimental.validate(figment)?;
146
147 Ok(())
148 }
149}
150
151impl RootConfig {
152 pub async fn generate<R>(mut rng: R) -> anyhow::Result<Self>
158 where
159 R: Rng + Send,
160 {
161 Ok(Self {
162 clients: ClientsConfig::default(),
163 http: HttpConfig::default(),
164 database: DatabaseConfig::default(),
165 telemetry: TelemetryConfig::default(),
166 templates: TemplatesConfig::default(),
167 email: EmailConfig::default(),
168 passwords: PasswordsConfig::default(),
169 secrets: SecretsConfig::generate(&mut rng).await?,
170 matrix: MatrixConfig::generate(&mut rng),
171 policy: PolicyConfig::default(),
172 rate_limiting: RateLimitingConfig::default(),
173 upstream_oauth2: UpstreamOAuth2Config::default(),
174 branding: BrandingConfig::default(),
175 captcha: CaptchaConfig::default(),
176 account: AccountConfig::default(),
177 experimental: ExperimentalConfig::default(),
178 })
179 }
180
181 #[must_use]
183 pub fn test() -> Self {
184 Self {
185 clients: ClientsConfig::default(),
186 http: HttpConfig::default(),
187 database: DatabaseConfig::default(),
188 telemetry: TelemetryConfig::default(),
189 templates: TemplatesConfig::default(),
190 passwords: PasswordsConfig::default(),
191 email: EmailConfig::default(),
192 secrets: SecretsConfig::test(),
193 matrix: MatrixConfig::test(),
194 policy: PolicyConfig::default(),
195 rate_limiting: RateLimitingConfig::default(),
196 upstream_oauth2: UpstreamOAuth2Config::default(),
197 branding: BrandingConfig::default(),
198 captcha: CaptchaConfig::default(),
199 account: AccountConfig::default(),
200 experimental: ExperimentalConfig::default(),
201 }
202 }
203}
204
205#[allow(missing_docs)]
207#[derive(Debug, Deserialize)]
208pub struct AppConfig {
209 #[serde(default)]
210 pub http: HttpConfig,
211
212 #[serde(default)]
213 pub database: DatabaseConfig,
214
215 #[serde(default)]
216 pub templates: TemplatesConfig,
217
218 #[serde(default)]
219 pub email: EmailConfig,
220
221 pub secrets: SecretsConfig,
222
223 #[serde(default)]
224 pub passwords: PasswordsConfig,
225
226 pub matrix: MatrixConfig,
227
228 #[serde(default)]
229 pub policy: PolicyConfig,
230
231 #[serde(default)]
232 pub rate_limiting: RateLimitingConfig,
233
234 #[serde(default)]
235 pub branding: BrandingConfig,
236
237 #[serde(default)]
238 pub captcha: CaptchaConfig,
239
240 #[serde(default)]
241 pub account: AccountConfig,
242
243 #[serde(default)]
244 pub experimental: ExperimentalConfig,
245}
246
247impl ConfigurationSection for AppConfig {
248 fn validate(&self, figment: &figment::Figment) -> Result<(), figment::Error> {
249 self.http.validate(figment)?;
250 self.database.validate(figment)?;
251 self.templates.validate(figment)?;
252 self.email.validate(figment)?;
253 self.passwords.validate(figment)?;
254 self.secrets.validate(figment)?;
255 self.matrix.validate(figment)?;
256 self.policy.validate(figment)?;
257 self.rate_limiting.validate(figment)?;
258 self.branding.validate(figment)?;
259 self.captcha.validate(figment)?;
260 self.account.validate(figment)?;
261 self.experimental.validate(figment)?;
262
263 Ok(())
264 }
265}
266
267#[allow(missing_docs)]
269#[derive(Debug, Deserialize)]
270pub struct SyncConfig {
271 #[serde(default)]
272 pub database: DatabaseConfig,
273
274 pub secrets: SecretsConfig,
275
276 #[serde(default)]
277 pub clients: ClientsConfig,
278
279 #[serde(default)]
280 pub upstream_oauth2: UpstreamOAuth2Config,
281}
282
283impl ConfigurationSection for SyncConfig {
284 fn validate(&self, figment: &figment::Figment) -> Result<(), figment::Error> {
285 self.database.validate(figment)?;
286 self.secrets.validate(figment)?;
287 self.clients.validate(figment)?;
288 self.upstream_oauth2.validate(figment)?;
289
290 Ok(())
291 }
292}