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