Skip to content

Commit 1b168ed

Browse files
authored
Admin API to expose a few configuration values (#5010)
2 parents b516802 + f9f23fb commit 1b168ed

File tree

5 files changed

+210
-2
lines changed

5 files changed

+210
-2
lines changed

crates/handlers/src/admin/mod.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use axum::{
2020
use hyper::header::{ACCEPT, AUTHORIZATION, CONTENT_TYPE};
2121
use indexmap::IndexMap;
2222
use mas_axum_utils::InternalError;
23-
use mas_data_model::BoxRng;
23+
use mas_data_model::{BoxRng, SiteConfig};
2424
use mas_http::CorsLayerExt;
2525
use mas_matrix::HomeserverConnection;
2626
use mas_policy::PolicyFactory;
@@ -43,6 +43,11 @@ use crate::passwords::PasswordManager;
4343

4444
fn finish(t: TransformOpenApi) -> TransformOpenApi {
4545
t.title("Matrix Authentication Service admin API")
46+
.tag(Tag {
47+
name: "server".to_owned(),
48+
description: Some("Information about the server".to_owned()),
49+
..Tag::default()
50+
})
4651
.tag(Tag {
4752
name: "compat-session".to_owned(),
4853
description: Some("Manage compatibility sessions from legacy clients".to_owned()),
@@ -153,6 +158,7 @@ where
153158
Templates: FromRef<S>,
154159
UrlBuilder: FromRef<S>,
155160
Arc<PolicyFactory>: FromRef<S>,
161+
SiteConfig: FromRef<S>,
156162
{
157163
// We *always* want to explicitly set the possible responses, beacuse the
158164
// infered ones are not necessarily correct

crates/handlers/src/admin/v1/mod.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use aide::axum::{
1111
routing::{get_with, post_with},
1212
};
1313
use axum::extract::{FromRef, FromRequestParts};
14-
use mas_data_model::BoxRng;
14+
use mas_data_model::{BoxRng, SiteConfig};
1515
use mas_matrix::HomeserverConnection;
1616
use mas_policy::PolicyFactory;
1717

@@ -21,6 +21,7 @@ use crate::passwords::PasswordManager;
2121
mod compat_sessions;
2222
mod oauth2_sessions;
2323
mod policy_data;
24+
mod site_config;
2425
mod upstream_oauth_links;
2526
mod user_emails;
2627
mod user_registration_tokens;
@@ -32,11 +33,16 @@ where
3233
S: Clone + Send + Sync + 'static,
3334
Arc<dyn HomeserverConnection>: FromRef<S>,
3435
PasswordManager: FromRef<S>,
36+
SiteConfig: FromRef<S>,
3537
Arc<PolicyFactory>: FromRef<S>,
3638
BoxRng: FromRequestParts<S>,
3739
CallContext: FromRequestParts<S>,
3840
{
3941
ApiRouter::<S>::new()
42+
.api_route(
43+
"/site-config",
44+
get_with(self::site_config::handler, self::site_config::doc),
45+
)
4046
.api_route(
4147
"/compat-sessions",
4248
get_with(self::compat_sessions::list, self::compat_sessions::list_doc),
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// Copyright 2025 New Vector Ltd.
2+
//
3+
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
4+
// Please see LICENSE files in the repository root for full details.
5+
6+
use aide::transform::TransformOperation;
7+
use axum::{Json, extract::State};
8+
use schemars::JsonSchema;
9+
use serde::Serialize;
10+
11+
use crate::admin::call_context::CallContext;
12+
13+
#[allow(clippy::struct_excessive_bools)]
14+
#[derive(Serialize, JsonSchema)]
15+
pub struct SiteConfig {
16+
/// The Matrix server name for which this instance is configured
17+
server_name: String,
18+
19+
/// Whether password login is enabled.
20+
pub password_login_enabled: bool,
21+
22+
/// Whether password registration is enabled.
23+
pub password_registration_enabled: bool,
24+
25+
/// Whether registration tokens are required for password registrations.
26+
pub registration_token_required: bool,
27+
28+
/// Whether users can change their email.
29+
pub email_change_allowed: bool,
30+
31+
/// Whether users can change their display name.
32+
pub displayname_change_allowed: bool,
33+
34+
/// Whether users can change their password.
35+
pub password_change_allowed: bool,
36+
37+
/// Whether users can recover their account via email.
38+
pub account_recovery_allowed: bool,
39+
40+
/// Whether users can delete their own account.
41+
pub account_deactivation_allowed: bool,
42+
43+
/// Whether CAPTCHA during registration is enabled.
44+
pub captcha_enabled: bool,
45+
46+
/// Minimum password complexity, between 0 and 4.
47+
/// This is a score from zxcvbn.
48+
#[schemars(range(min = 0, max = 4))]
49+
pub minimum_password_complexity: u8,
50+
}
51+
52+
pub fn doc(operation: TransformOperation) -> TransformOperation {
53+
operation
54+
.id("siteConfig")
55+
.tag("server")
56+
.summary("Get informations about the configuration of this MAS instance")
57+
.response_with::<200, Json<SiteConfig>, _>(|t| {
58+
t.example(SiteConfig {
59+
server_name: "example.com".to_owned(),
60+
password_login_enabled: true,
61+
password_registration_enabled: true,
62+
registration_token_required: true,
63+
email_change_allowed: true,
64+
displayname_change_allowed: true,
65+
password_change_allowed: true,
66+
account_recovery_allowed: true,
67+
account_deactivation_allowed: true,
68+
captcha_enabled: true,
69+
minimum_password_complexity: 3,
70+
})
71+
})
72+
}
73+
74+
#[tracing::instrument(name = "handler.admin.v1.site_config", skip_all)]
75+
pub async fn handler(
76+
_: CallContext,
77+
State(site_config): State<mas_data_model::SiteConfig>,
78+
) -> Json<SiteConfig> {
79+
Json(SiteConfig {
80+
server_name: site_config.server_name,
81+
password_login_enabled: site_config.password_login_enabled,
82+
password_registration_enabled: site_config.password_registration_enabled,
83+
registration_token_required: site_config.registration_token_required,
84+
email_change_allowed: site_config.email_change_allowed,
85+
displayname_change_allowed: site_config.displayname_change_allowed,
86+
password_change_allowed: site_config.password_change_allowed,
87+
account_recovery_allowed: site_config.account_recovery_allowed,
88+
account_deactivation_allowed: site_config.account_deactivation_allowed,
89+
captcha_enabled: site_config.captcha.is_some(),
90+
minimum_password_complexity: site_config.minimum_password_complexity,
91+
})
92+
}

crates/handlers/src/bin/api-schema.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ impl_from_ref!(Arc<dyn mas_matrix::HomeserverConnection>);
5959
impl_from_ref!(mas_keystore::Keystore);
6060
impl_from_ref!(mas_handlers::passwords::PasswordManager);
6161
impl_from_ref!(Arc<mas_policy::PolicyFactory>);
62+
impl_from_ref!(mas_data_model::SiteConfig);
6263

6364
fn main() -> Result<(), Box<dyn std::error::Error>> {
6465
let (mut api, _) = mas_handlers::admin_api_router::<DummyState>();

docs/api/spec.json

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,40 @@
1616
}
1717
],
1818
"paths": {
19+
"/api/admin/v1/site-config": {
20+
"get": {
21+
"tags": [
22+
"server"
23+
],
24+
"summary": "Get informations about the configuration of this MAS instance",
25+
"operationId": "siteConfig",
26+
"responses": {
27+
"200": {
28+
"description": "",
29+
"content": {
30+
"application/json": {
31+
"schema": {
32+
"$ref": "#/components/schemas/SiteConfig"
33+
},
34+
"example": {
35+
"server_name": "example.com",
36+
"password_login_enabled": true,
37+
"password_registration_enabled": true,
38+
"registration_token_required": true,
39+
"email_change_allowed": true,
40+
"displayname_change_allowed": true,
41+
"password_change_allowed": true,
42+
"account_recovery_allowed": true,
43+
"account_deactivation_allowed": true,
44+
"captcha_enabled": true,
45+
"minimum_password_complexity": 3
46+
}
47+
}
48+
}
49+
}
50+
}
51+
}
52+
},
1953
"/api/admin/v1/compat-sessions": {
2054
"get": {
2155
"tags": [
@@ -3186,6 +3220,71 @@
31863220
}
31873221
},
31883222
"schemas": {
3223+
"SiteConfig": {
3224+
"type": "object",
3225+
"required": [
3226+
"account_deactivation_allowed",
3227+
"account_recovery_allowed",
3228+
"captcha_enabled",
3229+
"displayname_change_allowed",
3230+
"email_change_allowed",
3231+
"minimum_password_complexity",
3232+
"password_change_allowed",
3233+
"password_login_enabled",
3234+
"password_registration_enabled",
3235+
"registration_token_required",
3236+
"server_name"
3237+
],
3238+
"properties": {
3239+
"server_name": {
3240+
"description": "The Matrix server name for which this instance is configured",
3241+
"type": "string"
3242+
},
3243+
"password_login_enabled": {
3244+
"description": "Whether password login is enabled.",
3245+
"type": "boolean"
3246+
},
3247+
"password_registration_enabled": {
3248+
"description": "Whether password registration is enabled.",
3249+
"type": "boolean"
3250+
},
3251+
"registration_token_required": {
3252+
"description": "Whether registration tokens are required for password registrations.",
3253+
"type": "boolean"
3254+
},
3255+
"email_change_allowed": {
3256+
"description": "Whether users can change their email.",
3257+
"type": "boolean"
3258+
},
3259+
"displayname_change_allowed": {
3260+
"description": "Whether users can change their display name.",
3261+
"type": "boolean"
3262+
},
3263+
"password_change_allowed": {
3264+
"description": "Whether users can change their password.",
3265+
"type": "boolean"
3266+
},
3267+
"account_recovery_allowed": {
3268+
"description": "Whether users can recover their account via email.",
3269+
"type": "boolean"
3270+
},
3271+
"account_deactivation_allowed": {
3272+
"description": "Whether users can delete their own account.",
3273+
"type": "boolean"
3274+
},
3275+
"captcha_enabled": {
3276+
"description": "Whether CAPTCHA during registration is enabled.",
3277+
"type": "boolean"
3278+
},
3279+
"minimum_password_complexity": {
3280+
"description": "Minimum password complexity, between 0 and 4. This is a score from zxcvbn.",
3281+
"type": "integer",
3282+
"format": "uint8",
3283+
"maximum": 4.0,
3284+
"minimum": 0.0
3285+
}
3286+
}
3287+
},
31893288
"PaginationParams": {
31903289
"type": "object",
31913290
"properties": {
@@ -4586,6 +4685,10 @@
45864685
}
45874686
],
45884687
"tags": [
4688+
{
4689+
"name": "server",
4690+
"description": "Information about the server"
4691+
},
45894692
{
45904693
"name": "compat-session",
45914694
"description": "Manage compatibility sessions from legacy clients"

0 commit comments

Comments
 (0)