ruma_events/room/
power_levels.rs

1//! Types for the [`m.room.power_levels`] event.
2//!
3//! [`m.room.power_levels`]: https://spec.matrix.org/latest/client-server-api/#mroompower_levels
4
5use std::{cmp::max, collections::BTreeMap};
6
7use js_int::{int, Int};
8use ruma_common::{
9    power_levels::{default_power_level, NotificationPowerLevels},
10    push::PushConditionPowerLevelsCtx,
11    OwnedUserId, RoomVersionId, UserId,
12};
13use ruma_macros::EventContent;
14use serde::{Deserialize, Serialize};
15
16use crate::{
17    EmptyStateKey, EventContent, MessageLikeEventType, RedactContent, RedactedStateEventContent,
18    StateEventType, StaticEventContent, TimelineEventType,
19};
20
21/// The content of an `m.room.power_levels` event.
22///
23/// Defines the power levels (privileges) of users in the room.
24#[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
25#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
26#[ruma_event(type = "m.room.power_levels", kind = State, state_key_type = EmptyStateKey, custom_redacted)]
27pub struct RoomPowerLevelsEventContent {
28    /// The level required to ban a user.
29    #[serde(
30        default = "default_power_level",
31        skip_serializing_if = "is_default_power_level",
32        deserialize_with = "ruma_common::serde::deserialize_v1_powerlevel"
33    )]
34    pub ban: Int,
35
36    /// The level required to send specific event types.
37    ///
38    /// This is a mapping from event type to power level required.
39    #[serde(
40        default,
41        skip_serializing_if = "BTreeMap::is_empty",
42        deserialize_with = "ruma_common::serde::btreemap_deserialize_v1_powerlevel_values"
43    )]
44    pub events: BTreeMap<TimelineEventType, Int>,
45
46    /// The default level required to send message events.
47    #[serde(
48        default,
49        skip_serializing_if = "ruma_common::serde::is_default",
50        deserialize_with = "ruma_common::serde::deserialize_v1_powerlevel"
51    )]
52    pub events_default: Int,
53
54    /// The level required to invite a user.
55    #[serde(
56        default,
57        skip_serializing_if = "ruma_common::serde::is_default",
58        deserialize_with = "ruma_common::serde::deserialize_v1_powerlevel"
59    )]
60    pub invite: Int,
61
62    /// The level required to kick a user.
63    #[serde(
64        default = "default_power_level",
65        skip_serializing_if = "is_default_power_level",
66        deserialize_with = "ruma_common::serde::deserialize_v1_powerlevel"
67    )]
68    pub kick: Int,
69
70    /// The level required to redact an event.
71    #[serde(
72        default = "default_power_level",
73        skip_serializing_if = "is_default_power_level",
74        deserialize_with = "ruma_common::serde::deserialize_v1_powerlevel"
75    )]
76    pub redact: Int,
77
78    /// The default level required to send state events.
79    #[serde(
80        default = "default_power_level",
81        skip_serializing_if = "is_default_power_level",
82        deserialize_with = "ruma_common::serde::deserialize_v1_powerlevel"
83    )]
84    pub state_default: Int,
85
86    /// The power levels for specific users.
87    ///
88    /// This is a mapping from `user_id` to power level for that user.
89    #[serde(
90        default,
91        skip_serializing_if = "BTreeMap::is_empty",
92        deserialize_with = "ruma_common::serde::btreemap_deserialize_v1_powerlevel_values"
93    )]
94    pub users: BTreeMap<OwnedUserId, Int>,
95
96    /// The default power level for every user in the room.
97    #[serde(
98        default,
99        skip_serializing_if = "ruma_common::serde::is_default",
100        deserialize_with = "ruma_common::serde::deserialize_v1_powerlevel"
101    )]
102    pub users_default: Int,
103
104    /// The power level requirements for specific notification types.
105    ///
106    /// This is a mapping from `key` to power level for that notifications key.
107    #[serde(default, skip_serializing_if = "NotificationPowerLevels::is_default")]
108    pub notifications: NotificationPowerLevels,
109}
110
111impl RoomPowerLevelsEventContent {
112    /// Creates a new `RoomPowerLevelsEventContent` with all-default values.
113    pub fn new() -> Self {
114        // events_default, users_default and invite having a default of 0 while the others have a
115        // default of 50 is not an oversight, these defaults are from the Matrix specification.
116        Self {
117            ban: default_power_level(),
118            events: BTreeMap::new(),
119            events_default: int!(0),
120            invite: int!(0),
121            kick: default_power_level(),
122            redact: default_power_level(),
123            state_default: default_power_level(),
124            users: BTreeMap::new(),
125            users_default: int!(0),
126            notifications: NotificationPowerLevels::default(),
127        }
128    }
129}
130
131impl Default for RoomPowerLevelsEventContent {
132    fn default() -> Self {
133        Self::new()
134    }
135}
136
137impl RedactContent for RoomPowerLevelsEventContent {
138    type Redacted = RedactedRoomPowerLevelsEventContent;
139
140    fn redact(self, version: &RoomVersionId) -> Self::Redacted {
141        let Self {
142            ban,
143            events,
144            events_default,
145            invite,
146            kick,
147            redact,
148            state_default,
149            users,
150            users_default,
151            ..
152        } = self;
153
154        let invite = match version {
155            RoomVersionId::V1
156            | RoomVersionId::V2
157            | RoomVersionId::V3
158            | RoomVersionId::V4
159            | RoomVersionId::V5
160            | RoomVersionId::V6
161            | RoomVersionId::V7
162            | RoomVersionId::V8
163            | RoomVersionId::V9
164            | RoomVersionId::V10 => int!(0),
165            _ => invite,
166        };
167
168        RedactedRoomPowerLevelsEventContent {
169            ban,
170            events,
171            events_default,
172            invite,
173            kick,
174            redact,
175            state_default,
176            users,
177            users_default,
178        }
179    }
180}
181
182/// Used with `#[serde(skip_serializing_if)]` to omit default power levels.
183#[allow(clippy::trivially_copy_pass_by_ref)]
184fn is_default_power_level(l: &Int) -> bool {
185    *l == int!(50)
186}
187
188impl RoomPowerLevelsEvent {
189    /// Obtain the effective power levels, regardless of whether this event is redacted.
190    pub fn power_levels(&self) -> RoomPowerLevels {
191        match self {
192            Self::Original(ev) => ev.content.clone().into(),
193            Self::Redacted(ev) => ev.content.clone().into(),
194        }
195    }
196}
197
198impl SyncRoomPowerLevelsEvent {
199    /// Obtain the effective power levels, regardless of whether this event is redacted.
200    pub fn power_levels(&self) -> RoomPowerLevels {
201        match self {
202            Self::Original(ev) => ev.content.clone().into(),
203            Self::Redacted(ev) => ev.content.clone().into(),
204        }
205    }
206}
207
208impl StrippedRoomPowerLevelsEvent {
209    /// Obtain the effective power levels from this event.
210    pub fn power_levels(&self) -> RoomPowerLevels {
211        self.content.clone().into()
212    }
213}
214
215/// Redacted form of [`RoomPowerLevelsEventContent`].
216#[derive(Clone, Debug, Deserialize, Serialize)]
217#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
218pub struct RedactedRoomPowerLevelsEventContent {
219    /// The level required to ban a user.
220    #[serde(
221        default = "default_power_level",
222        skip_serializing_if = "is_default_power_level",
223        deserialize_with = "ruma_common::serde::deserialize_v1_powerlevel"
224    )]
225    pub ban: Int,
226
227    /// The level required to send specific event types.
228    ///
229    /// This is a mapping from event type to power level required.
230    #[serde(
231        default,
232        skip_serializing_if = "BTreeMap::is_empty",
233        deserialize_with = "ruma_common::serde::btreemap_deserialize_v1_powerlevel_values"
234    )]
235    pub events: BTreeMap<TimelineEventType, Int>,
236
237    /// The default level required to send message events.
238    #[serde(
239        default,
240        skip_serializing_if = "ruma_common::serde::is_default",
241        deserialize_with = "ruma_common::serde::deserialize_v1_powerlevel"
242    )]
243    pub events_default: Int,
244
245    /// The level required to invite a user.
246    ///
247    /// This field was redacted in room versions 1 through 10. Starting from room version 11 it is
248    /// preserved.
249    #[serde(
250        default,
251        skip_serializing_if = "ruma_common::serde::is_default",
252        deserialize_with = "ruma_common::serde::deserialize_v1_powerlevel"
253    )]
254    pub invite: Int,
255
256    /// The level required to kick a user.
257    #[serde(
258        default = "default_power_level",
259        skip_serializing_if = "is_default_power_level",
260        deserialize_with = "ruma_common::serde::deserialize_v1_powerlevel"
261    )]
262    pub kick: Int,
263
264    /// The level required to redact an event.
265    #[serde(
266        default = "default_power_level",
267        skip_serializing_if = "is_default_power_level",
268        deserialize_with = "ruma_common::serde::deserialize_v1_powerlevel"
269    )]
270    pub redact: Int,
271
272    /// The default level required to send state events.
273    #[serde(
274        default = "default_power_level",
275        skip_serializing_if = "is_default_power_level",
276        deserialize_with = "ruma_common::serde::deserialize_v1_powerlevel"
277    )]
278    pub state_default: Int,
279
280    /// The power levels for specific users.
281    ///
282    /// This is a mapping from `user_id` to power level for that user.
283    #[serde(
284        default,
285        skip_serializing_if = "BTreeMap::is_empty",
286        deserialize_with = "ruma_common::serde::btreemap_deserialize_v1_powerlevel_values"
287    )]
288    pub users: BTreeMap<OwnedUserId, Int>,
289
290    /// The default power level for every user in the room.
291    #[serde(
292        default,
293        skip_serializing_if = "ruma_common::serde::is_default",
294        deserialize_with = "ruma_common::serde::deserialize_v1_powerlevel"
295    )]
296    pub users_default: Int,
297}
298
299impl EventContent for RedactedRoomPowerLevelsEventContent {
300    type EventType = StateEventType;
301
302    fn event_type(&self) -> Self::EventType {
303        StateEventType::RoomPowerLevels
304    }
305}
306
307impl StaticEventContent for RedactedRoomPowerLevelsEventContent {
308    const TYPE: &'static str = "m.room.power_levels";
309}
310
311impl RedactedStateEventContent for RedactedRoomPowerLevelsEventContent {
312    type StateKey = EmptyStateKey;
313}
314
315/// The effective power levels of a room.
316///
317/// This struct contains the same fields as [`RoomPowerLevelsEventContent`] and be created from that
318/// using a `From` trait implementation, but it is also implements
319/// `From<`[`RedactedRoomPowerLevelsEventContent`]`>`, so can be used when wanting to inspect the
320/// power levels of a room, regardless of whether the most recent power-levels event is redacted or
321/// not.
322#[derive(Clone, Debug)]
323#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
324pub struct RoomPowerLevels {
325    /// The level required to ban a user.
326    pub ban: Int,
327
328    /// The level required to send specific event types.
329    ///
330    /// This is a mapping from event type to power level required.
331    pub events: BTreeMap<TimelineEventType, Int>,
332
333    /// The default level required to send message events.
334    pub events_default: Int,
335
336    /// The level required to invite a user.
337    pub invite: Int,
338
339    /// The level required to kick a user.
340    pub kick: Int,
341
342    /// The level required to redact an event.
343    pub redact: Int,
344
345    /// The default level required to send state events.
346    pub state_default: Int,
347
348    /// The power levels for specific users.
349    ///
350    /// This is a mapping from `user_id` to power level for that user.
351    pub users: BTreeMap<OwnedUserId, Int>,
352
353    /// The default power level for every user in the room.
354    pub users_default: Int,
355
356    /// The power level requirements for specific notification types.
357    ///
358    /// This is a mapping from `key` to power level for that notifications key.
359    pub notifications: NotificationPowerLevels,
360}
361
362impl RoomPowerLevels {
363    /// Get the power level of a specific user.
364    pub fn for_user(&self, user_id: &UserId) -> Int {
365        self.users.get(user_id).map_or(self.users_default, |pl| *pl)
366    }
367
368    /// Get the power level required to perform a given action.
369    pub fn for_action(&self, action: PowerLevelAction) -> Int {
370        match action {
371            PowerLevelAction::Ban => self.ban,
372            PowerLevelAction::Unban => self.ban.max(self.kick),
373            PowerLevelAction::Invite => self.invite,
374            PowerLevelAction::Kick => self.kick,
375            PowerLevelAction::RedactOwn => self.for_message(MessageLikeEventType::RoomRedaction),
376            PowerLevelAction::RedactOther => {
377                self.redact.max(self.for_message(MessageLikeEventType::RoomRedaction))
378            }
379            PowerLevelAction::SendMessage(msg_type) => self.for_message(msg_type),
380            PowerLevelAction::SendState(state_type) => self.for_state(state_type),
381            PowerLevelAction::TriggerNotification(NotificationPowerLevelType::Room) => {
382                self.notifications.room
383            }
384        }
385    }
386
387    /// Get the power level required to send the given message type.
388    pub fn for_message(&self, msg_type: MessageLikeEventType) -> Int {
389        self.events.get(&msg_type.into()).copied().unwrap_or(self.events_default)
390    }
391
392    /// Get the power level required to send the given state event type.
393    pub fn for_state(&self, state_type: StateEventType) -> Int {
394        self.events.get(&state_type.into()).copied().unwrap_or(self.state_default)
395    }
396
397    /// Whether the given user can ban other users based on the power levels.
398    ///
399    /// Shorthand for `power_levels.user_can_do(user_id, PowerLevelAction::Ban)`.
400    pub fn user_can_ban(&self, user_id: &UserId) -> bool {
401        self.for_user(user_id) >= self.ban
402    }
403
404    /// Whether the acting user can ban the target user based on the power levels.
405    ///
406    /// On top of `power_levels.user_can_ban(acting_user_id)`, this performs an extra check
407    /// to make sure the acting user has at greater power level than the target user.
408    ///
409    /// Shorthand for `power_levels.user_can_do_to_user(acting_user_id, target_user_id,
410    /// PowerLevelUserAction::Ban)`.
411    pub fn user_can_ban_user(&self, acting_user_id: &UserId, target_user_id: &UserId) -> bool {
412        let acting_pl = self.for_user(acting_user_id);
413        let target_pl = self.for_user(target_user_id);
414        acting_pl >= self.ban && target_pl < acting_pl
415    }
416
417    /// Whether the given user can unban other users based on the power levels.
418    ///
419    /// This action requires to be allowed to ban and to kick.
420    ///
421    /// Shorthand for `power_levels.user_can_do(user_id, PowerLevelAction::Unban)`.
422    pub fn user_can_unban(&self, user_id: &UserId) -> bool {
423        let pl = self.for_user(user_id);
424        pl >= self.ban && pl >= self.kick
425    }
426
427    /// Whether the acting user can unban the target user based on the power levels.
428    ///
429    /// This action requires to be allowed to ban and to kick.
430    ///
431    /// On top of `power_levels.user_can_unban(acting_user_id)`, this performs an extra check
432    /// to make sure the acting user has at greater power level than the target user.
433    ///
434    /// Shorthand for `power_levels.user_can_do_to_user(acting_user_id, target_user_id,
435    /// PowerLevelUserAction::Unban)`.
436    pub fn user_can_unban_user(&self, acting_user_id: &UserId, target_user_id: &UserId) -> bool {
437        let acting_pl = self.for_user(acting_user_id);
438        let target_pl = self.for_user(target_user_id);
439        acting_pl >= self.ban && acting_pl >= self.kick && target_pl < acting_pl
440    }
441
442    /// Whether the given user can invite other users based on the power levels.
443    ///
444    /// Shorthand for `power_levels.user_can_do(user_id, PowerLevelAction::Invite)`.
445    pub fn user_can_invite(&self, user_id: &UserId) -> bool {
446        self.for_user(user_id) >= self.invite
447    }
448
449    /// Whether the given user can kick other users based on the power levels.
450    ///
451    /// Shorthand for `power_levels.user_can_do(user_id, PowerLevelAction::Kick)`.
452    pub fn user_can_kick(&self, user_id: &UserId) -> bool {
453        self.for_user(user_id) >= self.kick
454    }
455
456    /// Whether the acting user can kick the target user based on the power levels.
457    ///
458    /// On top of `power_levels.user_can_kick(acting_user_id)`, this performs an extra check
459    /// to make sure the acting user has at least the same power level as the target user.
460    ///
461    /// Shorthand for `power_levels.user_can_do_to_user(acting_user_id, target_user_id,
462    /// PowerLevelUserAction::Kick)`.
463    pub fn user_can_kick_user(&self, acting_user_id: &UserId, target_user_id: &UserId) -> bool {
464        let acting_pl = self.for_user(acting_user_id);
465        let target_pl = self.for_user(target_user_id);
466        acting_pl >= self.kick && target_pl < acting_pl
467    }
468
469    /// Whether the given user can redact their own events based on the power levels.
470    ///
471    /// Shorthand for `power_levels.user_can_do(user_id, PowerLevelAction::RedactOwn)`.
472    pub fn user_can_redact_own_event(&self, user_id: &UserId) -> bool {
473        self.user_can_send_message(user_id, MessageLikeEventType::RoomRedaction)
474    }
475
476    /// Whether the given user can redact events of other users based on the power levels.
477    ///
478    /// Shorthand for `power_levels.user_can_do(user_id, PowerLevelAction::RedactOthers)`.
479    pub fn user_can_redact_event_of_other(&self, user_id: &UserId) -> bool {
480        self.user_can_redact_own_event(user_id) && self.for_user(user_id) >= self.redact
481    }
482
483    /// Whether the given user can send message events based on the power levels.
484    ///
485    /// Shorthand for `power_levels.user_can_do(user_id, PowerLevelAction::SendMessage(msg_type))`.
486    pub fn user_can_send_message(&self, user_id: &UserId, msg_type: MessageLikeEventType) -> bool {
487        self.for_user(user_id) >= self.for_message(msg_type)
488    }
489
490    /// Whether the given user can send state events based on the power levels.
491    ///
492    /// Shorthand for `power_levels.user_can_do(user_id, PowerLevelAction::SendState(state_type))`.
493    pub fn user_can_send_state(&self, user_id: &UserId, state_type: StateEventType) -> bool {
494        self.for_user(user_id) >= self.for_state(state_type)
495    }
496
497    /// Whether the given user can notify everybody in the room by writing `@room` in a message.
498    ///
499    /// Shorthand for `power_levels.user_can_do(user_id,
500    /// PowerLevelAction::TriggerNotification(NotificationPowerLevelType::Room))`.
501    pub fn user_can_trigger_room_notification(&self, user_id: &UserId) -> bool {
502        self.for_user(user_id) >= self.notifications.room
503    }
504
505    /// Whether the acting user can change the power level of the target user.
506    ///
507    /// Shorthand for `power_levels.user_can_do_to_user(acting_user_id, target_user_id,
508    /// PowerLevelUserAction::ChangePowerLevel`.
509    pub fn user_can_change_user_power_level(
510        &self,
511        acting_user_id: &UserId,
512        target_user_id: &UserId,
513    ) -> bool {
514        // Check that the user can change the power levels first.
515        if !self.user_can_send_state(acting_user_id, StateEventType::RoomPowerLevels) {
516            return false;
517        }
518
519        // A user can change their own power level.
520        if acting_user_id == target_user_id {
521            return true;
522        }
523
524        // The permission is different whether the target user is added or changed/removed, so
525        // we need to check that.
526        if let Some(target_pl) = self.users.get(target_user_id).copied() {
527            self.for_user(acting_user_id) > target_pl
528        } else {
529            true
530        }
531    }
532
533    /// Whether the given user can do the given action based on the power levels.
534    pub fn user_can_do(&self, user_id: &UserId, action: PowerLevelAction) -> bool {
535        match action {
536            PowerLevelAction::Ban => self.user_can_ban(user_id),
537            PowerLevelAction::Unban => self.user_can_unban(user_id),
538            PowerLevelAction::Invite => self.user_can_invite(user_id),
539            PowerLevelAction::Kick => self.user_can_kick(user_id),
540            PowerLevelAction::RedactOwn => self.user_can_redact_own_event(user_id),
541            PowerLevelAction::RedactOther => self.user_can_redact_event_of_other(user_id),
542            PowerLevelAction::SendMessage(message_type) => {
543                self.user_can_send_message(user_id, message_type)
544            }
545            PowerLevelAction::SendState(state_type) => {
546                self.user_can_send_state(user_id, state_type)
547            }
548            PowerLevelAction::TriggerNotification(NotificationPowerLevelType::Room) => {
549                self.user_can_trigger_room_notification(user_id)
550            }
551        }
552    }
553
554    /// Whether the acting user can do the given action to the target user based on the power
555    /// levels.
556    pub fn user_can_do_to_user(
557        &self,
558        acting_user_id: &UserId,
559        target_user_id: &UserId,
560        action: PowerLevelUserAction,
561    ) -> bool {
562        match action {
563            PowerLevelUserAction::Ban => self.user_can_ban_user(acting_user_id, target_user_id),
564            PowerLevelUserAction::Unban => self.user_can_unban_user(acting_user_id, target_user_id),
565            PowerLevelUserAction::Invite => self.user_can_invite(acting_user_id),
566            PowerLevelUserAction::Kick => self.user_can_kick_user(acting_user_id, target_user_id),
567            PowerLevelUserAction::ChangePowerLevel => {
568                self.user_can_change_user_power_level(acting_user_id, target_user_id)
569            }
570        }
571    }
572
573    /// Get the maximum power level of any user.
574    pub fn max(&self) -> Int {
575        self.users.values().fold(self.users_default, |max_pl, user_pl| max(max_pl, *user_pl))
576    }
577}
578
579impl From<RoomPowerLevelsEventContent> for RoomPowerLevels {
580    fn from(c: RoomPowerLevelsEventContent) -> Self {
581        Self {
582            ban: c.ban,
583            events: c.events,
584            events_default: c.events_default,
585            invite: c.invite,
586            kick: c.kick,
587            redact: c.redact,
588            state_default: c.state_default,
589            users: c.users,
590            users_default: c.users_default,
591            notifications: c.notifications,
592        }
593    }
594}
595
596impl From<RedactedRoomPowerLevelsEventContent> for RoomPowerLevels {
597    fn from(c: RedactedRoomPowerLevelsEventContent) -> Self {
598        Self {
599            ban: c.ban,
600            events: c.events,
601            events_default: c.events_default,
602            invite: c.invite,
603            kick: c.kick,
604            redact: c.redact,
605            state_default: c.state_default,
606            users: c.users,
607            users_default: c.users_default,
608            notifications: NotificationPowerLevels::default(),
609        }
610    }
611}
612
613impl From<RoomPowerLevels> for RoomPowerLevelsEventContent {
614    fn from(c: RoomPowerLevels) -> Self {
615        Self {
616            ban: c.ban,
617            events: c.events,
618            events_default: c.events_default,
619            invite: c.invite,
620            kick: c.kick,
621            redact: c.redact,
622            state_default: c.state_default,
623            users: c.users,
624            users_default: c.users_default,
625            notifications: c.notifications,
626        }
627    }
628}
629
630impl From<RoomPowerLevels> for PushConditionPowerLevelsCtx {
631    fn from(c: RoomPowerLevels) -> Self {
632        Self { users: c.users, users_default: c.users_default, notifications: c.notifications }
633    }
634}
635
636/// The actions that can be limited by power levels.
637#[derive(Clone, Debug, PartialEq, Eq)]
638#[non_exhaustive]
639pub enum PowerLevelAction {
640    /// Ban a user.
641    Ban,
642
643    /// Unban a user.
644    Unban,
645
646    /// Invite a user.
647    Invite,
648
649    /// Kick a user.
650    Kick,
651
652    /// Redact one's own event.
653    RedactOwn,
654
655    /// Redact the event of another user.
656    RedactOther,
657
658    /// Send a message-like event.
659    SendMessage(MessageLikeEventType),
660
661    /// Send a state event.
662    SendState(StateEventType),
663
664    /// Trigger a notification.
665    TriggerNotification(NotificationPowerLevelType),
666}
667
668/// The notification types that can be limited by power levels.
669#[derive(Clone, Debug, PartialEq, Eq)]
670#[non_exhaustive]
671pub enum NotificationPowerLevelType {
672    /// `@room` notifications.
673    Room,
674}
675
676/// The actions to other users that can be limited by power levels.
677#[derive(Clone, Debug, PartialEq, Eq)]
678#[non_exhaustive]
679pub enum PowerLevelUserAction {
680    /// Ban a user.
681    Ban,
682
683    /// Unban a user.
684    Unban,
685
686    /// Invite a user.
687    Invite,
688
689    /// Kick a user.
690    Kick,
691
692    /// Change a user's power level.
693    ChangePowerLevel,
694}
695
696#[cfg(test)]
697mod tests {
698    use std::collections::BTreeMap;
699
700    use assign::assign;
701    use js_int::int;
702    use maplit::btreemap;
703    use ruma_common::user_id;
704    use serde_json::{json, to_value as to_json_value};
705
706    use super::{default_power_level, NotificationPowerLevels, RoomPowerLevelsEventContent};
707
708    #[test]
709    fn serialization_with_optional_fields_as_none() {
710        let default = default_power_level();
711
712        let power_levels = RoomPowerLevelsEventContent {
713            ban: default,
714            events: BTreeMap::new(),
715            events_default: int!(0),
716            invite: int!(0),
717            kick: default,
718            redact: default,
719            state_default: default,
720            users: BTreeMap::new(),
721            users_default: int!(0),
722            notifications: NotificationPowerLevels::default(),
723        };
724
725        let actual = to_json_value(&power_levels).unwrap();
726        let expected = json!({});
727
728        assert_eq!(actual, expected);
729    }
730
731    #[test]
732    fn serialization_with_all_fields() {
733        let user = user_id!("@carl:example.com");
734        let power_levels_event = RoomPowerLevelsEventContent {
735            ban: int!(23),
736            events: btreemap! {
737                "m.dummy".into() => int!(23)
738            },
739            events_default: int!(23),
740            invite: int!(23),
741            kick: int!(23),
742            redact: int!(23),
743            state_default: int!(23),
744            users: btreemap! {
745                user.to_owned() => int!(23)
746            },
747            users_default: int!(23),
748            notifications: assign!(NotificationPowerLevels::new(), { room: int!(23) }),
749        };
750
751        let actual = to_json_value(&power_levels_event).unwrap();
752        let expected = json!({
753            "ban": 23,
754            "events": {
755                "m.dummy": 23
756            },
757            "events_default": 23,
758            "invite": 23,
759            "kick": 23,
760            "redact": 23,
761            "state_default": 23,
762            "users": {
763                "@carl:example.com": 23
764            },
765            "users_default": 23,
766            "notifications": {
767                "room": 23
768            },
769        });
770
771        assert_eq!(actual, expected);
772    }
773}