diff --git a/Cargo.lock b/Cargo.lock index f1b25072..df340175 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2903,7 +2903,7 @@ dependencies = [ [[package]] name = "ruma" version = "0.10.1" -source = "git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0#9a5bfad8494b7a4e6c40421c3d0675db4b434ec0" +source = "git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5#c51ccb2c68d2e3557eb12b1a49036531711ec0e5" dependencies = [ "assign", "js_int", @@ -2924,7 +2924,7 @@ dependencies = [ [[package]] name = "ruma-appservice-api" version = "0.10.0" -source = "git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0#9a5bfad8494b7a4e6c40421c3d0675db4b434ec0" +source = "git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5#c51ccb2c68d2e3557eb12b1a49036531711ec0e5" dependencies = [ "js_int", "ruma-common", @@ -2936,7 +2936,7 @@ dependencies = [ [[package]] name = "ruma-client-api" version = "0.18.0" -source = "git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0#9a5bfad8494b7a4e6c40421c3d0675db4b434ec0" +source = "git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5#c51ccb2c68d2e3557eb12b1a49036531711ec0e5" dependencies = [ "as_variant", "assign", @@ -2959,7 +2959,7 @@ dependencies = [ [[package]] name = "ruma-common" version = "0.13.0" -source = "git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0#9a5bfad8494b7a4e6c40421c3d0675db4b434ec0" +source = "git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5#c51ccb2c68d2e3557eb12b1a49036531711ec0e5" dependencies = [ "as_variant", "base64 0.22.1", @@ -2972,7 +2972,7 @@ dependencies = [ "percent-encoding", "rand", "regex", - "ruma-identifiers-validation 0.9.5 (git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0)", + "ruma-identifiers-validation 0.9.5 (git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5)", "ruma-macros", "serde", "serde_html_form", @@ -2989,7 +2989,7 @@ dependencies = [ [[package]] name = "ruma-events" version = "0.28.1" -source = "git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0#9a5bfad8494b7a4e6c40421c3d0675db4b434ec0" +source = "git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5#c51ccb2c68d2e3557eb12b1a49036531711ec0e5" dependencies = [ "as_variant", "indexmap 2.2.6", @@ -2999,7 +2999,7 @@ dependencies = [ "pulldown-cmark", "regex", "ruma-common", - "ruma-identifiers-validation 0.9.5 (git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0)", + "ruma-identifiers-validation 0.9.5 (git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5)", "ruma-macros", "serde", "serde_json", @@ -3012,7 +3012,7 @@ dependencies = [ [[package]] name = "ruma-federation-api" version = "0.9.0" -source = "git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0#9a5bfad8494b7a4e6c40421c3d0675db4b434ec0" +source = "git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5#c51ccb2c68d2e3557eb12b1a49036531711ec0e5" dependencies = [ "js_int", "ruma-common", @@ -3024,7 +3024,7 @@ dependencies = [ [[package]] name = "ruma-identifiers-validation" version = "0.9.5" -source = "git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0#9a5bfad8494b7a4e6c40421c3d0675db4b434ec0" +source = "git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5#c51ccb2c68d2e3557eb12b1a49036531711ec0e5" dependencies = [ "js_int", "thiserror", @@ -3042,7 +3042,7 @@ dependencies = [ [[package]] name = "ruma-identity-service-api" version = "0.9.0" -source = "git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0#9a5bfad8494b7a4e6c40421c3d0675db4b434ec0" +source = "git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5#c51ccb2c68d2e3557eb12b1a49036531711ec0e5" dependencies = [ "js_int", "ruma-common", @@ -3052,13 +3052,13 @@ dependencies = [ [[package]] name = "ruma-macros" version = "0.13.0" -source = "git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0#9a5bfad8494b7a4e6c40421c3d0675db4b434ec0" +source = "git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5#c51ccb2c68d2e3557eb12b1a49036531711ec0e5" dependencies = [ "once_cell", "proc-macro-crate", "proc-macro2", "quote", - "ruma-identifiers-validation 0.9.5 (git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0)", + "ruma-identifiers-validation 0.9.5 (git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5)", "serde", "syn 2.0.68", "toml", @@ -3067,7 +3067,7 @@ dependencies = [ [[package]] name = "ruma-push-gateway-api" version = "0.9.0" -source = "git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0#9a5bfad8494b7a4e6c40421c3d0675db4b434ec0" +source = "git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5#c51ccb2c68d2e3557eb12b1a49036531711ec0e5" dependencies = [ "js_int", "ruma-common", @@ -3079,7 +3079,7 @@ dependencies = [ [[package]] name = "ruma-server-util" version = "0.3.0" -source = "git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0#9a5bfad8494b7a4e6c40421c3d0675db4b434ec0" +source = "git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5#c51ccb2c68d2e3557eb12b1a49036531711ec0e5" dependencies = [ "headers", "http 1.1.0", @@ -3092,7 +3092,7 @@ dependencies = [ [[package]] name = "ruma-signatures" version = "0.15.0" -source = "git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0#9a5bfad8494b7a4e6c40421c3d0675db4b434ec0" +source = "git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5#c51ccb2c68d2e3557eb12b1a49036531711ec0e5" dependencies = [ "base64 0.22.1", "ed25519-dalek", @@ -3108,7 +3108,7 @@ dependencies = [ [[package]] name = "ruma-state-res" version = "0.11.0" -source = "git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0#9a5bfad8494b7a4e6c40421c3d0675db4b434ec0" +source = "git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5#c51ccb2c68d2e3557eb12b1a49036531711ec0e5" dependencies = [ "itertools 0.12.1", "js_int", diff --git a/Cargo.toml b/Cargo.toml index b8b69d71..a52b4138 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -274,7 +274,7 @@ version = "0.1.2" [workspace.dependencies.ruma] git = "https://github.com/girlbossceo/ruwuma" #branch = "conduwuit-changes" -rev = "9a5bfad8494b7a4e6c40421c3d0675db4b434ec0" +rev = "c51ccb2c68d2e3557eb12b1a49036531711ec0e5" features = [ "compat", "rand", @@ -294,6 +294,7 @@ features = [ "unstable-msc2870", "unstable-msc3026", "unstable-msc3061", + "unstable-msc3266", "unstable-msc3575", "unstable-msc4121", "unstable-msc4125", diff --git a/src/api/client/unstable.rs b/src/api/client/unstable.rs index 5fecfb71..f53460a8 100644 --- a/src/api/client/unstable.rs +++ b/src/api/client/unstable.rs @@ -1,5 +1,8 @@ +use axum_client_ip::InsecureClientIp; +use conduit::{warn, RumaResponse}; use ruma::{ - api::client::{error::ErrorKind, membership::mutual_rooms}, + api::client::{error::ErrorKind, membership::mutual_rooms, room::get_summary}, + events::room::member::MembershipState, OwnedRoomId, }; @@ -12,8 +15,9 @@ use crate::{services, Error, Result, Ruma}; /// TODO: Implement pagination, currently this just returns everything /// /// An implementation of [MSC2666](https://github.com/matrix-org/matrix-spec-proposals/pull/2666) +#[tracing::instrument(skip_all, fields(%client), name = "mutual_rooms")] pub(crate) async fn get_mutual_rooms_route( - body: Ruma, + InsecureClientIp(client): InsecureClientIp, body: Ruma, ) -> Result { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); @@ -43,3 +47,116 @@ pub(crate) async fn get_mutual_rooms_route( next_batch_token: None, }) } + +/// # `GET /_matrix/client/unstable/im.nheko.summary/rooms/{roomIdOrAlias}/summary` +/// +/// Returns a short description of the state of a room. +/// +/// This is the "wrong" endpoint that some implementations/clients may use +/// according to the MSC. Request and response bodies are the same as +/// `get_room_summary`. +/// +/// An implementation of [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266) +pub(crate) async fn get_room_summary_legacy( + InsecureClientIp(client): InsecureClientIp, body: Ruma, +) -> Result> { + get_room_summary(InsecureClientIp(client), body) + .await + .map(RumaResponse) +} + +/// # `GET /_matrix/client/unstable/im.nheko.summary/summary/{roomIdOrAlias}` +/// +/// Returns a short description of the state of a room. +/// +/// TODO: support fetching remote room info if we don't know the room +/// +/// An implementation of [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266) +#[tracing::instrument(skip_all, fields(%client), name = "room_summary")] +pub(crate) async fn get_room_summary( + InsecureClientIp(client): InsecureClientIp, body: Ruma, +) -> Result { + let sender_user = body.sender_user.as_ref(); + + let room_id = services() + .rooms + .alias + .resolve(&body.room_id_or_alias) + .await?; + + if !services().rooms.metadata.exists(&room_id)? { + return Err(Error::BadRequest(ErrorKind::NotFound, "Room is unknown to this server")); + } + + if sender_user.is_none() + && !services() + .rooms + .state_accessor + .is_world_readable(&room_id) + .unwrap_or(false) + { + return Err(Error::BadRequest( + ErrorKind::forbidden(), + "Room is not world readable, authentication is required", + )); + } + + Ok(get_summary::msc3266::Response { + room_id: room_id.clone(), + canonical_alias: services() + .rooms + .state_accessor + .get_canonical_alias(&room_id)?, + avatar_url: services() + .rooms + .state_accessor + .get_avatar(&room_id)? + .into_option() + .unwrap_or_default() + .url, + guest_can_join: services().rooms.state_accessor.guest_can_join(&room_id)?, + name: services() + .rooms + .state_accessor + .get_name(&room_id) + .unwrap_or(None), + num_joined_members: services() + .rooms + .state_cache + .room_joined_count(&room_id) + .unwrap_or_default() + .unwrap_or_else(|| { + warn!("Room {room_id} has no member count"); + 0 + }) + .try_into() + .expect("user count should not be that big"), + topic: services() + .rooms + .state_accessor + .get_room_topic(&room_id) + .unwrap_or(None), + world_readable: services() + .rooms + .state_accessor + .is_world_readable(&room_id) + .unwrap_or(false), + join_rule: services().rooms.state_accessor.get_join_rule(&room_id)?.0, + room_type: services().rooms.state_accessor.get_room_type(&room_id)?, + room_version: Some(services().rooms.state.get_room_version(&room_id)?), + membership: if let Some(sender_user) = sender_user { + services() + .rooms + .state_accessor + .get_member(&room_id, sender_user)? + .map_or_else(|| Some(MembershipState::Leave), |content| Some(content.membership)) + } else { + None + }, + encryption: services() + .rooms + .state_accessor + .get_room_encryption(&room_id) + .unwrap_or_else(|_e| None), + }) +} diff --git a/src/api/routes.rs b/src/api/routes.rs index 7510c6b9..94951aec 100644 --- a/src/api/routes.rs +++ b/src/api/routes.rs @@ -172,7 +172,6 @@ pub fn build(router: Router, server: &Server) -> Router { .ruma_route(client::get_key_changes_route) .ruma_route(client::get_pushers_route) .ruma_route(client::set_pushers_route) - // .ruma_route(client::third_party_route) .ruma_route(client::upgrade_room_route) .ruma_route(client::get_threads_route) .ruma_route(client::get_relating_events_with_rel_type_and_event_type_route) @@ -180,6 +179,11 @@ pub fn build(router: Router, server: &Server) -> Router { .ruma_route(client::get_relating_events_route) .ruma_route(client::get_hierarchy_route) .ruma_route(client::get_mutual_rooms_route) + .ruma_route(client::get_room_summary) + .route( + "/_matrix/client/unstable/im.nheko.summary/rooms/:room_id_or_alias/summary", + get(client::get_room_summary_legacy) + ) .ruma_route(client::well_known_support) .ruma_route(client::well_known_client) .route("/_conduwuit/server_version", get(client::conduwuit_server_version)) diff --git a/src/service/rooms/state_accessor/mod.rs b/src/service/rooms/state_accessor/mod.rs index 65c43905..cdd8bec9 100644 --- a/src/service/rooms/state_accessor/mod.rs +++ b/src/service/rooms/state_accessor/mod.rs @@ -14,6 +14,8 @@ use ruma::{ room::{ avatar::RoomAvatarEventContent, canonical_alias::RoomCanonicalAliasEventContent, + create::RoomCreateEventContent, + encryption::RoomEncryptionEventContent, guest_access::{GuestAccess, RoomGuestAccessEventContent}, history_visibility::{HistoryVisibility, RoomHistoryVisibilityEventContent}, join_rules::{AllowRule, JoinRule, RoomJoinRulesEventContent, RoomMembership}, @@ -24,8 +26,10 @@ use ruma::{ }, StateEventType, }, + room::RoomType, space::SpaceRoomJoinRule, - EventId, OwnedRoomAliasId, OwnedRoomId, OwnedServerName, OwnedUserId, RoomId, ServerName, UserId, + EventEncryptionAlgorithm, EventId, OwnedRoomAliasId, OwnedRoomId, OwnedServerName, OwnedUserId, RoomId, ServerName, + UserId, }; use serde_json::value::to_raw_value; @@ -451,4 +455,31 @@ impl Service { } room_ids } + + pub fn get_room_type(&self, room_id: &RoomId) -> Result> { + Ok(self + .room_state_get(room_id, &StateEventType::RoomCreate, "")? + .map(|s| { + serde_json::from_str::(s.content.get()).map_err(|e| { + error!("Invalid room create event in database: {e}"); + Error::BadDatabase("Invalid room create event in database.") + }) + }) + .transpose()? + .and_then(|e| e.room_type)) + } + + /// Gets the room's encryption algorithm if `m.room.encryption` state event + /// is found + pub fn get_room_encryption(&self, room_id: &RoomId) -> Result> { + self.room_state_get(room_id, &StateEventType::RoomEncryption, "")? + .map_or(Ok(None), |s| { + serde_json::from_str::(s.content.get()) + .map(|content| Some(content.algorithm)) + .map_err(|e| { + error!("Invalid room encryption event in database: {e}"); + Error::BadDatabase("Invalid room encryption event in database.") + }) + }) + } }