split up alias.rs a bit (alias checks and room alias server name stuff)

Signed-off-by: strawberry <strawberry@puppygock.gay>
This commit is contained in:
strawberry 2024-05-01 00:01:49 -04:00 committed by June
parent e00b65b0e0
commit f4a2b39d55

View file

@ -8,20 +8,23 @@ use ruma::{
}, },
federation, federation,
}, },
OwnedRoomAliasId, OwnedServerName, OwnedRoomAliasId, OwnedRoomId, OwnedServerName,
}; };
use tracing::debug; use tracing::debug;
use crate::{debug_info, debug_warn, services, utils::server_name::server_is_ours, Error, Result, Ruma}; use crate::{
debug_info, debug_warn, service::appservice::RegistrationInfo, services, utils::server_name::server_is_ours, Error,
Result, Ruma,
};
/// # `PUT /_matrix/client/v3/directory/room/{roomAlias}` /// # `PUT /_matrix/client/v3/directory/room/{roomAlias}`
/// ///
/// Creates a new room alias on this server. /// Creates a new room alias on this server.
pub(crate) async fn create_alias_route(body: Ruma<create_alias::v3::Request>) -> Result<create_alias::v3::Response> { pub(crate) async fn create_alias_route(body: Ruma<create_alias::v3::Request>) -> Result<create_alias::v3::Response> {
if !server_is_ours(body.room_alias.server_name()) { alias_checks(&body.room_alias, &body.appservice_info).await?;
return Err(Error::BadRequest(ErrorKind::InvalidParam, "Alias is from another server."));
}
// this isn't apart of alias_checks or delete alias route because we should
// allow removing forbidden room aliases
if services() if services()
.globals .globals
.forbidden_alias_names() .forbidden_alias_names()
@ -30,18 +33,6 @@ pub(crate) async fn create_alias_route(body: Ruma<create_alias::v3::Request>) ->
return Err(Error::BadRequest(ErrorKind::Unknown, "Room alias is forbidden.")); return Err(Error::BadRequest(ErrorKind::Unknown, "Room alias is forbidden."));
} }
if let Some(ref info) = body.appservice_info {
if !info.aliases.is_match(body.room_alias.as_str()) {
return Err(Error::BadRequest(ErrorKind::Exclusive, "Room alias is not in namespace."));
}
} else if services()
.appservice
.is_exclusive_alias(&body.room_alias)
.await
{
return Err(Error::BadRequest(ErrorKind::Exclusive, "Room alias reserved by appservice."));
}
if services() if services()
.rooms .rooms
.alias .alias
@ -73,9 +64,7 @@ pub(crate) async fn create_alias_route(body: Ruma<create_alias::v3::Request>) ->
/// - TODO: additional access control checks /// - TODO: additional access control checks
/// - TODO: Update canonical alias event /// - TODO: Update canonical alias event
pub(crate) async fn delete_alias_route(body: Ruma<delete_alias::v3::Request>) -> Result<delete_alias::v3::Response> { pub(crate) async fn delete_alias_route(body: Ruma<delete_alias::v3::Request>) -> Result<delete_alias::v3::Response> {
if !server_is_ours(body.room_alias.server_name()) { alias_checks(&body.room_alias, &body.appservice_info).await?;
return Err(Error::BadRequest(ErrorKind::InvalidParam, "Alias is from another server."));
}
if services() if services()
.rooms .rooms
@ -86,18 +75,6 @@ pub(crate) async fn delete_alias_route(body: Ruma<delete_alias::v3::Request>) ->
return Err(Error::BadRequest(ErrorKind::NotFound, "Alias does not exist.")); return Err(Error::BadRequest(ErrorKind::NotFound, "Alias does not exist."));
} }
if let Some(ref info) = body.appservice_info {
if !info.aliases.is_match(body.room_alias.as_str()) {
return Err(Error::BadRequest(ErrorKind::Exclusive, "Room alias is not in namespace."));
}
} else if services()
.appservice
.is_exclusive_alias(&body.room_alias)
.await
{
return Err(Error::BadRequest(ErrorKind::Exclusive, "Room alias reserved by appservice."));
}
if services() if services()
.rooms .rooms
.alias .alias
@ -180,42 +157,16 @@ pub(crate) async fn get_alias_helper(
if let Ok(response) = response { if let Ok(response) = response {
let room_id = response.room_id; let room_id = response.room_id;
let mut servers = response.servers; let mut pre_servers = response.servers;
// since the room alis server responded, insert it into the list
pre_servers.push(room_alias.server_name().into());
// since the room alias server_name responded, insert it into the list let servers = room_available_servers(&room_id, &room_alias, &Some(pre_servers));
servers.push(room_alias.server_name().into()); debug_warn!(
"room alias servers from federation response for room ID {room_id} and room alias {room_alias}: \
// find active servers in room state cache to suggest {servers:?}"
servers.extend(
services()
.rooms
.state_cache
.room_servers(&room_id)
.filter_map(Result::ok),
); );
servers.sort_unstable();
servers.dedup();
// shuffle list of servers randomly after sort and dedupe
servers.shuffle(&mut rand::thread_rng());
// prefer the very first server to be ourselves if available, else prefer the
// room alias server first
if let Some(server_index) = servers
.iter()
.position(|server_name| server_is_ours(server_name))
{
servers.remove(server_index);
servers.insert(0, services().globals.server_name().to_owned());
} else if let Some(alias_server_index) = servers
.iter()
.position(|server| server == room_alias.server_name())
{
servers.remove(alias_server_index);
servers.insert(0, room_alias.server_name().into());
}
return Ok(get_alias::v3::Response::new(room_id, servers)); return Ok(get_alias::v3::Response::new(room_id, servers));
} }
@ -260,28 +211,69 @@ pub(crate) async fn get_alias_helper(
return Err(Error::BadRequest(ErrorKind::NotFound, "Room with alias not found.")); return Err(Error::BadRequest(ErrorKind::NotFound, "Room with alias not found."));
}; };
let servers = room_available_servers(&room_id, &room_alias, &None);
debug_warn!("room alias servers for room ID {room_id} and room alias {room_alias}");
Ok(get_alias::v3::Response::new(room_id, servers))
}
fn room_available_servers(
room_id: &OwnedRoomId, room_alias: &OwnedRoomAliasId, pre_servers: &Option<Vec<OwnedServerName>>,
) -> Vec<OwnedServerName> {
// find active servers in room state cache to suggest // find active servers in room state cache to suggest
let mut servers: Vec<OwnedServerName> = services() let mut servers: Vec<OwnedServerName> = services()
.rooms .rooms
.state_cache .state_cache
.room_servers(&room_id) .room_servers(room_id)
.filter_map(Result::ok) .filter_map(Result::ok)
.collect(); .collect();
// push any servers we want in the list already (e.g. responded remote alias
// servers, room alias server itself)
if let Some(pre_servers) = pre_servers {
servers.extend(pre_servers.clone());
};
servers.sort_unstable(); servers.sort_unstable();
servers.dedup(); servers.dedup();
// shuffle list of servers randomly after sort and dedupe // shuffle list of servers randomly after sort and dedupe
servers.shuffle(&mut rand::thread_rng()); servers.shuffle(&mut rand::thread_rng());
// insert our server as the very first choice if in list // insert our server as the very first choice if in list, else check if we can
// prefer the room alias server first
if let Some(server_index) = servers if let Some(server_index) = servers
.iter() .iter()
.position(|server_name| server_is_ours(server_name)) .position(|server_name| server_is_ours(server_name))
{ {
servers.remove(server_index); servers.remove(server_index);
servers.insert(0, services().globals.server_name().to_owned()); servers.insert(0, services().globals.server_name().to_owned());
} else if let Some(alias_server_index) = servers
.iter()
.position(|server| server == room_alias.server_name())
{
servers.remove(alias_server_index);
servers.insert(0, room_alias.server_name().into());
} }
Ok(get_alias::v3::Response::new(room_id, servers)) servers
}
async fn alias_checks(room_alias: &OwnedRoomAliasId, appservice_info: &Option<RegistrationInfo>) -> Result<()> {
if !server_is_ours(room_alias.server_name()) {
return Err(Error::BadRequest(ErrorKind::InvalidParam, "Alias is from another server."));
}
if let Some(ref info) = appservice_info {
if !info.aliases.is_match(room_alias.as_str()) {
return Err(Error::BadRequest(ErrorKind::Exclusive, "Room alias is not in namespace."));
}
}
if services().appservice.is_exclusive_alias(room_alias).await {
return Err(Error::BadRequest(ErrorKind::Exclusive, "Room alias reserved by appservice."));
}
Ok(())
} }