Skip to main content

tuwunel_api/client/
well_known.rs

1use axum::extract::State;
2use ruma::api::client::discovery::{
3	discover_homeserver::{self, HomeserverInfo},
4	discover_support::{self, Contact},
5};
6use tuwunel_core::{Err, Result};
7
8use crate::{Ruma, client::rtc};
9
10/// # `GET /.well-known/matrix/client`
11///
12/// Returns the .well-known URL if it is configured, otherwise returns 404.
13/// Also includes RTC transport configuration for Element Call (MSC4143).
14pub(crate) async fn well_known_client(
15	State(services): State<crate::State>,
16	_body: Ruma<discover_homeserver::Request>,
17) -> Result<discover_homeserver::Response> {
18	let homeserver = HomeserverInfo {
19		base_url: match services.server.config.well_known.client.as_ref() {
20			| Some(url) => url.to_string(),
21			| None => return Err!(Request(NotFound("Not found."))),
22		},
23	};
24
25	let rtc_foci = rtc::get_transports(&services)?;
26
27	Ok(discover_homeserver::Response {
28		rtc_foci,
29		..discover_homeserver::Response::new(homeserver)
30	})
31}
32
33/// # `GET /.well-known/matrix/support`
34///
35/// Server support contact and support page of a homeserver's domain.
36pub(crate) async fn well_known_support(
37	State(services): State<crate::State>,
38	_body: Ruma<discover_support::Request>,
39) -> Result<discover_support::Response> {
40	let support_page = services
41		.server
42		.config
43		.well_known
44		.support_page
45		.as_ref()
46		.map(ToString::to_string);
47
48	let role = services
49		.server
50		.config
51		.well_known
52		.support_role
53		.clone();
54
55	// support page or role must be either defined for this to be valid
56	if support_page.is_none() && role.is_none() {
57		return Err!(Request(NotFound("Not found.")));
58	}
59
60	let email_address = services
61		.server
62		.config
63		.well_known
64		.support_email
65		.clone();
66
67	let matrix_id = services
68		.server
69		.config
70		.well_known
71		.support_mxid
72		.clone();
73
74	// if a role is specified, an email address or matrix id is required
75	if role.is_some() && (email_address.is_none() && matrix_id.is_none()) {
76		return Err!(Request(NotFound("Not found.")));
77	}
78
79	// TODO: support defining multiple contacts in the config
80	let mut contacts: Vec<Contact> = vec![];
81
82	if let Some(role) = role {
83		let contact = Contact { role, email_address, matrix_id };
84
85		contacts.push(contact);
86	}
87
88	// support page or role+contacts must be either defined for this to be valid
89	if contacts.is_empty() && support_page.is_none() {
90		return Err!(Request(NotFound("Not found.")));
91	}
92
93	Ok(discover_support::Response { contacts, support_page })
94}