arminius_server_client/handlers/
discovery.rs1mod tests;
8
9use arminius_lib_component::{
10 ArminiusConfig, Component, ServerState, ruma_requests::ArminiusResponse,
11};
12use axum::{Router, extract::State, routing::get};
13use ruma::api::{
14 FeatureFlag, MatrixVersion,
15 client::discovery::{discover_homeserver, get_capabilities, get_supported_versions},
16};
17
18use crate::client_request::{
19 AuthenticatedClientRequest, OptionallyAuthenticatedClientRequest, UnauthenticatedClientRequest,
20};
21
22async fn get_supported_versions_handler(
27 OptionallyAuthenticatedClientRequest(_, _): OptionallyAuthenticatedClientRequest<
28 get_supported_versions::Request,
29 >,
30) -> ArminiusResponse<get_supported_versions::Response> {
31 #[expect(
32 clippy::expect_used,
33 reason = "Calling `MatrixVersion::as_str()` returns `None` only for its `V1_0` variant"
34 )]
35 let mut response = get_supported_versions::Response::new(vec![
36 MatrixVersion::V1_9.as_str().expect("Only `MatrixVersion::V1_0` returns `None`").to_owned(),
37 MatrixVersion::V1_10
38 .as_str()
39 .expect("Only `MatrixVersion::V1_0` returns `None`")
40 .to_owned(),
41 MatrixVersion::V1_11
42 .as_str()
43 .expect("Only `MatrixVersion::V1_0` returns `None`")
44 .to_owned(),
45 ]);
46
47 response.unstable_features.insert(FeatureFlag::Msc4186.to_string(), true);
48
49 response.into()
50}
51
52async fn discover_homeserver_handler(
57 config: State<ArminiusConfig>,
58 UnauthenticatedClientRequest(_): UnauthenticatedClientRequest<discover_homeserver::Request>,
59) -> ArminiusResponse<discover_homeserver::Response> {
60 discover_homeserver::Response::new(discover_homeserver::HomeserverInfo::new(
61 config.client_base_url.to_string(),
62 ))
63 .into()
64}
65
66async fn get_capabilities_handler(
72 AuthenticatedClientRequest(_, _): AuthenticatedClientRequest<get_capabilities::v3::Request>,
73) -> ArminiusResponse<get_capabilities::v3::Response> {
74 let mut capabilities = get_capabilities::v3::Capabilities::new();
75 capabilities.change_password = get_capabilities::v3::ChangePasswordCapability::new(false);
76
77 capabilities.room_versions = get_capabilities::v3::RoomVersionsCapability::new(
78 arminius_lib_events::KnownRoomVersionId::default().into(),
79 arminius_lib_events::SUPPORTED_ROOM_VERSIONS
80 .into_iter()
81 .map(|version| (version.into(), get_capabilities::v3::RoomVersionStability::Stable))
82 .collect(),
83 );
84
85 capabilities.profile_fields = Some(get_capabilities::v3::ProfileFieldsCapability::new(false));
86 capabilities.thirdparty_id_changes =
87 get_capabilities::v3::ThirdPartyIdChangesCapability::new(false);
88 capabilities.get_login_token = get_capabilities::v3::GetLoginTokenCapability::new(false);
89
90 let response = get_capabilities::v3::Response::new(capabilities);
91 response.into()
92}
93
94#[derive(Debug)]
96pub struct DiscoveryComponent;
97
98impl Component for DiscoveryComponent {
99 fn router() -> Router<ServerState> {
100 Router::new()
101 .route("/_matrix/client/versions", get(get_supported_versions_handler))
102 .route("/_matrix/client/v3/capabilities", get(get_capabilities_handler))
103 .route("/.well-known/matrix/client", get(discover_homeserver_handler))
104 }
105}