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::canonical_json::assert_to_canonical_json_eq;
74 use serde_json::{from_value as from_json_value, json};
75
76 use crate::{
77 AnyStateEvent, StateEvent,
78 room::encrypted::{
79 EncryptedEventScheme, MegolmV1AesSha2ContentInit,
80 unstable_state::StateRoomEncryptedEventContent,
81 },
82 };
83
84 #[test]
85 fn serialize_content() {
86 let key_verification_start_content = StateRoomEncryptedEventContent {
87 scheme: EncryptedEventScheme::MegolmV1AesSha2(
88 MegolmV1AesSha2ContentInit {
89 ciphertext: "ciphertext".into(),
90 sender_key: "sender_key".into(),
91 device_id: "device_id".into(),
92 session_id: "session_id".into(),
93 }
94 .into(),
95 ),
96 };
97
98 assert_to_canonical_json_eq!(
99 key_verification_start_content,
100 json!({
101 "algorithm": "m.megolm.v1.aes-sha2",
102 "ciphertext": "ciphertext",
103 "sender_key": "sender_key",
104 "device_id": "device_id",
105 "session_id": "session_id",
106 }),
107 );
108 }
109
110 #[test]
111 #[allow(deprecated)]
112 fn deserialize_content() {
113 let json_data = json!({
114 "algorithm": "m.megolm.v1.aes-sha2",
115 "ciphertext": "ciphertext",
116 "session_id": "session_id",
117 });
118
119 let content: StateRoomEncryptedEventContent = from_json_value(json_data).unwrap();
120
121 assert_matches!(content.scheme, EncryptedEventScheme::MegolmV1AesSha2(scheme));
122 assert_eq!(scheme.ciphertext, "ciphertext");
123 assert_eq!(scheme.sender_key, None);
124 assert_eq!(scheme.device_id, None);
125 assert_eq!(scheme.session_id, "session_id");
126 }
127
128 #[test]
129 #[allow(deprecated)]
130 fn deserialize_event() {
131 let json_data = json!({
132 "type": "m.room.encrypted",
133 "event_id": "$event_id:example.com",
134 "room_id": "!roomid:example.com",
135 "sender": "@example:example.com",
136 "origin_server_ts": 1_234_567_890,
137 "state_key": "",
138 "content": {
139 "algorithm": "m.megolm.v1.aes-sha2",
140 "ciphertext": "ciphertext",
141 "session_id": "session_id",
142 }
143 });
144 let event = from_json_value::<AnyStateEvent>(json_data).unwrap();
145
146 assert_matches!(event, AnyStateEvent::RoomEncrypted(StateEvent::Original(ev)));
147
148 assert_matches!(ev.content.scheme, EncryptedEventScheme::MegolmV1AesSha2(scheme));
149 assert_eq!(scheme.ciphertext, "ciphertext");
150 assert_eq!(scheme.sender_key, None);
151 assert_eq!(scheme.device_id, None);
152 assert_eq!(scheme.session_id, "session_id");
153
154 assert_eq!(ev.sender, "@example:example.com");
155 assert_eq!(ev.room_id, "!roomid:example.com");
156 assert_eq!(ev.origin_server_ts.0, uint!(1_234_567_890));
157 assert_eq!(ev.state_key, "");
158 }
159}