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::{
42 Algorithm as PasswordAlgorithm, HashingScheme as PasswordHashingScheme, PasswordsConfig,
43 },
44 policy::PolicyConfig,
45 rate_limiting::RateLimitingConfig,
46 secrets::SecretsConfig,
47 telemetry::{
48 MetricsConfig, MetricsExporterKind, Propagator, TelemetryConfig, TracingConfig,
49 TracingExporterKind,
50 },
51 templates::TemplatesConfig,
52 upstream_oauth2::{
53 ClaimsImports as UpstreamOAuth2ClaimsImports, DiscoveryMode as UpstreamOAuth2DiscoveryMode,
54 EmailImportPreference as UpstreamOAuth2EmailImportPreference,
55 ImportAction as UpstreamOAuth2ImportAction,
56 OnBackchannelLogout as UpstreamOAuth2OnBackchannelLogout,
57 PkceMethod as UpstreamOAuth2PkceMethod, Provider as UpstreamOAuth2Provider,
58 ResponseMode as UpstreamOAuth2ResponseMode,
59 TokenAuthMethod as UpstreamOAuth2TokenAuthMethod, UpstreamOAuth2Config,
60 },
61};
62use crate::util::ConfigurationSection;
63
64#[derive(Debug, Serialize, Deserialize, JsonSchema)]
66pub struct RootConfig {
67 #[serde(default, skip_serializing_if = "ClientsConfig::is_default")]
69 pub clients: ClientsConfig,
70
71 #[serde(default)]
73 pub http: HttpConfig,
74
75 #[serde(default)]
77 pub database: DatabaseConfig,
78
79 #[serde(default, skip_serializing_if = "TelemetryConfig::is_default")]
81 pub telemetry: TelemetryConfig,
82
83 #[serde(default, skip_serializing_if = "TemplatesConfig::is_default")]
85 pub templates: TemplatesConfig,
86
87 #[serde(default)]
89 pub email: EmailConfig,
90
91 pub secrets: SecretsConfig,
93
94 #[serde(default)]
96 pub passwords: PasswordsConfig,
97
98 pub matrix: MatrixConfig,
100
101 #[serde(default, skip_serializing_if = "PolicyConfig::is_default")]
103 pub policy: PolicyConfig,
104
105 #[serde(default, skip_serializing_if = "RateLimitingConfig::is_default")]
108 pub rate_limiting: RateLimitingConfig,
109
110 #[serde(default, skip_serializing_if = "UpstreamOAuth2Config::is_default")]
112 pub upstream_oauth2: UpstreamOAuth2Config,
113
114 #[serde(default, skip_serializing_if = "BrandingConfig::is_default")]
116 pub branding: BrandingConfig,
117
118 #[serde(default, skip_serializing_if = "CaptchaConfig::is_default")]
120 pub captcha: CaptchaConfig,
121
122 #[serde(default, skip_serializing_if = "AccountConfig::is_default")]
125 pub account: AccountConfig,
126
127 #[serde(default, skip_serializing_if = "ExperimentalConfig::is_default")]
129 pub experimental: ExperimentalConfig,
130}
131
132impl ConfigurationSection for RootConfig {
133 fn validate(&self, figment: &figment::Figment) -> Result<(), figment::Error> {
134 self.clients.validate(figment)?;
135 self.http.validate(figment)?;
136 self.database.validate(figment)?;
137 self.telemetry.validate(figment)?;
138 self.templates.validate(figment)?;
139 self.email.validate(figment)?;
140 self.passwords.validate(figment)?;
141 self.secrets.validate(figment)?;
142 self.matrix.validate(figment)?;
143 self.policy.validate(figment)?;
144 self.rate_limiting.validate(figment)?;
145 self.upstream_oauth2.validate(figment)?;
146 self.branding.validate(figment)?;
147 self.captcha.validate(figment)?;
148 self.account.validate(figment)?;
149 self.experimental.validate(figment)?;
150
151 Ok(())
152 }
153}
154
155impl RootConfig {
156 pub async fn generate<R>(mut rng: R) -> anyhow::Result<Self>
162 where
163 R: Rng + Send,
164 {
165 Ok(Self {
166 clients: ClientsConfig::default(),
167 http: HttpConfig::default(),
168 database: DatabaseConfig::default(),
169 telemetry: TelemetryConfig::default(),
170 templates: TemplatesConfig::default(),
171 email: EmailConfig::default(),
172 passwords: PasswordsConfig::default(),
173 secrets: SecretsConfig::generate(&mut rng).await?,
174 matrix: MatrixConfig::generate(&mut rng),
175 policy: PolicyConfig::default(),
176 rate_limiting: RateLimitingConfig::default(),
177 upstream_oauth2: UpstreamOAuth2Config::default(),
178 branding: BrandingConfig::default(),
179 captcha: CaptchaConfig::default(),
180 account: AccountConfig::default(),
181 experimental: ExperimentalConfig::default(),
182 })
183 }
184
185 #[must_use]
187 pub fn test() -> Self {
188 Self {
189 clients: ClientsConfig::default(),
190 http: HttpConfig::default(),
191 database: DatabaseConfig::default(),
192 telemetry: TelemetryConfig::default(),
193 templates: TemplatesConfig::default(),
194 passwords: PasswordsConfig::default(),
195 email: EmailConfig::default(),
196 secrets: SecretsConfig::test(),
197 matrix: MatrixConfig::test(),
198 policy: PolicyConfig::default(),
199 rate_limiting: RateLimitingConfig::default(),
200 upstream_oauth2: UpstreamOAuth2Config::default(),
201 branding: BrandingConfig::default(),
202 captcha: CaptchaConfig::default(),
203 account: AccountConfig::default(),
204 experimental: ExperimentalConfig::default(),
205 }
206 }
207}
208
209#[allow(missing_docs)]
211#[derive(Debug, Deserialize)]
212pub struct AppConfig {
213 #[serde(default)]
214 pub http: HttpConfig,
215
216 #[serde(default)]
217 pub database: DatabaseConfig,
218
219 #[serde(default)]
220 pub templates: TemplatesConfig,
221
222 #[serde(default)]
223 pub email: EmailConfig,
224
225 pub secrets: SecretsConfig,
226
227 #[serde(default)]
228 pub passwords: PasswordsConfig,
229
230 pub matrix: MatrixConfig,
231
232 #[serde(default)]
233 pub policy: PolicyConfig,
234
235 #[serde(default)]
236 pub rate_limiting: RateLimitingConfig,
237
238 #[serde(default)]
239 pub branding: BrandingConfig,
240
241 #[serde(default)]
242 pub captcha: CaptchaConfig,
243
244 #[serde(default)]
245 pub account: AccountConfig,
246
247 #[serde(default)]
248 pub experimental: ExperimentalConfig,
249}
250
251impl ConfigurationSection for AppConfig {
252 fn validate(&self, figment: &figment::Figment) -> Result<(), figment::Error> {
253 self.http.validate(figment)?;
254 self.database.validate(figment)?;
255 self.templates.validate(figment)?;
256 self.email.validate(figment)?;
257 self.passwords.validate(figment)?;
258 self.secrets.validate(figment)?;
259 self.matrix.validate(figment)?;
260 self.policy.validate(figment)?;
261 self.rate_limiting.validate(figment)?;
262 self.branding.validate(figment)?;
263 self.captcha.validate(figment)?;
264 self.account.validate(figment)?;
265 self.experimental.validate(figment)?;
266
267 Ok(())
268 }
269}
270
271#[allow(missing_docs)]
273#[derive(Debug, Deserialize)]
274pub struct SyncConfig {
275 #[serde(default)]
276 pub database: DatabaseConfig,
277
278 pub secrets: SecretsConfig,
279
280 #[serde(default)]
281 pub clients: ClientsConfig,
282
283 #[serde(default)]
284 pub upstream_oauth2: UpstreamOAuth2Config,
285}
286
287impl ConfigurationSection for SyncConfig {
288 fn validate(&self, figment: &figment::Figment) -> Result<(), figment::Error> {
289 self.database.validate(figment)?;
290 self.secrets.validate(figment)?;
291 self.clients.validate(figment)?;
292 self.upstream_oauth2.validate(figment)?;
293
294 Ok(())
295 }
296}