Skip to main content

ruma_events/
invite_permission_config.rs

1//! Types for the [`m.invite_permission_config`] account data.
2//!
3//! [`m.invite_permission_config`]: https://spec.matrix.org/v1.19/client-server-api/#minvite_permission_config
4
5use ruma_macros::{EventContent, StringEnum};
6use serde::{Deserialize, Serialize};
7
8use crate::PrivOwnedStr;
9
10/// The content of an [`m.invite_permission_config`] account data.
11///
12/// Controls whether invites to this account are permitted.
13///
14/// [`m.invite_permission_config`]: https://spec.matrix.org/v1.19/client-server-api/#minvite_permission_config
15#[derive(Clone, Debug, Default, Deserialize, Serialize, EventContent)]
16#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
17#[ruma_event(
18    kind = GlobalAccountData,
19    type = "m.invite_permission_config",
20)]
21pub struct InvitePermissionConfigEventContent {
22    /// The default action chosen by the user that the homeserver should perform automatically when
23    /// receiving an invitation for this account.
24    ///
25    /// A missing, invalid or unsupported value means that the user wants to receive invites as
26    /// normal. Other parts of the specification might still have effects on invites, like
27    /// [ignoring users].
28    ///
29    /// [ignoring users]: https://spec.matrix.org/v1.19/client-server-api/#ignoring-users
30    #[serde(
31        default,
32        deserialize_with = "ruma_common::serde::default_on_error",
33        skip_serializing_if = "Option::is_none"
34    )]
35    pub default_action: Option<InvitePermissionAction>,
36}
37
38impl InvitePermissionConfigEventContent {
39    /// Creates a new empty `InvitePermissionConfigEventContent`.
40    pub fn new() -> Self {
41        Self::default()
42    }
43}
44
45/// Possible actions in response to an invite.
46#[doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/doc/string_enum.md"))]
47#[derive(Clone, StringEnum)]
48#[ruma_enum(rename_all = "lowercase")]
49#[non_exhaustive]
50pub enum InvitePermissionAction {
51    /// Reject the invite.
52    Block,
53
54    /// Reject the invite if no non-public rooms are shared between the sender and recipient.
55    #[cfg(feature = "unstable-msc4494")]
56    #[ruma_enum(rename = "uk.timedout.msc4494.deny_public")]
57    DenyPublic,
58
59    #[doc(hidden)]
60    _Custom(PrivOwnedStr),
61}
62
63/// The content of an [`org.matrix.msc4380.invite_permission_config`][MSC4380] account data, the
64/// unstable version of [`InvitePermissionConfigEventContent`].
65///
66/// Controls whether invites to this account are permitted.
67///
68/// [MSC4380]: https://github.com/matrix-org/matrix-spec-proposals/pull/4380
69#[cfg(feature = "unstable-msc4380")]
70#[derive(Clone, Debug, Default, Deserialize, Serialize, EventContent)]
71#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
72#[ruma_event(
73    kind = GlobalAccountData,
74    type = "org.matrix.msc4380.invite_permission_config",
75)]
76pub struct UnstableInvitePermissionConfigEventContent {
77    /// When set to true, indicates that the user does not wish to receive *any* room invites, and
78    /// they should be blocked.
79    #[serde(default, deserialize_with = "ruma_common::serde::default_on_error")]
80    pub block_all: bool,
81}
82
83#[cfg(feature = "unstable-msc4380")]
84impl UnstableInvitePermissionConfigEventContent {
85    /// Creates a new `UnstableInvitePermissionConfigEventContent` from the desired boolean state.
86    pub fn new(block_all: bool) -> Self {
87        Self { block_all }
88    }
89}
90
91#[cfg(feature = "unstable-msc4380")]
92impl From<UnstableInvitePermissionConfigEventContent> for InvitePermissionConfigEventContent {
93    fn from(value: UnstableInvitePermissionConfigEventContent) -> Self {
94        Self { default_action: value.block_all.then_some(InvitePermissionAction::Block) }
95    }
96}
97
98#[cfg(feature = "unstable-msc4380")]
99impl From<InvitePermissionConfigEventContent> for UnstableInvitePermissionConfigEventContent {
100    fn from(value: InvitePermissionConfigEventContent) -> Self {
101        Self {
102            block_all: value
103                .default_action
104                .is_some_and(|action| matches!(action, InvitePermissionAction::Block)),
105        }
106    }
107}
108
109#[cfg(test)]
110mod tests {
111    use assert_matches2::assert_matches;
112    use ruma_common::canonical_json::assert_to_canonical_json_eq;
113    use serde_json::{from_value as from_json_value, json};
114
115    #[cfg(feature = "unstable-msc4380")]
116    use super::UnstableInvitePermissionConfigEventContent;
117    use super::{InvitePermissionAction, InvitePermissionConfigEventContent};
118    use crate::AnyGlobalAccountDataEvent;
119
120    #[cfg(feature = "unstable-msc4380")]
121    #[test]
122    fn unstable_serialization() {
123        let invite_permission_config = UnstableInvitePermissionConfigEventContent::new(true);
124
125        assert_to_canonical_json_eq!(
126            invite_permission_config,
127            json!({
128                "block_all": true,
129            }),
130        );
131    }
132
133    #[cfg(feature = "unstable-msc4380")]
134    #[test]
135    fn unstable_deserialization() {
136        let json = json!({
137            "content": {
138                "block_all": true,
139            },
140            "type": "org.matrix.msc4380.invite_permission_config",
141        });
142
143        assert_matches!(
144            from_json_value::<AnyGlobalAccountDataEvent>(json),
145            Ok(AnyGlobalAccountDataEvent::UnstableInvitePermissionConfig(ev))
146        );
147        assert!(ev.content.block_all);
148    }
149
150    #[test]
151    fn stable_serialization() {
152        let mut invite_permission_config = InvitePermissionConfigEventContent::new();
153        assert_to_canonical_json_eq!(invite_permission_config, json!({}),);
154
155        invite_permission_config.default_action = Some(InvitePermissionAction::Block);
156        assert_to_canonical_json_eq!(
157            invite_permission_config,
158            json!({
159                "default_action": "block",
160            }),
161        );
162    }
163
164    #[test]
165    fn stable_deserialization() {
166        let json = json!({
167            "content": {
168                "default_action": "block",
169            },
170            "type": "m.invite_permission_config",
171        });
172        assert_matches!(
173            from_json_value::<AnyGlobalAccountDataEvent>(json),
174            Ok(AnyGlobalAccountDataEvent::InvitePermissionConfig(ev))
175        );
176        assert_eq!(ev.content.default_action, Some(InvitePermissionAction::Block));
177
178        let json = json!({
179            "content": {},
180            "type": "m.invite_permission_config",
181        });
182        assert_matches!(
183            from_json_value::<AnyGlobalAccountDataEvent>(json),
184            Ok(AnyGlobalAccountDataEvent::InvitePermissionConfig(ev))
185        );
186        assert_eq!(ev.content.default_action, None);
187    }
188}