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 canonical_alias;
|
||||
pub mod create;
|
||||
// pub mod encrypted;
|
||||
pub mod encrypted;
|
||||
pub mod encryption;
|
||||
pub mod guest_access;
|
||||
pub mod history_visibility;
|
||||
|
@ -1,21 +1,41 @@
|
||||
//! Types for the *m.room.encrypted* event.
|
||||
|
||||
use std::{convert::TryFrom, str::FromStr};
|
||||
|
||||
use js_int::UInt;
|
||||
use ruma_identifiers::DeviceId;
|
||||
use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
|
||||
use ruma_identifiers::{DeviceId, EventId, RoomId, UserId};
|
||||
use serde::{de::Error, ser::SerializeStruct, Deserialize, Deserializer, Serialize, Serializer};
|
||||
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 type is to be used within a room. For a to-device event, use `EncryptedEventContent`
|
||||
/// directly.
|
||||
pub struct EncryptedEvent(EncryptedEventContent) {}
|
||||
/// 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, 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 of an *m.room.encrypted* event.
|
||||
/// The payload for `EncryptedEvent`.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum EncryptedEventContent {
|
||||
/// An event encrypted with *m.olm.v1.curve25519-aes-sha2*.
|
||||
@ -30,7 +50,224 @@ pub enum EncryptedEventContent {
|
||||
__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)]
|
||||
pub struct OlmV1Curve25519AesSha2Content {
|
||||
/// The encryption algorithm used to encrypt this event.
|
||||
@ -56,7 +293,7 @@ pub struct CiphertextInfo {
|
||||
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)]
|
||||
pub struct MegolmV1AesSha2Content {
|
||||
/// 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)]
|
||||
mod tests {
|
||||
use serde_json::{from_str, to_string};
|
||||
use serde_json::to_string;
|
||||
|
||||
use super::{Algorithm, EncryptedEventContent, MegolmV1AesSha2Content};
|
||||
|
||||
@ -168,9 +362,8 @@ mod tests {
|
||||
});
|
||||
|
||||
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(),
|
||||
key_verification_start_content
|
||||
);
|
||||
@ -179,7 +372,7 @@ mod tests {
|
||||
#[test]
|
||||
fn deserialization_failure() {
|
||||
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