feat: Automatically set well-known support contacts

This commit is contained in:
Jade Ellis 2025-05-21 20:29:53 +01:00
parent ce40304667
commit 60960c6e09
No known key found for this signature in database
GPG key ID: 8705A2A3EBF77BD2
3 changed files with 69 additions and 21 deletions

View file

@ -1641,19 +1641,29 @@
#
#server =
# This item is undocumented. Please contribute documentation for it.
# URL to a support page for the server, which will be served as part of
# the MSC1929 server support endpoint at /.well-known/matrix/support.
# Will be included alongside any contact information
#
#support_page =
# This item is undocumented. Please contribute documentation for it.
# Role string for server support contacts, to be served as part of the
# MSC1929 server support endpoint at /.well-known/matrix/support.
#
#support_role =
#support_role = "m.role.admin"
# This item is undocumented. Please contribute documentation for it.
# Email address for server support contacts, to be served as part of the
# MSC1929 server support endpoint.
# This will be used along with support_mxid if specified.
#
#support_email =
# This item is undocumented. Please contribute documentation for it.
# Matrix ID for server support contacts, to be served as part of the
# MSC1929 server support endpoint.
# This will be used along with support_email if specified.
#
# If no email or mxid is specified, all of the server's admins will be
# listed.
#
#support_mxid =

View file

@ -1,5 +1,6 @@
use axum::{Json, extract::State, response::IntoResponse};
use conduwuit::{Error, Result};
use futures::StreamExt;
use ruma::api::client::{
discovery::{
discover_homeserver::{self, HomeserverInfo, SlidingSyncProxyInfo},
@ -33,6 +34,8 @@ pub(crate) async fn well_known_client(
/// # `GET /.well-known/matrix/support`
///
/// Server support contact and support page of a homeserver's domain.
/// Implements MSC1929 for server discovery.
/// If no configuration is set, uses admin users as contacts.
pub(crate) async fn well_known_support(
State(services): State<crate::State>,
_body: Ruma<discover_support::Request>,
@ -45,32 +48,51 @@ pub(crate) async fn well_known_support(
.as_ref()
.map(ToString::to_string);
let role = services.server.config.well_known.support_role.clone();
// support page or role must be either defined for this to be valid
if support_page.is_none() && role.is_none() {
return Err(Error::BadRequest(ErrorKind::NotFound, "Not found."));
}
let email_address = services.server.config.well_known.support_email.clone();
let matrix_id = services.server.config.well_known.support_mxid.clone();
// if a role is specified, an email address or matrix id is required
if role.is_some() && (email_address.is_none() && matrix_id.is_none()) {
return Err(Error::BadRequest(ErrorKind::NotFound, "Not found."));
}
// TODO: support defining multiple contacts in the config
let mut contacts: Vec<Contact> = vec![];
if let Some(role) = role {
let contact = Contact { role, email_address, matrix_id };
let role_value = services
.server
.config
.well_known
.support_role
.clone()
.unwrap_or_else(|| "m.role.admin".to_owned().into());
contacts.push(contact);
// Add configured contact if at least one contact method is specified
if email_address.is_some() || matrix_id.is_some() {
contacts.push(Contact {
role: role_value.clone(),
email_address: email_address.clone(),
matrix_id: matrix_id.clone(),
});
}
// Try to add admin users as contacts if no contacts are configured
if contacts.is_empty() {
if let Ok(admin_room) = services.admin.get_admin_room().await {
let admin_users = services.rooms.state_cache.room_members(&admin_room);
let mut stream = admin_users;
while let Some(user_id) = stream.next().await {
// Skip server user
if *user_id == services.globals.server_user {
break;
}
contacts.push(Contact {
role: role_value.clone(),
email_address: None,
matrix_id: Some(user_id.to_owned()),
});
}
}
}
// support page or role+contacts must be either defined for this to be valid
if contacts.is_empty() && support_page.is_none() {
// No admin room, no configured contacts, and no support page
return Err(Error::BadRequest(ErrorKind::NotFound, "Not found."));
}

View file

@ -1897,12 +1897,28 @@ pub struct WellKnownConfig {
/// example: "matrix.example.com:443"
pub server: Option<OwnedServerName>,
/// URL to a support page for the server, which will be served as part of
/// the MSC1929 server support endpoint at /.well-known/matrix/support.
/// Will be included alongside any contact information
pub support_page: Option<Url>,
/// Role string for server support contacts, to be served as part of the
/// MSC1929 server support endpoint at /.well-known/matrix/support.
///
/// default: "m.role.admin"
pub support_role: Option<ContactRole>,
/// Email address for server support contacts, to be served as part of the
/// MSC1929 server support endpoint.
/// This will be used along with support_mxid if specified.
pub support_email: Option<String>,
/// Matrix ID for server support contacts, to be served as part of the
/// MSC1929 server support endpoint.
/// This will be used along with support_email if specified.
///
/// If no email or mxid is specified, all of the server's admins will be
/// listed.
pub support_mxid: Option<OwnedUserId>,
}