Skip to main content

tuwunel_core/matrix/pdu/
unsigned.rs

1use std::collections::BTreeMap;
2
3use ruma::{MilliSecondsSinceUnixEpoch, events::room::member::MembershipState, serde::Raw};
4use serde::Serialize;
5use serde_json::value::{RawValue as RawJsonValue, Value as JsonValue, to_raw_value};
6
7use super::Pdu;
8use crate::{Result, err, implement};
9
10#[implement(Pdu)]
11pub fn remove_transaction_id(&mut self) -> Result {
12	use BTreeMap as Map;
13
14	let Some(unsigned) = &self.unsigned else {
15		return Ok(());
16	};
17
18	let mut unsigned: Map<&str, Raw<JsonValue>> = serde_json::from_str(unsigned.get())
19		.map_err(|e| err!(Database("Invalid unsigned in pdu event: {e}")))?;
20
21	unsigned.remove("transaction_id");
22	self.unsigned = to_raw_value(&unsigned)
23		.map(Some)
24		.expect("unsigned is valid");
25
26	Ok(())
27}
28
29#[implement(Pdu)]
30pub fn add_age(&mut self) -> Result {
31	use BTreeMap as Map;
32
33	let mut unsigned: Map<&str, Raw<JsonValue>> = self
34		.unsigned
35		.as_deref()
36		.map(RawJsonValue::get)
37		.map_or_else(|| Ok(Map::new()), serde_json::from_str)
38		.map_err(|e| err!(Database("Invalid unsigned in pdu event: {e}")))?;
39
40	// deliberately allowing for the possibility of negative age
41	let now: i128 = MilliSecondsSinceUnixEpoch::now().get().into();
42	let then: i128 = self.origin_server_ts.into();
43	let this_age = now.saturating_sub(then);
44
45	unsigned.insert("age", raw_of(&this_age)?);
46	self.unsigned = Some(to_raw_value(&unsigned)?);
47
48	Ok(())
49}
50
51/// MSC4115: annotate the served event with the requesting user's room
52/// membership at the time of the event.
53#[implement(Pdu)]
54pub fn add_membership(&mut self, membership: &MembershipState) -> Result {
55	use BTreeMap as Map;
56
57	let mut unsigned: Map<&str, Raw<JsonValue>> = self
58		.unsigned
59		.as_deref()
60		.map(RawJsonValue::get)
61		.map_or_else(|| Ok(Map::new()), serde_json::from_str)
62		.map_err(|e| err!(Database("Invalid unsigned in pdu event: {e}")))?;
63
64	unsigned.insert("membership", raw_of(membership)?);
65	self.unsigned = Some(to_raw_value(&unsigned)?);
66
67	Ok(())
68}
69
70#[implement(Pdu)]
71pub fn add_relation(&mut self, name: &str, pdu: Option<&Pdu>) -> Result {
72	use serde_json::Map;
73
74	let mut unsigned: Map<String, JsonValue> = self
75		.unsigned
76		.as_deref()
77		.map(RawJsonValue::get)
78		.map_or_else(|| Ok(Map::new()), serde_json::from_str)
79		.map_err(|e| err!(Database("Invalid unsigned in pdu event: {e}")))?;
80
81	let pdu = pdu
82		.map(serde_json::to_value)
83		.transpose()?
84		.unwrap_or_else(|| JsonValue::Object(Map::new()));
85
86	unsigned
87		.entry("m.relations")
88		.or_insert(JsonValue::Object(Map::new()))
89		.as_object_mut()
90		.map(|object| object.insert(name.to_owned(), pdu));
91
92	self.unsigned = Some(to_raw_value(&unsigned)?);
93
94	Ok(())
95}
96
97#[inline]
98fn raw_of<T: Serialize>(value: &T) -> Result<Raw<JsonValue>> {
99	Ok(Raw::from_raw_value(&to_raw_value(value)?))
100}