Skip to main content

tuwunel_api/client/
thirdparty.rs

1use axum::extract::State;
2use ruma::api::client::thirdparty::{
3	get_location_for_protocol, get_location_for_room_alias, get_protocol, get_protocols,
4	get_user_for_protocol, get_user_for_user_id,
5};
6use tuwunel_core::{Result, err};
7
8use crate::Ruma;
9
10/// # `GET /_matrix/client/v3/thirdparty/protocols`
11///
12/// Fetches the third-party network protocols advertised by registered
13/// appservices. Bridges are queried only for protocols named in their
14/// registration, and overlapping declarations are combined under one protocol
15/// id.
16pub(crate) async fn get_protocols_route(
17	State(services): State<crate::State>,
18	_body: Ruma<get_protocols::v3::Request>,
19) -> Result<get_protocols::v3::Response> {
20	let protocols = services
21		.appservice
22		.thirdparty_protocols(None)
23		.await;
24
25	Ok(get_protocols::v3::Response { protocols })
26}
27
28/// # `GET /_matrix/client/v3/thirdparty/protocol/{protocol}`
29///
30/// Fetches metadata from every appservice declaring the requested protocol.
31/// The route returns `M_NOT_FOUND` when no registered bridge advertises it or
32/// none of the declaring bridges returns a successfully decoded response.
33pub(crate) async fn get_protocol_route(
34	State(services): State<crate::State>,
35	body: Ruma<get_protocol::v3::Request>,
36) -> Result<get_protocol::v3::Response> {
37	let protocol = services
38		.appservice
39		.thirdparty_protocols(Some(body.protocol.as_str()))
40		.await
41		.remove(&body.protocol)
42		.ok_or_else(|| err!(Request(NotFound("Unknown protocol."))))?;
43
44	Ok(get_protocol::v3::Response { protocol })
45}
46
47/// # `GET /_matrix/client/v3/thirdparty/user/{protocol}`
48///
49/// Looks up third-party users through every appservice declaring `protocol`.
50/// Query fields are forwarded without the client's access token, and one
51/// bridge's failure does not discard results supplied by another.
52pub(crate) async fn get_user_for_protocol_route(
53	State(services): State<crate::State>,
54	body: Ruma<get_user_for_protocol::v3::Request>,
55) -> Result<get_user_for_protocol::v3::Response> {
56	let users = services
57		.appservice
58		.thirdparty_users(&body.protocol, &body.fields)
59		.await;
60
61	Ok(get_user_for_protocol::v3::Response { users })
62}
63
64/// # `GET /_matrix/client/v3/thirdparty/location/{protocol}`
65///
66/// Looks up third-party locations on a protocol via the registered appservices.
67/// Successful bridge responses retain appservice-id order and the order of the
68/// locations within each response.
69pub(crate) async fn get_location_for_protocol_route(
70	State(services): State<crate::State>,
71	body: Ruma<get_location_for_protocol::v3::Request>,
72) -> Result<get_location_for_protocol::v3::Response> {
73	let locations = services
74		.appservice
75		.thirdparty_locations(&body.protocol, &body.fields)
76		.await;
77
78	Ok(get_location_for_protocol::v3::Response { locations })
79}
80
81/// # `GET /_matrix/client/v3/thirdparty/user`
82///
83/// Reverse third-party lookup by Matrix user id. Tuwunel does no server-side
84/// namespace routing for these, so the result is empty, matching Synapse.
85pub(crate) async fn get_user_for_user_id_route(
86	_body: Ruma<get_user_for_user_id::v3::Request>,
87) -> Result<get_user_for_user_id::v3::Response> {
88	Ok(get_user_for_user_id::v3::Response { users: Vec::new() })
89}
90
91/// # `GET /_matrix/client/v3/thirdparty/location`
92///
93/// Reverse third-party lookup by Matrix room alias; empty for the same reason
94/// as the user reverse lookup.
95pub(crate) async fn get_location_for_room_alias_route(
96	_body: Ruma<get_location_for_room_alias::v3::Request>,
97) -> Result<get_location_for_room_alias::v3::Response> {
98	Ok(get_location_for_room_alias::v3::Response { locations: Vec::new() })
99}