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