From 04980b3ee7add06d1c658633216cea8dec5ff620 Mon Sep 17 00:00:00 2001 From: timedout Date: Tue, 23 Dec 2025 19:50:37 +0000 Subject: [PATCH] feat: Enhance invite security checks & do away with stripped state --- Cargo.lock | 22 +- Cargo.toml | 124 +++++------ src/api/client/membership/invite.rs | 2 +- src/api/server/invite.rs | 262 +++++++++++++++++------- src/api/server/send_knock.rs | 6 +- src/service/rooms/state/mod.rs | 23 ++- src/service/rooms/state_cache/update.rs | 8 +- 7 files changed, 281 insertions(+), 166 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 88817c5a..52cd586b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4063,7 +4063,7 @@ checksum = "88f8660c1ff60292143c98d08fc6e2f654d722db50410e3f3797d40baaf9d8f3" [[package]] name = "ruma" version = "0.10.1" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=27abe0dcd33fd4056efc94bab3582646b31b6ce9#27abe0dcd33fd4056efc94bab3582646b31b6ce9" +source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e60876b6ff2d207a46aa8910a02474268bac8592#e60876b6ff2d207a46aa8910a02474268bac8592" dependencies = [ "assign", "js_int", @@ -4083,7 +4083,7 @@ dependencies = [ [[package]] name = "ruma-appservice-api" version = "0.10.0" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=27abe0dcd33fd4056efc94bab3582646b31b6ce9#27abe0dcd33fd4056efc94bab3582646b31b6ce9" +source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e60876b6ff2d207a46aa8910a02474268bac8592#e60876b6ff2d207a46aa8910a02474268bac8592" dependencies = [ "js_int", "ruma-common", @@ -4095,7 +4095,7 @@ dependencies = [ [[package]] name = "ruma-client-api" version = "0.18.0" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=27abe0dcd33fd4056efc94bab3582646b31b6ce9#27abe0dcd33fd4056efc94bab3582646b31b6ce9" +source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e60876b6ff2d207a46aa8910a02474268bac8592#e60876b6ff2d207a46aa8910a02474268bac8592" dependencies = [ "as_variant", "assign", @@ -4118,7 +4118,7 @@ dependencies = [ [[package]] name = "ruma-common" version = "0.13.0" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=27abe0dcd33fd4056efc94bab3582646b31b6ce9#27abe0dcd33fd4056efc94bab3582646b31b6ce9" +source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e60876b6ff2d207a46aa8910a02474268bac8592#e60876b6ff2d207a46aa8910a02474268bac8592" dependencies = [ "as_variant", "base64 0.22.1", @@ -4150,7 +4150,7 @@ dependencies = [ [[package]] name = "ruma-events" version = "0.28.1" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=27abe0dcd33fd4056efc94bab3582646b31b6ce9#27abe0dcd33fd4056efc94bab3582646b31b6ce9" +source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e60876b6ff2d207a46aa8910a02474268bac8592#e60876b6ff2d207a46aa8910a02474268bac8592" dependencies = [ "as_variant", "indexmap", @@ -4175,7 +4175,7 @@ dependencies = [ [[package]] name = "ruma-federation-api" version = "0.9.0" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=27abe0dcd33fd4056efc94bab3582646b31b6ce9#27abe0dcd33fd4056efc94bab3582646b31b6ce9" +source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e60876b6ff2d207a46aa8910a02474268bac8592#e60876b6ff2d207a46aa8910a02474268bac8592" dependencies = [ "bytes", "headers", @@ -4197,7 +4197,7 @@ dependencies = [ [[package]] name = "ruma-identifiers-validation" version = "0.9.5" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=27abe0dcd33fd4056efc94bab3582646b31b6ce9#27abe0dcd33fd4056efc94bab3582646b31b6ce9" +source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e60876b6ff2d207a46aa8910a02474268bac8592#e60876b6ff2d207a46aa8910a02474268bac8592" dependencies = [ "js_int", "thiserror 2.0.17", @@ -4206,7 +4206,7 @@ dependencies = [ [[package]] name = "ruma-identity-service-api" version = "0.9.0" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=27abe0dcd33fd4056efc94bab3582646b31b6ce9#27abe0dcd33fd4056efc94bab3582646b31b6ce9" +source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e60876b6ff2d207a46aa8910a02474268bac8592#e60876b6ff2d207a46aa8910a02474268bac8592" dependencies = [ "js_int", "ruma-common", @@ -4216,7 +4216,7 @@ dependencies = [ [[package]] name = "ruma-macros" version = "0.13.0" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=27abe0dcd33fd4056efc94bab3582646b31b6ce9#27abe0dcd33fd4056efc94bab3582646b31b6ce9" +source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e60876b6ff2d207a46aa8910a02474268bac8592#e60876b6ff2d207a46aa8910a02474268bac8592" dependencies = [ "cfg-if", "proc-macro-crate", @@ -4231,7 +4231,7 @@ dependencies = [ [[package]] name = "ruma-push-gateway-api" version = "0.9.0" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=27abe0dcd33fd4056efc94bab3582646b31b6ce9#27abe0dcd33fd4056efc94bab3582646b31b6ce9" +source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e60876b6ff2d207a46aa8910a02474268bac8592#e60876b6ff2d207a46aa8910a02474268bac8592" dependencies = [ "js_int", "ruma-common", @@ -4243,7 +4243,7 @@ dependencies = [ [[package]] name = "ruma-signatures" version = "0.15.0" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=27abe0dcd33fd4056efc94bab3582646b31b6ce9#27abe0dcd33fd4056efc94bab3582646b31b6ce9" +source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e60876b6ff2d207a46aa8910a02474268bac8592#e60876b6ff2d207a46aa8910a02474268bac8592" dependencies = [ "base64 0.22.1", "ed25519-dalek", diff --git a/Cargo.toml b/Cargo.toml index 42a463da..105f8795 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,11 +33,11 @@ features = ["serde"] [workspace.dependencies.smallvec] version = "1.14.0" features = [ - "const_generics", - "const_new", - "serde", - "union", - "write", + "const_generics", + "const_new", + "serde", + "union", + "write", ] [workspace.dependencies.smallstr] @@ -96,13 +96,13 @@ version = "1.11.1" version = "0.7.9" default-features = false features = [ - "form", - "http1", - "http2", - "json", - "matched-path", - "tokio", - "tracing", + "form", + "http1", + "http2", + "json", + "matched-path", + "tokio", + "tracing", ] [workspace.dependencies.axum-extra] @@ -149,10 +149,10 @@ features = ["aws_lc_rs"] version = "0.12.15" default-features = false features = [ - "rustls-tls-native-roots", - "socks", - "hickory-dns", - "http2", + "rustls-tls-native-roots", + "socks", + "hickory-dns", + "http2", ] [workspace.dependencies.serde] @@ -188,18 +188,18 @@ default-features = false version = "0.25.5" default-features = false features = [ - "jpeg", - "png", - "gif", - "webp", + "jpeg", + "png", + "gif", + "webp", ] [workspace.dependencies.blurhash] version = "0.2.3" default-features = false features = [ - "fast-linear-to-srgb", - "image", + "fast-linear-to-srgb", + "image", ] # logging @@ -229,13 +229,13 @@ default-features = false version = "4.5.35" default-features = false features = [ - "derive", - "env", - "error-context", - "help", - "std", - "string", - "usage", + "derive", + "env", + "error-context", + "help", + "std", + "string", + "usage", ] [workspace.dependencies.futures] @@ -247,15 +247,15 @@ features = ["std", "async-await"] version = "1.44.2" default-features = false features = [ - "fs", - "net", - "macros", - "sync", - "signal", - "time", - "rt-multi-thread", - "io-util", - "tracing", + "fs", + "net", + "macros", + "sync", + "signal", + "time", + "rt-multi-thread", + "io-util", + "tracing", ] [workspace.dependencies.tokio-metrics] @@ -280,18 +280,18 @@ default-features = false version = "1.6.0" default-features = false features = [ - "server", - "http1", - "http2", + "server", + "http1", + "http2", ] [workspace.dependencies.hyper-util] version = "=0.1.17" default-features = false features = [ - "server-auto", - "server-graceful", - "tokio", + "server-auto", + "server-graceful", + "tokio", ] # to support multiple variations of setting a config option @@ -310,9 +310,9 @@ features = ["env", "toml"] version = "0.25.1" default-features = false features = [ - "serde", - "system-config", - "tokio", + "serde", + "system-config", + "tokio", ] # Used for conduwuit::Error type @@ -351,7 +351,7 @@ version = "0.1.2" # Used for matrix spec type definitions and helpers [workspace.dependencies.ruma] git = "https://forgejo.ellis.link/continuwuation/ruwuma" -rev = "27abe0dcd33fd4056efc94bab3582646b31b6ce9" +rev = "e60876b6ff2d207a46aa8910a02474268bac8592" features = [ "compat", "rand", @@ -381,13 +381,13 @@ features = [ "unstable-msc4095", "unstable-msc4121", "unstable-msc4125", - "unstable-msc4155", + "unstable-msc4155", "unstable-msc4186", "unstable-msc4203", # sending to-device events to appservices "unstable-msc4210", # remove legacy mentions "unstable-extensible-events", "unstable-pdu", - "unstable-msc4155" + "unstable-msc4155" ] [workspace.dependencies.rust-rocksdb] @@ -395,11 +395,11 @@ git = "https://forgejo.ellis.link/continuwuation/rust-rocksdb-zaidoon1" rev = "61d9d23872197e9ace4a477f2617d5c9f50ecb23" default-features = false features = [ - "multi-threaded-cf", - "mt_static", - "lz4", - "zstd", - "bzip2", + "multi-threaded-cf", + "mt_static", + "lz4", + "zstd", + "bzip2", ] [workspace.dependencies.sha2] @@ -458,16 +458,16 @@ git = "https://forgejo.ellis.link/continuwuation/jemallocator" rev = "82af58d6a13ddd5dcdc7d4e91eae3b63292995b8" default-features = false features = [ - "background_threads_runtime_support", - "unprefixed_malloc_on_supported_platforms", + "background_threads_runtime_support", + "unprefixed_malloc_on_supported_platforms", ] [workspace.dependencies.tikv-jemallocator] git = "https://forgejo.ellis.link/continuwuation/jemallocator" rev = "82af58d6a13ddd5dcdc7d4e91eae3b63292995b8" default-features = false features = [ - "background_threads_runtime_support", - "unprefixed_malloc_on_supported_platforms", + "background_threads_runtime_support", + "unprefixed_malloc_on_supported_platforms", ] [workspace.dependencies.tikv-jemalloc-ctl] git = "https://forgejo.ellis.link/continuwuation/jemallocator" @@ -491,9 +491,9 @@ default-features = false version = "0.1.2" default-features = false features = [ - "static", - "gcc", - "light", + "static", + "gcc", + "light", ] [workspace.dependencies.rustyline-async] diff --git a/src/api/client/membership/invite.rs b/src/api/client/membership/invite.rs index 72e8c0d2..77ed7851 100644 --- a/src/api/client/membership/invite.rs +++ b/src/api/client/membership/invite.rs @@ -146,7 +146,7 @@ pub(crate) async fn invite_helper( ) .await?; - let invite_room_state = services.rooms.state.summary_stripped(&pdu, room_id).await; + let invite_room_state = services.rooms.state.summary(&pdu, room_id).await; drop(state_lock); diff --git a/src/api/server/invite.rs b/src/api/server/invite.rs index e017c171..cb14c79c 100644 --- a/src/api/server/invite.rs +++ b/src/api/server/invite.rs @@ -1,21 +1,172 @@ +use std::collections::HashMap; + use axum::extract::State; use axum_client_ip::InsecureClientIp; use base64::{Engine as _, engine::general_purpose}; use conduwuit::{ - Err, Error, PduEvent, Result, err, - matrix::{Event, event::gen_event_id}, + Err, Error, EventTypeExt, PduEvent, Result, RoomVersion, err, + matrix::{Event, StateKey, event::gen_event_id}, utils::{self, hash::sha256}, warn, }; use ruma::{ - CanonicalJsonValue, OwnedUserId, UserId, + CanonicalJsonValue, OwnedUserId, RoomId, RoomVersionId, ServerName, UserId, api::{client::error::ErrorKind, federation::membership::create_invite}, - events::room::member::{MembershipState, RoomMemberEventContent}, - serde::JsonObject, + events::{ + AnyStateEvent, StateEventType, + room::{ + create::RoomCreateEventContent, + member::{MembershipState, RoomMemberEventContent}, + }, + }, + serde::Raw, }; +use service::{Services, rooms::timeline::pdu_fits}; use crate::Ruma; +/// Ensures that the state received from the invite endpoint is sane, correct, +/// and complies with the room version's requirements. +async fn check_invite_state( + services: &Services, + stripped_state: &Vec>, + room_id: &RoomId, + room_version_id: &RoomVersionId, +) -> Result<()> { + let room_version = RoomVersion::new(room_version_id).map_err(|e| { + err!(Request(UnsupportedRoomVersion("Invalid room version provided: {e}"))) + })?; + let mut room_state: HashMap<(StateEventType, StateKey), PduEvent> = HashMap::new(); + + // Build the room state from the provided state events, + // ensuring that there's no duplicates. We need to check that m.room.create is + // present and lines up with the other things we've been told, and then verify + // any signatures present to ensure this isn't forged. + for raw_event in stripped_state { + let event = raw_event + .deserialize_as::() + .map_err(|e| err!(Request(InvalidParam("Invalid state event: {e}"))))?; + if event.state_key().is_none() { + return Err!(Request(InvalidParam("State event missing event type."))); + } + let key = event + .event_type() + .with_state_key(event.state_key().unwrap()); + if room_state.contains_key(&key) { + return Err!(Request(InvalidParam("Duplicate state event found for {key:?}"))); + } + + // verify the event + let canonical = utils::to_canonical_object(raw_event)?; + if !pdu_fits(&mut canonical.clone()) { + return Err!(Request(InvalidParam("An invite state event PDU is too large"))); + } + services + .server_keys + .verify_event(&canonical, Some(room_version_id)) + .await + .map_err(|e| err!(Request(InvalidParam("Signature failed verification: {e}"))))?; + + // Ensure all events are in the same room + if event.room_id_or_hash() != room_id { + return Err!(Request(InvalidParam( + "State event room ID for {} does not match the expected room ID {}.", + event.event_id, + room_id, + ))); + } + room_state.insert(key, event); + } + + // verify m.room.create is present, has a matching room ID, and a matching room + // version. + let create_event = room_state + .get(&(StateEventType::RoomCreate, "".into())) + .ok_or_else(|| err!(Request(MissingParam("Missing m.room.create in stripped state."))))?; + let create_event_content: RoomCreateEventContent = create_event + .get_content() + .map_err(|e| err!(Request(InvalidParam("Invalid m.room.create content: {e}"))))?; + // Room v12 removed room IDs over federation, so we'll need to see if the event + // ID matches the room ID instead. + if room_version.room_ids_as_hashes { + let given_room_id = create_event.event_id().as_str().replace('$', "!"); + if given_room_id != room_id.as_str() { + return Err!(Request(InvalidParam( + "m.room.create event ID does not match the room ID." + ))); + } + } else if create_event.room_id().unwrap() != room_id { + return Err!(Request(InvalidParam("m.room.create room ID does not match the room ID."))); + } + + // Make sure the room version matches + if &create_event_content.room_version != room_version_id { + return Err!(Request(InvalidParam( + "m.room.create room version does not match the given room version." + ))); + } + + // Looks solid + Ok(()) +} + +/// Ensures that the invite event received from the invite endpoint is sane, +/// correct, and complies with the room version's requirements. +/// Returns the invited user ID on success. +async fn check_invite_event( + services: &Services, + invite_event: &PduEvent, + origin: &ServerName, + room_id: &RoomId, + room_version_id: &RoomVersionId, +) -> Result { + // Check: The event sender is not a user ID on the origin server. + if invite_event.sender.server_name() != origin { + return Err!(Request(InvalidParam( + "Invite event sender's server does not match the origin server." + ))); + } + // Check: The `state_key` is not a user ID on the receiving server. + let state_key: &UserId = invite_event + .state_key() + .ok_or_else(|| err!(Request(MissingParam("Invite event missing state_key."))))? + .try_into() + .map_err(|e| err!(Request(InvalidParam("Invalid state_key property: {e}"))))?; + if !services.globals.server_is_ours(state_key.server_name()) { + return Err!(Request(InvalidParam( + "Invite event state_key does not belong to this homeserver." + ))); + } + + // Check: The event's room ID matches the expected room ID. + if let Some(evt_room_id) = invite_event.room_id() { + if evt_room_id != room_id { + return Err!(Request(InvalidParam( + "Invite event room ID does not match the expected room ID." + ))); + } + } else { + return Err!(Request(MissingParam("Invite event missing room ID."))); + } + + // Check: the membership really is "invite" + let content = invite_event.get_content::()?; + if content.membership != MembershipState::Invite { + return Err!(Request(InvalidParam("Invite event is not a membership invite."))); + } + + // Check: signature is valid + services + .server_keys + .verify_event(&utils::to_canonical_object(invite_event)?, Some(room_version_id)) + .await + .map_err(|e| { + err!(Request(InvalidParam("Invite event signature failed verification: {e}"))) + })?; + + Ok(state_key.to_owned()) +} + /// # `PUT /_matrix/federation/v2/invite/{roomId}/{eventId}` /// /// Invites a remote user to a room. @@ -61,57 +212,39 @@ pub(crate) async fn create_invite_route( let mut signed_event = utils::to_canonical_object(&body.event) .map_err(|_| err!(Request(InvalidParam("Invite event is invalid."))))?; - // Ensure this is a membership event - if signed_event - .get("type") - .expect("event must have a type") - .as_str() - .expect("type must be a string") - != "m.room.member" - { - return Err!(Request(BadJson( - "Not allowed to send non-membership event to invite endpoint." + // We need to hash and sign the event before we can generate the event ID. + // It is important that this signed event does not get sent back to the caller + // until we've verified this isn't incorrect. + services + .server_keys + .hash_and_sign_event(&mut signed_event, &body.room_version) + .map_err(|e| err!(Request(InvalidParam("Failed to sign event: {e}"))))?; + let event_id = gen_event_id(&signed_event.clone(), &body.room_version)?; + if event_id != body.event_id { + return Err!(Request(InvalidParam( + "Event ID does not match the generated event ID ({} vs {}).", + event_id, + body.event_id, ))); } - let content: RoomMemberEventContent = serde_json::from_value( - signed_event - .get("content") - .ok_or_else(|| err!(Request(BadJson("Event missing content property"))))? - .clone() - .into(), - ) - .map_err(|e| err!(Request(BadJson(warn!("Event content is empty or invalid: {e}")))))?; + let pdu = PduEvent::from_id_val(&event_id, signed_event.clone()) + .map_err(|e| err!(Request(InvalidParam("Invite event is invalid: {e}"))))?; - // Ensure this is an invite membership event - if content.membership != MembershipState::Invite { - return Err!(Request(BadJson( - "Not allowed to send a non-invite membership event to invite endpoint." - ))); - } + // Check the invite event is valid. + let recipient_user = + check_invite_event(&services, &pdu, body.origin(), &body.room_id, &body.room_version) + .await?; - // Ensure the sending user isn't a lying bozo - let sender_server = signed_event - .get("sender") - .try_into() - .map(UserId::server_name) - .map_err(|e| err!(Request(InvalidParam("Invalid sender property: {e}"))))?; - if sender_server != body.origin() { - return Err!(Request(Forbidden("Sender's server does not match the origin server.",))); - } - - // Ensure the target user belongs to this server - let recipient_user: OwnedUserId = signed_event - .get("state_key") - .try_into() - .map(UserId::to_owned) - .map_err(|e| err!(Request(InvalidParam("Invalid state_key property: {e}"))))?; - - if !services - .globals - .server_is_ours(recipient_user.server_name()) + // Make sure the room isn't banned and we allow invites + if services.config.block_non_admin_invites && !services.users.is_admin(&recipient_user).await { - return Err!(Request(InvalidParam("User does not belong to this homeserver."))); + return Err!(Request(Forbidden("This server does not allow room invites."))); + } + if services.rooms.metadata.is_banned(&body.room_id).await + && !services.users.is_admin(&recipient_user).await + { + return Err!(Request(Forbidden("This room is banned on this homeserver."))); } // Make sure we're not ACL'ed from their room. @@ -121,13 +254,9 @@ pub(crate) async fn create_invite_route( .acl_check(recipient_user.server_name(), &body.room_id) .await?; - services - .server_keys - .hash_and_sign_event(&mut signed_event, &body.room_version) - .map_err(|e| err!(Request(InvalidParam("Failed to sign event: {e}"))))?; - - // Generate event id - let event_id = gen_event_id(&signed_event, &body.room_version)?; + // And check the invite state is valid. + check_invite_state(&services, &body.invite_room_state, &body.room_id, &body.room_version) + .await?; // Add event_id back signed_event.insert("event_id".to_owned(), CanonicalJsonValue::String(event_id.to_string())); @@ -137,27 +266,8 @@ pub(crate) async fn create_invite_route( .try_into() .map_err(|e| err!(Request(InvalidParam("Invalid sender property: {e}"))))?; - if services.rooms.metadata.is_banned(&body.room_id).await - && !services.users.is_admin(&recipient_user).await - { - return Err!(Request(Forbidden("This room is banned on this homeserver."))); - } - - if services.config.block_non_admin_invites && !services.users.is_admin(&recipient_user).await - { - return Err!(Request(Forbidden("This server does not allow room invites."))); - } - let mut invite_state = body.invite_room_state.clone(); - let mut event: JsonObject = serde_json::from_str(body.event.get()) - .map_err(|e| err!(Request(BadJson("Invalid invite event PDU: {e}"))))?; - - event.insert("event_id".to_owned(), "$placeholder".into()); - - let pdu: PduEvent = serde_json::from_value(event.into()) - .map_err(|e| err!(Request(BadJson("Invalid invite event PDU: {e}"))))?; - invite_state.push(pdu.to_format()); // If we are active in the room, the remote server will notify us about the diff --git a/src/api/server/send_knock.rs b/src/api/server/send_knock.rs index 52550ced..0e3bf500 100644 --- a/src/api/server/send_knock.rs +++ b/src/api/server/send_knock.rs @@ -175,11 +175,7 @@ pub(crate) async fn create_knock_event_v1_route( .send_pdu_room(&body.room_id, &pdu_id) .await?; - let knock_room_state = services - .rooms - .state - .summary_stripped(&pdu, &body.room_id) - .await; + let knock_room_state = services.rooms.state.summary(&pdu, &body.room_id).await; Ok(send_knock::v1::Response { knock_room_state }) } diff --git a/src/service/rooms/state/mod.rs b/src/service/rooms/state/mod.rs index 554dae84..d2f50644 100644 --- a/src/service/rooms/state/mod.rs +++ b/src/service/rooms/state/mod.rs @@ -19,8 +19,7 @@ use futures::{ use ruma::{ EventId, OwnedEventId, OwnedRoomId, RoomId, RoomVersionId, UserId, events::{ - AnyStrippedStateEvent, StateEventType, TimelineEventType, - room::create::RoomCreateEventContent, + AnyStateEvent, StateEventType, TimelineEventType, room::create::RoomCreateEventContent, }, serde::Raw, }; @@ -307,12 +306,22 @@ impl Service { } } + /// Get a summary of the room state for invites and knock responses. + /// + /// This used to return stripped state, but now returns complete events. + /// + /// Returns: + /// + /// - m.room.create + /// - m.room.join_rules + /// - m.room.canonical_alias + /// - m.room.name + /// - m.room.avatar + /// - m.room.member (of the event sender) + /// - m.room.encryption + /// - m.room.topic #[tracing::instrument(skip_all, level = "debug")] - pub async fn summary_stripped<'a, E>( - &self, - event: &'a E, - room_id: &RoomId, - ) -> Vec> + pub async fn summary<'a, E>(&self, event: &'a E, room_id: &RoomId) -> Vec> where E: Event + Send + Sync, &'a E: Event + Send, diff --git a/src/service/rooms/state_cache/update.rs b/src/service/rooms/state_cache/update.rs index f08ff4a0..378e3537 100644 --- a/src/service/rooms/state_cache/update.rs +++ b/src/service/rooms/state_cache/update.rs @@ -1,13 +1,13 @@ use std::collections::HashSet; -use conduwuit::{Err, Event, Pdu, Result, implement, is_not_empty, utils::ReadyExt, warn}; +use conduwuit::{Err, Event, Pdu, Result, implement, is_not_empty, utils::ReadyExt}; use database::{Json, serialize_key}; use futures::StreamExt; use ruma::{ OwnedServerName, RoomId, UserId, events::{ - AnyStrippedStateEvent, GlobalAccountDataEventType, RoomAccountDataEventType, - StateEventType, + AnyStateEvent, AnyStrippedStateEvent, GlobalAccountDataEventType, + RoomAccountDataEventType, StateEventType, direct::DirectEvent, invite_permission_config::FilterLevel, room::{ @@ -334,7 +334,7 @@ pub async fn mark_as_invited( user_id: &UserId, room_id: &RoomId, sender_user: &UserId, - last_state: Option>>, + last_state: Option>>, invite_via: Option>, ) -> Result<()> { // return an error for blocked invites. ignored invites aren't handled here