mirror of
https://gitlab.computer.surgery/matrix/grapevine.git
synced 2025-12-16 15:21:24 +01:00
allow adding canonical aliases from remote servers
Like is mentioned in the comment, this isn't explicitly required by the spec, but it's reasonable and what synapse does.
This commit is contained in:
parent
29d8fbaefa
commit
472f51c350
4 changed files with 57 additions and 12 deletions
|
|
@ -311,3 +311,5 @@ This will be the first release of Grapevine since it was forked from Conduit
|
|||
([!121](https://gitlab.computer.surgery/matrix/grapevine/-/merge_requests/121))
|
||||
25. Add configuration options to tune the value of each cache individually.
|
||||
([!124](https://gitlab.computer.surgery/matrix/grapevine/-/merge_requests/124))
|
||||
26. Allow adding canonical aliases from remote servers.
|
||||
([!158](https://gitlab.computer.surgery/matrix/grapevine/-/merge_requests/158))
|
||||
|
|
|
|||
|
|
@ -107,6 +107,8 @@ pub(crate) async fn get_alias_route(
|
|||
get_alias_helper(body.body.room_alias).await.map(Ra)
|
||||
}
|
||||
|
||||
// Can't use `services().rooms.alias.resolve_alias` because we also need the set
|
||||
// of servers from the remote get_room_information request.
|
||||
pub(crate) async fn get_alias_helper(
|
||||
room_alias: OwnedRoomAliasId,
|
||||
) -> Result<get_alias::v3::Response> {
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ async fn send_state_event_for_key_helper(
|
|||
let sender_user = sender;
|
||||
|
||||
if event_type == &StateEventType::RoomCanonicalAlias {
|
||||
validate_canonical_alias_event(room_id, json.cast_ref())?;
|
||||
validate_canonical_alias_event(room_id, json.cast_ref()).await?;
|
||||
}
|
||||
|
||||
let room_token = services()
|
||||
|
|
@ -253,7 +253,7 @@ async fn send_state_event_for_key_helper(
|
|||
/// > are already present in the state event.
|
||||
///
|
||||
/// [spec]: https://spec.matrix.org/v1.13/client-server-api/#put_matrixclientv3roomsroomidstateeventtypestatekey
|
||||
fn validate_canonical_alias_event(
|
||||
async fn validate_canonical_alias_event(
|
||||
room_id: &RoomId,
|
||||
json: &Raw<RoomCanonicalAliasEventContent>,
|
||||
) -> Result<()> {
|
||||
|
|
@ -311,13 +311,11 @@ fn validate_canonical_alias_event(
|
|||
)
|
||||
})?;
|
||||
|
||||
if alias.server_name() != services().globals.server_name()
|
||||
|| services()
|
||||
.rooms
|
||||
.alias
|
||||
.resolve_local_alias(&alias)?
|
||||
.filter(|room| room == room_id)
|
||||
.is_none()
|
||||
// The spec doesn't say explicitly that we should allow adding new
|
||||
// remote canonical aliases, but it's reasonable behavior and what
|
||||
// synapse does.
|
||||
if services().rooms.alias.resolve_alias(&alias).await?.as_deref()
|
||||
!= Some(room_id)
|
||||
{
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::BadAlias,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use http::StatusCode;
|
||||
use ruma::{
|
||||
api::client::error::ErrorKind, OwnedRoomAliasId, OwnedRoomId, RoomAliasId,
|
||||
RoomId, UserId,
|
||||
api::{client::error::ErrorKind, federation},
|
||||
OwnedRoomAliasId, OwnedRoomId, RoomAliasId, RoomId, UserId,
|
||||
};
|
||||
|
||||
use crate::{services, Error, Result};
|
||||
|
|
@ -60,7 +61,7 @@ impl Service {
|
|||
self.db.remove_alias(alias)
|
||||
}
|
||||
|
||||
/// Looks up the roomid for the given alias.
|
||||
/// Looks up the roomid for the given local alias.
|
||||
pub(crate) fn resolve_local_alias(
|
||||
&self,
|
||||
alias: &RoomAliasId,
|
||||
|
|
@ -75,4 +76,46 @@ impl Service {
|
|||
) -> Box<dyn Iterator<Item = Result<OwnedRoomAliasId>> + 'a> {
|
||||
self.db.local_aliases_for_room(room_id)
|
||||
}
|
||||
|
||||
/// Looks up the roomid for the given alias, fetching over federation if
|
||||
/// remote.
|
||||
pub(crate) async fn resolve_alias(
|
||||
&self,
|
||||
alias: &RoomAliasId,
|
||||
) -> Result<Option<OwnedRoomId>> {
|
||||
if alias.server_name() == services().globals.server_name() {
|
||||
self.resolve_local_alias(alias)
|
||||
} else {
|
||||
self.resolve_remote_alias(alias).await
|
||||
}
|
||||
}
|
||||
|
||||
/// Look up an alias on a remote server over federation.
|
||||
async fn resolve_remote_alias(
|
||||
&self,
|
||||
alias: &RoomAliasId,
|
||||
) -> Result<Option<OwnedRoomId>> {
|
||||
let result = services()
|
||||
.sending
|
||||
.send_federation_request(
|
||||
alias.server_name(),
|
||||
federation::query::get_room_information::v1::Request {
|
||||
room_alias: alias.to_owned(),
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
||||
match result {
|
||||
Ok(response) => Ok(Some(response.room_id)),
|
||||
// The spec only names the 404 status code explicitly, but matching
|
||||
// on M_NOT_FOUND as well seems reasonable.
|
||||
Err(Error::Federation(_, error))
|
||||
if error.status_code == StatusCode::NOT_FOUND
|
||||
|| error.error_kind() == Some(&ErrorKind::NotFound) =>
|
||||
{
|
||||
Ok(None)
|
||||
}
|
||||
Err(error) => Err(error),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue