add server-side support for /.well-known/matrix/support

Signed-off-by: strawberry <strawberry@puppygock.gay>
This commit is contained in:
strawberry 2024-04-06 18:42:00 -04:00 committed by June
parent c946352e7f
commit 39946beda8
6 changed files with 79 additions and 12 deletions

View file

@ -258,6 +258,7 @@ features = [
"unstable-msc2870",
"unstable-msc3026",
"unstable-msc3061",
"unstable-msc4121",
"unstable-extensible-events",
]

View file

@ -51,7 +51,6 @@
#sentry_traces_sample_rate = 0.15
### Database configuration
# This is the only directory where conduwuit will save its data, including media
@ -63,7 +62,6 @@ database_path = "/var/lib/matrix-conduit/"
database_backend = "rocksdb"
### Network
# The port(s) conduwuit will be running on. You need to set up a reverse proxy such as
@ -75,7 +73,7 @@ port = 6167
# default address (IPv4 or IPv6) conduwuit will listen on. Generally you want this to be
# localhost (127.0.0.1 / ::1). If you are using Docker or a container NAT networking setup, you
# likely need this to be 0.0.0.0.
# likely need this to be 0.0.0.0.
address = "127.0.0.1"
# How many requests conduwuit sends to other servers at the same time concurrently. Default is 500
@ -153,7 +151,6 @@ ip_range_denylist = [
]
### Moderation / Privacy / Security
# Set to true to allow user type "guest" registrations. Element attempts to register guest users automatically.
@ -250,6 +247,13 @@ url_preview_max_spider_size = 384_000
# Useful if the domain contains allowlist is still too broad for you but you still want to allow all the subdomains under a root domain.
url_preview_check_root_domain = false
# A single contact and/or support page for /.well-known/matrix/support
# All options here are strings. Currently only supports 1 single contact.
# No default.
#well_known_support_page = ""
#well_known_support_role = ""
#well_known_support_email = ""
#well_known_support_mxid = ""
### Misc
@ -344,7 +348,6 @@ url_preview_check_root_domain = false
#cleanup_second_interval = 1800
### RocksDB options
# Set this to true to use RocksDB config options that are tailored to HDDs (slower device storage)
@ -439,7 +442,6 @@ url_preview_check_root_domain = false
#rocksdb_recovery_mode = 1
### Domain Name Resolution and Caching
# Maximum entries stored in DNS memory-cache. The size of an entry may vary so please take care if
@ -470,7 +472,6 @@ url_preview_check_root_domain = false
#query_all_nameservers = false
### Request Timeouts, Connection Timeouts, and Connection Pooling
## Request Timeouts are HTTP response timeouts
@ -548,7 +549,6 @@ url_preview_check_root_domain = false
#pusher_idle_timeout = 15
### Presence / Typing Indicators / Read Receipts
# Config option to control local (your server only) presence updates/requests. Defaults to true.
@ -597,7 +597,6 @@ url_preview_check_root_domain = false
#typing_client_timeout_max_s = 45
# Other options not in [global]:
#
#

View file

@ -1,7 +1,13 @@
use std::collections::BTreeMap;
use axum::{response::IntoResponse, Json};
use ruma::api::client::{discovery::get_supported_versions, error::ErrorKind};
use ruma::api::client::{
discovery::{
discover_support::{self, Contact},
get_supported_versions,
},
error::ErrorKind,
};
use crate::{services, Error, Result, Ruma};
@ -62,6 +68,51 @@ pub async fn well_known_client_route() -> Result<impl IntoResponse> {
})))
}
/// # `GET /.well-known/matrix/support`
///
/// Server support contact and support page of a homeserver's domain.
pub async fn well_known_support(_body: Ruma<discover_support::Request>) -> Result<discover_support::Response> {
let support_page = services().globals.well_known_support_page().clone();
let role = services().globals.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().globals.well_known_support_email().clone();
let matrix_id = services().globals.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."));
}
// TOOD: 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,
};
contacts.push(contact);
}
// support page or role+contacts must be either defined for this to be valid
if contacts.is_empty() && support_page.is_none() {
return Err(Error::BadRequest(ErrorKind::NotFound, "Not found."));
}
Ok(discover_support::Response {
contacts,
support_page,
})
}
/// # `GET /client/server.json`
///
/// Endpoint provided by sliding sync proxy used by some clients such as Element

View file

@ -15,7 +15,9 @@ use figment::{
};
use itertools::Itertools;
use regex::RegexSet;
use ruma::{OwnedRoomId, OwnedServerName, RoomVersionId};
use ruma::{
api::client::discovery::discover_support::ContactRole, OwnedRoomId, OwnedServerName, OwnedUserId, RoomVersionId,
};
use serde::{de::IgnoredAny, Deserialize};
use tracing::{debug, error, warn};
@ -254,6 +256,11 @@ pub struct Config {
#[serde(default = "default_ip_range_denylist")]
pub ip_range_denylist: Vec<String>,
pub well_known_support_page: Option<String>,
pub well_known_support_role: Option<ContactRole>,
pub well_known_support_email: Option<String>,
pub well_known_support_mxid: Option<OwnedUserId>,
#[serde(default = "Vec::new")]
pub url_preview_domain_contains_allowlist: Vec<String>,
#[serde(default = "Vec::new")]

View file

@ -206,6 +206,7 @@ pub fn routes() -> Router {
.ruma_route(server_server::get_keys_route)
.ruma_route(server_server::claim_keys_route)
.ruma_route(server_server::get_hierarchy_route)
.ruma_route(client_server::well_known_support)
.route("/_conduwuit/server_version", get(client_server::conduwuit_server_version))
.route("/_matrix/client/r0/rooms/:room_id/initialSync", get(initial_sync))
.route("/_matrix/client/v3/rooms/:room_id/initialSync", get(initial_sync))

View file

@ -17,7 +17,7 @@ use hickory_resolver::TokioAsyncResolver;
use regex::RegexSet;
use ruma::{
api::{
client::sync::sync_events,
client::{discovery::discover_support::ContactRole, sync::sync_events},
federation::discovery::{ServerSigningKeys, VerifyKey},
},
serde::Base64,
@ -307,6 +307,14 @@ impl Service<'_> {
pub fn ip_range_denylist(&self) -> &[String] { &self.config.ip_range_denylist }
pub fn well_known_support_page(&self) -> &Option<String> { &self.config.well_known_support_page }
pub fn well_known_support_role(&self) -> &Option<ContactRole> { &self.config.well_known_support_role }
pub fn well_known_support_email(&self) -> &Option<String> { &self.config.well_known_support_email }
pub fn well_known_support_mxid(&self) -> &Option<OwnedUserId> { &self.config.well_known_support_mxid }
pub fn block_non_admin_invites(&self) -> bool { self.config.block_non_admin_invites }
pub fn supported_room_versions(&self) -> Vec<RoomVersionId> {