continuwuity/src/api/client_server/unversioned.rs
strawberry bfa68e7bc5 refactor well-known stuff to use proper ruma types, config types, etc
this does deprecate the original `well_known_` prefixed config options
with a dedicated/proper config sub-block (`[config.well_known]`)

Signed-off-by: strawberry <strawberry@puppygock.gay>
2024-04-14 22:35:23 -04:00

168 lines
5 KiB
Rust

use std::collections::BTreeMap;
use axum::{response::IntoResponse, Json};
use ruma::api::client::{
discovery::{
discover_homeserver::{self, HomeserverInfo, SlidingSyncProxyInfo},
discover_support::{self, Contact},
get_supported_versions,
},
error::ErrorKind,
};
use crate::{services, Error, Result, Ruma};
/// # `GET /_matrix/client/versions`
///
/// Get the versions of the specification and unstable features supported by
/// this server.
///
/// - Versions take the form MAJOR.MINOR.PATCH
/// - Only the latest PATCH release will be reported for each MAJOR.MINOR value
/// - Unstable features are namespaced and may include version information in
/// their name
///
/// Note: Unstable features are used while developing new features. Clients
/// should avoid using unstable features in their stable releases
pub async fn get_supported_versions_route(
_body: Ruma<get_supported_versions::Request>,
) -> Result<get_supported_versions::Response> {
let resp = get_supported_versions::Response {
versions: vec![
"r0.0.1".to_owned(),
"r0.1.0".to_owned(),
"r0.2.0".to_owned(),
"r0.3.0".to_owned(),
"r0.4.0".to_owned(),
"r0.5.0".to_owned(),
"r0.6.0".to_owned(),
"r0.6.1".to_owned(),
"v1.1".to_owned(),
"v1.2".to_owned(),
"v1.3".to_owned(),
"v1.4".to_owned(),
"v1.5".to_owned(),
],
unstable_features: BTreeMap::from_iter([
("org.matrix.e2e_cross_signing".to_owned(), true),
("org.matrix.msc2285.stable".to_owned(), true),
("uk.half-shot.msc2666.query_mutual_rooms".to_owned(), true),
("org.matrix.msc2836".to_owned(), true),
("org.matrix.msc2946".to_owned(), true),
("org.matrix.msc3026.busy_presence".to_owned(), true),
("org.matrix.msc3827".to_owned(), true),
]),
};
Ok(resp)
}
/// # `GET /.well-known/matrix/client`
///
/// Returns the .well-known URL if it is configured, otherwise returns 404.
pub async fn well_known_client(_body: Ruma<discover_homeserver::Request>) -> Result<discover_homeserver::Response> {
let client_url = match services().globals.well_known_client() {
Some(url) => url.to_string(),
None => return Err(Error::BadRequest(ErrorKind::NotFound, "Not found.")),
};
Ok(discover_homeserver::Response {
homeserver: HomeserverInfo {
base_url: client_url.clone(),
},
identity_server: None,
sliding_sync_proxy: Some(SlidingSyncProxyInfo {
url: client_url,
}),
tile_server: None,
})
}
/// # `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()
.as_ref()
.map(ToString::to_string);
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
/// Web as a non-standard health check.
pub async fn syncv3_client_server_json() -> Result<impl IntoResponse> {
let server_url = match services().globals.well_known_client() {
Some(url) => url.to_string(),
None => match services().globals.well_known_server() {
Some(url) => url.to_string(),
None => return Err(Error::BadRequest(ErrorKind::NotFound, "Not found.")),
},
};
let version = match option_env!("CONDUIT_VERSION_EXTRA") {
Some(extra) => format!("{} ({})", env!("CARGO_PKG_VERSION"), extra),
None => env!("CARGO_PKG_VERSION").to_owned(),
};
Ok(Json(serde_json::json!({
"server": server_url,
"version": version,
})))
}
/// # `GET /_conduwuit/server_version`
///
/// Conduwuit-specific API to get the server version, results akin to
/// `/_matrix/federation/v1/version`
pub async fn conduwuit_server_version() -> Result<impl IntoResponse> {
let version = match option_env!("CONDUIT_VERSION_EXTRA") {
Some(extra) => format!("{} ({})", env!("CARGO_PKG_VERSION"), extra),
None => env!("CARGO_PKG_VERSION").to_owned(),
};
Ok(Json(serde_json::json!({
"name": "Conduwuit",
"version": version,
})))
}