Skip to main content

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