Add send transaction endpoint
Also refactor PDU types and move them to ruma-events
This commit is contained in:
parent
7c934e1b8f
commit
bfad8cf1f1
@ -10,6 +10,7 @@ Breaking changes:
|
|||||||
struct variants
|
struct variants
|
||||||
* This change removes the types `EventMatchCondition`, `RoomMemberCountCondition` and
|
* This change removes the types `EventMatchCondition`, `RoomMemberCountCondition` and
|
||||||
`SenderNotificationPermissionCondition`
|
`SenderNotificationPermissionCondition`
|
||||||
|
* Add PDU types: `pdu::{Pdu, PduStub}`
|
||||||
|
|
||||||
Improvements:
|
Improvements:
|
||||||
|
|
||||||
|
@ -147,6 +147,7 @@ pub mod forwarded_room_key;
|
|||||||
pub mod fully_read;
|
pub mod fully_read;
|
||||||
pub mod ignored_user_list;
|
pub mod ignored_user_list;
|
||||||
pub mod key;
|
pub mod key;
|
||||||
|
pub mod pdu;
|
||||||
pub mod presence;
|
pub mod presence;
|
||||||
pub mod push_rules;
|
pub mod push_rules;
|
||||||
pub mod receipt;
|
pub mod receipt;
|
||||||
|
325
ruma-events/src/pdu.rs
Normal file
325
ruma-events/src/pdu.rs
Normal file
@ -0,0 +1,325 @@
|
|||||||
|
//! Types for persistent data unit schemas
|
||||||
|
//!
|
||||||
|
//! The differences between the `RoomV1Pdu` schema and the `RoomV3Pdu` schema are
|
||||||
|
//! that the `RoomV1Pdu` takes an `event_id` field (`RoomV3Pdu` does not), and
|
||||||
|
//! `auth_events` and `prev_events` take `Vec<(EventId, EventHash)> rather than
|
||||||
|
//! `Vec<EventId>` in `RoomV3Pdu`.
|
||||||
|
//!
|
||||||
|
//! The stubbed versions of each PDU type remove the `event_id` field (if any)
|
||||||
|
//! and the `room_id` field for use in PDU templates.
|
||||||
|
|
||||||
|
use std::{collections::BTreeMap, time::SystemTime};
|
||||||
|
|
||||||
|
use js_int::UInt;
|
||||||
|
use ruma_events::EventType;
|
||||||
|
use ruma_identifiers::{EventId, RoomId, UserId};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_json::Value as JsonValue;
|
||||||
|
|
||||||
|
/// Enum for PDU schemas
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum Pdu {
|
||||||
|
/// PDU for room versions 1 and 2.
|
||||||
|
RoomV1Pdu(RoomV1Pdu),
|
||||||
|
/// PDU for room versions 3 and above.
|
||||||
|
RoomV3Pdu(RoomV3Pdu),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A 'persistent data unit' (event) for room versions 1 and 2.
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
pub struct RoomV1Pdu {
|
||||||
|
/// Event ID for the PDU.
|
||||||
|
pub event_id: EventId,
|
||||||
|
|
||||||
|
/// The room this event belongs to.
|
||||||
|
pub room_id: RoomId,
|
||||||
|
|
||||||
|
/// The user id of the user who sent this event.
|
||||||
|
pub sender: UserId,
|
||||||
|
|
||||||
|
/// The `server_name` of the homeserver that created this event.
|
||||||
|
pub origin: String,
|
||||||
|
|
||||||
|
/// Timestamp (milliseconds since the UNIX epoch) on originating homeserver
|
||||||
|
/// of when this event was created.
|
||||||
|
#[serde(with = "ruma_serde::time::ms_since_unix_epoch")]
|
||||||
|
pub origin_server_ts: SystemTime,
|
||||||
|
|
||||||
|
// TODO: Encode event type as content enum variant, like event enums do
|
||||||
|
/// The event's type.
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
pub kind: EventType,
|
||||||
|
|
||||||
|
/// The event's content.
|
||||||
|
pub content: JsonValue,
|
||||||
|
|
||||||
|
/// A key that determines which piece of room state the event represents.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub state_key: Option<String>,
|
||||||
|
|
||||||
|
/// Event IDs for the most recent events in the room that the homeserver was
|
||||||
|
/// aware of when it created this event.
|
||||||
|
#[serde(skip_serializing_if = "Vec::is_empty")]
|
||||||
|
pub prev_events: Vec<(EventId, EventHash)>,
|
||||||
|
|
||||||
|
/// The maximum depth of the `prev_events`, plus one.
|
||||||
|
pub depth: UInt,
|
||||||
|
|
||||||
|
/// Event IDs for the authorization events that would allow this event to be
|
||||||
|
/// in the room.
|
||||||
|
#[serde(skip_serializing_if = "Vec::is_empty")]
|
||||||
|
pub auth_events: Vec<(EventId, EventHash)>,
|
||||||
|
|
||||||
|
/// For redaction events, the ID of the event being redacted.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub redacts: Option<EventId>,
|
||||||
|
|
||||||
|
/// Additional data added by the origin server but not covered by the
|
||||||
|
/// signatures.
|
||||||
|
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
|
||||||
|
pub unsigned: BTreeMap<String, JsonValue>,
|
||||||
|
|
||||||
|
/// Content hashes of the PDU.
|
||||||
|
pub hashes: EventHash,
|
||||||
|
|
||||||
|
/// Signatures for the PDU.
|
||||||
|
pub signatures: BTreeMap<String, BTreeMap<String, String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A 'persistent data unit' (event) for room versions 3 and beyond.
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
pub struct RoomV3Pdu {
|
||||||
|
/// The room this event belongs to.
|
||||||
|
pub room_id: RoomId,
|
||||||
|
|
||||||
|
/// The user id of the user who sent this event.
|
||||||
|
pub sender: UserId,
|
||||||
|
|
||||||
|
/// The `server_name` of the homeserver that created this event.
|
||||||
|
pub origin: String,
|
||||||
|
|
||||||
|
/// Timestamp (milliseconds since the UNIX epoch) on originating homeserver
|
||||||
|
/// of when this event was created.
|
||||||
|
#[serde(with = "ruma_serde::time::ms_since_unix_epoch")]
|
||||||
|
pub origin_server_ts: SystemTime,
|
||||||
|
|
||||||
|
// TODO: Encode event type as content enum variant, like event enums do
|
||||||
|
/// The event's type.
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
pub kind: EventType,
|
||||||
|
|
||||||
|
/// The event's content.
|
||||||
|
pub content: JsonValue,
|
||||||
|
|
||||||
|
/// A key that determines which piece of room state the event represents.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub state_key: Option<String>,
|
||||||
|
|
||||||
|
/// Event IDs for the most recent events in the room that the homeserver was
|
||||||
|
/// aware of when it created this event.
|
||||||
|
pub prev_events: Vec<EventId>,
|
||||||
|
|
||||||
|
/// The maximum depth of the `prev_events`, plus one.
|
||||||
|
pub depth: UInt,
|
||||||
|
|
||||||
|
/// Event IDs for the authorization events that would allow this event to be
|
||||||
|
/// in the room.
|
||||||
|
pub auth_events: Vec<EventId>,
|
||||||
|
|
||||||
|
/// For redaction events, the ID of the event being redacted.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub redacts: Option<EventId>,
|
||||||
|
|
||||||
|
/// Additional data added by the origin server but not covered by the
|
||||||
|
/// signatures.
|
||||||
|
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
|
||||||
|
pub unsigned: BTreeMap<String, JsonValue>,
|
||||||
|
|
||||||
|
/// Content hashes of the PDU.
|
||||||
|
pub hashes: EventHash,
|
||||||
|
|
||||||
|
/// Signatures for the PDU.
|
||||||
|
pub signatures: BTreeMap<String, BTreeMap<String, String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// PDU type without event and room IDs.
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum PduStub {
|
||||||
|
/// Stub for PDUs of room version 1 and 2.
|
||||||
|
RoomV1PduStub(RoomV1PduStub),
|
||||||
|
|
||||||
|
/// Stub for PDUs of room versions 3 and above.
|
||||||
|
RoomV3PduStub(RoomV3PduStub),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PduStub {
|
||||||
|
/// Helper method to get PDU from a PDU stub.
|
||||||
|
pub fn into_pdu(self, room_id: RoomId, event_id: EventId) -> Pdu {
|
||||||
|
match self {
|
||||||
|
PduStub::RoomV1PduStub(v1_stub) => {
|
||||||
|
Pdu::RoomV1Pdu(v1_stub.into_v1_pdu(room_id, event_id))
|
||||||
|
}
|
||||||
|
PduStub::RoomV3PduStub(v3_stub) => Pdu::RoomV3Pdu(v3_stub.into_v3_pdu(room_id)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Stub for PDUs of room version 1 and 2.
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
pub struct RoomV1PduStub {
|
||||||
|
/// The user id of the user who sent this event.
|
||||||
|
pub sender: UserId,
|
||||||
|
|
||||||
|
/// The `server_name` of the homeserver that created this event.
|
||||||
|
pub origin: String,
|
||||||
|
|
||||||
|
/// Timestamp (milliseconds since the UNIX epoch) on originating homeserver
|
||||||
|
/// of when this event was created.
|
||||||
|
#[serde(with = "ruma_serde::time::ms_since_unix_epoch")]
|
||||||
|
pub origin_server_ts: SystemTime,
|
||||||
|
|
||||||
|
// TODO: Encode event type as content enum variant, like event enums do
|
||||||
|
/// The event's type.
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
pub kind: EventType,
|
||||||
|
|
||||||
|
/// The event's content.
|
||||||
|
pub content: JsonValue,
|
||||||
|
|
||||||
|
/// A key that determines which piece of room state the event represents.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub state_key: Option<String>,
|
||||||
|
|
||||||
|
/// Event IDs for the most recent events in the room that the homeserver was
|
||||||
|
/// aware of when it created this event.
|
||||||
|
pub prev_events: Vec<(EventId, EventHash)>,
|
||||||
|
|
||||||
|
/// The maximum depth of the `prev_events`, plus one.
|
||||||
|
pub depth: UInt,
|
||||||
|
|
||||||
|
/// Event IDs for the authorization events that would allow this event to be
|
||||||
|
/// in the room.
|
||||||
|
pub auth_events: Vec<(EventId, EventHash)>,
|
||||||
|
|
||||||
|
/// For redaction events, the ID of the event being redacted.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub redacts: Option<EventId>,
|
||||||
|
|
||||||
|
/// Additional data added by the origin server but not covered by the
|
||||||
|
/// signatures.
|
||||||
|
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
|
||||||
|
pub unsigned: BTreeMap<String, JsonValue>,
|
||||||
|
|
||||||
|
/// Content hashes of the PDU.
|
||||||
|
pub hashes: EventHash,
|
||||||
|
|
||||||
|
/// Signatures for the PDU.
|
||||||
|
pub signatures: BTreeMap<String, BTreeMap<String, String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RoomV1PduStub {
|
||||||
|
/// Converts a V1 PDU stub into a full V1 PDU.
|
||||||
|
pub fn into_v1_pdu(self, room_id: RoomId, event_id: EventId) -> RoomV1Pdu {
|
||||||
|
RoomV1Pdu {
|
||||||
|
event_id,
|
||||||
|
room_id,
|
||||||
|
sender: self.sender,
|
||||||
|
origin: self.origin,
|
||||||
|
origin_server_ts: self.origin_server_ts,
|
||||||
|
kind: self.kind,
|
||||||
|
content: self.content,
|
||||||
|
state_key: self.state_key,
|
||||||
|
prev_events: self.prev_events,
|
||||||
|
depth: self.depth,
|
||||||
|
auth_events: self.auth_events,
|
||||||
|
redacts: self.redacts,
|
||||||
|
unsigned: self.unsigned,
|
||||||
|
hashes: self.hashes,
|
||||||
|
signatures: self.signatures,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Stub for PDUs of room versions 3 and above.
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
pub struct RoomV3PduStub {
|
||||||
|
/// The user id of the user who sent this event.
|
||||||
|
pub sender: UserId,
|
||||||
|
|
||||||
|
/// The `server_name` of the homeserver that created this event.
|
||||||
|
pub origin: String,
|
||||||
|
|
||||||
|
/// Timestamp (milliseconds since the UNIX epoch) on originating homeserver
|
||||||
|
/// of when this event was created.
|
||||||
|
#[serde(with = "ruma_serde::time::ms_since_unix_epoch")]
|
||||||
|
pub origin_server_ts: SystemTime,
|
||||||
|
|
||||||
|
// TODO: Encode event type as content enum variant, like event enums do
|
||||||
|
/// The event's type.
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
pub kind: EventType,
|
||||||
|
|
||||||
|
/// The event's content.
|
||||||
|
pub content: JsonValue,
|
||||||
|
|
||||||
|
/// A key that determines which piece of room state the event represents.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub state_key: Option<String>,
|
||||||
|
|
||||||
|
/// Event IDs for the most recent events in the room that the homeserver was
|
||||||
|
/// aware of when it created this event.
|
||||||
|
pub prev_events: Vec<EventId>,
|
||||||
|
|
||||||
|
/// The maximum depth of the `prev_events`, plus one.
|
||||||
|
pub depth: UInt,
|
||||||
|
|
||||||
|
/// Event IDs for the authorization events that would allow this event to be
|
||||||
|
/// in the room.
|
||||||
|
pub auth_events: Vec<EventId>,
|
||||||
|
|
||||||
|
/// For redaction events, the ID of the event being redacted.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub redacts: Option<EventId>,
|
||||||
|
|
||||||
|
/// Additional data added by the origin server but not covered by the
|
||||||
|
/// signatures.
|
||||||
|
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
|
||||||
|
pub unsigned: BTreeMap<String, JsonValue>,
|
||||||
|
|
||||||
|
/// Content hashes of the PDU.
|
||||||
|
pub hashes: EventHash,
|
||||||
|
|
||||||
|
/// Signatures for the PDU.
|
||||||
|
pub signatures: BTreeMap<String, BTreeMap<String, String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RoomV3PduStub {
|
||||||
|
/// Converts a V3 PDU stub into a full V3 PDU.
|
||||||
|
pub fn into_v3_pdu(self, room_id: RoomId) -> RoomV3Pdu {
|
||||||
|
RoomV3Pdu {
|
||||||
|
room_id,
|
||||||
|
sender: self.sender,
|
||||||
|
origin: self.origin,
|
||||||
|
origin_server_ts: self.origin_server_ts,
|
||||||
|
kind: self.kind,
|
||||||
|
content: self.content,
|
||||||
|
state_key: self.state_key,
|
||||||
|
prev_events: self.prev_events,
|
||||||
|
depth: self.depth,
|
||||||
|
auth_events: self.auth_events,
|
||||||
|
redacts: self.redacts,
|
||||||
|
unsigned: self.unsigned,
|
||||||
|
hashes: self.hashes,
|
||||||
|
signatures: self.signatures,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Content hashes of a PDU.
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
pub struct EventHash {
|
||||||
|
/// The SHA-256 hash.
|
||||||
|
pub sha256: String,
|
||||||
|
}
|
605
ruma-events/tests/pdu.rs
Normal file
605
ruma-events/tests/pdu.rs
Normal file
@ -0,0 +1,605 @@
|
|||||||
|
use std::{
|
||||||
|
collections::BTreeMap,
|
||||||
|
convert::TryFrom,
|
||||||
|
time::{Duration, SystemTime},
|
||||||
|
};
|
||||||
|
|
||||||
|
use matches::assert_matches;
|
||||||
|
use ruma_events::{
|
||||||
|
pdu::{EventHash, Pdu, PduStub, RoomV1Pdu, RoomV1PduStub, RoomV3Pdu, RoomV3PduStub},
|
||||||
|
EventType,
|
||||||
|
};
|
||||||
|
use ruma_identifiers::{EventId, RoomId, UserId};
|
||||||
|
use serde_json::{from_value as from_json_value, json, to_value as to_json_value};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn serialize_stub_as_v1() {
|
||||||
|
let mut signatures = BTreeMap::new();
|
||||||
|
let mut inner_signature = BTreeMap::new();
|
||||||
|
inner_signature.insert(
|
||||||
|
"ed25519:key_version".to_string(),
|
||||||
|
"86BytesOfSignatureOfTheRedactedEvent".to_string(),
|
||||||
|
);
|
||||||
|
signatures.insert("example.com".to_string(), inner_signature);
|
||||||
|
|
||||||
|
let mut unsigned = BTreeMap::new();
|
||||||
|
unsigned.insert("somekey".to_string(), json!({"a": 456}));
|
||||||
|
|
||||||
|
let v1_stub = RoomV1PduStub {
|
||||||
|
sender: UserId::try_from("@sender:example.com").unwrap(),
|
||||||
|
origin: "matrix.org".to_string(),
|
||||||
|
origin_server_ts: SystemTime::UNIX_EPOCH + Duration::from_millis(1_592_050_773_658),
|
||||||
|
kind: EventType::RoomPowerLevels,
|
||||||
|
content: json!({"testing": 123}),
|
||||||
|
state_key: Some("state".to_string()),
|
||||||
|
prev_events: vec![(
|
||||||
|
EventId::try_from("$previousevent:matrix.org").unwrap(),
|
||||||
|
EventHash { sha256: "123567".to_string() },
|
||||||
|
)],
|
||||||
|
depth: 2_u32.into(),
|
||||||
|
auth_events: vec![(
|
||||||
|
EventId::try_from("$someauthevent:matrix.org").unwrap(),
|
||||||
|
EventHash { sha256: "21389CFEDABC".to_string() },
|
||||||
|
)],
|
||||||
|
redacts: Some(EventId::try_from("$9654:matrix.org").unwrap()),
|
||||||
|
unsigned,
|
||||||
|
hashes: EventHash { sha256: "1233543bABACDEF".to_string() },
|
||||||
|
signatures,
|
||||||
|
};
|
||||||
|
let pdu_stub = PduStub::RoomV1PduStub(v1_stub);
|
||||||
|
let json = json!({
|
||||||
|
"sender": "@sender:example.com",
|
||||||
|
"origin": "matrix.org",
|
||||||
|
"origin_server_ts": 1_592_050_773_658 as usize,
|
||||||
|
"type": "m.room.power_levels",
|
||||||
|
"content": {
|
||||||
|
"testing": 123
|
||||||
|
},
|
||||||
|
"state_key": "state",
|
||||||
|
"prev_events": [
|
||||||
|
[ "$previousevent:matrix.org", {"sha256": "123567"} ]
|
||||||
|
],
|
||||||
|
"depth": 2,
|
||||||
|
"auth_events": [
|
||||||
|
["$someauthevent:matrix.org", {"sha256": "21389CFEDABC"}]
|
||||||
|
],
|
||||||
|
"redacts": "$9654:matrix.org",
|
||||||
|
"unsigned": {
|
||||||
|
"somekey": { "a": 456 } },
|
||||||
|
"hashes": { "sha256": "1233543bABACDEF" },
|
||||||
|
"signatures": {
|
||||||
|
"example.com": { "ed25519:key_version":"86BytesOfSignatureOfTheRedactedEvent" }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(to_json_value(&pdu_stub).unwrap(), json);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn serialize_stub_as_v3() {
|
||||||
|
let mut signatures = BTreeMap::new();
|
||||||
|
let mut inner_signature = BTreeMap::new();
|
||||||
|
inner_signature.insert(
|
||||||
|
"ed25519:key_version".to_string(),
|
||||||
|
"86BytesOfSignatureOfTheRedactedEvent".to_string(),
|
||||||
|
);
|
||||||
|
signatures.insert("example.com".to_string(), inner_signature);
|
||||||
|
|
||||||
|
let mut unsigned = BTreeMap::new();
|
||||||
|
unsigned.insert("somekey".to_string(), json!({"a": 456}));
|
||||||
|
|
||||||
|
let v3_stub = RoomV3PduStub {
|
||||||
|
sender: UserId::try_from("@sender:example.com").unwrap(),
|
||||||
|
origin: "matrix.org".to_string(),
|
||||||
|
origin_server_ts: SystemTime::UNIX_EPOCH + Duration::from_millis(1_592_050_773_658),
|
||||||
|
kind: EventType::RoomPowerLevels,
|
||||||
|
content: json!({"testing": 123}),
|
||||||
|
state_key: Some("state".to_string()),
|
||||||
|
prev_events: vec![EventId::try_from("$previousevent:matrix.org").unwrap()],
|
||||||
|
depth: 2_u32.into(),
|
||||||
|
auth_events: vec![EventId::try_from("$someauthevent:matrix.org").unwrap()],
|
||||||
|
redacts: Some(EventId::try_from("$9654:matrix.org").unwrap()),
|
||||||
|
unsigned,
|
||||||
|
hashes: EventHash { sha256: "1233543bABACDEF".to_string() },
|
||||||
|
signatures,
|
||||||
|
};
|
||||||
|
let pdu_stub = PduStub::RoomV3PduStub(v3_stub);
|
||||||
|
let json = json!({
|
||||||
|
"sender": "@sender:example.com",
|
||||||
|
"origin": "matrix.org",
|
||||||
|
"origin_server_ts": 1_592_050_773_658 as usize,
|
||||||
|
"type": "m.room.power_levels",
|
||||||
|
"content": {
|
||||||
|
"testing": 123
|
||||||
|
},
|
||||||
|
"state_key": "state",
|
||||||
|
"prev_events": [ "$previousevent:matrix.org" ],
|
||||||
|
"depth": 2,
|
||||||
|
"auth_events": ["$someauthevent:matrix.org" ],
|
||||||
|
"redacts": "$9654:matrix.org",
|
||||||
|
"unsigned": {
|
||||||
|
"somekey": { "a": 456 } },
|
||||||
|
"hashes": { "sha256": "1233543bABACDEF" },
|
||||||
|
"signatures": {
|
||||||
|
"example.com": { "ed25519:key_version":"86BytesOfSignatureOfTheRedactedEvent" }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(to_json_value(&pdu_stub).unwrap(), json);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_deserialize_stub_as_v1() {
|
||||||
|
let json = json!({
|
||||||
|
"auth_events": [
|
||||||
|
[
|
||||||
|
"$abc123:matrix.org",
|
||||||
|
{
|
||||||
|
"sha256": "Base64EncodedSha256HashesShouldBe43BytesLong"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"content": {
|
||||||
|
"key": "value"
|
||||||
|
},
|
||||||
|
"depth": 12,
|
||||||
|
"event_id": "$a4ecee13e2accdadf56c1025:example.com",
|
||||||
|
"hashes": {
|
||||||
|
"sha256": "ThisHashCoversAllFieldsInCaseThisIsRedacted"
|
||||||
|
},
|
||||||
|
"origin": "matrix.org",
|
||||||
|
"origin_server_ts": 1_234_567_890,
|
||||||
|
"prev_events": [
|
||||||
|
[
|
||||||
|
"$abc123:matrix.org",
|
||||||
|
{
|
||||||
|
"sha256": "Base64EncodedSha256HashesShouldBe43BytesLong"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"redacts": "$def456:matrix.org",
|
||||||
|
"room_id": "!abc123:matrix.org",
|
||||||
|
"sender": "@someone:matrix.org",
|
||||||
|
"signatures": {
|
||||||
|
"example.com": {
|
||||||
|
"ed25519:key_version:": "86BytesOfSignatureOfTheRedactedEvent"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"state_key": "my_key",
|
||||||
|
"type": "m.room.message",
|
||||||
|
"unsigned": {
|
||||||
|
"key": "value"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let parsed = from_json_value::<PduStub>(json).unwrap();
|
||||||
|
|
||||||
|
match parsed {
|
||||||
|
PduStub::RoomV1PduStub(v1_stub) => {
|
||||||
|
assert_eq!(
|
||||||
|
v1_stub.auth_events.first().unwrap().0,
|
||||||
|
EventId::try_from("$abc123:matrix.org").unwrap()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
v1_stub.auth_events.first().unwrap().1.sha256,
|
||||||
|
"Base64EncodedSha256HashesShouldBe43BytesLong"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
PduStub::RoomV3PduStub(_) => panic!("Matched V3 stub"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn deserialize_stub_as_v3() {
|
||||||
|
let json = json!({
|
||||||
|
"auth_events": [
|
||||||
|
"$abc123:matrix.org"
|
||||||
|
],
|
||||||
|
"content": {
|
||||||
|
"key": "value"
|
||||||
|
},
|
||||||
|
"depth": 12,
|
||||||
|
"event_id": "$a4ecee13e2accdadf56c1025:example.com",
|
||||||
|
"hashes": {
|
||||||
|
"sha256": "ThisHashCoversAllFieldsInCaseThisIsRedacted"
|
||||||
|
},
|
||||||
|
"origin": "matrix.org",
|
||||||
|
"origin_server_ts": 1_234_567_890,
|
||||||
|
"prev_events": [
|
||||||
|
"$abc123:matrix.org"
|
||||||
|
],
|
||||||
|
"redacts": "$def456:matrix.org",
|
||||||
|
"room_id": "!abc123:matrix.org",
|
||||||
|
"sender": "@someone:matrix.org",
|
||||||
|
"signatures": {
|
||||||
|
"example.com": {
|
||||||
|
"ed25519:key_version:": "86BytesOfSignatureOfTheRedactedEvent"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"state_key": "my_key",
|
||||||
|
"type": "m.room.message",
|
||||||
|
"unsigned": {
|
||||||
|
"key": "value"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let parsed = from_json_value::<PduStub>(json).unwrap();
|
||||||
|
|
||||||
|
match parsed {
|
||||||
|
PduStub::RoomV1PduStub(_) => panic!("Matched V1 stub"),
|
||||||
|
PduStub::RoomV3PduStub(v3_stub) => {
|
||||||
|
assert_eq!(
|
||||||
|
v3_stub.auth_events.first().unwrap(),
|
||||||
|
&EventId::try_from("$abc123:matrix.org").unwrap()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn serialize_pdu_as_v1() {
|
||||||
|
let mut signatures = BTreeMap::new();
|
||||||
|
let mut inner_signature = BTreeMap::new();
|
||||||
|
inner_signature.insert(
|
||||||
|
"ed25519:key_version".to_string(),
|
||||||
|
"86BytesOfSignatureOfTheRedactedEvent".to_string(),
|
||||||
|
);
|
||||||
|
signatures.insert("example.com".to_string(), inner_signature);
|
||||||
|
|
||||||
|
let mut unsigned = BTreeMap::new();
|
||||||
|
unsigned.insert("somekey".to_string(), json!({"a": 456}));
|
||||||
|
|
||||||
|
let v1_pdu = RoomV1Pdu {
|
||||||
|
room_id: RoomId::try_from("!n8f893n9:example.com").unwrap(),
|
||||||
|
event_id: EventId::try_from("$somejoinevent:matrix.org").unwrap(),
|
||||||
|
sender: UserId::try_from("@sender:example.com").unwrap(),
|
||||||
|
origin: "matrix.org".to_string(),
|
||||||
|
origin_server_ts: SystemTime::UNIX_EPOCH + Duration::from_millis(1_592_050_773_658),
|
||||||
|
kind: EventType::RoomPowerLevels,
|
||||||
|
content: json!({"testing": 123}),
|
||||||
|
state_key: Some("state".to_string()),
|
||||||
|
prev_events: vec![(
|
||||||
|
EventId::try_from("$previousevent:matrix.org").unwrap(),
|
||||||
|
EventHash { sha256: "123567".to_string() },
|
||||||
|
)],
|
||||||
|
depth: 2_u32.into(),
|
||||||
|
auth_events: vec![(
|
||||||
|
EventId::try_from("$someauthevent:matrix.org").unwrap(),
|
||||||
|
EventHash { sha256: "21389CFEDABC".to_string() },
|
||||||
|
)],
|
||||||
|
redacts: Some(EventId::try_from("$9654:matrix.org").unwrap()),
|
||||||
|
unsigned,
|
||||||
|
hashes: EventHash { sha256: "1233543bABACDEF".to_string() },
|
||||||
|
signatures,
|
||||||
|
};
|
||||||
|
let pdu = Pdu::RoomV1Pdu(v1_pdu);
|
||||||
|
let json = json!({
|
||||||
|
"room_id": "!n8f893n9:example.com",
|
||||||
|
"event_id": "$somejoinevent:matrix.org",
|
||||||
|
"sender": "@sender:example.com",
|
||||||
|
"origin": "matrix.org",
|
||||||
|
"origin_server_ts": 1_592_050_773_658 as usize,
|
||||||
|
"type": "m.room.power_levels",
|
||||||
|
"content": {
|
||||||
|
"testing": 123
|
||||||
|
},
|
||||||
|
"state_key": "state",
|
||||||
|
"prev_events": [
|
||||||
|
[ "$previousevent:matrix.org", {"sha256": "123567"} ]
|
||||||
|
],
|
||||||
|
"depth": 2,
|
||||||
|
"auth_events": [
|
||||||
|
["$someauthevent:matrix.org", {"sha256": "21389CFEDABC"}]
|
||||||
|
],
|
||||||
|
"redacts": "$9654:matrix.org",
|
||||||
|
"unsigned": {
|
||||||
|
"somekey": { "a": 456 } },
|
||||||
|
"hashes": { "sha256": "1233543bABACDEF" },
|
||||||
|
"signatures": {
|
||||||
|
"example.com": { "ed25519:key_version":"86BytesOfSignatureOfTheRedactedEvent" }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(to_json_value(&pdu).unwrap(), json);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn serialize_pdu_as_v3() {
|
||||||
|
let mut signatures = BTreeMap::new();
|
||||||
|
let mut inner_signature = BTreeMap::new();
|
||||||
|
inner_signature.insert(
|
||||||
|
"ed25519:key_version".to_string(),
|
||||||
|
"86BytesOfSignatureOfTheRedactedEvent".to_string(),
|
||||||
|
);
|
||||||
|
signatures.insert("example.com".to_string(), inner_signature);
|
||||||
|
|
||||||
|
let mut unsigned = BTreeMap::new();
|
||||||
|
unsigned.insert("somekey".to_string(), json!({"a": 456}));
|
||||||
|
|
||||||
|
let v3_pdu = RoomV3Pdu {
|
||||||
|
room_id: RoomId::try_from("!n8f893n9:example.com").unwrap(),
|
||||||
|
sender: UserId::try_from("@sender:example.com").unwrap(),
|
||||||
|
origin: "matrix.org".to_string(),
|
||||||
|
origin_server_ts: SystemTime::UNIX_EPOCH + Duration::from_millis(1_592_050_773_658),
|
||||||
|
kind: EventType::RoomPowerLevels,
|
||||||
|
content: json!({"testing": 123}),
|
||||||
|
state_key: Some("state".to_string()),
|
||||||
|
prev_events: vec![EventId::try_from("$previousevent:matrix.org").unwrap()],
|
||||||
|
depth: 2_u32.into(),
|
||||||
|
auth_events: vec![EventId::try_from("$someauthevent:matrix.org").unwrap()],
|
||||||
|
redacts: Some(EventId::try_from("$9654:matrix.org").unwrap()),
|
||||||
|
unsigned,
|
||||||
|
hashes: EventHash { sha256: "1233543bABACDEF".to_string() },
|
||||||
|
signatures,
|
||||||
|
};
|
||||||
|
let pdu_stub = Pdu::RoomV3Pdu(v3_pdu);
|
||||||
|
let json = json!({
|
||||||
|
"room_id": "!n8f893n9:example.com",
|
||||||
|
"sender": "@sender:example.com",
|
||||||
|
"origin": "matrix.org",
|
||||||
|
"origin_server_ts": 1_592_050_773_658 as usize,
|
||||||
|
"type": "m.room.power_levels",
|
||||||
|
"content": {
|
||||||
|
"testing": 123
|
||||||
|
},
|
||||||
|
"state_key": "state",
|
||||||
|
"prev_events": [ "$previousevent:matrix.org" ],
|
||||||
|
"depth": 2,
|
||||||
|
"auth_events": ["$someauthevent:matrix.org" ],
|
||||||
|
"redacts": "$9654:matrix.org",
|
||||||
|
"unsigned": {
|
||||||
|
"somekey": { "a": 456 } },
|
||||||
|
"hashes": { "sha256": "1233543bABACDEF" },
|
||||||
|
"signatures": {
|
||||||
|
"example.com": { "ed25519:key_version":"86BytesOfSignatureOfTheRedactedEvent" }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(to_json_value(&pdu_stub).unwrap(), json);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_deserialize_pdu_as_v1() {
|
||||||
|
let json = json!({
|
||||||
|
"room_id": "!n8f893n9:example.com",
|
||||||
|
"event_id": "$somejoinevent:matrix.org",
|
||||||
|
"auth_events": [
|
||||||
|
[
|
||||||
|
"$abc123:matrix.org",
|
||||||
|
{
|
||||||
|
"sha256": "Base64EncodedSha256HashesShouldBe43BytesLong"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"content": {
|
||||||
|
"key": "value"
|
||||||
|
},
|
||||||
|
"depth": 12,
|
||||||
|
"event_id": "$a4ecee13e2accdadf56c1025:example.com",
|
||||||
|
"hashes": {
|
||||||
|
"sha256": "ThisHashCoversAllFieldsInCaseThisIsRedacted"
|
||||||
|
},
|
||||||
|
"origin": "matrix.org",
|
||||||
|
"origin_server_ts": 1_234_567_890,
|
||||||
|
"prev_events": [
|
||||||
|
[
|
||||||
|
"$abc123:matrix.org",
|
||||||
|
{
|
||||||
|
"sha256": "Base64EncodedSha256HashesShouldBe43BytesLong"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"redacts": "$def456:matrix.org",
|
||||||
|
"room_id": "!abc123:matrix.org",
|
||||||
|
"sender": "@someone:matrix.org",
|
||||||
|
"signatures": {
|
||||||
|
"example.com": {
|
||||||
|
"ed25519:key_version:": "86BytesOfSignatureOfTheRedactedEvent"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"state_key": "my_key",
|
||||||
|
"type": "m.room.message",
|
||||||
|
"unsigned": {
|
||||||
|
"key": "value"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let parsed = from_json_value::<Pdu>(json).unwrap();
|
||||||
|
|
||||||
|
match parsed {
|
||||||
|
Pdu::RoomV1Pdu(v1_pdu) => {
|
||||||
|
assert_eq!(
|
||||||
|
v1_pdu.auth_events.first().unwrap().0,
|
||||||
|
EventId::try_from("$abc123:matrix.org").unwrap()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
v1_pdu.auth_events.first().unwrap().1.sha256,
|
||||||
|
"Base64EncodedSha256HashesShouldBe43BytesLong"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Pdu::RoomV3Pdu(_) => panic!("Matched V3 PDU"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn deserialize_pdu_as_v3() {
|
||||||
|
let json = json!({
|
||||||
|
"room_id": "!n8f893n9:example.com",
|
||||||
|
"auth_events": [
|
||||||
|
"$abc123:matrix.org"
|
||||||
|
],
|
||||||
|
"content": {
|
||||||
|
"key": "value"
|
||||||
|
},
|
||||||
|
"depth": 12,
|
||||||
|
"event_id": "$a4ecee13e2accdadf56c1025:example.com",
|
||||||
|
"hashes": {
|
||||||
|
"sha256": "ThisHashCoversAllFieldsInCaseThisIsRedacted"
|
||||||
|
},
|
||||||
|
"origin": "matrix.org",
|
||||||
|
"origin_server_ts": 1_234_567_890,
|
||||||
|
"prev_events": [
|
||||||
|
"$abc123:matrix.org"
|
||||||
|
],
|
||||||
|
"redacts": "$def456:matrix.org",
|
||||||
|
"room_id": "!abc123:matrix.org",
|
||||||
|
"sender": "@someone:matrix.org",
|
||||||
|
"signatures": {
|
||||||
|
"example.com": {
|
||||||
|
"ed25519:key_version:": "86BytesOfSignatureOfTheRedactedEvent"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"state_key": "my_key",
|
||||||
|
"type": "m.room.message",
|
||||||
|
"unsigned": {
|
||||||
|
"key": "value"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let parsed = from_json_value::<Pdu>(json).unwrap();
|
||||||
|
|
||||||
|
match parsed {
|
||||||
|
Pdu::RoomV1Pdu(_) => panic!("Matched V1 PDU"),
|
||||||
|
Pdu::RoomV3Pdu(v3_pdu) => {
|
||||||
|
assert_eq!(
|
||||||
|
v3_pdu.auth_events.first().unwrap(),
|
||||||
|
&EventId::try_from("$abc123:matrix.org").unwrap()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn convert_v1_stub_to_pdu() {
|
||||||
|
let mut signatures = BTreeMap::new();
|
||||||
|
let mut inner_signature = BTreeMap::new();
|
||||||
|
inner_signature.insert(
|
||||||
|
"ed25519:key_version".to_string(),
|
||||||
|
"86BytesOfSignatureOfTheRedactedEvent".to_string(),
|
||||||
|
);
|
||||||
|
signatures.insert("example.com".to_string(), inner_signature);
|
||||||
|
|
||||||
|
let mut unsigned = BTreeMap::new();
|
||||||
|
unsigned.insert("somekey".to_string(), json!({"a": 456}));
|
||||||
|
|
||||||
|
let v1_stub = RoomV1PduStub {
|
||||||
|
sender: UserId::try_from("@sender:example.com").unwrap(),
|
||||||
|
origin: "matrix.org".to_string(),
|
||||||
|
origin_server_ts: SystemTime::UNIX_EPOCH + Duration::from_millis(1_592_050_773_658),
|
||||||
|
kind: EventType::RoomPowerLevels,
|
||||||
|
content: json!({"testing": 123}),
|
||||||
|
state_key: Some("state".to_string()),
|
||||||
|
prev_events: vec![(
|
||||||
|
EventId::try_from("$previousevent:matrix.org").unwrap(),
|
||||||
|
EventHash { sha256: "123567".to_string() },
|
||||||
|
)],
|
||||||
|
depth: 2_u32.into(),
|
||||||
|
auth_events: vec![(
|
||||||
|
EventId::try_from("$someauthevent:matrix.org").unwrap(),
|
||||||
|
EventHash { sha256: "21389CFEDABC".to_string() },
|
||||||
|
)],
|
||||||
|
redacts: Some(EventId::try_from("$9654:matrix.org").unwrap()),
|
||||||
|
unsigned: (&unsigned).clone(),
|
||||||
|
hashes: EventHash { sha256: "1233543bABACDEF".to_string() },
|
||||||
|
signatures: (&signatures).clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_matches!(
|
||||||
|
v1_stub.into_v1_pdu(
|
||||||
|
RoomId::try_from("!n8f893n9:example.com").unwrap(),
|
||||||
|
EventId::try_from("$somejoinevent:matrix.org").unwrap()
|
||||||
|
),
|
||||||
|
RoomV1Pdu {
|
||||||
|
room_id,
|
||||||
|
event_id,
|
||||||
|
sender,
|
||||||
|
origin,
|
||||||
|
origin_server_ts,
|
||||||
|
kind,
|
||||||
|
content,
|
||||||
|
state_key,
|
||||||
|
prev_events,
|
||||||
|
depth,
|
||||||
|
auth_events,
|
||||||
|
redacts,
|
||||||
|
unsigned,
|
||||||
|
hashes: EventHash { sha256 },
|
||||||
|
signatures,
|
||||||
|
} if room_id == RoomId::try_from("!n8f893n9:example.com").unwrap()
|
||||||
|
&& event_id == EventId::try_from("$somejoinevent:matrix.org").unwrap()
|
||||||
|
&& sender == UserId::try_from("@sender:example.com").unwrap()
|
||||||
|
&& origin == "matrix.org"
|
||||||
|
&& origin_server_ts == SystemTime::UNIX_EPOCH + Duration::from_millis(1_592_050_773_658)
|
||||||
|
&& kind == EventType::RoomPowerLevels
|
||||||
|
&& content == json!({"testing": 123})
|
||||||
|
&& state_key == Some("state".to_string())
|
||||||
|
&& prev_events[0].0 == EventId::try_from("$previousevent:matrix.org").unwrap()
|
||||||
|
&& prev_events[0].1.sha256 == "123567"
|
||||||
|
&& depth == 2_u32.into()
|
||||||
|
&& auth_events.first().unwrap().0 == EventId::try_from("$someauthevent:matrix.org").unwrap()
|
||||||
|
&& auth_events.first().unwrap().1.sha256 == "21389CFEDABC"
|
||||||
|
&& redacts == Some(EventId::try_from("$9654:matrix.org").unwrap())
|
||||||
|
&& unsigned == (&unsigned).clone()
|
||||||
|
&& sha256 == "1233543bABACDEF"
|
||||||
|
&& signatures == (&signatures).clone()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn convert_v3_stub_to_pdu() {
|
||||||
|
let mut signatures = BTreeMap::new();
|
||||||
|
let mut inner_signature = BTreeMap::new();
|
||||||
|
inner_signature.insert(
|
||||||
|
"ed25519:key_version".to_string(),
|
||||||
|
"86BytesOfSignatureOfTheRedactedEvent".to_string(),
|
||||||
|
);
|
||||||
|
signatures.insert("example.com".to_string(), inner_signature);
|
||||||
|
|
||||||
|
let mut unsigned = BTreeMap::new();
|
||||||
|
unsigned.insert("somekey".to_string(), json!({"a": 456}));
|
||||||
|
|
||||||
|
let v3_stub = RoomV3PduStub {
|
||||||
|
sender: UserId::try_from("@sender:example.com").unwrap(),
|
||||||
|
origin: "matrix.org".to_string(),
|
||||||
|
origin_server_ts: SystemTime::UNIX_EPOCH + Duration::from_millis(1_592_050_773_658),
|
||||||
|
kind: EventType::RoomPowerLevels,
|
||||||
|
content: json!({"testing": 123}),
|
||||||
|
state_key: Some("state".to_string()),
|
||||||
|
prev_events: vec![EventId::try_from("$previousevent:matrix.org").unwrap()],
|
||||||
|
depth: 2_u32.into(),
|
||||||
|
auth_events: vec![EventId::try_from("$someauthevent:matrix.org").unwrap()],
|
||||||
|
redacts: Some(EventId::try_from("$9654:matrix.org").unwrap()),
|
||||||
|
unsigned: (&unsigned).clone(),
|
||||||
|
hashes: EventHash { sha256: "1233543bABACDEF".to_string() },
|
||||||
|
signatures: (&signatures).clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_matches!(
|
||||||
|
v3_stub.into_v3_pdu(RoomId::try_from("!n8f893n9:example.com").unwrap()),
|
||||||
|
RoomV3Pdu {
|
||||||
|
room_id,
|
||||||
|
sender,
|
||||||
|
origin,
|
||||||
|
origin_server_ts,
|
||||||
|
kind,
|
||||||
|
content,
|
||||||
|
state_key,
|
||||||
|
prev_events,
|
||||||
|
depth,
|
||||||
|
auth_events,
|
||||||
|
redacts,
|
||||||
|
unsigned,
|
||||||
|
hashes: EventHash { sha256 },
|
||||||
|
signatures,
|
||||||
|
} if room_id == RoomId::try_from("!n8f893n9:example.com").unwrap()
|
||||||
|
&& sender == UserId::try_from("@sender:example.com").unwrap()
|
||||||
|
&& origin == "matrix.org"
|
||||||
|
&& origin_server_ts == SystemTime::UNIX_EPOCH + Duration::from_millis(1_592_050_773_658)
|
||||||
|
&& kind == EventType::RoomPowerLevels
|
||||||
|
&& content == json!({"testing": 123})
|
||||||
|
&& state_key == Some("state".to_string())
|
||||||
|
&& prev_events == vec![EventId::try_from("$previousevent:matrix.org").unwrap()]
|
||||||
|
&& depth == 2_u32.into()
|
||||||
|
&& auth_events == vec![EventId::try_from("$someauthevent:matrix.org").unwrap()]
|
||||||
|
&& redacts == Some(EventId::try_from("$9654:matrix.org").unwrap())
|
||||||
|
&& unsigned == (&unsigned).clone()
|
||||||
|
&& sha256 == "1233543bABACDEF"
|
||||||
|
&& signatures == (&signatures).clone()
|
||||||
|
);
|
||||||
|
}
|
@ -1,5 +1,9 @@
|
|||||||
# [unreleased]
|
# [unreleased]
|
||||||
|
|
||||||
|
Breaking Changes:
|
||||||
|
|
||||||
|
* Replace `RoomV3Pdu` with `ruma_events::pdu::{Pdu, PduStub}`.
|
||||||
|
|
||||||
Improvements:
|
Improvements:
|
||||||
|
|
||||||
* Add endpoints:
|
* Add endpoints:
|
||||||
@ -15,6 +19,7 @@ Improvements:
|
|||||||
create_join_event_template::v1
|
create_join_event_template::v1
|
||||||
},
|
},
|
||||||
query::get_room_information::v1,
|
query::get_room_information::v1,
|
||||||
|
transactions::send_transaction_message::v1,
|
||||||
version::get_server_version::v1
|
version::get_server_version::v1
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -2,69 +2,10 @@
|
|||||||
|
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
|
|
||||||
use std::{collections::BTreeMap, time::SystemTime};
|
|
||||||
|
|
||||||
use ::serde::{Deserialize, Serialize};
|
|
||||||
use js_int::UInt;
|
|
||||||
use ruma_events::EventType;
|
|
||||||
use ruma_identifiers::{EventId, RoomId, UserId};
|
|
||||||
use serde_json::Value as JsonValue;
|
|
||||||
|
|
||||||
mod serde;
|
mod serde;
|
||||||
|
|
||||||
pub mod directory;
|
pub mod directory;
|
||||||
pub mod discovery;
|
pub mod discovery;
|
||||||
pub mod membership;
|
pub mod membership;
|
||||||
pub mod query;
|
pub mod query;
|
||||||
|
pub mod transactions;
|
||||||
/// A 'persistent data unit' (event) for room versions 3 and beyond.
|
|
||||||
#[derive(Deserialize, Serialize)]
|
|
||||||
pub struct RoomV3Pdu {
|
|
||||||
/// The room this event belongs to.
|
|
||||||
pub room_id: RoomId,
|
|
||||||
/// The user id of the user who sent this event.
|
|
||||||
pub sender: UserId,
|
|
||||||
/// The `server_name` of the homeserver that created this event.
|
|
||||||
pub origin: String,
|
|
||||||
/// Timestamp (milliseconds since the UNIX epoch) on originating homeserver
|
|
||||||
/// of when this event was created.
|
|
||||||
#[serde(with = "ruma_serde::time::ms_since_unix_epoch")]
|
|
||||||
pub origin_server_ts: SystemTime,
|
|
||||||
|
|
||||||
// TODO: Replace with event content collection from ruma-events once that exists
|
|
||||||
/// The event's type.
|
|
||||||
#[serde(rename = "type")]
|
|
||||||
pub kind: EventType,
|
|
||||||
/// The event's content.
|
|
||||||
pub content: JsonValue,
|
|
||||||
|
|
||||||
/// A key that determines which piece of room state the event represents.
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
pub state_key: Option<String>,
|
|
||||||
/// Event IDs for the most recent events in the room that the homeserver was
|
|
||||||
/// aware of when it created this event.
|
|
||||||
pub prev_events: Vec<EventId>,
|
|
||||||
/// The maximum depth of the `prev_events`, plus one.
|
|
||||||
pub depth: UInt,
|
|
||||||
/// Event IDs for the authorization events that would allow this event to be
|
|
||||||
/// in the room.
|
|
||||||
pub auth_events: Vec<EventId>,
|
|
||||||
/// For redaction events, the ID of the event being redacted.
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
pub redacts: Option<EventId>,
|
|
||||||
/// Additional data added by the origin server but not covered by the
|
|
||||||
/// signatures.
|
|
||||||
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
|
|
||||||
pub unsigned: BTreeMap<String, JsonValue>,
|
|
||||||
/// Content hashes of the PDU.
|
|
||||||
pub hashes: EventHash,
|
|
||||||
/// Signatures for the PDU.
|
|
||||||
pub signatures: BTreeMap<String, BTreeMap<String, String>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Content hashes of a PDU.
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
|
||||||
pub struct EventHash {
|
|
||||||
/// The SHA-256 hash.
|
|
||||||
pub sha256: String,
|
|
||||||
}
|
|
||||||
|
@ -2,11 +2,9 @@
|
|||||||
|
|
||||||
pub mod v1;
|
pub mod v1;
|
||||||
|
|
||||||
use ruma_events::EventJson;
|
use ruma_events::{pdu::Pdu, EventJson};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::RoomV3Pdu;
|
|
||||||
|
|
||||||
/// Full state of the room.
|
/// Full state of the room.
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
pub struct RoomState {
|
pub struct RoomState {
|
||||||
@ -14,7 +12,7 @@ pub struct RoomState {
|
|||||||
pub origin: String,
|
pub origin: String,
|
||||||
/// The full set of authorization events that make up the state of the room,
|
/// The full set of authorization events that make up the state of the room,
|
||||||
/// and their authorization events, recursively.
|
/// and their authorization events, recursively.
|
||||||
pub auth_chain: Vec<EventJson<RoomV3Pdu>>,
|
pub auth_chain: Vec<EventJson<Pdu>>,
|
||||||
/// The room state.
|
/// The room state.
|
||||||
pub state: Vec<EventJson<RoomV3Pdu>>,
|
pub state: Vec<EventJson<Pdu>>,
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,10 @@
|
|||||||
//! [PUT /_matrix/federation/v1/send_join/{roomId}/{eventId}](https://matrix.org/docs/spec/server_server/r0.1.3#put-matrix-federation-v1-send-join-roomid-eventid)
|
//! [PUT /_matrix/federation/v1/send_join/{roomId}/{eventId}](https://matrix.org/docs/spec/server_server/r0.1.3#put-matrix-federation-v1-send-join-roomid-eventid)
|
||||||
|
|
||||||
use std::{collections::BTreeMap, time::SystemTime};
|
|
||||||
|
|
||||||
use js_int::UInt;
|
|
||||||
use ruma_api::ruma_api;
|
use ruma_api::ruma_api;
|
||||||
use ruma_events::EventType;
|
use ruma_events::pdu::PduStub;
|
||||||
use ruma_identifiers::{EventId, RoomId, UserId};
|
use ruma_identifiers::{EventId, RoomId};
|
||||||
use serde_json::Value as JsonValue;
|
|
||||||
|
|
||||||
use super::RoomState;
|
use super::RoomState;
|
||||||
use crate::{EventHash, RoomV3Pdu};
|
|
||||||
|
|
||||||
ruma_api! {
|
ruma_api! {
|
||||||
metadata {
|
metadata {
|
||||||
@ -29,44 +24,9 @@ ruma_api! {
|
|||||||
#[ruma_api(path)]
|
#[ruma_api(path)]
|
||||||
pub event_id: EventId,
|
pub event_id: EventId,
|
||||||
|
|
||||||
/// The user id of the user who sent this event.
|
/// PDU type without event and room IDs.
|
||||||
pub sender: UserId,
|
#[ruma_api(body)]
|
||||||
/// The `server_name` of the homeserver that created this event.
|
pub pdu_stub: PduStub,
|
||||||
pub origin: String,
|
|
||||||
/// Timestamp (milliseconds since the UNIX epoch) on originating homeserver
|
|
||||||
/// of when this event was created.
|
|
||||||
#[serde(with = "ruma_serde::time::ms_since_unix_epoch")]
|
|
||||||
pub origin_server_ts: SystemTime,
|
|
||||||
|
|
||||||
// TODO: Replace with event content collection from ruma-events once that exists
|
|
||||||
/// The event's type.
|
|
||||||
#[serde(rename = "type")]
|
|
||||||
pub kind: EventType,
|
|
||||||
/// The event's content.
|
|
||||||
pub content: JsonValue,
|
|
||||||
|
|
||||||
/// A key that determines which piece of room state the event represents.
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
pub state_key: Option<String>,
|
|
||||||
/// Event IDs for the most recent events in the room that the homeserver was
|
|
||||||
/// aware of when it created this event.
|
|
||||||
pub prev_events: Vec<EventId>,
|
|
||||||
/// The maximum depth of the `prev_events`, plus one.
|
|
||||||
pub depth: UInt,
|
|
||||||
/// Event IDs for the authorization events that would allow this event to be
|
|
||||||
/// in the room.
|
|
||||||
pub auth_events: Vec<EventId>,
|
|
||||||
/// For redaction events, the ID of the event being redacted.
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
pub redacts: Option<EventId>,
|
|
||||||
/// Additional data added by the origin server but not covered by the
|
|
||||||
/// signatures.
|
|
||||||
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
|
|
||||||
pub unsigned: BTreeMap<String, JsonValue>,
|
|
||||||
/// Content hashes of the PDU.
|
|
||||||
pub hashes: EventHash,
|
|
||||||
/// Signatures for the PDU.
|
|
||||||
pub signatures: BTreeMap<String, BTreeMap<String, String>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
response {
|
response {
|
||||||
@ -76,29 +36,3 @@ ruma_api! {
|
|||||||
pub room_state: RoomState,
|
pub room_state: RoomState,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Request {
|
|
||||||
/// Helper method to get event ID and PDU (with room ID) from the request
|
|
||||||
/// parameters.
|
|
||||||
pub fn into_id_and_v3_pdu(self) -> (EventId, RoomV3Pdu) {
|
|
||||||
(
|
|
||||||
self.event_id,
|
|
||||||
RoomV3Pdu {
|
|
||||||
room_id: self.room_id,
|
|
||||||
sender: self.sender,
|
|
||||||
origin: self.origin,
|
|
||||||
origin_server_ts: self.origin_server_ts,
|
|
||||||
kind: self.kind,
|
|
||||||
content: self.content,
|
|
||||||
state_key: self.state_key,
|
|
||||||
prev_events: self.prev_events,
|
|
||||||
depth: self.depth,
|
|
||||||
auth_events: self.auth_events,
|
|
||||||
redacts: self.redacts,
|
|
||||||
unsigned: self.unsigned,
|
|
||||||
hashes: self.hashes,
|
|
||||||
signatures: self.signatures,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -2,11 +2,9 @@
|
|||||||
|
|
||||||
use js_int::UInt;
|
use js_int::UInt;
|
||||||
use ruma_api::ruma_api;
|
use ruma_api::ruma_api;
|
||||||
use ruma_events::EventJson;
|
use ruma_events::{pdu::Pdu, EventJson};
|
||||||
use ruma_identifiers::{RoomId, UserId};
|
use ruma_identifiers::{RoomId, UserId};
|
||||||
|
|
||||||
use crate::RoomV3Pdu;
|
|
||||||
|
|
||||||
ruma_api! {
|
ruma_api! {
|
||||||
metadata {
|
metadata {
|
||||||
description: "Send a request for a join event template to a resident server.",
|
description: "Send a request for a join event template to a resident server.",
|
||||||
@ -34,6 +32,6 @@ ruma_api! {
|
|||||||
/// The version of the room where the server is trying to join.
|
/// The version of the room where the server is trying to join.
|
||||||
pub room_version: Option<UInt>,
|
pub room_version: Option<UInt>,
|
||||||
/// An unsigned template event.
|
/// An unsigned template event.
|
||||||
pub event: EventJson<RoomV3Pdu>,
|
pub event: EventJson<Pdu>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
//! Modules for custom serde de/-serialization implementations.
|
//! Modules for custom serde de/-serialization implementations.
|
||||||
|
|
||||||
|
pub mod pdu_process_response;
|
||||||
pub mod room_state;
|
pub mod room_state;
|
||||||
|
156
ruma-federation-api/src/serde/pdu_process_response.rs
Normal file
156
ruma-federation-api/src/serde/pdu_process_response.rs
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
use std::{collections::BTreeMap, fmt};
|
||||||
|
|
||||||
|
use ruma_identifiers::EventId;
|
||||||
|
use serde::{
|
||||||
|
de::{Deserializer, MapAccess, Visitor},
|
||||||
|
ser::{SerializeMap, Serializer},
|
||||||
|
Deserialize, Serialize,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn serialize<S>(
|
||||||
|
response: &BTreeMap<EventId, Result<(), String>>,
|
||||||
|
serializer: S,
|
||||||
|
) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
let mut map = serializer.serialize_map(Some(response.len()))?;
|
||||||
|
for (key, value) in response {
|
||||||
|
let wrapped_error = WrappedError {
|
||||||
|
error: match value {
|
||||||
|
Ok(_) => None,
|
||||||
|
Err(error) => Some(error.clone()),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
map.serialize_entry(&key, &wrapped_error)?;
|
||||||
|
}
|
||||||
|
map.end()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deserialize<'de, D>(
|
||||||
|
deserializer: D,
|
||||||
|
) -> Result<BTreeMap<EventId, Result<(), String>>, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
deserializer.deserialize_map(PduProcessResponseVisitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
struct WrappedError {
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
error: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PduProcessResponseVisitor;
|
||||||
|
|
||||||
|
impl<'de> Visitor<'de> for PduProcessResponseVisitor {
|
||||||
|
type Value = BTreeMap<EventId, Result<(), String>>;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
formatter.write_str("A map of EventIds to a map of optional errors")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
|
||||||
|
where
|
||||||
|
M: MapAccess<'de>,
|
||||||
|
{
|
||||||
|
let mut map = BTreeMap::new();
|
||||||
|
|
||||||
|
while let Some((key, value)) = access.next_entry::<EventId, WrappedError>()? {
|
||||||
|
let v = match value.error {
|
||||||
|
None => Ok(()),
|
||||||
|
Some(error) => Err(error),
|
||||||
|
};
|
||||||
|
map.insert(key, v);
|
||||||
|
}
|
||||||
|
Ok(map)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use std::{collections::BTreeMap, convert::TryFrom};
|
||||||
|
|
||||||
|
use ruma_identifiers::EventId;
|
||||||
|
use serde_json::{json, value::Serializer as JsonSerializer};
|
||||||
|
|
||||||
|
use super::{deserialize, serialize};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn serialize_error() {
|
||||||
|
let mut response: BTreeMap<EventId, Result<(), String>> = BTreeMap::new();
|
||||||
|
response.insert(
|
||||||
|
EventId::try_from("$someevent:matrix.org").unwrap(),
|
||||||
|
Err("Some processing error.".into()),
|
||||||
|
);
|
||||||
|
|
||||||
|
let serialized = serialize(&response, JsonSerializer).unwrap();
|
||||||
|
let json = json!({
|
||||||
|
"$someevent:matrix.org": { "error": "Some processing error." }
|
||||||
|
});
|
||||||
|
assert_eq!(serialized, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn serialize_ok() {
|
||||||
|
let mut response: BTreeMap<EventId, Result<(), String>> = BTreeMap::new();
|
||||||
|
response.insert(EventId::try_from("$someevent:matrix.org").unwrap(), Ok(()));
|
||||||
|
|
||||||
|
let serialized = serialize(&response, serde_json::value::Serializer).unwrap();
|
||||||
|
let json = json!({
|
||||||
|
"$someevent:matrix.org": {}
|
||||||
|
});
|
||||||
|
assert_eq!(serialized, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn deserialize_error() {
|
||||||
|
let json = json!({
|
||||||
|
"$someevent:matrix.org": { "error": "Some processing error." }
|
||||||
|
});
|
||||||
|
|
||||||
|
let response = deserialize(json).unwrap();
|
||||||
|
let event_id = EventId::try_from("$someevent:matrix.org").unwrap();
|
||||||
|
|
||||||
|
let event_response = response.get(&event_id).unwrap().clone().unwrap_err();
|
||||||
|
assert_eq!(event_response, "Some processing error.");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn deserialize_null_error_is_ok() {
|
||||||
|
let json = json!({
|
||||||
|
"$someevent:matrix.org": { "error": null }
|
||||||
|
});
|
||||||
|
|
||||||
|
let response = deserialize(json).unwrap();
|
||||||
|
let event_id = EventId::try_from("$someevent:matrix.org").unwrap();
|
||||||
|
|
||||||
|
assert!(response.get(&event_id).unwrap().is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn desieralize_empty_error_is_err() {
|
||||||
|
let json = json!({
|
||||||
|
"$someevent:matrix.org": { "error": "" }
|
||||||
|
});
|
||||||
|
|
||||||
|
let response = deserialize(json).unwrap();
|
||||||
|
let event_id = EventId::try_from("$someevent:matrix.org").unwrap();
|
||||||
|
|
||||||
|
let event_response = response.get(&event_id).unwrap().clone().unwrap_err();
|
||||||
|
assert_eq!(event_response, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn deserialize_ok() {
|
||||||
|
let json = json!({
|
||||||
|
"$someevent:matrix.org": {}
|
||||||
|
});
|
||||||
|
let response = deserialize(json).unwrap();
|
||||||
|
assert!(response
|
||||||
|
.get(&EventId::try_from("$someevent:matrix.org").unwrap())
|
||||||
|
.unwrap()
|
||||||
|
.is_ok());
|
||||||
|
}
|
||||||
|
}
|
3
ruma-federation-api/src/transactions.rs
Normal file
3
ruma-federation-api/src/transactions.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
//! Endpoints for exchanging transaction messages between homeservers.
|
||||||
|
|
||||||
|
pub mod send_transaction_message;
|
@ -0,0 +1,3 @@
|
|||||||
|
//! Endpoint to send live activity messages to another server.
|
||||||
|
|
||||||
|
pub mod v1;
|
@ -0,0 +1,59 @@
|
|||||||
|
//! [PUT /_matrix/federation/v1/send/{txnId}](https://matrix.org/docs/spec/server_server/r0.1.3#put-matrix-federation-v1-send-txnid)
|
||||||
|
|
||||||
|
use std::{collections::BTreeMap, time::SystemTime};
|
||||||
|
|
||||||
|
use ruma_api::ruma_api;
|
||||||
|
use ruma_events::pdu::Pdu;
|
||||||
|
use ruma_identifiers::EventId;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_json::Value as JsonValue;
|
||||||
|
|
||||||
|
ruma_api! {
|
||||||
|
metadata {
|
||||||
|
description: "Send transaction messages to another server",
|
||||||
|
name: "send_transaction_message",
|
||||||
|
method: PUT,
|
||||||
|
path: "/_matrix/federation/v1/send/:transaction_id",
|
||||||
|
rate_limited: false,
|
||||||
|
requires_authentication: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
request {
|
||||||
|
/// A transaction ID unique between sending and receiving homeservers.
|
||||||
|
#[ruma_api(path)]
|
||||||
|
pub transaction_id: String,
|
||||||
|
|
||||||
|
/// The server_name of the homeserver sending this transaction.
|
||||||
|
pub origin: String,
|
||||||
|
|
||||||
|
/// POSIX timestamp in milliseconds on the originating homeserver when this transaction started.
|
||||||
|
#[serde(with = "ruma_serde::time::ms_since_unix_epoch")]
|
||||||
|
pub origin_server_ts: SystemTime,
|
||||||
|
|
||||||
|
/// List of persistent updates to rooms.
|
||||||
|
///
|
||||||
|
/// Must not be more than 50 items.
|
||||||
|
pub pdus: Vec<Pdu>,
|
||||||
|
|
||||||
|
/// List of ephemeral messages.
|
||||||
|
///
|
||||||
|
/// Must not be more than 100 items.
|
||||||
|
#[serde(skip_serializing_if = "Vec::is_empty")]
|
||||||
|
pub edus: Vec<Edu>,
|
||||||
|
}
|
||||||
|
|
||||||
|
response {
|
||||||
|
/// Map of event IDs and response for each PDU given in the request.
|
||||||
|
#[serde(with = "crate::serde::pdu_process_response")]
|
||||||
|
pub pdus: BTreeMap<EventId, Result<(), String>>,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Type for passing ephemeral data to homeservers.
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
pub struct Edu {
|
||||||
|
/// Type of the ephemeral message.
|
||||||
|
pub edu_type: String,
|
||||||
|
/// Content of ephemeral message
|
||||||
|
pub content: JsonValue,
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user