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:
@@ -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
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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.")));
|
||||||
|
|||||||
Reference in New Issue
Block a user