Skip to main content

tuwunel_service/rooms/state_res/events/
create.rs

1//! Types to deserialize `m.room.create` events.
2
3use std::{borrow::Cow, iter, ops::Deref};
4
5use ruma::{
6	OwnedUserId, RoomVersionId, UserId, room_version_rules::AuthorizationRules,
7	serde::from_raw_json_value,
8};
9use serde::{Deserialize, de::IgnoredAny};
10use tuwunel_core::{Error, Result, err, matrix::Event};
11
12/// A helper type for an [`Event`] of type `m.room.create`.
13///
14/// This is a type that deserializes each field lazily, when requested.
15#[derive(Debug)]
16pub struct RoomCreateEvent<E: Event>(E);
17
18impl<E: Event> RoomCreateEvent<E> {
19	/// Construct a new `RoomCreateEvent` around the given event.
20	#[inline]
21	pub fn new(event: E) -> Self { Self(event) }
22
23	/// The version of the room.
24	pub fn room_version(&self) -> Result<RoomVersionId> {
25		#[derive(Deserialize)]
26		struct RoomCreateContentRoomVersion {
27			room_version: Option<RoomVersionId>,
28		}
29
30		let content: RoomCreateContentRoomVersion =
31			from_raw_json_value(self.content()).map_err(|err: Error| {
32				err!("invalid `room_version` field in `m.room.create` event: {err}")
33			})?;
34
35		Ok(content.room_version.unwrap_or(RoomVersionId::V1))
36	}
37
38	/// Whether the room is federated.
39	pub fn federate(&self) -> Result<bool> {
40		#[derive(Deserialize)]
41		struct RoomCreateContentFederate {
42			#[serde(rename = "m.federate")]
43			federate: Option<bool>,
44		}
45
46		let content: RoomCreateContentFederate =
47			from_raw_json_value(self.content()).map_err(|err: Error| {
48				err!("invalid `m.federate` field in `m.room.create` event: {err}")
49			})?;
50
51		Ok(content.federate.unwrap_or(true))
52	}
53
54	/// The creator of the room.
55	///
56	/// If the `use_room_create_sender` field of `AuthorizationRules` is set,
57	/// the creator is the sender of this `m.room.create` event, otherwise it
58	/// is deserialized from the `creator` field of this event's content.
59	pub fn creator(&self, rules: &AuthorizationRules) -> Result<Cow<'_, UserId>> {
60		#[derive(Deserialize)]
61		struct RoomCreateContentCreator {
62			creator: OwnedUserId,
63		}
64
65		if rules.use_room_create_sender {
66			Ok(Cow::Borrowed(self.sender()))
67		} else {
68			let content: RoomCreateContentCreator =
69				from_raw_json_value(self.content()).map_err(|err: Error| {
70					err!("missing or invalid `creator` field in `m.room.create` event: {err}")
71				})?;
72
73			Ok(Cow::Owned(content.creator))
74		}
75	}
76
77	/// The creators of the room.
78	///
79	/// If the `use_room_create_sender` field of `AuthorizationRules` is set,
80	/// the creator is the sender of this `m.room.create` event, otherwise it
81	/// is deserialized from the `creator` field of this event's content.
82	/// Additionally if the `explicitly_privilege_room_creators`
83	/// field of `AuthorizationRules` is set, any additional user IDs in
84	/// `additional_creators`, if present, will also be considered creators.
85	pub fn creators<'a>(
86		&'a self,
87		rules: &'a AuthorizationRules,
88	) -> Result<impl Iterator<Item = OwnedUserId> + Clone + use<'a, E>> {
89		let initial = self.creator(rules)?.into_owned();
90		let additional = self.additional_creators(rules)?;
91
92		Ok(iter::once(initial).chain(additional))
93	}
94
95	/// The additional creators of the room (if any).
96	///
97	/// If the `explicitly_privilege_room_creators`
98	/// field of `AuthorizationRules` is set, any additional user IDs in
99	/// `additional_creators`, if present, will also be considered creators.
100	///
101	/// This function ignores the primary room creator, and should only be used
102	/// in `check_room_member_join`. Otherwise, you should use `creators`
103	/// instead.
104	pub(super) fn additional_creators(
105		&self,
106		rules: &AuthorizationRules,
107	) -> Result<impl Iterator<Item = OwnedUserId> + Clone> {
108		#[derive(Deserialize)]
109		struct RoomCreateContentAdditionalCreators {
110			#[serde(default)]
111			additional_creators: Vec<OwnedUserId>,
112		}
113
114		Ok(if rules.additional_room_creators {
115			let mut content: RoomCreateContentAdditionalCreators =
116				from_raw_json_value(self.content()).map_err(|err: serde_json::Error| {
117					err!("invalid `additional_creators` field in `m.room.create` event: {err}")
118				})?;
119
120			content.additional_creators.sort();
121			content.additional_creators.dedup();
122			content.additional_creators.into_iter()
123		} else {
124			Vec::new().into_iter()
125		})
126	}
127
128	/// Whether the event has a `creator` field.
129	pub fn has_creator(&self) -> Result<bool> {
130		#[derive(Deserialize)]
131		struct RoomCreateContentCreator {
132			creator: Option<IgnoredAny>,
133		}
134
135		let content: RoomCreateContentCreator =
136			from_raw_json_value(self.content()).map_err(|err: Error| {
137				err!("invalid `creator` field in `m.room.create` event: {err}")
138			})?;
139
140		Ok(content.creator.is_some())
141	}
142}
143
144impl<E: Event> Deref for RoomCreateEvent<E> {
145	type Target = E;
146
147	#[inline]
148	fn deref(&self) -> &Self::Target { &self.0 }
149}