aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorZeyla Hellyer <[email protected]>2018-01-06 15:02:05 -0800
committerZeyla Hellyer <[email protected]>2018-01-06 15:02:05 -0800
commit222382ca48cb9786aaf5d0b5fc16958e482e7c5f (patch)
tree9607694a5ec604e4ff3b73938772093e4d90cba3 /src
parentAdd Guild::greater_member_hierarchy (diff)
downloadserenity-222382ca48cb9786aaf5d0b5fc16958e482e7c5f.tar.xz
serenity-222382ca48cb9786aaf5d0b5fc16958e482e7c5f.zip
Add some role position hierarchy checks
Diffstat (limited to 'src')
-rw-r--r--src/model/error.rs9
-rw-r--r--src/model/guild/member.rs18
-rw-r--r--src/model/guild/mod.rs17
3 files changed, 36 insertions, 8 deletions
diff --git a/src/model/error.rs b/src/model/error.rs
index 340bd18..a2b8325 100644
--- a/src/model/error.rs
+++ b/src/model/error.rs
@@ -86,6 +86,14 @@ pub enum Error {
/// [`GuildId`]: ../model/struct.GuildId.html
/// [`Cache`]: ../cache/struct.Cache.html
GuildNotFound,
+ /// Indicates that there are hierarchy problems restricting an action.
+ ///
+ /// For example, when banning a user, if the other user has a role with an
+ /// equal to or higher position, then they can not be banned.
+ ///
+ /// When editing a role, if the role is higher in position than the current
+ /// user's highest role, then the role can not be edited.
+ Hierarchy,
/// Indicates that you do not have the required permissions to perform an
/// operation.
///
@@ -126,6 +134,7 @@ impl StdError for Error {
Error::DeleteMessageDaysAmount(_) => "Invalid delete message days",
Error::EmbedTooLarge(_) => "Embed too large",
Error::GuildNotFound => "Guild not found in the cache",
+ Error::Hierarchy => "Role hierarchy prevents this action",
Error::InvalidPermissions(_) => "Invalid permissions",
Error::InvalidUser => "The current user can not perform the action",
Error::ItemMissing => "The required item is missing from the cache",
diff --git a/src/model/guild/member.rs b/src/model/guild/member.rs
index 3622489..b93349e 100644
--- a/src/model/guild/member.rs
+++ b/src/model/guild/member.rs
@@ -309,16 +309,18 @@ impl Member {
pub fn kick(&self) -> Result<()> {
#[cfg(feature = "cache")]
{
- let req = Permissions::KICK_MEMBERS;
+ let cache = CACHE.read();
- let has_perms = CACHE
- .read()
- .guilds
- .get(&self.guild_id)
- .map(|guild| guild.read().has_perms(req));
+ if let Some(guild) = self.guilds.get(&self.guild_id) {
+ let reader = guild.read();
+
+ if !guild.has_perms(req) {
+ let req = Permissions::KICK_MEMBERS;
+
+ return Err(Error::Model(ModelError::InvalidPermissions(req)));
+ }
- if let Some(false) = has_perms {
- return Err(Error::Model(ModelError::InvalidPermissions(req)));
+ guild.check_hierarchy(&self.user.read().id)?;
}
}
diff --git a/src/model/guild/mod.rs b/src/model/guild/mod.rs
index f9eca59..c74b4b2 100644
--- a/src/model/guild/mod.rs
+++ b/src/model/guild/mod.rs
@@ -144,6 +144,19 @@ pub struct Guild {
#[cfg(feature = "model")]
impl Guild {
+ #[cfg(feature = "cache")]
+ fn check_hierarchy(&self, other_user: UserId) -> Result<()> {
+ let current_id = CACHE.read().user.id;
+
+ if let Some(higher) = self.greater_member_hierarchy(user, current_id) {
+ if higher != current_id {
+ return Err(Error::Model(ModelError::Hierarchy));
+ }
+ }
+
+ Ok(())
+ }
+
/// Returns the "default" channel of the guild for the passed user id.
/// (This returns the first channel that can be read by the user, if there isn't one,
/// returns `None`)
@@ -215,6 +228,8 @@ impl Guild {
/// [`User`]: struct.User.html
/// [Ban Members]: permissions/constant.BAN_MEMBERS.html
pub fn ban<U: Into<UserId>, BO: BanOptions>(&self, user: U, options: &BO) -> Result<()> {
+ let user = user.into();
+
#[cfg(feature = "cache")]
{
let req = Permissions::BAN_MEMBERS;
@@ -222,6 +237,8 @@ impl Guild {
if !self.has_perms(req) {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
+
+ self.check_hierarchy(user)?;
}
self.id.ban(user, options)