Fix alias resolution logic; element-web v1.11.111 compat

element-hq/element-web#30641
element-hq/element-web#30611

Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
dasha_uwu
2025-09-09 00:08:19 +05:00
committed by Jason Volk
parent deda746222
commit adadafa88f
3 changed files with 54 additions and 55 deletions

View File

@@ -403,18 +403,18 @@ async fn public_rooms_chunk(services: &Services, room_id: OwnedRoomId) -> Public
let canonical_alias = services let canonical_alias = services
.state_accessor .state_accessor
.get_canonical_alias(&room_id) .get_canonical_alias(&room_id)
.and_then(async |alias| { .ok()
if services .then(async |alias| {
.globals if let Some(alias) = alias
.server_is_ours(alias.server_name()) && services.globals.alias_is_local(&alias)
&& !services.alias.local_alias_exists(&alias).await && let Ok(alias_room_id) = services.alias.resolve_local_alias(&alias).await
&& alias_room_id == room_id
{ {
return Err!(Request(NotFound("Canonical alias not found."))); Some(alias)
} else {
None
} }
});
Ok(alias)
})
.ok();
let avatar_url = services let avatar_url = services
.state_accessor .state_accessor

View File

@@ -11,7 +11,9 @@ use std::{
use async_trait::async_trait; use async_trait::async_trait;
use data::Data; use data::Data;
use regex::RegexSet; use regex::RegexSet;
use ruma::{OwnedEventId, OwnedRoomAliasId, OwnedServerName, OwnedUserId, ServerName, UserId}; use ruma::{
OwnedEventId, OwnedRoomAliasId, OwnedServerName, OwnedUserId, RoomAliasId, ServerName, UserId,
};
use tuwunel_core::{Result, Server, error, utils::bytes::pretty}; use tuwunel_core::{Result, Server, error, utils::bytes::pretty};
use crate::service; use crate::service;
@@ -250,6 +252,12 @@ impl Service {
self.server_is_ours(user_id.server_name()) self.server_is_ours(user_id.server_name())
} }
#[inline]
#[must_use]
pub fn alias_is_local(&self, alias: &RoomAliasId) -> bool {
self.server_is_ours(alias.server_name())
}
#[inline] #[inline]
#[must_use] #[must_use]
pub fn server_is_ours(&self, server_name: &ServerName) -> bool { pub fn server_is_ours(&self, server_name: &ServerName) -> bool {

View File

@@ -125,33 +125,30 @@ impl Service {
room_alias: &RoomAliasId, room_alias: &RoomAliasId,
servers: Option<Vec<OwnedServerName>>, servers: Option<Vec<OwnedServerName>>,
) -> Result<(OwnedRoomId, Vec<OwnedServerName>)> { ) -> Result<(OwnedRoomId, Vec<OwnedServerName>)> {
let server_name = room_alias.server_name(); if self
let server_is_ours = self.services.globals.server_is_ours(server_name); .services
let servers_contains_ours = || { .globals
servers .server_is_ours(room_alias.server_name())
.as_ref() {
.is_some_and(|servers| servers.contains(&self.services.server.name)) if let Ok(room_id) = self.resolve_local_alias(room_alias).await {
}; return Ok((room_id, Vec::new()));
}
if !server_is_ours && !servers_contains_ours() { if let Ok(room_id) = self.resolve_appservice_alias(room_alias).await {
return self return Ok((room_id, Vec::new()));
.remote_resolve(room_alias, servers.unwrap_or_default()) }
.await;
return Err!(Request(NotFound("Room with alias not found.")));
} }
let room_id = match self.resolve_local_alias(room_alias).await { return self
| Ok(r) => Some(r), .remote_resolve(room_alias, servers.unwrap_or_default())
| Err(_) => self.resolve_appservice_alias(room_alias).await?, .await;
};
room_id.map_or_else(
|| Err!(Request(NotFound("Room with alias not found."))),
|room_id| Ok((room_id, Vec::new())),
)
} }
#[tracing::instrument(skip(self), level = "trace")] #[tracing::instrument(skip(self), level = "trace")]
pub async fn resolve_local_alias(&self, alias: &RoomAliasId) -> Result<OwnedRoomId> { pub async fn resolve_local_alias(&self, alias: &RoomAliasId) -> Result<OwnedRoomId> {
self.check_alias_local(alias)?;
self.db self.db
.alias_roomid .alias_roomid
.get(alias.alias()) .get(alias.alias())
@@ -159,15 +156,6 @@ impl Service {
.deserialized() .deserialized()
} }
#[tracing::instrument(skip(self), level = "trace")]
pub async fn local_alias_exists(&self, alias: &RoomAliasId) -> bool {
self.db
.alias_roomid
.exists(alias.alias())
.await
.is_ok()
}
#[tracing::instrument(skip(self), level = "debug")] #[tracing::instrument(skip(self), level = "debug")]
pub fn local_aliases_for_room<'a>( pub fn local_aliases_for_room<'a>(
&'a self, &'a self,
@@ -191,6 +179,8 @@ impl Service {
} }
async fn user_can_remove_alias(&self, alias: &RoomAliasId, user_id: &UserId) -> Result<bool> { async fn user_can_remove_alias(&self, alias: &RoomAliasId, user_id: &UserId) -> Result<bool> {
self.check_alias_local(alias)?;
let room_id = self let room_id = self
.resolve_local_alias(alias) .resolve_local_alias(alias)
.await .await
@@ -237,6 +227,8 @@ impl Service {
} }
async fn who_created_alias(&self, alias: &RoomAliasId) -> Result<OwnedUserId> { async fn who_created_alias(&self, alias: &RoomAliasId) -> Result<OwnedUserId> {
self.check_alias_local(alias)?;
self.db self.db
.alias_userid .alias_userid
.get(alias.alias()) .get(alias.alias())
@@ -244,12 +236,11 @@ impl Service {
.deserialized() .deserialized()
} }
async fn resolve_appservice_alias( async fn resolve_appservice_alias(&self, room_alias: &RoomAliasId) -> Result<OwnedRoomId> {
&self,
room_alias: &RoomAliasId,
) -> Result<Option<OwnedRoomId>> {
use ruma::api::appservice::query::query_room_alias; use ruma::api::appservice::query::query_room_alias;
self.check_alias_local(room_alias)?;
for appservice in self.services.appservice.read().await.values() { for appservice in self.services.appservice.read().await.values() {
if appservice.aliases.is_match(room_alias.as_str()) if appservice.aliases.is_match(room_alias.as_str())
&& matches!( && matches!(
@@ -265,12 +256,19 @@ impl Service {
return self return self
.resolve_local_alias(room_alias) .resolve_local_alias(room_alias)
.await .await
.map_err(|_| err!(Request(NotFound("Room does not exist.")))) .map_err(|_| err!(Request(NotFound("Room does not exist."))));
.map(Some);
} }
} }
Ok(None) Err!(Request(NotFound("Room does not exist.")))
}
fn check_alias_local(&self, alias: &RoomAliasId) -> Result {
if !self.services.globals.alias_is_local(alias) {
return Err!(Request(InvalidParam("Alias is from another server.")));
}
Ok(())
} }
#[tracing::instrument(skip(self, appservice_info), level = "trace")] #[tracing::instrument(skip(self, appservice_info), level = "trace")]
@@ -279,14 +277,7 @@ impl Service {
room_alias: &RoomAliasId, room_alias: &RoomAliasId,
appservice_info: &Option<RegistrationInfo>, appservice_info: &Option<RegistrationInfo>,
) -> Result { ) -> Result {
if !self self.check_alias_local(room_alias)?;
.services
.globals
.server_is_ours(room_alias.server_name())
{
return Err!(Request(InvalidParam("Alias is from another server.")));
}
if let Some(info) = appservice_info { if let Some(info) = appservice_info {
if !info.aliases.is_match(room_alias.as_str()) { if !info.aliases.is_match(room_alias.as_str()) {
return Err!(Request(Exclusive("Room alias is not in namespace."))); return Err!(Request(Exclusive("Room alias is not in namespace.")));