diff --git a/Cargo.lock b/Cargo.lock index 6be278be..03232b2a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -522,6 +522,7 @@ dependencies = [ "tracing-flame", "tracing-opentelemetry", "tracing-subscriber", + "url", "webpage", ] diff --git a/Cargo.toml b/Cargo.toml index 97a7a952..d6c05719 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -75,6 +75,9 @@ http = "0.2.12" # used to replace the channels of the tokio runtime loole = "0.3.0" +# Validating urls in config, was already a transitive dependency +url = { version = "2", features = ["serde"] } + # standard date and time tools [dependencies.chrono] version = "0.4.37" diff --git a/conduwuit-example.toml b/conduwuit-example.toml index 8128d150..73084f96 100644 --- a/conduwuit-example.toml +++ b/conduwuit-example.toml @@ -2,6 +2,8 @@ # This is the official example config for conduwuit. # If you use it for your server, you will need to adjust it to your own needs. # At the very least, change the server_name field! +# +# This documentation can also be found at https://conduwuit.puppyirl.gay/configuration.html # ============================================================================= [global] @@ -247,14 +249,6 @@ 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 = "" - # Config option to allow or disallow incoming federation requests that obtain the profiles # of our local users from `/_matrix/federation/v1/query/profile` # @@ -281,12 +275,6 @@ allow_profile_lookup_federation_requests = true # Defaults to false. #allow_check_for_updates = false -# If you are using delegation via well-known files and you cannot serve them from your reverse proxy, you can -# uncomment these to serve them directly from conduwuit. This requires proxying all requests to conduwuit, not just `/_matrix` to work. -#well_known_server = "matrix.example.com:443" -#well_known_client = "https://matrix.example.com" -# Note that whatever you put will show up in the well-known JSON values. - # Set to false to disable users from joining or creating room versions that aren't 100% officially supported by conduwuit. # conduwuit officially supports room versions 6 - 10. conduwuit has experimental/unstable support for 3 - 5, and 11. # Defaults to true. @@ -623,3 +611,20 @@ allow_profile_lookup_federation_requests = true # This config option is only available if conduwuit was built with `axum_dual_protocol` feature (not default feature) # Defaults to false #dual_protocol = false + + +# If you are using delegation via well-known files and you cannot serve them from your reverse proxy, you can +# uncomment these to serve them directly from conduwuit. This requires proxying all requests to conduwuit, not just `/_matrix` to work. +# +#[global.well_known] +#server = "matrix.example.com:443" +#client = "https://matrix.example.com" +# +# 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 = "" diff --git a/src/api/client_server/session.rs b/src/api/client_server/session.rs index 9ac7f918..70ed113c 100644 --- a/src/api/client_server/session.rs +++ b/src/api/client_server/session.rs @@ -199,15 +199,13 @@ pub async fn login_route(body: Ruma) -> Result = services() + .globals + .well_known_client() + .as_ref() + .map(|server| DiscoveryInfo::new(HomeserverInfo::new(server.to_string()))); - info!("{} logged in", user_id); + info!("{user_id} logged in"); // home_server is deprecated but apparently must still be sent despite it being // deprecated over 6 years ago. initially i thought this macro was unnecessary, @@ -217,13 +215,7 @@ pub async fn login_route(body: Ruma) -> Result Result { +/// +/// Returns the .well-known URL if it is configured, otherwise returns 404. +pub async fn well_known_client(_body: Ruma) -> Result { let client_url = match services().globals.well_known_client() { - Some(url) => url.clone(), + Some(url) => url.to_string(), None => return Err(Error::BadRequest(ErrorKind::NotFound, "Not found.")), }; - Ok(Json(serde_json::json!({ - "m.homeserver": {"base_url": client_url}, - "org.matrix.msc3575.proxy": {"url": client_url} - }))) + 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) -> Result { - let support_page = services().globals.well_known_support_page().clone(); + let support_page = services() + .globals + .well_known_support_page() + .as_ref() + .map(ToString::to_string); let role = services().globals.well_known_support_role().clone(); @@ -120,9 +133,9 @@ pub async fn well_known_support(_body: Ruma) -> Resul /// Web as a non-standard health check. pub async fn syncv3_client_server_json() -> Result { let server_url = match services().globals.well_known_client() { - Some(url) => url.clone(), + Some(url) => url.to_string(), None => match services().globals.well_known_server() { - Some(url) => url.clone(), + Some(url) => url.to_string(), None => return Err(Error::BadRequest(ErrorKind::NotFound, "Not found.")), }, }; diff --git a/src/api/server_server.rs b/src/api/server_server.rs index 4faa4747..4fca290c 100644 --- a/src/api/server_server.rs +++ b/src/api/server_server.rs @@ -18,7 +18,7 @@ use ruma::{ backfill::get_backfill, device::get_devices::{self, v1::UserDevice}, directory::{get_public_rooms, get_public_rooms_filtered}, - discovery::{get_server_keys, get_server_version, ServerSigningKeys, VerifyKey}, + discovery::{discover_homeserver, get_server_keys, get_server_version, ServerSigningKeys, VerifyKey}, event::{get_event, get_missing_events, get_room_state, get_room_state_ids}, keys::{claim_keys, get_keys}, membership::{create_invite, create_join_event, prepare_join_event}, @@ -1559,19 +1559,19 @@ pub async fn claim_keys_route(body: Ruma) -> Result Result { +/// +/// Returns the .well-known URL if it is configured, otherwise returns 404. +pub async fn well_known_server(_body: Ruma) -> Result { if !services().globals.allow_federation() { return Err(Error::bad_config("Federation is disabled.")); } - let server_url = match services().globals.well_known_server() { - Some(url) => url.clone(), - None => return Err(Error::BadRequest(ErrorKind::NotFound, "Not found.")), - }; - - Ok(Json(serde_json::json!({ - "m.server": server_url - }))) + Ok(discover_homeserver::Response { + server: match services().globals.well_known_server() { + Some(server_name) => server_name.to_owned(), + None => return Err(Error::BadRequest(ErrorKind::NotFound, "Not found.")), + }, + }) } /// # `GET /_matrix/federation/v1/hierarchy/{roomId}` diff --git a/src/config/mod.rs b/src/config/mod.rs index d57bdcc8..bfda89fe 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -20,6 +20,7 @@ use ruma::{ }; use serde::{de::IgnoredAny, Deserialize}; use tracing::{debug, error, warn}; +use url::Url; use self::proxy::ProxyConfig; use crate::utils::error::Error; @@ -158,8 +159,7 @@ pub struct Config { pub allow_unstable_room_versions: bool, #[serde(default = "default_default_room_version")] pub default_room_version: RoomVersionId, - pub well_known_client: Option, - pub well_known_server: Option, + pub well_known: WellKnownConfig, #[serde(default)] pub allow_jaeger: bool, #[serde(default)] @@ -264,11 +264,6 @@ pub struct Config { #[serde(default = "default_ip_range_denylist")] pub ip_range_denylist: Vec, - pub well_known_support_page: Option, - pub well_known_support_role: Option, - pub well_known_support_email: Option, - pub well_known_support_mxid: Option, - #[serde(default = "Vec::new")] pub url_preview_domain_contains_allowlist: Vec, #[serde(default = "Vec::new")] @@ -319,7 +314,25 @@ pub struct TlsConfig { pub dual_protocol: bool, } -const DEPRECATED_KEYS: &[&str] = &["cache_capacity"]; +#[derive(Clone, Debug, Deserialize)] +pub struct WellKnownConfig { + pub client: Option, + pub server: Option, + pub support_page: Option, + pub support_role: Option, + pub support_email: Option, + pub support_mxid: Option, +} + +const DEPRECATED_KEYS: &[&str] = &[ + "cache_capacity", + "well_known_client", + "well_known_server", + "well_known_support_page", + "well_known_support_role", + "well_known_support_email", + "well_known_support_mxid", +]; impl Config { /// Initialize config @@ -367,8 +380,8 @@ impl Config { if was_deprecated { warn!( - "Read conduit documentation and check your configuration if any new configuration parameters should \ - be adjusted" + "Read conduwuit config documentation at https://conduwuit.puppyirl.gay/configuration.html and check \ + your configuration if any new configuration parameters should be adjusted" ); } } @@ -690,6 +703,46 @@ impl fmt::Display for Config { ("Sentry.io send server_name in logs", &self.sentry_send_server_name.to_string()), #[cfg(feature = "sentry_telemetry")] ("Sentry.io tracing sample rate", &self.sentry_traces_sample_rate.to_string()), + ( + "Well-known server name", + &if let Some(server) = &self.well_known.server { + server.to_string() + } else { + String::new() + }, + ), + ( + "Well-known support email", + &if let Some(support_email) = &self.well_known.support_email { + support_email.to_string() + } else { + String::new() + }, + ), + ( + "Well-known support Matrix ID", + &if let Some(support_mxid) = &self.well_known.support_mxid { + support_mxid.to_string() + } else { + String::new() + }, + ), + ( + "Well-known support role", + &if let Some(support_role) = &self.well_known.support_role { + support_role.to_string() + } else { + String::new() + }, + ), + ( + "Well-known support page/URL", + &if let Some(support_page) = &self.well_known.support_page { + support_page.to_string() + } else { + String::new() + }, + ), ]; let mut msg: String = "Active config values:\n\n".to_owned(); diff --git a/src/routes.rs b/src/routes.rs index caeeba69..8deaba62 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -208,12 +208,12 @@ pub fn routes() -> Router { .ruma_route(server_server::get_hierarchy_route) .ruma_route(client_server::get_mutual_rooms_route) .ruma_route(client_server::well_known_support) + .ruma_route(client_server::well_known_client) + .ruma_route(server_server::well_known_server) .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)) .route("/client/server.json", get(client_server::syncv3_client_server_json)) - .route("/.well-known/matrix/client", get(client_server::well_known_client_route)) - .route("/.well-known/matrix/server", get(server_server::well_known_server_route)) .route("/", get(it_works)) .fallback(not_found) } diff --git a/src/service/globals/mod.rs b/src/service/globals/mod.rs index 8c767e9e..a6a4ea40 100644 --- a/src/service/globals/mod.rs +++ b/src/service/globals/mod.rs @@ -27,6 +27,7 @@ use ruma::{ use tokio::sync::{broadcast, watch::Receiver, Mutex, RwLock, Semaphore}; use tracing::{error, info}; use tracing_subscriber::{EnvFilter, Registry}; +use url::Url; use crate::{services, Config, Result}; @@ -314,13 +315,13 @@ impl Service<'_> { pub fn ip_range_denylist(&self) -> &[String] { &self.config.ip_range_denylist } - pub fn well_known_support_page(&self) -> &Option { &self.config.well_known_support_page } + pub fn well_known_support_page(&self) -> &Option { &self.config.well_known.support_page } - pub fn well_known_support_role(&self) -> &Option { &self.config.well_known_support_role } + pub fn well_known_support_role(&self) -> &Option { &self.config.well_known.support_role } - pub fn well_known_support_email(&self) -> &Option { &self.config.well_known_support_email } + pub fn well_known_support_email(&self) -> &Option { &self.config.well_known.support_email } - pub fn well_known_support_mxid(&self) -> &Option { &self.config.well_known_support_mxid } + pub fn well_known_support_mxid(&self) -> &Option { &self.config.well_known.support_mxid } pub fn block_non_admin_invites(&self) -> bool { self.config.block_non_admin_invites } @@ -401,9 +402,9 @@ impl Service<'_> { r } - pub fn well_known_client(&self) -> &Option { &self.config.well_known_client } + pub fn well_known_client(&self) -> &Option { &self.config.well_known.client } - pub fn well_known_server(&self) -> &Option { &self.config.well_known_server } + pub fn well_known_server(&self) -> &Option { &self.config.well_known.server } pub fn unix_socket_path(&self) -> &Option { &self.config.unix_socket_path }