mas_config/sections/
matrix.rs

1// Copyright 2024, 2025 New Vector Ltd.
2// Copyright 2022-2024 The Matrix.org Foundation C.I.C.
3//
4// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
5// Please see LICENSE files in the repository root for full details.
6
7use rand::{
8    Rng,
9    distributions::{Alphanumeric, DistString},
10};
11use schemars::JsonSchema;
12use serde::{Deserialize, Serialize};
13use serde_with::serde_as;
14use url::Url;
15
16use super::ConfigurationSection;
17
18fn default_homeserver() -> String {
19    "localhost:8008".to_owned()
20}
21
22fn default_endpoint() -> Url {
23    Url::parse("http://localhost:8008/").unwrap()
24}
25
26/// The kind of homeserver it is.
27#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
28#[serde(rename_all = "snake_case")]
29pub enum HomeserverKind {
30    /// Homeserver is Synapse, using the legacy API
31    ///
32    /// This will switch to using the modern API in a few releases.
33    #[default]
34    Synapse,
35
36    /// Homeserver is Synapse, using the legacy API, in read-only mode
37    ///
38    /// This is meant for testing rolling out Matrix Authentication Service with
39    /// no risk of writing data to the homeserver.
40    ///
41    /// This will switch to using the modern API in a few releases.
42    SynapseReadOnly,
43
44    /// Homeserver is Synapse, using the legacy API,
45    SynapseLegacy,
46
47    /// Homeserver is Synapse, with the modern API available
48    SynapseModern,
49}
50
51/// Configuration related to the Matrix homeserver
52#[serde_as]
53#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
54pub struct MatrixConfig {
55    /// The kind of homeserver it is.
56    #[serde(default)]
57    pub kind: HomeserverKind,
58
59    /// The server name of the homeserver.
60    #[serde(default = "default_homeserver")]
61    pub homeserver: String,
62
63    /// Shared secret to use for calls to the admin API
64    pub secret: String,
65
66    /// The base URL of the homeserver's client API
67    #[serde(default = "default_endpoint")]
68    pub endpoint: Url,
69}
70
71impl ConfigurationSection for MatrixConfig {
72    const PATH: Option<&'static str> = Some("matrix");
73}
74
75impl MatrixConfig {
76    pub(crate) fn generate<R>(mut rng: R) -> Self
77    where
78        R: Rng + Send,
79    {
80        Self {
81            kind: HomeserverKind::default(),
82            homeserver: default_homeserver(),
83            secret: Alphanumeric.sample_string(&mut rng, 32),
84            endpoint: default_endpoint(),
85        }
86    }
87
88    pub(crate) fn test() -> Self {
89        Self {
90            kind: HomeserverKind::default(),
91            homeserver: default_homeserver(),
92            secret: "test".to_owned(),
93            endpoint: default_endpoint(),
94        }
95    }
96}
97
98#[cfg(test)]
99mod tests {
100    use figment::{
101        Figment, Jail,
102        providers::{Format, Yaml},
103    };
104
105    use super::*;
106
107    #[test]
108    fn load_config() {
109        Jail::expect_with(|jail| {
110            jail.create_file(
111                "config.yaml",
112                r"
113                    matrix:
114                      homeserver: matrix.org
115                      secret: test
116                ",
117            )?;
118
119            let config = Figment::new()
120                .merge(Yaml::file("config.yaml"))
121                .extract_inner::<MatrixConfig>("matrix")?;
122
123            assert_eq!(&config.homeserver, "matrix.org");
124            assert_eq!(&config.secret, "test");
125
126            Ok(())
127        });
128    }
129}