ruma_events/room/
join_rules.rs

1//! Types for the [`m.room.join_rules`] event.
2//!
3//! [`m.room.join_rules`]: https://spec.matrix.org/latest/client-server-api/#mroomjoin_rules
4
5pub use ruma_common::room::{AllowRule, JoinRule, Restricted};
6use ruma_macros::EventContent;
7use serde::{de, Deserialize, Serialize};
8
9use crate::EmptyStateKey;
10
11/// The content of an `m.room.join_rules` event.
12///
13/// Describes how users are allowed to join the room.
14#[derive(Clone, Debug, Serialize, EventContent)]
15#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
16#[ruma_event(type = "m.room.join_rules", kind = State, state_key_type = EmptyStateKey)]
17pub struct RoomJoinRulesEventContent {
18    /// The type of rules used for users wishing to join this room.
19    #[ruma_event(skip_redaction)]
20    #[serde(flatten)]
21    pub join_rule: JoinRule,
22}
23
24impl RoomJoinRulesEventContent {
25    /// Creates a new `RoomJoinRulesEventContent` with the given rule.
26    pub fn new(join_rule: JoinRule) -> Self {
27        Self { join_rule }
28    }
29
30    /// Creates a new `RoomJoinRulesEventContent` with the restricted rule and the given set of
31    /// allow rules.
32    pub fn restricted(allow: Vec<AllowRule>) -> Self {
33        Self { join_rule: JoinRule::Restricted(Restricted::new(allow)) }
34    }
35
36    /// Creates a new `RoomJoinRulesEventContent` with the knock restricted rule and the given set
37    /// of allow rules.
38    pub fn knock_restricted(allow: Vec<AllowRule>) -> Self {
39        Self { join_rule: JoinRule::KnockRestricted(Restricted::new(allow)) }
40    }
41}
42
43impl<'de> Deserialize<'de> for RoomJoinRulesEventContent {
44    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
45    where
46        D: de::Deserializer<'de>,
47    {
48        let join_rule = JoinRule::deserialize(deserializer)?;
49        Ok(RoomJoinRulesEventContent { join_rule })
50    }
51}
52
53impl RoomJoinRulesEvent {
54    /// Obtain the join rule, regardless of whether this event is redacted.
55    pub fn join_rule(&self) -> &JoinRule {
56        match self {
57            Self::Original(ev) => &ev.content.join_rule,
58            Self::Redacted(ev) => &ev.content.join_rule,
59        }
60    }
61}
62
63impl SyncRoomJoinRulesEvent {
64    /// Obtain the join rule, regardless of whether this event is redacted.
65    pub fn join_rule(&self) -> &JoinRule {
66        match self {
67            Self::Original(ev) => &ev.content.join_rule,
68            Self::Redacted(ev) => &ev.content.join_rule,
69        }
70    }
71}
72
73#[cfg(test)]
74mod tests {
75    use assert_matches2::assert_matches;
76    use ruma_common::owned_room_id;
77
78    use super::{AllowRule, JoinRule, OriginalSyncRoomJoinRulesEvent, RoomJoinRulesEventContent};
79
80    #[test]
81    fn deserialize() {
82        let json = r#"{"join_rule": "public"}"#;
83        let event: RoomJoinRulesEventContent = serde_json::from_str(json).unwrap();
84        assert_matches!(event, RoomJoinRulesEventContent { join_rule: JoinRule::Public });
85    }
86
87    #[test]
88    fn deserialize_restricted() {
89        let json = r#"{
90            "join_rule": "restricted",
91            "allow": [
92                {
93                    "type": "m.room_membership",
94                    "room_id": "!mods:example.org"
95                },
96                {
97                    "type": "m.room_membership",
98                    "room_id": "!users:example.org"
99                }
100            ]
101        }"#;
102        let event: RoomJoinRulesEventContent = serde_json::from_str(json).unwrap();
103        assert_matches!(event.join_rule, JoinRule::Restricted(restricted));
104        assert_eq!(
105            restricted.allow,
106            &[
107                AllowRule::room_membership(owned_room_id!("!mods:example.org")),
108                AllowRule::room_membership(owned_room_id!("!users:example.org"))
109            ]
110        );
111    }
112
113    #[test]
114    fn deserialize_restricted_event() {
115        let json = r#"{
116            "type": "m.room.join_rules",
117            "sender": "@admin:community.rs",
118            "content": {
119                "join_rule": "restricted",
120                "allow": [
121                    { "type": "m.room_membership","room_id": "!KqeUnzmXPIhHRaWMTs:mccarty.io" }
122                ]
123            },
124            "state_key": "",
125            "origin_server_ts":1630508835342,
126            "unsigned": {
127                "age":4165521871
128            },
129            "event_id": "$0ACb9KSPlT3al3kikyRYvFhMqXPP9ZcQOBrsdIuh58U"
130        }"#;
131
132        assert_matches!(serde_json::from_str::<OriginalSyncRoomJoinRulesEvent>(json), Ok(_));
133    }
134
135    #[test]
136    fn restricted_room_no_allow_field() {
137        let json = r#"{"join_rule":"restricted"}"#;
138        let join_rules: RoomJoinRulesEventContent = serde_json::from_str(json).unwrap();
139        assert_matches!(
140            join_rules,
141            RoomJoinRulesEventContent { join_rule: JoinRule::Restricted(_) }
142        );
143    }
144}