de-global services() from api

Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
Jason Volk 2024-07-16 08:05:25 +00:00
parent 463f1a1287
commit 8b6018d77d
61 changed files with 1485 additions and 1320 deletions

View file

@ -1,9 +1,10 @@
use axum::extract::State;
use conduit::{Error, Result};
use ruma::{
api::{client::error::ErrorKind, federation::backfill::get_backfill},
uint, user_id, MilliSecondsSinceUnixEpoch,
};
use service::{sending::convert_to_outgoing_federation_event, services};
use service::sending::convert_to_outgoing_federation_event;
use crate::Ruma;
@ -11,19 +12,21 @@ use crate::Ruma;
///
/// Retrieves events from before the sender joined the room, if the room's
/// history visibility allows.
pub(crate) async fn get_backfill_route(body: Ruma<get_backfill::v1::Request>) -> Result<get_backfill::v1::Response> {
pub(crate) async fn get_backfill_route(
State(services): State<crate::State>, body: Ruma<get_backfill::v1::Request>,
) -> Result<get_backfill::v1::Response> {
let origin = body.origin.as_ref().expect("server is authenticated");
services()
services
.rooms
.event_handler
.acl_check(origin, &body.room_id)?;
if !services()
if !services
.rooms
.state_accessor
.is_world_readable(&body.room_id)?
&& !services()
&& !services
.rooms
.state_cache
.server_in_room(origin, &body.room_id)?
@ -34,7 +37,7 @@ pub(crate) async fn get_backfill_route(body: Ruma<get_backfill::v1::Request>) ->
let until = body
.v
.iter()
.map(|event_id| services().rooms.timeline.get_pdu_count(event_id))
.map(|event_id| services.rooms.timeline.get_pdu_count(event_id))
.filter_map(|r| r.ok().flatten())
.max()
.ok_or_else(|| Error::BadRequest(ErrorKind::InvalidParam, "Event not found."))?;
@ -45,7 +48,7 @@ pub(crate) async fn get_backfill_route(body: Ruma<get_backfill::v1::Request>) ->
.try_into()
.expect("UInt could not be converted to usize");
let all_events = services()
let all_events = services
.rooms
.timeline
.pdus_until(user_id!("@doesntmatter:conduit.rs"), &body.room_id, until)?
@ -55,20 +58,20 @@ pub(crate) async fn get_backfill_route(body: Ruma<get_backfill::v1::Request>) ->
.filter_map(Result::ok)
.filter(|(_, e)| {
matches!(
services()
services
.rooms
.state_accessor
.server_can_see_event(origin, &e.room_id, &e.event_id,),
Ok(true),
)
})
.map(|(_, pdu)| services().rooms.timeline.get_pdu_json(&pdu.event_id))
.map(|(_, pdu)| services.rooms.timeline.get_pdu_json(&pdu.event_id))
.filter_map(|r| r.ok().flatten())
.map(convert_to_outgoing_federation_event)
.collect();
Ok(get_backfill::v1::Response {
origin: services().globals.server_name().to_owned(),
origin: services.globals.server_name().to_owned(),
origin_server_ts: MilliSecondsSinceUnixEpoch::now(),
pdus: events,
})

View file

@ -1,9 +1,10 @@
use axum::extract::State;
use conduit::{Error, Result};
use ruma::{
api::{client::error::ErrorKind, federation::event::get_event},
MilliSecondsSinceUnixEpoch, RoomId,
};
use service::{sending::convert_to_outgoing_federation_event, services};
use service::sending::convert_to_outgoing_federation_event;
use crate::Ruma;
@ -13,10 +14,12 @@ use crate::Ruma;
///
/// - Only works if a user of this server is currently invited or joined the
/// room
pub(crate) async fn get_event_route(body: Ruma<get_event::v1::Request>) -> Result<get_event::v1::Response> {
pub(crate) async fn get_event_route(
State(services): State<crate::State>, body: Ruma<get_event::v1::Request>,
) -> Result<get_event::v1::Response> {
let origin = body.origin.as_ref().expect("server is authenticated");
let event = services()
let event = services
.rooms
.timeline
.get_pdu_json(&body.event_id)?
@ -30,16 +33,13 @@ pub(crate) async fn get_event_route(body: Ruma<get_event::v1::Request>) -> Resul
let room_id =
<&RoomId>::try_from(room_id_str).map_err(|_| Error::bad_database("Invalid room_id in event in database."))?;
if !services().rooms.state_accessor.is_world_readable(room_id)?
&& !services()
.rooms
.state_cache
.server_in_room(origin, room_id)?
if !services.rooms.state_accessor.is_world_readable(room_id)?
&& !services.rooms.state_cache.server_in_room(origin, room_id)?
{
return Err(Error::BadRequest(ErrorKind::forbidden(), "Server is not in room."));
}
if !services()
if !services
.rooms
.state_accessor
.server_can_see_event(origin, room_id, &body.event_id)?
@ -48,7 +48,7 @@ pub(crate) async fn get_event_route(body: Ruma<get_event::v1::Request>) -> Resul
}
Ok(get_event::v1::Response {
origin: services().globals.server_name().to_owned(),
origin: services.globals.server_name().to_owned(),
origin_server_ts: MilliSecondsSinceUnixEpoch::now(),
pdu: convert_to_outgoing_federation_event(event),
})

View file

@ -1,11 +1,12 @@
use std::sync::Arc;
use axum::extract::State;
use conduit::{Error, Result};
use ruma::{
api::{client::error::ErrorKind, federation::authorization::get_event_authorization},
RoomId,
};
use service::{sending::convert_to_outgoing_federation_event, services};
use service::sending::convert_to_outgoing_federation_event;
use crate::Ruma;
@ -15,20 +16,20 @@ use crate::Ruma;
///
/// - This does not include the event itself
pub(crate) async fn get_event_authorization_route(
body: Ruma<get_event_authorization::v1::Request>,
State(services): State<crate::State>, body: Ruma<get_event_authorization::v1::Request>,
) -> Result<get_event_authorization::v1::Response> {
let origin = body.origin.as_ref().expect("server is authenticated");
services()
services
.rooms
.event_handler
.acl_check(origin, &body.room_id)?;
if !services()
if !services
.rooms
.state_accessor
.is_world_readable(&body.room_id)?
&& !services()
&& !services
.rooms
.state_cache
.server_in_room(origin, &body.room_id)?
@ -36,7 +37,7 @@ pub(crate) async fn get_event_authorization_route(
return Err(Error::BadRequest(ErrorKind::forbidden(), "Server is not in room."));
}
let event = services()
let event = services
.rooms
.timeline
.get_pdu_json(&body.event_id)?
@ -50,7 +51,7 @@ pub(crate) async fn get_event_authorization_route(
let room_id =
<&RoomId>::try_from(room_id_str).map_err(|_| Error::bad_database("Invalid room_id in event in database."))?;
let auth_chain_ids = services()
let auth_chain_ids = services
.rooms
.auth_chain
.event_ids_iter(room_id, vec![Arc::from(&*body.event_id)])
@ -58,7 +59,7 @@ pub(crate) async fn get_event_authorization_route(
Ok(get_event_authorization::v1::Response {
auth_chain: auth_chain_ids
.filter_map(|id| services().rooms.timeline.get_pdu_json(&id).ok()?)
.filter_map(|id| services.rooms.timeline.get_pdu_json(&id).ok()?)
.map(convert_to_outgoing_federation_event)
.collect(),
})

View file

@ -1,9 +1,10 @@
use axum::extract::State;
use conduit::{Error, Result};
use ruma::{
api::{client::error::ErrorKind, federation::event::get_missing_events},
OwnedEventId, RoomId,
};
use service::{sending::convert_to_outgoing_federation_event, services};
use service::sending::convert_to_outgoing_federation_event;
use crate::Ruma;
@ -11,20 +12,20 @@ use crate::Ruma;
///
/// Retrieves events that the sender is missing.
pub(crate) async fn get_missing_events_route(
body: Ruma<get_missing_events::v1::Request>,
State(services): State<crate::State>, body: Ruma<get_missing_events::v1::Request>,
) -> Result<get_missing_events::v1::Response> {
let origin = body.origin.as_ref().expect("server is authenticated");
services()
services
.rooms
.event_handler
.acl_check(origin, &body.room_id)?;
if !services()
if !services
.rooms
.state_accessor
.is_world_readable(&body.room_id)?
&& !services()
&& !services
.rooms
.state_cache
.server_in_room(origin, &body.room_id)?
@ -43,7 +44,7 @@ pub(crate) async fn get_missing_events_route(
let mut i: usize = 0;
while i < queued_events.len() && events.len() < limit {
if let Some(pdu) = services().rooms.timeline.get_pdu_json(&queued_events[i])? {
if let Some(pdu) = services.rooms.timeline.get_pdu_json(&queued_events[i])? {
let room_id_str = pdu
.get("room_id")
.and_then(|val| val.as_str())
@ -61,7 +62,7 @@ pub(crate) async fn get_missing_events_route(
continue;
}
if !services()
if !services
.rooms
.state_accessor
.server_can_see_event(origin, &body.room_id, &queued_events[i])?

View file

@ -1,16 +1,19 @@
use axum::extract::State;
use ruma::api::{client::error::ErrorKind, federation::space::get_hierarchy};
use crate::{services, Error, Result, Ruma};
use crate::{Error, Result, Ruma};
/// # `GET /_matrix/federation/v1/hierarchy/{roomId}`
///
/// Gets the space tree in a depth-first manner to locate child rooms of a given
/// space.
pub(crate) async fn get_hierarchy_route(body: Ruma<get_hierarchy::v1::Request>) -> Result<get_hierarchy::v1::Response> {
pub(crate) async fn get_hierarchy_route(
State(services): State<crate::State>, body: Ruma<get_hierarchy::v1::Request>,
) -> Result<get_hierarchy::v1::Response> {
let origin = body.origin.as_ref().expect("server is authenticated");
if services().rooms.metadata.exists(&body.room_id)? {
services()
if services.rooms.metadata.exists(&body.room_id)? {
services
.rooms
.spaces
.get_federation_hierarchy(&body.room_id, origin, body.suggested_only)

View file

@ -1,3 +1,4 @@
use axum::extract::State;
use axum_client_ip::InsecureClientIp;
use conduit::{utils, warn, Error, PduEvent, Result};
use ruma::{
@ -6,7 +7,7 @@ use ruma::{
serde::JsonObject,
CanonicalJsonValue, EventId, OwnedUserId,
};
use service::{sending::convert_to_outgoing_federation_event, server_is_ours, services};
use service::{sending::convert_to_outgoing_federation_event, server_is_ours};
use crate::Ruma;
@ -15,17 +16,18 @@ use crate::Ruma;
/// Invites a remote user to a room.
#[tracing::instrument(skip_all, fields(%client), name = "invite")]
pub(crate) async fn create_invite_route(
InsecureClientIp(client): InsecureClientIp, body: Ruma<create_invite::v2::Request>,
State(services): State<crate::State>, InsecureClientIp(client): InsecureClientIp,
body: Ruma<create_invite::v2::Request>,
) -> Result<create_invite::v2::Response> {
let origin = body.origin.as_ref().expect("server is authenticated");
// ACL check origin
services()
services
.rooms
.event_handler
.acl_check(origin, &body.room_id)?;
if !services()
if !services
.globals
.supported_room_versions()
.contains(&body.room_version)
@ -39,7 +41,7 @@ pub(crate) async fn create_invite_route(
}
if let Some(server) = body.room_id.server_name() {
if services()
if services
.globals
.config
.forbidden_remote_server_names
@ -52,7 +54,7 @@ pub(crate) async fn create_invite_route(
}
}
if services()
if services
.globals
.config
.forbidden_remote_server_names
@ -94,14 +96,14 @@ pub(crate) async fn create_invite_route(
}
// Make sure we're not ACL'ed from their room.
services()
services
.rooms
.event_handler
.acl_check(invited_user.server_name(), &body.room_id)?;
ruma::signatures::hash_and_sign_event(
services().globals.server_name().as_str(),
services().globals.keypair(),
services.globals.server_name().as_str(),
services.globals.keypair(),
&mut signed_event,
&body.room_version,
)
@ -127,14 +129,14 @@ pub(crate) async fn create_invite_route(
)
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "sender is not a user ID."))?;
if services().rooms.metadata.is_banned(&body.room_id)? && !services().users.is_admin(&invited_user)? {
if services.rooms.metadata.is_banned(&body.room_id)? && !services.users.is_admin(&invited_user)? {
return Err(Error::BadRequest(
ErrorKind::forbidden(),
"This room is banned on this homeserver.",
));
}
if services().globals.block_non_admin_invites() && !services().users.is_admin(&invited_user)? {
if services.globals.block_non_admin_invites() && !services.users.is_admin(&invited_user)? {
return Err(Error::BadRequest(
ErrorKind::forbidden(),
"This server does not allow room invites.",
@ -155,12 +157,12 @@ pub(crate) async fn create_invite_route(
// If we are active in the room, the remote server will notify us about the join
// via /send
if !services()
if !services
.rooms
.state_cache
.server_in_room(services().globals.server_name(), &body.room_id)?
.server_in_room(services.globals.server_name(), &body.room_id)?
{
services().rooms.state_cache.update_membership(
services.rooms.state_cache.update_membership(
&body.room_id,
&invited_user,
RoomMemberEventContent::new(MembershipState::Invite),

View file

@ -3,7 +3,7 @@ use std::{
time::{Duration, SystemTime},
};
use axum::{response::IntoResponse, Json};
use axum::{extract::State, response::IntoResponse, Json};
use ruma::{
api::{
federation::discovery::{get_server_keys, ServerSigningKeys, VerifyKey},
@ -13,7 +13,7 @@ use ruma::{
MilliSecondsSinceUnixEpoch, OwnedServerSigningKeyId,
};
use crate::{services, Result};
use crate::Result;
/// # `GET /_matrix/key/v2/server`
///
@ -23,20 +23,20 @@ use crate::{services, Result};
/// this will be valid forever.
// Response type for this endpoint is Json because we need to calculate a
// signature for the response
pub(crate) async fn get_server_keys_route() -> Result<impl IntoResponse> {
pub(crate) async fn get_server_keys_route(State(services): State<crate::State>) -> Result<impl IntoResponse> {
let verify_keys: BTreeMap<OwnedServerSigningKeyId, VerifyKey> = BTreeMap::from([(
format!("ed25519:{}", services().globals.keypair().version())
format!("ed25519:{}", services.globals.keypair().version())
.try_into()
.expect("found invalid server signing keys in DB"),
VerifyKey {
key: Base64::new(services().globals.keypair().public_key().to_vec()),
key: Base64::new(services.globals.keypair().public_key().to_vec()),
},
)]);
let mut response = serde_json::from_slice(
get_server_keys::v2::Response {
server_key: Raw::new(&ServerSigningKeys {
server_name: services().globals.server_name().to_owned(),
server_name: services.globals.server_name().to_owned(),
verify_keys,
old_verify_keys: BTreeMap::new(),
signatures: BTreeMap::new(),
@ -56,8 +56,8 @@ pub(crate) async fn get_server_keys_route() -> Result<impl IntoResponse> {
.unwrap();
ruma::signatures::sign_json(
services().globals.server_name().as_str(),
services().globals.keypair(),
services.globals.server_name().as_str(),
services.globals.keypair(),
&mut response,
)
.unwrap();
@ -71,4 +71,6 @@ pub(crate) async fn get_server_keys_route() -> Result<impl IntoResponse> {
///
/// - Matrix does not support invalidating public keys, so the key returned by
/// this will be valid forever.
pub(crate) async fn get_server_keys_deprecated_route() -> impl IntoResponse { get_server_keys_route().await }
pub(crate) async fn get_server_keys_deprecated_route(State(services): State<crate::State>) -> impl IntoResponse {
get_server_keys_route(State(services)).await
}

View file

@ -1,3 +1,4 @@
use axum::extract::State;
use ruma::{
api::{client::error::ErrorKind, federation::membership::prepare_join_event},
events::{
@ -12,15 +13,18 @@ use ruma::{
use serde_json::value::to_raw_value;
use tracing::warn;
use crate::{service::pdu::PduBuilder, services, Error, Result, Ruma};
use crate::{
service::{pdu::PduBuilder, Services},
Error, Result, Ruma,
};
/// # `GET /_matrix/federation/v1/make_join/{roomId}/{userId}`
///
/// Creates a join template.
pub(crate) async fn create_join_event_template_route(
body: Ruma<prepare_join_event::v1::Request>,
State(services): State<crate::State>, body: Ruma<prepare_join_event::v1::Request>,
) -> Result<prepare_join_event::v1::Response> {
if !services().rooms.metadata.exists(&body.room_id)? {
if !services.rooms.metadata.exists(&body.room_id)? {
return Err(Error::BadRequest(ErrorKind::NotFound, "Room is unknown to this server."));
}
@ -33,12 +37,12 @@ pub(crate) async fn create_join_event_template_route(
}
// ACL check origin server
services()
services
.rooms
.event_handler
.acl_check(origin, &body.room_id)?;
if services()
if services
.globals
.config
.forbidden_remote_server_names
@ -56,7 +60,7 @@ pub(crate) async fn create_join_event_template_route(
}
if let Some(server) = body.room_id.server_name() {
if services()
if services
.globals
.config
.forbidden_remote_server_names
@ -69,25 +73,25 @@ pub(crate) async fn create_join_event_template_route(
}
}
let room_version_id = services().rooms.state.get_room_version(&body.room_id)?;
let room_version_id = services.rooms.state.get_room_version(&body.room_id)?;
let state_lock = services().rooms.state.mutex.lock(&body.room_id).await;
let state_lock = services.rooms.state.mutex.lock(&body.room_id).await;
let join_authorized_via_users_server = if (services()
let join_authorized_via_users_server = if (services
.rooms
.state_cache
.is_left(&body.user_id, &body.room_id)
.unwrap_or(true))
&& user_can_perform_restricted_join(&body.user_id, &body.room_id, &room_version_id)?
&& user_can_perform_restricted_join(services, &body.user_id, &body.room_id, &room_version_id)?
{
let auth_user = services()
let auth_user = services
.rooms
.state_cache
.room_members(&body.room_id)
.filter_map(Result::ok)
.filter(|user| user.server_name() == services().globals.server_name())
.filter(|user| user.server_name() == services.globals.server_name())
.find(|user| {
services()
services
.rooms
.state_accessor
.user_can_invite(&body.room_id, user, &body.user_id, &state_lock)
@ -106,7 +110,7 @@ pub(crate) async fn create_join_event_template_route(
None
};
let room_version_id = services().rooms.state.get_room_version(&body.room_id)?;
let room_version_id = services.rooms.state.get_room_version(&body.room_id)?;
if !body.ver.contains(&room_version_id) {
return Err(Error::BadRequest(
ErrorKind::IncompatibleRoomVersion {
@ -128,7 +132,7 @@ pub(crate) async fn create_join_event_template_route(
})
.expect("member event is valid value");
let (_pdu, mut pdu_json) = services().rooms.timeline.create_hash_and_sign_event(
let (_pdu, mut pdu_json) = services.rooms.timeline.create_hash_and_sign_event(
PduBuilder {
event_type: TimelineEventType::RoomMember,
content,
@ -157,15 +161,14 @@ pub(crate) async fn create_join_event_template_route(
/// externally, either by using the state cache or attempting to authorize the
/// event.
pub(crate) fn user_can_perform_restricted_join(
user_id: &UserId, room_id: &RoomId, room_version_id: &RoomVersionId,
services: &Services, user_id: &UserId, room_id: &RoomId, room_version_id: &RoomVersionId,
) -> Result<bool> {
use RoomVersionId::*;
let join_rules_event =
services()
.rooms
.state_accessor
.room_state_get(room_id, &StateEventType::RoomJoinRules, "")?;
let join_rules_event = services
.rooms
.state_accessor
.room_state_get(room_id, &StateEventType::RoomJoinRules, "")?;
let Some(join_rules_event_content) = join_rules_event
.as_ref()
@ -198,7 +201,7 @@ pub(crate) fn user_can_perform_restricted_join(
}
})
.any(|m| {
services()
services
.rooms
.state_cache
.is_joined(user_id, &m.room_id)

View file

@ -1,3 +1,4 @@
use axum::extract::State;
use conduit::{Error, Result};
use ruma::{
api::{client::error::ErrorKind, federation::membership::prepare_leave_event},
@ -9,15 +10,15 @@ use ruma::{
use serde_json::value::to_raw_value;
use super::make_join::maybe_strip_event_id;
use crate::{service::pdu::PduBuilder, services, Ruma};
use crate::{service::pdu::PduBuilder, Ruma};
/// # `PUT /_matrix/federation/v1/make_leave/{roomId}/{eventId}`
///
/// Creates a leave template.
pub(crate) async fn create_leave_event_template_route(
body: Ruma<prepare_leave_event::v1::Request>,
State(services): State<crate::State>, body: Ruma<prepare_leave_event::v1::Request>,
) -> Result<prepare_leave_event::v1::Response> {
if !services().rooms.metadata.exists(&body.room_id)? {
if !services.rooms.metadata.exists(&body.room_id)? {
return Err(Error::BadRequest(ErrorKind::NotFound, "Room is unknown to this server."));
}
@ -30,13 +31,13 @@ pub(crate) async fn create_leave_event_template_route(
}
// ACL check origin
services()
services
.rooms
.event_handler
.acl_check(origin, &body.room_id)?;
let room_version_id = services().rooms.state.get_room_version(&body.room_id)?;
let state_lock = services().rooms.state.mutex.lock(&body.room_id).await;
let room_version_id = services.rooms.state.get_room_version(&body.room_id)?;
let state_lock = services.rooms.state.mutex.lock(&body.room_id).await;
let content = to_raw_value(&RoomMemberEventContent {
avatar_url: None,
blurhash: None,
@ -49,7 +50,7 @@ pub(crate) async fn create_leave_event_template_route(
})
.expect("member event is valid value");
let (_pdu, mut pdu_json) = services().rooms.timeline.create_hash_and_sign_event(
let (_pdu, mut pdu_json) = services.rooms.timeline.create_hash_and_sign_event(
PduBuilder {
event_type: TimelineEventType::RoomMember,
content,

View file

@ -1,16 +1,15 @@
use axum::extract::State;
use ruma::api::federation::openid::get_openid_userinfo;
use crate::{services, Result, Ruma};
use crate::{Result, Ruma};
/// # `GET /_matrix/federation/v1/openid/userinfo`
///
/// Get information about the user that generated the OpenID token.
pub(crate) async fn get_openid_userinfo_route(
body: Ruma<get_openid_userinfo::v1::Request>,
State(services): State<crate::State>, body: Ruma<get_openid_userinfo::v1::Request>,
) -> Result<get_openid_userinfo::v1::Response> {
Ok(get_openid_userinfo::v1::Response::new(
services()
.users
.find_from_openid_token(&body.access_token)?,
services.users.find_from_openid_token(&body.access_token)?,
))
}

View file

@ -1,3 +1,4 @@
use axum::extract::State;
use axum_client_ip::InsecureClientIp;
use ruma::{
api::{
@ -7,16 +8,17 @@ use ruma::{
directory::Filter,
};
use crate::{services, Error, Result, Ruma};
use crate::{Error, Result, Ruma};
/// # `POST /_matrix/federation/v1/publicRooms`
///
/// Lists the public rooms on this server.
#[tracing::instrument(skip_all, fields(%client), name = "publicrooms")]
pub(crate) async fn get_public_rooms_filtered_route(
InsecureClientIp(client): InsecureClientIp, body: Ruma<get_public_rooms_filtered::v1::Request>,
State(services): State<crate::State>, InsecureClientIp(client): InsecureClientIp,
body: Ruma<get_public_rooms_filtered::v1::Request>,
) -> Result<get_public_rooms_filtered::v1::Response> {
if !services()
if !services
.globals
.allow_public_room_directory_over_federation()
{
@ -24,6 +26,7 @@ pub(crate) async fn get_public_rooms_filtered_route(
}
let response = crate::client::get_public_rooms_filtered_helper(
services,
None,
body.limit,
body.since.as_deref(),
@ -46,9 +49,10 @@ pub(crate) async fn get_public_rooms_filtered_route(
/// Lists the public rooms on this server.
#[tracing::instrument(skip_all, fields(%client), "publicrooms")]
pub(crate) async fn get_public_rooms_route(
InsecureClientIp(client): InsecureClientIp, body: Ruma<get_public_rooms::v1::Request>,
State(services): State<crate::State>, InsecureClientIp(client): InsecureClientIp,
body: Ruma<get_public_rooms::v1::Request>,
) -> Result<get_public_rooms::v1::Response> {
if !services()
if !services
.globals
.allow_public_room_directory_over_federation()
{
@ -56,6 +60,7 @@ pub(crate) async fn get_public_rooms_route(
}
let response = crate::client::get_public_rooms_filtered_helper(
services,
None,
body.limit,
body.since.as_deref(),

View file

@ -1,3 +1,4 @@
use axum::extract::State;
use get_profile_information::v1::ProfileField;
use rand::seq::SliceRandom;
use ruma::{
@ -8,21 +9,21 @@ use ruma::{
OwnedServerName,
};
use crate::{service::server_is_ours, services, Error, Result, Ruma};
use crate::{service::server_is_ours, Error, Result, Ruma};
/// # `GET /_matrix/federation/v1/query/directory`
///
/// Resolve a room alias to a room id.
pub(crate) async fn get_room_information_route(
body: Ruma<get_room_information::v1::Request>,
State(services): State<crate::State>, body: Ruma<get_room_information::v1::Request>,
) -> Result<get_room_information::v1::Response> {
let room_id = services()
let room_id = services
.rooms
.alias
.resolve_local_alias(&body.room_alias)?
.ok_or_else(|| Error::BadRequest(ErrorKind::NotFound, "Room alias not found."))?;
let mut servers: Vec<OwnedServerName> = services()
let mut servers: Vec<OwnedServerName> = services
.rooms
.state_cache
.room_servers(&room_id)
@ -37,10 +38,10 @@ pub(crate) async fn get_room_information_route(
// insert our server as the very first choice if in list
if let Some(server_index) = servers
.iter()
.position(|server| server == services().globals.server_name())
.position(|server| server == services.globals.server_name())
{
servers.swap_remove(server_index);
servers.insert(0, services().globals.server_name().to_owned());
servers.insert(0, services.globals.server_name().to_owned());
}
Ok(get_room_information::v1::Response {
@ -54,12 +55,9 @@ pub(crate) async fn get_room_information_route(
///
/// Gets information on a profile.
pub(crate) async fn get_profile_information_route(
body: Ruma<get_profile_information::v1::Request>,
State(services): State<crate::State>, body: Ruma<get_profile_information::v1::Request>,
) -> Result<get_profile_information::v1::Response> {
if !services()
.globals
.allow_profile_lookup_federation_requests()
{
if !services.globals.allow_profile_lookup_federation_requests() {
return Err(Error::BadRequest(
ErrorKind::forbidden(),
"Profile lookup over federation is not allowed on this homeserver.",
@ -79,18 +77,18 @@ pub(crate) async fn get_profile_information_route(
match &body.field {
Some(ProfileField::DisplayName) => {
displayname = services().users.displayname(&body.user_id)?;
displayname = services.users.displayname(&body.user_id)?;
},
Some(ProfileField::AvatarUrl) => {
avatar_url = services().users.avatar_url(&body.user_id)?;
blurhash = services().users.blurhash(&body.user_id)?;
avatar_url = services.users.avatar_url(&body.user_id)?;
blurhash = services.users.blurhash(&body.user_id)?;
},
// TODO: what to do with custom
Some(_) => {},
None => {
displayname = services().users.displayname(&body.user_id)?;
avatar_url = services().users.avatar_url(&body.user_id)?;
blurhash = services().users.blurhash(&body.user_id)?;
displayname = services.users.displayname(&body.user_id)?;
avatar_url = services.users.avatar_url(&body.user_id)?;
blurhash = services.users.blurhash(&body.user_id)?;
},
}

View file

@ -34,7 +34,7 @@ type ResolvedMap = BTreeMap<OwnedEventId, Result<(), Error>>;
/// Push EDUs and PDUs to this server.
#[tracing::instrument(skip_all, fields(%client), name = "send")]
pub(crate) async fn send_transaction_message_route(
State(services): State<&Services>, InsecureClientIp(client): InsecureClientIp,
State(services): State<crate::State>, InsecureClientIp(client): InsecureClientIp,
body: Ruma<send_transaction_message::v1::Request>,
) -> Result<send_transaction_message::v1::Response> {
let origin = body.origin.as_ref().expect("server is authenticated");

View file

@ -2,6 +2,7 @@
use std::collections::BTreeMap;
use axum::extract::State;
use conduit::{Error, Result};
use ruma::{
api::{client::error::ErrorKind, federation::membership::create_join_event},
@ -13,7 +14,7 @@ use ruma::{
};
use serde_json::value::{to_raw_value, RawValue as RawJsonValue};
use service::{
pdu::gen_event_id_canonical_json, sending::convert_to_outgoing_federation_event, services, user_is_local,
pdu::gen_event_id_canonical_json, sending::convert_to_outgoing_federation_event, user_is_local, Services,
};
use tokio::sync::RwLock;
use tracing::warn;
@ -22,18 +23,18 @@ use crate::Ruma;
/// helper method for /send_join v1 and v2
async fn create_join_event(
origin: &ServerName, room_id: &RoomId, pdu: &RawJsonValue,
services: &Services, origin: &ServerName, room_id: &RoomId, pdu: &RawJsonValue,
) -> Result<create_join_event::v1::RoomState> {
if !services().rooms.metadata.exists(room_id)? {
if !services.rooms.metadata.exists(room_id)? {
return Err(Error::BadRequest(ErrorKind::NotFound, "Room is unknown to this server."));
}
// ACL check origin server
services().rooms.event_handler.acl_check(origin, room_id)?;
services.rooms.event_handler.acl_check(origin, room_id)?;
// We need to return the state prior to joining, let's keep a reference to that
// here
let shortstatehash = services()
let shortstatehash = services
.rooms
.state
.get_room_shortstatehash(room_id)?
@ -44,7 +45,7 @@ async fn create_join_event(
// We do not add the event_id field to the pdu here because of signature and
// hashes checks
let room_version_id = services().rooms.state.get_room_version(room_id)?;
let room_version_id = services.rooms.state.get_room_version(room_id)?;
let Ok((event_id, mut value)) = gen_event_id_canonical_json(pdu, &room_version_id) else {
// Event could not be converted to canonical json
@ -96,7 +97,7 @@ async fn create_join_event(
)
.map_err(|_| Error::BadRequest(ErrorKind::BadJson, "sender is not a valid user ID."))?;
services()
services
.rooms
.event_handler
.acl_check(sender.server_name(), room_id)?;
@ -128,18 +129,18 @@ async fn create_join_event(
if content
.join_authorized_via_users_server
.is_some_and(|user| user_is_local(&user))
&& super::user_can_perform_restricted_join(&sender, room_id, &room_version_id).unwrap_or_default()
&& super::user_can_perform_restricted_join(services, &sender, room_id, &room_version_id).unwrap_or_default()
{
ruma::signatures::hash_and_sign_event(
services().globals.server_name().as_str(),
services().globals.keypair(),
services.globals.server_name().as_str(),
services.globals.keypair(),
&mut value,
&room_version_id,
)
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Failed to sign event."))?;
}
services()
services
.rooms
.event_handler
.fetch_required_signing_keys([&value], &pub_key_map)
@ -155,13 +156,13 @@ async fn create_join_event(
)
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "origin is not a server name."))?;
let mutex_lock = services()
let mutex_lock = services
.rooms
.event_handler
.mutex_federation
.lock(room_id)
.await;
let pdu_id: Vec<u8> = services()
let pdu_id: Vec<u8> = services
.rooms
.event_handler
.handle_incoming_pdu(&origin, room_id, &event_id, value.clone(), true, &pub_key_map)
@ -169,27 +170,27 @@ async fn create_join_event(
.ok_or_else(|| Error::BadRequest(ErrorKind::InvalidParam, "Could not accept as timeline event."))?;
drop(mutex_lock);
let state_ids = services()
let state_ids = services
.rooms
.state_accessor
.state_full_ids(shortstatehash)
.await?;
let auth_chain_ids = services()
let auth_chain_ids = services
.rooms
.auth_chain
.event_ids_iter(room_id, state_ids.values().cloned().collect())
.await?;
services().sending.send_pdu_room(room_id, &pdu_id)?;
services.sending.send_pdu_room(room_id, &pdu_id)?;
Ok(create_join_event::v1::RoomState {
auth_chain: auth_chain_ids
.filter_map(|id| services().rooms.timeline.get_pdu_json(&id).ok().flatten())
.filter_map(|id| services.rooms.timeline.get_pdu_json(&id).ok().flatten())
.map(convert_to_outgoing_federation_event)
.collect(),
state: state_ids
.iter()
.filter_map(|(_, id)| services().rooms.timeline.get_pdu_json(id).ok().flatten())
.filter_map(|(_, id)| services.rooms.timeline.get_pdu_json(id).ok().flatten())
.map(convert_to_outgoing_federation_event)
.collect(),
// Event field is required if the room version supports restricted join rules.
@ -204,11 +205,11 @@ async fn create_join_event(
///
/// Submits a signed join event.
pub(crate) async fn create_join_event_v1_route(
body: Ruma<create_join_event::v1::Request>,
State(services): State<crate::State>, body: Ruma<create_join_event::v1::Request>,
) -> Result<create_join_event::v1::Response> {
let origin = body.origin.as_ref().expect("server is authenticated");
if services()
if services
.globals
.config
.forbidden_remote_server_names
@ -225,7 +226,7 @@ pub(crate) async fn create_join_event_v1_route(
}
if let Some(server) = body.room_id.server_name() {
if services()
if services
.globals
.config
.forbidden_remote_server_names
@ -243,7 +244,7 @@ pub(crate) async fn create_join_event_v1_route(
}
}
let room_state = create_join_event(origin, &body.room_id, &body.pdu).await?;
let room_state = create_join_event(services, origin, &body.room_id, &body.pdu).await?;
Ok(create_join_event::v1::Response {
room_state,
@ -254,11 +255,11 @@ pub(crate) async fn create_join_event_v1_route(
///
/// Submits a signed join event.
pub(crate) async fn create_join_event_v2_route(
body: Ruma<create_join_event::v2::Request>,
State(services): State<crate::State>, body: Ruma<create_join_event::v2::Request>,
) -> Result<create_join_event::v2::Response> {
let origin = body.origin.as_ref().expect("server is authenticated");
if services()
if services
.globals
.config
.forbidden_remote_server_names
@ -271,7 +272,7 @@ pub(crate) async fn create_join_event_v2_route(
}
if let Some(server) = body.room_id.server_name() {
if services()
if services
.globals
.config
.forbidden_remote_server_names
@ -288,7 +289,7 @@ pub(crate) async fn create_join_event_v2_route(
auth_chain,
state,
event,
} = create_join_event(origin, &body.room_id, &body.pdu).await?;
} = create_join_event(services, origin, &body.room_id, &body.pdu).await?;
let room_state = create_join_event::v2::RoomState {
members_omitted: false,
auth_chain,

View file

@ -2,6 +2,7 @@
use std::collections::BTreeMap;
use axum::extract::State;
use ruma::{
api::{client::error::ErrorKind, federation::membership::create_leave_event},
events::{
@ -14,19 +15,19 @@ use serde_json::value::RawValue as RawJsonValue;
use tokio::sync::RwLock;
use crate::{
service::{pdu::gen_event_id_canonical_json, server_is_ours},
services, Error, Result, Ruma,
service::{pdu::gen_event_id_canonical_json, server_is_ours, Services},
Error, Result, Ruma,
};
/// # `PUT /_matrix/federation/v1/send_leave/{roomId}/{eventId}`
///
/// Submits a signed leave event.
pub(crate) async fn create_leave_event_v1_route(
body: Ruma<create_leave_event::v1::Request>,
State(services): State<crate::State>, body: Ruma<create_leave_event::v1::Request>,
) -> Result<create_leave_event::v1::Response> {
let origin = body.origin.as_ref().expect("server is authenticated");
create_leave_event(origin, &body.room_id, &body.pdu).await?;
create_leave_event(services, origin, &body.room_id, &body.pdu).await?;
Ok(create_leave_event::v1::Response::new())
}
@ -35,28 +36,30 @@ pub(crate) async fn create_leave_event_v1_route(
///
/// Submits a signed leave event.
pub(crate) async fn create_leave_event_v2_route(
body: Ruma<create_leave_event::v2::Request>,
State(services): State<crate::State>, body: Ruma<create_leave_event::v2::Request>,
) -> Result<create_leave_event::v2::Response> {
let origin = body.origin.as_ref().expect("server is authenticated");
create_leave_event(origin, &body.room_id, &body.pdu).await?;
create_leave_event(services, origin, &body.room_id, &body.pdu).await?;
Ok(create_leave_event::v2::Response::new())
}
async fn create_leave_event(origin: &ServerName, room_id: &RoomId, pdu: &RawJsonValue) -> Result<()> {
if !services().rooms.metadata.exists(room_id)? {
async fn create_leave_event(
services: &Services, origin: &ServerName, room_id: &RoomId, pdu: &RawJsonValue,
) -> Result<()> {
if !services.rooms.metadata.exists(room_id)? {
return Err(Error::BadRequest(ErrorKind::NotFound, "Room is unknown to this server."));
}
// ACL check origin
services().rooms.event_handler.acl_check(origin, room_id)?;
services.rooms.event_handler.acl_check(origin, room_id)?;
let pub_key_map = RwLock::new(BTreeMap::new());
// We do not add the event_id field to the pdu here because of signature and
// hashes checks
let room_version_id = services().rooms.state.get_room_version(room_id)?;
let room_version_id = services.rooms.state.get_room_version(room_id)?;
let Ok((event_id, value)) = gen_event_id_canonical_json(pdu, &room_version_id) else {
// Event could not be converted to canonical json
return Err(Error::BadRequest(
@ -107,7 +110,7 @@ async fn create_leave_event(origin: &ServerName, room_id: &RoomId, pdu: &RawJson
)
.map_err(|_| Error::BadRequest(ErrorKind::BadJson, "User ID in sender is invalid."))?;
services()
services
.rooms
.event_handler
.acl_check(sender.server_name(), room_id)?;
@ -145,19 +148,19 @@ async fn create_leave_event(origin: &ServerName, room_id: &RoomId, pdu: &RawJson
)
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "origin is not a server name."))?;
services()
services
.rooms
.event_handler
.fetch_required_signing_keys([&value], &pub_key_map)
.await?;
let mutex_lock = services()
let mutex_lock = services
.rooms
.event_handler
.mutex_federation
.lock(room_id)
.await;
let pdu_id: Vec<u8> = services()
let pdu_id: Vec<u8> = services
.rooms
.event_handler
.handle_incoming_pdu(&origin, room_id, &event_id, value, true, &pub_key_map)
@ -166,14 +169,14 @@ async fn create_leave_event(origin: &ServerName, room_id: &RoomId, pdu: &RawJson
drop(mutex_lock);
let servers = services()
let servers = services
.rooms
.state_cache
.room_servers(room_id)
.filter_map(Result::ok)
.filter(|server| !server_is_ours(server));
services().sending.send_pdu_servers(servers, &pdu_id)?;
services.sending.send_pdu_servers(servers, &pdu_id)?;
Ok(())
}

View file

@ -1,8 +1,9 @@
use std::sync::Arc;
use axum::extract::State;
use conduit::{Error, Result};
use ruma::api::{client::error::ErrorKind, federation::event::get_room_state};
use service::{sending::convert_to_outgoing_federation_event, services};
use service::sending::convert_to_outgoing_federation_event;
use crate::Ruma;
@ -10,20 +11,20 @@ use crate::Ruma;
///
/// Retrieves a snapshot of a room's state at a given event.
pub(crate) async fn get_room_state_route(
body: Ruma<get_room_state::v1::Request>,
State(services): State<crate::State>, body: Ruma<get_room_state::v1::Request>,
) -> Result<get_room_state::v1::Response> {
let origin = body.origin.as_ref().expect("server is authenticated");
services()
services
.rooms
.event_handler
.acl_check(origin, &body.room_id)?;
if !services()
if !services
.rooms
.state_accessor
.is_world_readable(&body.room_id)?
&& !services()
&& !services
.rooms
.state_cache
.server_in_room(origin, &body.room_id)?
@ -31,31 +32,22 @@ pub(crate) async fn get_room_state_route(
return Err(Error::BadRequest(ErrorKind::forbidden(), "Server is not in room."));
}
let shortstatehash = services()
let shortstatehash = services
.rooms
.state_accessor
.pdu_shortstatehash(&body.event_id)?
.ok_or_else(|| Error::BadRequest(ErrorKind::NotFound, "Pdu state not found."))?;
let pdus = services()
let pdus = services
.rooms
.state_accessor
.state_full_ids(shortstatehash)
.await?
.into_values()
.map(|id| {
convert_to_outgoing_federation_event(
services()
.rooms
.timeline
.get_pdu_json(&id)
.unwrap()
.unwrap(),
)
})
.map(|id| convert_to_outgoing_federation_event(services.rooms.timeline.get_pdu_json(&id).unwrap().unwrap()))
.collect();
let auth_chain_ids = services()
let auth_chain_ids = services
.rooms
.auth_chain
.event_ids_iter(&body.room_id, vec![Arc::from(&*body.event_id)])
@ -64,7 +56,7 @@ pub(crate) async fn get_room_state_route(
Ok(get_room_state::v1::Response {
auth_chain: auth_chain_ids
.filter_map(|id| {
services()
services
.rooms
.timeline
.get_pdu_json(&id)

View file

@ -1,28 +1,29 @@
use std::sync::Arc;
use axum::extract::State;
use ruma::api::{client::error::ErrorKind, federation::event::get_room_state_ids};
use crate::{services, Error, Result, Ruma};
use crate::{Error, Result, Ruma};
/// # `GET /_matrix/federation/v1/state_ids/{roomId}`
///
/// Retrieves a snapshot of a room's state at a given event, in the form of
/// event IDs.
pub(crate) async fn get_room_state_ids_route(
body: Ruma<get_room_state_ids::v1::Request>,
State(services): State<crate::State>, body: Ruma<get_room_state_ids::v1::Request>,
) -> Result<get_room_state_ids::v1::Response> {
let origin = body.origin.as_ref().expect("server is authenticated");
services()
services
.rooms
.event_handler
.acl_check(origin, &body.room_id)?;
if !services()
if !services
.rooms
.state_accessor
.is_world_readable(&body.room_id)?
&& !services()
&& !services
.rooms
.state_cache
.server_in_room(origin, &body.room_id)?
@ -30,13 +31,13 @@ pub(crate) async fn get_room_state_ids_route(
return Err(Error::BadRequest(ErrorKind::forbidden(), "Server is not in room."));
}
let shortstatehash = services()
let shortstatehash = services
.rooms
.state_accessor
.pdu_shortstatehash(&body.event_id)?
.ok_or_else(|| Error::BadRequest(ErrorKind::NotFound, "Pdu state not found."))?;
let pdu_ids = services()
let pdu_ids = services
.rooms
.state_accessor
.state_full_ids(shortstatehash)
@ -45,7 +46,7 @@ pub(crate) async fn get_room_state_ids_route(
.map(|id| (*id).to_owned())
.collect();
let auth_chain_ids = services()
let auth_chain_ids = services
.rooms
.auth_chain
.event_ids_iter(&body.room_id, vec![Arc::from(&*body.event_id)])

View file

@ -1,3 +1,4 @@
use axum::extract::State;
use ruma::api::{
client::error::ErrorKind,
federation::{
@ -9,13 +10,15 @@ use ruma::api::{
use crate::{
client::{claim_keys_helper, get_keys_helper},
service::user_is_local,
services, Error, Result, Ruma,
Error, Result, Ruma,
};
/// # `GET /_matrix/federation/v1/user/devices/{userId}`
///
/// Gets information on all devices of the user.
pub(crate) async fn get_devices_route(body: Ruma<get_devices::v1::Request>) -> Result<get_devices::v1::Response> {
pub(crate) async fn get_devices_route(
State(services): State<crate::State>, body: Ruma<get_devices::v1::Request>,
) -> Result<get_devices::v1::Response> {
if !user_is_local(&body.user_id) {
return Err(Error::BadRequest(
ErrorKind::InvalidParam,
@ -27,25 +30,25 @@ pub(crate) async fn get_devices_route(body: Ruma<get_devices::v1::Request>) -> R
Ok(get_devices::v1::Response {
user_id: body.user_id.clone(),
stream_id: services()
stream_id: services
.users
.get_devicelist_version(&body.user_id)?
.unwrap_or(0)
.try_into()
.expect("version will not grow that large"),
devices: services()
devices: services
.users
.all_devices_metadata(&body.user_id)
.filter_map(Result::ok)
.filter_map(|metadata| {
let device_id_string = metadata.device_id.as_str().to_owned();
let device_display_name = if services().globals.allow_device_name_federation() {
let device_display_name = if services.globals.allow_device_name_federation() {
metadata.display_name
} else {
Some(device_id_string)
};
Some(UserDevice {
keys: services()
keys: services
.users
.get_device_keys(&body.user_id, &metadata.device_id)
.ok()??,
@ -54,10 +57,10 @@ pub(crate) async fn get_devices_route(body: Ruma<get_devices::v1::Request>) -> R
})
})
.collect(),
master_key: services()
master_key: services
.users
.get_master_key(None, &body.user_id, &|u| u.server_name() == origin)?,
self_signing_key: services()
self_signing_key: services
.users
.get_self_signing_key(None, &body.user_id, &|u| u.server_name() == origin)?,
})
@ -66,7 +69,9 @@ pub(crate) async fn get_devices_route(body: Ruma<get_devices::v1::Request>) -> R
/// # `POST /_matrix/federation/v1/user/keys/query`
///
/// Gets devices and identity keys for the given users.
pub(crate) async fn get_keys_route(body: Ruma<get_keys::v1::Request>) -> Result<get_keys::v1::Response> {
pub(crate) async fn get_keys_route(
State(services): State<crate::State>, body: Ruma<get_keys::v1::Request>,
) -> Result<get_keys::v1::Response> {
if body.device_keys.iter().any(|(u, _)| !user_is_local(u)) {
return Err(Error::BadRequest(
ErrorKind::InvalidParam,
@ -75,10 +80,11 @@ pub(crate) async fn get_keys_route(body: Ruma<get_keys::v1::Request>) -> Result<
}
let result = get_keys_helper(
services,
None,
&body.device_keys,
|u| Some(u.server_name()) == body.origin.as_deref(),
services().globals.allow_device_name_federation(),
services.globals.allow_device_name_federation(),
)
.await?;
@ -92,7 +98,9 @@ pub(crate) async fn get_keys_route(body: Ruma<get_keys::v1::Request>) -> Result<
/// # `POST /_matrix/federation/v1/user/keys/claim`
///
/// Claims one-time keys.
pub(crate) async fn claim_keys_route(body: Ruma<claim_keys::v1::Request>) -> Result<claim_keys::v1::Response> {
pub(crate) async fn claim_keys_route(
State(services): State<crate::State>, body: Ruma<claim_keys::v1::Request>,
) -> Result<claim_keys::v1::Response> {
if body.one_time_keys.iter().any(|(u, _)| !user_is_local(u)) {
return Err(Error::BadRequest(
ErrorKind::InvalidParam,
@ -100,7 +108,7 @@ pub(crate) async fn claim_keys_route(body: Ruma<claim_keys::v1::Request>) -> Res
));
}
let result = claim_keys_helper(&body.one_time_keys).await?;
let result = claim_keys_helper(services, &body.one_time_keys).await?;
Ok(claim_keys::v1::Response {
one_time_keys: result.one_time_keys,

View file

@ -1,15 +1,16 @@
use axum::extract::State;
use ruma::api::{client::error::ErrorKind, federation::discovery::discover_homeserver};
use crate::{services, Error, Result, Ruma};
use crate::{Error, Result, Ruma};
/// # `GET /.well-known/matrix/server`
///
/// Returns the .well-known URL if it is configured, otherwise returns 404.
pub(crate) async fn well_known_server(
_body: Ruma<discover_homeserver::Request>,
State(services): State<crate::State>, _body: Ruma<discover_homeserver::Request>,
) -> Result<discover_homeserver::Response> {
Ok(discover_homeserver::Response {
server: match services().globals.well_known_server() {
server: match services.globals.well_known_server() {
Some(server_name) => server_name.to_owned(),
None => return Err(Error::BadRequest(ErrorKind::NotFound, "Not found.")),
},