ruma_events/room/encrypted/
unstable_state.rs

1//! Types for `m.room.encrypted` state events, as defined in [MSC3414][msc].
2//!
3//! [msc]: https://github.com/matrix-org/matrix-spec-proposals/pull/3414
4use ruma_macros::EventContent;
5use serde::{Deserialize, Serialize};
6
7use crate::{
8    room::encrypted::EncryptedEventScheme, PossiblyRedactedStateEventContent, StateEventType,
9    StaticEventContent,
10};
11
12/// The content of an `m.room.encrypted` state event.
13#[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
14#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
15#[ruma_event(type = "m.room.encrypted", kind = State, state_key_type = String, custom_possibly_redacted)]
16pub struct StateRoomEncryptedEventContent {
17    /// Algorithm-specific fields.
18    #[serde(flatten)]
19    pub scheme: EncryptedEventScheme,
20}
21
22/// The possibly redacted form of [`StateRoomEncryptedEventContent`].
23#[derive(Clone, Debug, Default, Serialize, Deserialize)]
24#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
25pub struct PossiblyRedactedStateRoomEncryptedEventContent {
26    /// Algorithm-specific fields.
27    #[serde(flatten, skip_serializing_if = "Option::is_none")]
28    pub scheme: Option<EncryptedEventScheme>,
29}
30
31impl StaticEventContent for PossiblyRedactedStateRoomEncryptedEventContent {
32    const TYPE: &'static str = StateRoomEncryptedEventContent::TYPE;
33    type IsPrefix = <StateRoomEncryptedEventContent as StaticEventContent>::IsPrefix;
34}
35
36impl PossiblyRedactedStateEventContent for PossiblyRedactedStateRoomEncryptedEventContent {
37    type StateKey = String;
38
39    fn event_type(&self) -> StateEventType {
40        StateEventType::RoomEncrypted
41    }
42}
43
44#[cfg(test)]
45mod tests {
46
47    use assert_matches2::assert_matches;
48    use js_int::uint;
49    use ruma_common::{room_id, user_id, MilliSecondsSinceUnixEpoch};
50    use serde_json::{from_value as from_json_value, json, to_value as to_json_value};
51
52    use crate::{
53        room::encrypted::{
54            unstable_state::StateRoomEncryptedEventContent, EncryptedEventScheme,
55            MegolmV1AesSha2ContentInit,
56        },
57        AnyStateEvent, StateEvent,
58    };
59
60    #[test]
61    fn serialize_content() {
62        let key_verification_start_content = StateRoomEncryptedEventContent {
63            scheme: EncryptedEventScheme::MegolmV1AesSha2(
64                MegolmV1AesSha2ContentInit {
65                    ciphertext: "ciphertext".into(),
66                    sender_key: "sender_key".into(),
67                    device_id: "device_id".into(),
68                    session_id: "session_id".into(),
69                }
70                .into(),
71            ),
72        };
73
74        let json_data = json!({
75            "algorithm": "m.megolm.v1.aes-sha2",
76            "ciphertext": "ciphertext",
77            "sender_key": "sender_key",
78            "device_id": "device_id",
79            "session_id": "session_id",
80        });
81
82        assert_eq!(to_json_value(&key_verification_start_content).unwrap(), json_data);
83    }
84
85    #[test]
86    #[allow(deprecated)]
87    fn deserialize_content() {
88        let json_data = json!({
89            "algorithm": "m.megolm.v1.aes-sha2",
90            "ciphertext": "ciphertext",
91            "session_id": "session_id",
92        });
93
94        let content: StateRoomEncryptedEventContent = from_json_value(json_data).unwrap();
95
96        assert_matches!(content.scheme, EncryptedEventScheme::MegolmV1AesSha2(scheme));
97        assert_eq!(scheme.ciphertext, "ciphertext");
98        assert_eq!(scheme.sender_key, None);
99        assert_eq!(scheme.device_id, None);
100        assert_eq!(scheme.session_id, "session_id");
101    }
102
103    #[test]
104    #[allow(deprecated)]
105    fn deserialize_event() {
106        let json_data = json!({
107            "type": "m.room.encrypted",
108            "event_id": "$event_id:example.com",
109            "room_id": "!roomid:example.com",
110            "sender": "@example:example.com",
111            "origin_server_ts": 1_234_567_890,
112            "state_key": "",
113            "content": {
114                "algorithm": "m.megolm.v1.aes-sha2",
115                "ciphertext": "ciphertext",
116                "session_id": "session_id",
117            }
118        });
119        let event = from_json_value::<AnyStateEvent>(json_data).unwrap();
120
121        assert_matches!(event, AnyStateEvent::RoomEncrypted(StateEvent::Original(ev)));
122
123        assert_matches!(ev.content.scheme, EncryptedEventScheme::MegolmV1AesSha2(scheme));
124        assert_eq!(scheme.ciphertext, "ciphertext");
125        assert_eq!(scheme.sender_key, None);
126        assert_eq!(scheme.device_id, None);
127        assert_eq!(scheme.session_id, "session_id");
128
129        assert_eq!(ev.sender, user_id!("@example:example.com"));
130        assert_eq!(ev.room_id, room_id!("!roomid:example.com"));
131        assert_eq!(ev.origin_server_ts, MilliSecondsSinceUnixEpoch(uint!(1_234_567_890)));
132        assert_eq!(ev.state_key, "");
133    }
134}