Convert m.room.encrypted to the new API.
This commit is contained in:
parent
0f49c5e7f6
commit
21351aaff0
@ -11,7 +11,7 @@ pub mod aliases;
|
|||||||
pub mod avatar;
|
pub mod avatar;
|
||||||
pub mod canonical_alias;
|
pub mod canonical_alias;
|
||||||
pub mod create;
|
pub mod create;
|
||||||
// pub mod encrypted;
|
pub mod encrypted;
|
||||||
pub mod encryption;
|
pub mod encryption;
|
||||||
pub mod guest_access;
|
pub mod guest_access;
|
||||||
pub mod history_visibility;
|
pub mod history_visibility;
|
||||||
|
@ -1,21 +1,41 @@
|
|||||||
//! Types for the *m.room.encrypted* event.
|
//! Types for the *m.room.encrypted* event.
|
||||||
|
|
||||||
|
use std::{convert::TryFrom, str::FromStr};
|
||||||
|
|
||||||
use js_int::UInt;
|
use js_int::UInt;
|
||||||
use ruma_identifiers::DeviceId;
|
use ruma_identifiers::{DeviceId, EventId, RoomId, UserId};
|
||||||
use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
|
use serde::{de::Error, ser::SerializeStruct, Deserialize, Deserializer, Serialize, Serializer};
|
||||||
use serde_json::{from_value, Value};
|
use serde_json::{from_value, Value};
|
||||||
|
|
||||||
use crate::Algorithm;
|
use crate::{Algorithm, Event, EventType, InvalidEvent, RoomEvent, StateEvent};
|
||||||
|
|
||||||
room_event! {
|
/// This event type is used when sending encrypted events.
|
||||||
/// This event type is used when sending encrypted events.
|
///
|
||||||
///
|
/// This type is to be used within a room. For a to-device event, use `EncryptedEventContent`
|
||||||
/// This type is to be used within a room. For a to-device event, use `EncryptedEventContent`
|
/// directly.
|
||||||
/// directly.
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct EncryptedEvent(EncryptedEventContent) {}
|
pub struct EncryptedEvent {
|
||||||
|
/// The event's content.
|
||||||
|
pub content: EncryptedEventContent,
|
||||||
|
|
||||||
|
/// The unique identifier for the event.
|
||||||
|
pub event_id: EventId,
|
||||||
|
|
||||||
|
/// Timestamp (milliseconds since the UNIX epoch) on originating homeserver when this
|
||||||
|
/// event was sent.
|
||||||
|
pub origin_server_ts: UInt,
|
||||||
|
|
||||||
|
/// The unique identifier for the room associated with this event.
|
||||||
|
pub room_id: Option<RoomId>,
|
||||||
|
|
||||||
|
/// The unique identifier for the user who sent this event.
|
||||||
|
pub sender: UserId,
|
||||||
|
|
||||||
|
/// Additional key-value pairs not signed by the homeserver.
|
||||||
|
pub unsigned: Option<Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The payload of an *m.room.encrypted* event.
|
/// The payload for `EncryptedEvent`.
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum EncryptedEventContent {
|
pub enum EncryptedEventContent {
|
||||||
/// An event encrypted with *m.olm.v1.curve25519-aes-sha2*.
|
/// An event encrypted with *m.olm.v1.curve25519-aes-sha2*.
|
||||||
@ -30,7 +50,224 @@ pub enum EncryptedEventContent {
|
|||||||
__Nonexhaustive,
|
__Nonexhaustive,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The payload of an *m.room.encrypted* event using the *m.olm.v1.curve25519-aes-sha2* algorithm.
|
impl FromStr for EncryptedEvent {
|
||||||
|
type Err = InvalidEvent;
|
||||||
|
|
||||||
|
/// Attempt to create `Self` from parsing a string of JSON data.
|
||||||
|
fn from_str(json: &str) -> Result<Self, Self::Err> {
|
||||||
|
let raw = serde_json::from_str::<raw::EncryptedEvent>(json)?;
|
||||||
|
|
||||||
|
let content = match raw.content {
|
||||||
|
raw::EncryptedEventContent::OlmV1Curve25519AesSha2(content) => {
|
||||||
|
EncryptedEventContent::OlmV1Curve25519AesSha2(content)
|
||||||
|
}
|
||||||
|
raw::EncryptedEventContent::MegolmV1AesSha2(content) => {
|
||||||
|
EncryptedEventContent::MegolmV1AesSha2(content)
|
||||||
|
}
|
||||||
|
raw::EncryptedEventContent::__Nonexhaustive => {
|
||||||
|
panic!("__Nonexhaustive enum variant is not intended for use.");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
content: content,
|
||||||
|
event_id: raw.event_id,
|
||||||
|
origin_server_ts: raw.origin_server_ts,
|
||||||
|
room_id: raw.room_id,
|
||||||
|
sender: raw.sender,
|
||||||
|
unsigned: raw.unsigned,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> TryFrom<&'a str> for EncryptedEvent {
|
||||||
|
type Error = InvalidEvent;
|
||||||
|
|
||||||
|
/// Attempt to create `Self` from parsing a string of JSON data.
|
||||||
|
fn try_from(json: &'a str) -> Result<Self, Self::Error> {
|
||||||
|
FromStr::from_str(json)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serialize for EncryptedEvent {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
let mut len = 6;
|
||||||
|
|
||||||
|
if self.room_id.is_some() {
|
||||||
|
len += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.unsigned.is_some() {
|
||||||
|
len += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut state = serializer.serialize_struct("EncryptedEvent", len)?;
|
||||||
|
|
||||||
|
state.serialize_field("content", &self.content)?;
|
||||||
|
state.serialize_field("event_id", &self.event_id)?;
|
||||||
|
state.serialize_field("origin_server_ts", &self.origin_server_ts)?;
|
||||||
|
|
||||||
|
if self.room_id.is_some() {
|
||||||
|
state.serialize_field("room_id", &self.room_id)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.unsigned.is_some() {
|
||||||
|
state.serialize_field("unsigned", &self.unsigned)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.serialize_field("sender", &self.sender)?;
|
||||||
|
state.serialize_field("type", &self.event_type())?;
|
||||||
|
|
||||||
|
state.end()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_room_event!(
|
||||||
|
EncryptedEvent,
|
||||||
|
EncryptedEventContent,
|
||||||
|
EventType::RoomEncrypted
|
||||||
|
);
|
||||||
|
|
||||||
|
impl FromStr for EncryptedEventContent {
|
||||||
|
type Err = InvalidEvent;
|
||||||
|
|
||||||
|
/// Attempt to create `Self` from parsing a string of JSON data.
|
||||||
|
fn from_str(json: &str) -> Result<Self, Self::Err> {
|
||||||
|
let raw = serde_json::from_str::<raw::EncryptedEventContent>(json)?;
|
||||||
|
|
||||||
|
match raw {
|
||||||
|
raw::EncryptedEventContent::OlmV1Curve25519AesSha2(content) => {
|
||||||
|
Ok(EncryptedEventContent::OlmV1Curve25519AesSha2(content))
|
||||||
|
}
|
||||||
|
raw::EncryptedEventContent::MegolmV1AesSha2(content) => {
|
||||||
|
Ok(EncryptedEventContent::MegolmV1AesSha2(content))
|
||||||
|
}
|
||||||
|
raw::EncryptedEventContent::__Nonexhaustive => {
|
||||||
|
panic!("__Nonexhaustive enum variant is not intended for use.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> TryFrom<&'a str> for EncryptedEventContent {
|
||||||
|
type Error = InvalidEvent;
|
||||||
|
|
||||||
|
/// Attempt to create `Self` from parsing a string of JSON data.
|
||||||
|
fn try_from(json: &'a str) -> Result<Self, Self::Error> {
|
||||||
|
FromStr::from_str(json)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod raw {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
/// This event type is used when sending encrypted events.
|
||||||
|
///
|
||||||
|
/// This type is to be used within a room. For a to-device event, use `EncryptedEventContent`
|
||||||
|
/// directly.
|
||||||
|
#[derive(Clone, Debug, Deserialize, PartialEq)]
|
||||||
|
pub struct EncryptedEvent {
|
||||||
|
/// The event's content.
|
||||||
|
pub content: EncryptedEventContent,
|
||||||
|
|
||||||
|
/// The unique identifier for the event.
|
||||||
|
pub event_id: EventId,
|
||||||
|
|
||||||
|
/// Timestamp (milliseconds since the UNIX epoch) on originating homeserver when this
|
||||||
|
/// event was sent.
|
||||||
|
pub origin_server_ts: UInt,
|
||||||
|
|
||||||
|
/// The unique identifier for the room associated with this event.
|
||||||
|
pub room_id: Option<RoomId>,
|
||||||
|
|
||||||
|
/// The unique identifier for the user who sent this event.
|
||||||
|
pub sender: UserId,
|
||||||
|
|
||||||
|
/// Additional key-value pairs not signed by the homeserver.
|
||||||
|
pub unsigned: Option<Value>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The payload for `EncryptedEvent`.
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub enum EncryptedEventContent {
|
||||||
|
/// An event encrypted with *m.olm.v1.curve25519-aes-sha2*.
|
||||||
|
OlmV1Curve25519AesSha2(OlmV1Curve25519AesSha2Content),
|
||||||
|
|
||||||
|
/// An event encrypted with *m.megolm.v1.aes-sha2*.
|
||||||
|
MegolmV1AesSha2(MegolmV1AesSha2Content),
|
||||||
|
|
||||||
|
/// Additional variants may be added in the future and will not be considered breaking
|
||||||
|
/// changes to ruma-events.
|
||||||
|
#[doc(hidden)]
|
||||||
|
__Nonexhaustive,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serialize for EncryptedEventContent {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
match *self {
|
||||||
|
EncryptedEventContent::OlmV1Curve25519AesSha2(ref content) => {
|
||||||
|
content.serialize(serializer)
|
||||||
|
}
|
||||||
|
EncryptedEventContent::MegolmV1AesSha2(ref content) => {
|
||||||
|
content.serialize(serializer)
|
||||||
|
}
|
||||||
|
_ => panic!("Attempted to serialize __Nonexhaustive variant."),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for EncryptedEventContent {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let value: Value = Deserialize::deserialize(deserializer)?;
|
||||||
|
|
||||||
|
let method_value = match value.get("algorithm") {
|
||||||
|
Some(value) => value.clone(),
|
||||||
|
None => return Err(D::Error::missing_field("algorithm")),
|
||||||
|
};
|
||||||
|
|
||||||
|
let method = match from_value::<Algorithm>(method_value.clone()) {
|
||||||
|
Ok(method) => method,
|
||||||
|
Err(error) => return Err(D::Error::custom(error.to_string())),
|
||||||
|
};
|
||||||
|
|
||||||
|
match method {
|
||||||
|
Algorithm::OlmV1Curve25519AesSha2 => {
|
||||||
|
let content = match from_value::<OlmV1Curve25519AesSha2Content>(value) {
|
||||||
|
Ok(content) => content,
|
||||||
|
Err(error) => return Err(D::Error::custom(error.to_string())),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(EncryptedEventContent::OlmV1Curve25519AesSha2(content))
|
||||||
|
}
|
||||||
|
Algorithm::MegolmV1AesSha2 => {
|
||||||
|
let content = match from_value::<MegolmV1AesSha2Content>(value) {
|
||||||
|
Ok(content) => content,
|
||||||
|
Err(error) => return Err(D::Error::custom(error.to_string())),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(EncryptedEventContent::MegolmV1AesSha2(content))
|
||||||
|
}
|
||||||
|
Algorithm::Custom(_) => Err(D::Error::custom(
|
||||||
|
"Custom algorithms are not supported by `EncryptedEventContent`.",
|
||||||
|
)),
|
||||||
|
Algorithm::__Nonexhaustive => Err(D::Error::custom(
|
||||||
|
"Attempted to deserialize __Nonexhaustive variant.",
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The payload for `EncryptedEvent` using the *m.olm.v1.curve25519-aes-sha2* algorithm.
|
||||||
#[derive(Clone, Debug, Serialize, PartialEq, Deserialize)]
|
#[derive(Clone, Debug, Serialize, PartialEq, Deserialize)]
|
||||||
pub struct OlmV1Curve25519AesSha2Content {
|
pub struct OlmV1Curve25519AesSha2Content {
|
||||||
/// The encryption algorithm used to encrypt this event.
|
/// The encryption algorithm used to encrypt this event.
|
||||||
@ -56,7 +293,7 @@ pub struct CiphertextInfo {
|
|||||||
pub message_type: UInt,
|
pub message_type: UInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The payload of an *m.room.encrypted* event using the *m.megolm.v1.aes-sha2* algorithm.
|
/// The payload for `EncryptedEvent` using the *m.megolm.v1.aes-sha2* algorithm.
|
||||||
#[derive(Clone, Debug, Serialize, PartialEq, Deserialize)]
|
#[derive(Clone, Debug, Serialize, PartialEq, Deserialize)]
|
||||||
pub struct MegolmV1AesSha2Content {
|
pub struct MegolmV1AesSha2Content {
|
||||||
/// The encryption algorithm used to encrypt this event.
|
/// The encryption algorithm used to encrypt this event.
|
||||||
@ -90,52 +327,9 @@ impl Serialize for EncryptedEventContent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for EncryptedEventContent {
|
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
let value: Value = Deserialize::deserialize(deserializer)?;
|
|
||||||
|
|
||||||
let method_value = match value.get("algorithm") {
|
|
||||||
Some(value) => value.clone(),
|
|
||||||
None => return Err(D::Error::missing_field("algorithm")),
|
|
||||||
};
|
|
||||||
|
|
||||||
let method = match from_value::<Algorithm>(method_value.clone()) {
|
|
||||||
Ok(method) => method,
|
|
||||||
Err(error) => return Err(D::Error::custom(error.to_string())),
|
|
||||||
};
|
|
||||||
|
|
||||||
match method {
|
|
||||||
Algorithm::OlmV1Curve25519AesSha2 => {
|
|
||||||
let content = match from_value::<OlmV1Curve25519AesSha2Content>(value) {
|
|
||||||
Ok(content) => content,
|
|
||||||
Err(error) => return Err(D::Error::custom(error.to_string())),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(EncryptedEventContent::OlmV1Curve25519AesSha2(content))
|
|
||||||
}
|
|
||||||
Algorithm::MegolmV1AesSha2 => {
|
|
||||||
let content = match from_value::<MegolmV1AesSha2Content>(value) {
|
|
||||||
Ok(content) => content,
|
|
||||||
Err(error) => return Err(D::Error::custom(error.to_string())),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(EncryptedEventContent::MegolmV1AesSha2(content))
|
|
||||||
}
|
|
||||||
Algorithm::Custom(_) => Err(D::Error::custom(
|
|
||||||
"Custom algorithms are not supported by `EncryptedEventContent`.",
|
|
||||||
)),
|
|
||||||
Algorithm::__Nonexhaustive => Err(D::Error::custom(
|
|
||||||
"Attempted to deserialize __Nonexhaustive variant.",
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use serde_json::{from_str, to_string};
|
use serde_json::to_string;
|
||||||
|
|
||||||
use super::{Algorithm, EncryptedEventContent, MegolmV1AesSha2Content};
|
use super::{Algorithm, EncryptedEventContent, MegolmV1AesSha2Content};
|
||||||
|
|
||||||
@ -168,9 +362,8 @@ mod tests {
|
|||||||
});
|
});
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
from_str::<EncryptedEventContent>(
|
r#"{"algorithm":"m.megolm.v1.aes-sha2","ciphertext":"ciphertext","sender_key":"sender_key","device_id":"device_id","session_id":"session_id"}"#
|
||||||
r#"{"algorithm":"m.megolm.v1.aes-sha2","ciphertext":"ciphertext","sender_key":"sender_key","device_id":"device_id","session_id":"session_id"}"#
|
.parse::<EncryptedEventContent>()
|
||||||
)
|
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
key_verification_start_content
|
key_verification_start_content
|
||||||
);
|
);
|
||||||
@ -179,7 +372,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn deserialization_failure() {
|
fn deserialization_failure() {
|
||||||
assert!(
|
assert!(
|
||||||
from_str::<EncryptedEventContent>(r#"{"algorithm":"m.megolm.v1.aes-sha2"}"#).is_err()
|
r#"{"algorithm":"m.megolm.v1.aes-sha2"}"#.parse::<EncryptedEventContent>().is_err()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user