mirror of
https://forgejo.ellis.link/continuwuation/continuwuity.git
synced 2026-05-26 20:49:55 +00:00
Implement room v12 (#943)
**Does not yet work!** Currently, state resolution does not correctly resolve conflicting states. Everything else appears to work as expected, so stateres will be fixed soon, then we should be clear for takeoff. Also: a lot of things currently accept a nullable room ID that really just don't need to. This will need tidying up before merge. Some authentication checks have also been disabled temporarily but nothing important. A lot of things are tagged with `TODO(hydra)`, those need resolving before merge. External contributors should PR to the `hydra/public` branch, *not* ` main`. --- This PR should be squash merged. Reviewed-on: https://forgejo.ellis.link/continuwuation/continuwuity/pulls/943 Co-authored-by: nexy7574 <git@nexy7574.co.uk> Co-committed-by: nexy7574 <git@nexy7574.co.uk>
This commit is contained in:
@@ -139,6 +139,7 @@ where
|
||||
&pdu_event,
|
||||
None, // TODO: third party invite
|
||||
state_fetch,
|
||||
create_event.as_pdu(),
|
||||
)
|
||||
.await
|
||||
.map_err(|e| err!(Request(Forbidden("Auth check failed: {e:?}"))))?;
|
||||
|
||||
@@ -99,7 +99,10 @@ impl Service {
|
||||
}
|
||||
|
||||
fn check_room_id<Pdu: Event>(room_id: &RoomId, pdu: &Pdu) -> Result {
|
||||
if pdu.room_id() != room_id {
|
||||
if pdu
|
||||
.room_id()
|
||||
.is_some_and(|claimed_room_id| claimed_room_id != room_id)
|
||||
{
|
||||
return Err!(Request(InvalidParam(error!(
|
||||
pdu_event_id = ?pdu.event_id(),
|
||||
pdu_room_id = ?pdu.room_id(),
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use conduwuit::{
|
||||
Result, err, implement, matrix::event::gen_event_id_canonical_json, result::FlatOk,
|
||||
Result, RoomVersion, err, implement, matrix::event::gen_event_id_canonical_json,
|
||||
result::FlatOk,
|
||||
};
|
||||
use ruma::{CanonicalJsonObject, CanonicalJsonValue, OwnedEventId, OwnedRoomId};
|
||||
use ruma::{CanonicalJsonObject, CanonicalJsonValue, OwnedEventId, OwnedRoomId, RoomVersionId};
|
||||
use serde_json::value::RawValue as RawJsonValue;
|
||||
|
||||
type Parsed = (OwnedRoomId, OwnedEventId, CanonicalJsonObject);
|
||||
@@ -11,12 +12,44 @@ pub async fn parse_incoming_pdu(&self, pdu: &RawJsonValue) -> Result<Parsed> {
|
||||
let value = serde_json::from_str::<CanonicalJsonObject>(pdu.get()).map_err(|e| {
|
||||
err!(BadServerResponse(debug_warn!("Error parsing incoming event {e:?}")))
|
||||
})?;
|
||||
|
||||
let room_id: OwnedRoomId = value
|
||||
.get("room_id")
|
||||
let event_type = value
|
||||
.get("type")
|
||||
.and_then(CanonicalJsonValue::as_str)
|
||||
.map(OwnedRoomId::parse)
|
||||
.flat_ok_or(err!(Request(InvalidParam("Invalid room_id in pdu"))))?;
|
||||
.ok_or_else(|| err!(Request(InvalidParam("Missing or invalid type in pdu"))))?;
|
||||
|
||||
let room_id: OwnedRoomId = if event_type != "m.room.create" {
|
||||
value
|
||||
.get("room_id")
|
||||
.and_then(CanonicalJsonValue::as_str)
|
||||
.map(OwnedRoomId::parse)
|
||||
.flat_ok_or(err!(Request(InvalidParam("Invalid room_id in pdu"))))?
|
||||
} else {
|
||||
// v12 rooms might have no room_id in the create event. We'll need to check the
|
||||
// content.room_version
|
||||
let content = value
|
||||
.get("content")
|
||||
.and_then(CanonicalJsonValue::as_object)
|
||||
.ok_or_else(|| err!(Request(InvalidParam("Missing or invalid content in pdu"))))?;
|
||||
let room_version = content
|
||||
.get("room_version")
|
||||
.and_then(CanonicalJsonValue::as_str)
|
||||
.unwrap_or("1");
|
||||
let vi = RoomVersionId::try_from(room_version).unwrap_or(RoomVersionId::V1);
|
||||
let vf = RoomVersion::new(&vi).expect("supported room version");
|
||||
if vf.room_ids_as_hashes {
|
||||
let (event_id, _) = gen_event_id_canonical_json(pdu, &vi).map_err(|e| {
|
||||
err!(Request(InvalidParam("Could not convert event to canonical json: {e}")))
|
||||
})?;
|
||||
OwnedRoomId::parse(event_id.as_str().replace('$', "!")).expect("valid room ID")
|
||||
} else {
|
||||
// V11 or below room, room_id must be present
|
||||
value
|
||||
.get("room_id")
|
||||
.and_then(CanonicalJsonValue::as_str)
|
||||
.map(OwnedRoomId::parse)
|
||||
.flat_ok_or(err!(Request(InvalidParam("Invalid or missing room_id in pdu"))))?
|
||||
}
|
||||
};
|
||||
|
||||
let room_version_id = self
|
||||
.services
|
||||
@@ -24,10 +57,8 @@ pub async fn parse_incoming_pdu(&self, pdu: &RawJsonValue) -> Result<Parsed> {
|
||||
.get_room_version(&room_id)
|
||||
.await
|
||||
.map_err(|_| err!("Server is not in room {room_id}"))?;
|
||||
|
||||
let (event_id, value) = gen_event_id_canonical_json(pdu, &room_version_id).map_err(|e| {
|
||||
err!(Request(InvalidParam("Could not convert event to canonical json: {e}")))
|
||||
})?;
|
||||
|
||||
Ok((room_id, event_id, value))
|
||||
}
|
||||
|
||||
@@ -102,6 +102,7 @@ where
|
||||
&incoming_pdu,
|
||||
None, // TODO: third party invite
|
||||
|ty, sk| state_fetch(ty.clone(), sk.into()),
|
||||
create_event.as_pdu(),
|
||||
)
|
||||
.await
|
||||
.map_err(|e| err!(Request(Forbidden("Auth check failed: {e:?}"))))?;
|
||||
@@ -123,6 +124,7 @@ where
|
||||
incoming_pdu.sender(),
|
||||
incoming_pdu.state_key(),
|
||||
incoming_pdu.content(),
|
||||
&room_version,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -140,6 +142,7 @@ where
|
||||
&incoming_pdu,
|
||||
None, // third-party invite
|
||||
state_fetch,
|
||||
create_event.as_pdu(),
|
||||
)
|
||||
.await
|
||||
.map_err(|e| err!(Request(Forbidden("Auth check failed: {e:?}"))))?;
|
||||
@@ -156,7 +159,7 @@ where
|
||||
!self
|
||||
.services
|
||||
.state_accessor
|
||||
.user_can_redact(&redact_id, incoming_pdu.sender(), incoming_pdu.room_id(), true)
|
||||
.user_can_redact(&redact_id, incoming_pdu.sender(), room_id, true)
|
||||
.await?,
|
||||
};
|
||||
|
||||
@@ -172,7 +175,7 @@ where
|
||||
// Now we calculate the set of extremities this room has after the incoming
|
||||
// event has been applied. We start with the previous extremities (aka leaves)
|
||||
trace!("Calculating extremities");
|
||||
let extremities: Vec<_> = self
|
||||
let mut extremities: Vec<_> = self
|
||||
.services
|
||||
.state
|
||||
.get_forward_extremities(room_id)
|
||||
@@ -192,6 +195,7 @@ where
|
||||
})
|
||||
.collect()
|
||||
.await;
|
||||
extremities.push(incoming_pdu.event_id().to_owned());
|
||||
|
||||
debug!(
|
||||
"Retained {} extremities checked against {} prev_events",
|
||||
@@ -303,6 +307,7 @@ where
|
||||
);
|
||||
// assert!(extremities.is_empty(), "soft_fail extremities empty");
|
||||
let extremities = extremities.iter().map(Borrow::borrow);
|
||||
debug_assert!(extremities.clone().count() > 0, "extremities not empty");
|
||||
|
||||
self.services
|
||||
.timeline
|
||||
@@ -313,6 +318,7 @@ where
|
||||
state_ids_compressed,
|
||||
soft_fail,
|
||||
&state_lock,
|
||||
room_id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -336,6 +342,7 @@ where
|
||||
.iter()
|
||||
.map(Borrow::borrow)
|
||||
.chain(once(incoming_pdu.event_id()));
|
||||
debug_assert!(extremities.clone().count() > 0, "extremities not empty");
|
||||
|
||||
let pdu_id = self
|
||||
.services
|
||||
@@ -347,6 +354,7 @@ where
|
||||
state_ids_compressed,
|
||||
soft_fail,
|
||||
&state_lock,
|
||||
room_id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user