ruma_events/room/encrypted/
unstable_state.rs1use ruma_common::room_version_rules::RedactionRules;
5use ruma_macros::EventContent;
6use serde::{Deserialize, Serialize};
7
8use crate::{
9 PossiblyRedactedStateEventContent, RedactContent, StateEventType, StaticEventContent,
10 room::encrypted::EncryptedEventScheme,
11};
12
13#[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
15#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
16#[ruma_event(type = "m.room.encrypted", kind = State, state_key_type = String, custom_possibly_redacted)]
17pub struct StateRoomEncryptedEventContent {
18 #[serde(flatten)]
20 pub scheme: EncryptedEventScheme,
21}
22
23#[derive(Clone, Debug, Default, Serialize, Deserialize)]
25#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
26pub struct PossiblyRedactedStateRoomEncryptedEventContent {
27 #[serde(flatten, skip_serializing_if = "Option::is_none")]
29 pub scheme: Option<EncryptedEventScheme>,
30}
31
32impl StaticEventContent for PossiblyRedactedStateRoomEncryptedEventContent {
33 const TYPE: &'static str = StateRoomEncryptedEventContent::TYPE;
34 type IsPrefix = <StateRoomEncryptedEventContent as StaticEventContent>::IsPrefix;
35}
36
37impl PossiblyRedactedStateEventContent for PossiblyRedactedStateRoomEncryptedEventContent {
38 type StateKey = String;
39
40 fn event_type(&self) -> StateEventType {
41 StateEventType::RoomEncrypted
42 }
43}
44
45impl RedactContent for PossiblyRedactedStateRoomEncryptedEventContent {
46 type Redacted = Self;
47
48 fn redact(self, _rules: &RedactionRules) -> Self::Redacted {
49 Self { scheme: None }
50 }
51}
52
53impl From<StateRoomEncryptedEventContent> for PossiblyRedactedStateRoomEncryptedEventContent {
54 fn from(value: StateRoomEncryptedEventContent) -> Self {
55 let StateRoomEncryptedEventContent { scheme } = value;
56 Self { scheme: Some(scheme) }
57 }
58}
59
60impl From<RedactedStateRoomEncryptedEventContent>
61 for PossiblyRedactedStateRoomEncryptedEventContent
62{
63 fn from(_value: RedactedStateRoomEncryptedEventContent) -> Self {
64 Self { scheme: None }
65 }
66}
67
68#[cfg(test)]
69mod tests {
70
71 use assert_matches2::assert_matches;
72 use js_int::uint;
73 use ruma_common::{
74 MilliSecondsSinceUnixEpoch, canonical_json::assert_to_canonical_json_eq, room_id, user_id,
75 };
76 use serde_json::{from_value as from_json_value, json};
77
78 use crate::{
79 AnyStateEvent, StateEvent,
80 room::encrypted::{
81 EncryptedEventScheme, MegolmV1AesSha2ContentInit,
82 unstable_state::StateRoomEncryptedEventContent,
83 },
84 };
85
86 #[test]
87 fn serialize_content() {
88 let key_verification_start_content = StateRoomEncryptedEventContent {
89 scheme: EncryptedEventScheme::MegolmV1AesSha2(
90 MegolmV1AesSha2ContentInit {
91 ciphertext: "ciphertext".into(),
92 sender_key: "sender_key".into(),
93 device_id: "device_id".into(),
94 session_id: "session_id".into(),
95 }
96 .into(),
97 ),
98 };
99
100 assert_to_canonical_json_eq!(
101 key_verification_start_content,
102 json!({
103 "algorithm": "m.megolm.v1.aes-sha2",
104 "ciphertext": "ciphertext",
105 "sender_key": "sender_key",
106 "device_id": "device_id",
107 "session_id": "session_id",
108 }),
109 );
110 }
111
112 #[test]
113 #[allow(deprecated)]
114 fn deserialize_content() {
115 let json_data = json!({
116 "algorithm": "m.megolm.v1.aes-sha2",
117 "ciphertext": "ciphertext",
118 "session_id": "session_id",
119 });
120
121 let content: StateRoomEncryptedEventContent = from_json_value(json_data).unwrap();
122
123 assert_matches!(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
130 #[test]
131 #[allow(deprecated)]
132 fn deserialize_event() {
133 let json_data = json!({
134 "type": "m.room.encrypted",
135 "event_id": "$event_id:example.com",
136 "room_id": "!roomid:example.com",
137 "sender": "@example:example.com",
138 "origin_server_ts": 1_234_567_890,
139 "state_key": "",
140 "content": {
141 "algorithm": "m.megolm.v1.aes-sha2",
142 "ciphertext": "ciphertext",
143 "session_id": "session_id",
144 }
145 });
146 let event = from_json_value::<AnyStateEvent>(json_data).unwrap();
147
148 assert_matches!(event, AnyStateEvent::RoomEncrypted(StateEvent::Original(ev)));
149
150 assert_matches!(ev.content.scheme, EncryptedEventScheme::MegolmV1AesSha2(scheme));
151 assert_eq!(scheme.ciphertext, "ciphertext");
152 assert_eq!(scheme.sender_key, None);
153 assert_eq!(scheme.device_id, None);
154 assert_eq!(scheme.session_id, "session_id");
155
156 assert_eq!(ev.sender, user_id!("@example:example.com"));
157 assert_eq!(ev.room_id, room_id!("!roomid:example.com"));
158 assert_eq!(ev.origin_server_ts, MilliSecondsSinceUnixEpoch(uint!(1_234_567_890)));
159 assert_eq!(ev.state_key, "");
160 }
161}