events: Add convenience methods about actions to other users according to power levels

Some of these actions are limited by the power level of the other user.
This commit is contained in:
Kévin Commaille 2024-01-02 11:10:24 +01:00 committed by Kévin Commaille
parent b7829d5607
commit 9d9827c165
2 changed files with 57 additions and 0 deletions

View File

@ -10,6 +10,8 @@ Improvements:
- We previously already accepted custom or slightly malformed relations
- Now, even invalid / missing `rel_type` and `event_id` are accepted
- Implement `From<RoomPowerLevels>` for `ruma_common::push::PushConditionPowerLevelsCtx`
- Add methods on `PowerLevels` to check if some actions are permitted based on
the target user's power level.
# 0.27.11

View File

@ -372,6 +372,19 @@ impl RoomPowerLevels {
self.for_user(user_id) >= self.ban
}
/// Whether the acting user can ban the target user based on the power levels.
///
/// On top of `power_levels.user_can_ban(acting_user_id)`, this performs an extra check
/// to make sure the acting user has at greater power level than the target user.
///
/// Shorthand for `power_levels.user_can_do_to_user(acting_user_id, target_user_id,
/// PowerLevelUserAction::Ban)`.
pub fn user_can_ban_user(&self, acting_user_id: &UserId, target_user_id: &UserId) -> bool {
let acting_pl = self.for_user(acting_user_id);
let target_pl = self.for_user(target_user_id);
acting_pl >= self.ban && target_pl < acting_pl
}
/// Whether the given user can invite other users based on the power levels.
///
/// Shorthand for `power_levels.user_can_do(user_id, PowerLevelAction::Invite)`.
@ -386,6 +399,19 @@ impl RoomPowerLevels {
self.for_user(user_id) >= self.kick
}
/// Whether the acting user can kick the target user based on the power levels.
///
/// On top of `power_levels.user_can_kick(acting_user_id)`, this performs an extra check
/// to make sure the acting user has at least the same power level as the target user.
///
/// Shorthand for `power_levels.user_can_do_to_user(acting_user_id, target_user_id,
/// PowerLevelUserAction::Kick)`.
pub fn user_can_kick_user(&self, acting_user_id: &UserId, target_user_id: &UserId) -> bool {
let acting_pl = self.for_user(acting_user_id);
let target_pl = self.for_user(target_user_id);
acting_pl >= self.kick && target_pl < acting_pl
}
/// Whether the given user can redact events based on the power levels.
///
/// Shorthand for `power_levels.user_can_do(user_id, PowerLevelAction::Redact)`.
@ -444,6 +470,21 @@ impl RoomPowerLevels {
}
}
/// Whether the acting user can do the given action to the target user based on the power
/// levels.
pub fn user_can_do_to_user(
&self,
acting_user_id: &UserId,
target_user_id: &UserId,
action: PowerLevelUserAction,
) -> bool {
match action {
PowerLevelUserAction::Ban => self.user_can_ban_user(acting_user_id, target_user_id),
PowerLevelUserAction::Invite => self.user_can_invite(acting_user_id),
PowerLevelUserAction::Kick => self.user_can_kick_user(acting_user_id, target_user_id),
}
}
/// Get the maximum power level of any user.
pub fn max(&self) -> Int {
self.users.values().fold(self.users_default, |max_pl, user_pl| max(max_pl, *user_pl))
@ -541,6 +582,20 @@ pub enum NotificationPowerLevelType {
Room,
}
/// The actions to other users that can be limited by power levels.
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum PowerLevelUserAction {
/// Ban a user.
Ban,
/// Invite a user.
Invite,
/// Kick a user.
Kick,
}
#[cfg(test)]
mod tests {
use std::collections::BTreeMap;