Add v1/v2 support to gen_event_id() scheme. (#12)
Add v1/v2 and improve reference and content hashing suite. (#12) Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
use ruma::{CanonicalJsonObject, OwnedEventId, RoomVersionId};
|
use ruma::{CanonicalJsonObject, CanonicalJsonValue, OwnedEventId, RoomVersionId};
|
||||||
use serde_json::value::RawValue as RawJsonValue;
|
use serde_json::value::RawValue as RawJsonValue;
|
||||||
|
|
||||||
use crate::{Result, debug_error, err, matrix::room_version};
|
use crate::{Result, debug_error, err, matrix::room_version};
|
||||||
@@ -20,13 +20,36 @@ pub fn gen_event_id_canonical_json(
|
|||||||
Ok((event_id, value))
|
Ok((event_id, value))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates a correct eventId for the incoming pdu.
|
/// Generates a correct eventId for the PDU. For v1/v2 incoming PDU's the
|
||||||
|
/// value's event_id is passed through. For all outgoing PDU's and for v3+
|
||||||
|
/// incoming PDU's it is generated.
|
||||||
pub fn gen_event_id(
|
pub fn gen_event_id(
|
||||||
value: &CanonicalJsonObject,
|
value: &CanonicalJsonObject,
|
||||||
room_version_id: &RoomVersionId,
|
room_version_id: &RoomVersionId,
|
||||||
) -> Result<OwnedEventId> {
|
) -> Result<OwnedEventId> {
|
||||||
let room_version_rules = room_version::rules(room_version_id)?;
|
let room_version_rules = room_version::rules(room_version_id)?;
|
||||||
|
let require_event_id = room_version_rules.event_format.require_event_id;
|
||||||
|
|
||||||
|
// We don't actually generate any event_id for incoming events in v1/v2 rooms,
|
||||||
|
// just pass them through.
|
||||||
|
if let Some(event_id) = require_event_id
|
||||||
|
.then(|| value.get("event_id"))
|
||||||
|
.flatten()
|
||||||
|
.and_then(CanonicalJsonValue::as_str)
|
||||||
|
.map(OwnedEventId::try_from)
|
||||||
|
.transpose()?
|
||||||
|
{
|
||||||
|
return Ok(event_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// For outgoing v1/v2 add the server part. This has to be our origin but we
|
||||||
|
// can't assert that here.
|
||||||
|
let server_name = require_event_id
|
||||||
|
.then(|| value.get("origin"))
|
||||||
|
.flatten()
|
||||||
|
.and_then(CanonicalJsonValue::as_str);
|
||||||
|
|
||||||
let reference_hash = ruma::signatures::reference_hash(value, &room_version_rules)?;
|
let reference_hash = ruma::signatures::reference_hash(value, &room_version_rules)?;
|
||||||
|
|
||||||
OwnedEventId::from_parts('$', &reference_hash, None).map_err(Into::into)
|
OwnedEventId::from_parts('$', &reference_hash, server_name).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,71 @@
|
|||||||
use ruma::{CanonicalJsonObject, RoomVersionId};
|
use ruma::{CanonicalJsonObject, CanonicalJsonValue, OwnedEventId, RoomVersionId};
|
||||||
use tuwunel_core::{Result, err, implement};
|
use tuwunel_core::{
|
||||||
|
Result, implement,
|
||||||
|
matrix::{event::gen_event_id, room_version},
|
||||||
|
};
|
||||||
|
|
||||||
#[implement(super::Service)]
|
#[implement(super::Service)]
|
||||||
pub fn sign_json(&self, object: &mut CanonicalJsonObject) -> Result {
|
pub fn gen_id_hash_and_sign_event(
|
||||||
use ruma::signatures::sign_json;
|
&self,
|
||||||
|
object: &mut CanonicalJsonObject,
|
||||||
|
room_version_id: &RoomVersionId,
|
||||||
|
) -> Result<OwnedEventId> {
|
||||||
|
object.remove("event_id");
|
||||||
|
|
||||||
let server_name = self.services.globals.server_name().as_str();
|
if room_version::rules(room_version_id)?
|
||||||
sign_json(server_name, self.keypair(), object).map_err(Into::into)
|
.event_format
|
||||||
|
.require_event_id
|
||||||
|
{
|
||||||
|
self.gen_id_hash_and_sign_event_v1(object, room_version_id)
|
||||||
|
} else {
|
||||||
|
self.gen_id_hash_and_sign_event_v3(object, room_version_id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[implement(super::Service)]
|
||||||
|
fn gen_id_hash_and_sign_event_v1(
|
||||||
|
&self,
|
||||||
|
object: &mut CanonicalJsonObject,
|
||||||
|
room_version_id: &RoomVersionId,
|
||||||
|
) -> Result<OwnedEventId> {
|
||||||
|
let event_id = gen_event_id(object, room_version_id)?;
|
||||||
|
|
||||||
|
object.insert("event_id".into(), CanonicalJsonValue::String(event_id.clone().into()));
|
||||||
|
|
||||||
|
self.services
|
||||||
|
.server_keys
|
||||||
|
.hash_and_sign_event(object, room_version_id)?;
|
||||||
|
|
||||||
|
Ok(event_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[implement(super::Service)]
|
||||||
|
fn gen_id_hash_and_sign_event_v3(
|
||||||
|
&self,
|
||||||
|
object: &mut CanonicalJsonObject,
|
||||||
|
room_version_id: &RoomVersionId,
|
||||||
|
) -> Result<OwnedEventId> {
|
||||||
|
self.services
|
||||||
|
.server_keys
|
||||||
|
.hash_and_sign_event(object, room_version_id)?;
|
||||||
|
|
||||||
|
let event_id = gen_event_id(object, room_version_id)?;
|
||||||
|
|
||||||
|
object.insert("event_id".into(), CanonicalJsonValue::String(event_id.clone().into()));
|
||||||
|
|
||||||
|
Ok(event_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[implement(super::Service)]
|
#[implement(super::Service)]
|
||||||
pub fn hash_and_sign_event(
|
pub fn hash_and_sign_event(
|
||||||
&self,
|
&self,
|
||||||
object: &mut CanonicalJsonObject,
|
object: &mut CanonicalJsonObject,
|
||||||
room_version: &RoomVersionId,
|
room_version_id: &RoomVersionId,
|
||||||
) -> Result {
|
) -> Result {
|
||||||
use ruma::signatures::hash_and_sign_event;
|
use ruma::signatures::hash_and_sign_event;
|
||||||
|
|
||||||
let server_name = &self.services.server.name;
|
let server_name = &self.services.server.name;
|
||||||
let room_version_rules = room_version.rules().ok_or_else(|| {
|
let room_version_rules = room_version::rules(room_version_id)?;
|
||||||
err!(Request(UnsupportedRoomVersion(
|
|
||||||
"Cannot hash and sign event for unknown room version {room_version:?}."
|
|
||||||
)))
|
|
||||||
})?;
|
|
||||||
|
|
||||||
hash_and_sign_event(
|
hash_and_sign_event(
|
||||||
server_name.as_str(),
|
server_name.as_str(),
|
||||||
@@ -32,3 +75,12 @@ pub fn hash_and_sign_event(
|
|||||||
)
|
)
|
||||||
.map_err(Into::into)
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[implement(super::Service)]
|
||||||
|
pub fn sign_json(&self, object: &mut CanonicalJsonObject) -> Result {
|
||||||
|
use ruma::signatures::sign_json;
|
||||||
|
|
||||||
|
let server_name = self.services.globals.server_name().as_str();
|
||||||
|
|
||||||
|
sign_json(server_name, self.keypair(), object).map_err(Into::into)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user