feat: Persist create events received during the invite process

This commit is contained in:
timedout authored and Ellis Git committed 2026-07-12 02:11:50 +00:00
1 parent e52bb5db69
commit 7225bf25ae
3 files changed
+43 -5

No files matched your search

+39 -2
View File
@@ -6,6 +6,7 @@ use base64::{Engine as _, engine::general_purpose};
use conduwuit::{
Err, Error, EventTypeExt, PduEvent, Result, err, error,
matrix::{Event, StateKey, event::gen_event_id},
state_res,
utils::hash::sha256,
warn,
};
@@ -70,7 +71,7 @@ pub(crate) async fn create_invite_route(
// First, validate the invite room state, so we can compare with the create
// event.
let (create_event_id, _) = validate_invite_state(
let (create_event_id, state) = validate_invite_state(
&services,
&body.invite_room_state,
&room_version_rules,
@@ -84,7 +85,7 @@ pub(crate) async fn create_invite_route(
&body.event,
&room_version_rules,
&body.identity,
create_event_id,
create_event_id.clone(),
body.room_id.clone(),
body.event_id.clone(),
)
@@ -152,6 +153,20 @@ pub(crate) async fn create_invite_route(
.server_in_room(services.globals.server_name(), &body.room_id)
.await
{
// We will start by recording the room's create event as an outlier.
// This will allow us to recognise it later in case the sender revokes the
// invite over federation later. We could store more state from the invite
// request, but we will get that during send_join anyway.
let create_event_json = state
.get(&StateEventType::RoomCreate.with_state_key(""))
.expect("must have create event in invite state by this point");
// This is safe to just add directly as an outlier as we already auth checked it
// during validation.
services
.rooms
.outlier
.add_pdu_outlier(&create_event_id, create_event_json);
services
.rooms
.state_cache
@@ -387,6 +402,28 @@ async fn validate_invite_state(
))),
| Entry::Vacant(entry) => {
if entry.key().0 == StateEventType::RoomCreate {
// Ensure this is a legal create event.
let pdu_event =
PduEvent::from_id_val(&state_event_id, state_event_json.clone())
.expect("must be able to create pdu event from event json");
if !state_res::auth_check(
room_version_rules,
&pdu_event,
None,
|_, _| async {
unreachable!(
"No state should be fetched when processing a lone create event"
);
},
&pdu_event,
)
.await
.unwrap_or_default()
{
return Err!(Request(InvalidParam(
"m.room.create event fails auth check"
)));
}
create_event_id = Some(state_event_id);
}
entry.insert(state_event_json);
@@ -14,10 +14,12 @@ impl super::Service {
/// This performs steps 1 through 4 of [S-S section 5.1][spec], returning
/// the parsed PDU and modified JSON object.
///
/// **External callers likely want `handle_incoming_pdu` instead.**
///
/// [spec]: https://spec.matrix.org/v1.19/server-server-api/#checks-performed-on-receipt-of-a-pdu
#[allow(clippy::too_many_arguments)]
#[tracing::instrument(name = "handle_outlier", skip_all)]
pub(super) async fn handle_outlier_pdu<'a, Pdu>(
pub async fn handle_outlier_pdu<'a, Pdu>(
&self,
origin: &'a ServerName,
create_event: &'a Pdu,
@@ -54,7 +56,6 @@ impl super::Service {
})?;
value.remove("unsigned");
let room_version_rules = get_room_version_rules(create_event)?;
// 2. Check signatures, otherwise drop.
// 3. Check content hash, redacting the event if it fails.
@@ -94,7 +94,7 @@ impl super::Service {
/// If the auth check fails, false is returned, otherwise true.
///
/// [spec]: https://spec.matrix.org/v1.19/server-server-api/#checks-performed-on-receipt-of-a-pdu
pub(super) async fn auth_state_check_4(
pub async fn auth_state_check_4(
&self,
pdu: &PduEvent,
room_version_rules: &RoomVersionRules,