Skip to main content

ruma_events/presence/
sharing.rs

1//! Types for the `m.presence.sharing` account data key.
2//!
3//! This uses the unstable prefix defined in [MSC4495].
4//!
5//! [MSC4495]: https://github.com/matrix-org/matrix-spec-proposals/pull/4495
6
7use std::collections::BTreeMap;
8
9use ruma_common::{OwnedRoomId, OwnedServerName, OwnedUserId};
10use ruma_macros::{EventContent, StringEnum};
11use serde::{Deserialize, Serialize};
12
13use crate::PrivOwnedStr;
14
15/// A possible state for a user in the `m.presence.sharing` configuration.
16#[derive(Clone, StringEnum)]
17#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
18#[ruma_enum(rename_all = "snake_case")]
19pub enum UserPresenceSharingState {
20    /// The user may receive presence updates.
21    Allow,
22
23    /// The user must not receive presence updates.
24    Deny,
25
26    #[doc(hidden)]
27    _Custom(PrivOwnedStr),
28}
29
30/// A possible state for a room in the `m.presence.sharing` configuration.
31#[derive(Clone, StringEnum)]
32#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
33#[ruma_enum(rename_all = "snake_case")]
34pub enum RoomPresenceSharingState {
35    /// The room may receive presence updates.
36    Allow,
37
38    #[doc(hidden)]
39    _Custom(PrivOwnedStr),
40}
41
42/// A possible state for a server in the `m.presence.sharing` configuration.
43#[derive(Clone, StringEnum)]
44#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
45#[ruma_enum(rename_all = "snake_case")]
46pub enum ServerPresenceSharingState {
47    /// The server must not receive presence updates.
48    Deny,
49
50    #[doc(hidden)]
51    _Custom(PrivOwnedStr),
52}
53
54/// The content of the `m.presence.sharing` account data key.
55///
56/// This uses the unstable prefix defined in [MSC4495].
57///
58/// [MSC4495]: https://github.com/matrix-org/matrix-spec-proposals/pull/4495
59#[derive(Clone, Default, Debug, Deserialize, Serialize, EventContent)]
60#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
61#[ruma_event(type = "org.continuwuity.presence_v2.msc4495.presence.sharing", kind = GlobalAccountData)]
62pub struct PresenceSharingEventContent {
63    /// Whether presence should be shared with all users on the local homeserver.
64    #[serde(default, skip_serializing_if = "std::ops::Not::not")]
65    pub share_locally: bool,
66
67    /// Configuration for sharing presence with users.
68    #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
69    pub users: BTreeMap<OwnedUserId, UserPresenceSharingState>,
70
71    /// Configuration for sharing presence with rooms.
72    ///
73    /// Sharing presence with rooms also depends on the room's presence sharing hint.
74    #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
75    pub rooms: BTreeMap<OwnedRoomId, RoomPresenceSharingState>,
76
77    /// Configuration for sharing presence with servers.
78    #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
79    pub servers: BTreeMap<OwnedServerName, ServerPresenceSharingState>,
80}
81
82impl PresenceSharingEventContent {
83    /// Creates a new `PresenceSharingEventContent` with the given parameters.
84    pub fn new(
85        share_locally: bool,
86        users: BTreeMap<OwnedUserId, UserPresenceSharingState>,
87        rooms: BTreeMap<OwnedRoomId, RoomPresenceSharingState>,
88        servers: BTreeMap<OwnedServerName, ServerPresenceSharingState>,
89    ) -> Self {
90        Self { share_locally, users, rooms, servers }
91    }
92}
93
94#[cfg(test)]
95mod tests {
96    use ruma_common::{
97        canonical_json::assert_to_canonical_json_eq, owned_room_id, owned_server_name,
98        owned_user_id, room_id, server_name, user_id,
99    };
100    use serde_json::{from_value as from_json_value, json};
101
102    use crate::presence::sharing::{
103        PresenceSharingEventContent, RoomPresenceSharingState, ServerPresenceSharingState,
104        UserPresenceSharingState,
105    };
106
107    #[test]
108    fn serialization() {
109        let content = PresenceSharingEventContent {
110            share_locally: true,
111            users: [
112                (owned_user_id!("@alice:example.com"), UserPresenceSharingState::Allow),
113                (owned_user_id!("@mallory:example.com"), UserPresenceSharingState::Deny),
114            ]
115            .into(),
116            rooms: [(owned_room_id!("!family-group-chat"), RoomPresenceSharingState::Allow)].into(),
117            servers: [(owned_server_name!("matrix.org"), ServerPresenceSharingState::Deny)].into(),
118        };
119
120        assert_to_canonical_json_eq!(
121            content,
122            json!({
123                "share_locally": true,
124                "users": {
125                    "@alice:example.com": "allow",
126                    "@mallory:example.com": "deny",
127                },
128                "rooms": {
129                    "!family-group-chat": "allow",
130                },
131                "servers": {
132                    "matrix.org": "deny",
133                },
134            }),
135        );
136    }
137
138    #[test]
139    fn deserialization() {
140        let json_data = json!({
141            "share_locally": true,
142            "users": {
143                "@alice:example.com": "allow",
144                "@mallory:example.com": "deny",
145            },
146            "rooms": {
147                "!family-group-chat": "allow",
148            },
149            "servers": {
150                "matrix.org": "deny",
151            }
152        });
153
154        let content = from_json_value::<PresenceSharingEventContent>(json_data).unwrap();
155
156        assert!(content.share_locally);
157        assert_eq!(content.users.len(), 2);
158        assert_eq!(
159            content.users.get(user_id!("@alice:example.com")).unwrap(),
160            &UserPresenceSharingState::Allow
161        );
162        assert_eq!(
163            content.users.get(user_id!("@mallory:example.com")).unwrap(),
164            &UserPresenceSharingState::Deny
165        );
166        assert_eq!(content.rooms.len(), 1);
167        assert_eq!(
168            content.rooms.get(room_id!("!family-group-chat")).unwrap(),
169            &RoomPresenceSharingState::Allow
170        );
171        assert_eq!(content.servers.len(), 1);
172        assert_eq!(
173            content.servers.get(server_name!("matrix.org")).unwrap(),
174            &ServerPresenceSharingState::Deny
175        );
176    }
177}