Skip to content

Commit

Permalink
Ignore Missing Cache Items on Permission Checks (#1233)
Browse files Browse the repository at this point in the history
* Ignore missing cache items on permission checks.

When a model's utility-method cannot find the
guild or member, it will issue the HTTP-request
instead of returning an error.

When the gateway intents are missing,
it's more efficient to try the HTTP-request and get
rejected by Discord instead of performing multiple
HTTP-requests to get the member and guild data
in the first place.

Co-authored-by: Alex M. M. <acdenissk69@gmail.com>

Co-authored-by: Alex M. M. <acdenissk69@gmail.com>
  • Loading branch information
Lakelezz and arqunis committed Feb 23, 2021
1 parent 83360f8 commit 2812236
Show file tree
Hide file tree
Showing 13 changed files with 168 additions and 102 deletions.
2 changes: 1 addition & 1 deletion src/model/application.rs
Expand Up @@ -170,5 +170,5 @@ pub enum MembershipState {

enum_number!(MembershipState {
Invited,
Accepted,
Accepted
});
36 changes: 21 additions & 15 deletions src/model/channel/guild_channel.rs
Expand Up @@ -152,11 +152,13 @@ impl GuildChannel {
#[cfg(feature = "cache")]
{
if let Some(cache) = cache_http.cache() {
let req = Permissions::CREATE_INVITE;

if !utils::user_has_perms(&cache, self.id, Some(self.guild_id), req).await? {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
utils::user_has_perms_cache(
cache,
self.id,
Some(self.guild_id),
Permissions::CREATE_INVITE,
)
.await?;
}
}

Expand Down Expand Up @@ -286,11 +288,13 @@ impl GuildChannel {
#[cfg(feature = "cache")]
{
if let Some(cache) = cache_http.cache() {
let req = Permissions::MANAGE_CHANNELS;

if !utils::user_has_perms(&cache, self.id, Some(self.guild_id), req).await? {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
utils::user_has_perms_cache(
cache,
self.id,
Some(self.guild_id),
Permissions::MANAGE_CHANNELS,
)
.await?;
}
}

Expand Down Expand Up @@ -390,11 +394,13 @@ impl GuildChannel {
#[cfg(feature = "cache")]
{
if let Some(cache) = cache_http.cache() {
let req = Permissions::MANAGE_CHANNELS;

if !utils::user_has_perms(&cache, self.id, Some(self.guild_id), req).await? {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
utils::user_has_perms_cache(
cache,
self.id,
Some(self.guild_id),
Permissions::MANAGE_CHANNELS,
)
.await?;
}
}

Expand Down
107 changes: 59 additions & 48 deletions src/model/channel/message.rs
Expand Up @@ -140,13 +140,14 @@ impl Message {
#[cfg(feature = "cache")]
{
if let Some(cache) = cache_http.cache() {
let req = Permissions::MANAGE_MESSAGES;
let permissions = Permissions::MANAGE_MESSAGES;
let is_author = self.author.id == cache.current_user().await.id;
let has_perms =
utils::user_has_perms(&cache, self.channel_id, self.guild_id, req).await?;

if !is_author && !has_perms {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
utils::user_has_perms_cache(cache, self.channel_id, self.guild_id, permissions)
.await?;

if !is_author {
return Err(Error::Model(ModelError::NotAuthor));
}
}
}
Expand All @@ -169,11 +170,13 @@ impl Message {
#[cfg(feature = "cache")]
{
if let Some(cache) = cache_http.cache() {
let req = Permissions::MANAGE_MESSAGES;

if !utils::user_has_perms(cache, self.channel_id, self.guild_id, req).await? {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
utils::user_has_perms_cache(
cache,
self.channel_id,
self.guild_id,
Permissions::MANAGE_MESSAGES,
)
.await?;
}
}

Expand All @@ -199,11 +202,13 @@ impl Message {
#[cfg(feature = "cache")]
{
if let Some(cache) = cache_http.cache() {
let req = Permissions::MANAGE_MESSAGES;

if !utils::user_has_perms(cache, self.channel_id, self.guild_id, req).await? {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
utils::user_has_perms_cache(
cache,
self.channel_id,
self.guild_id,
Permissions::MANAGE_MESSAGES,
)
.await?;
}
}

Expand Down Expand Up @@ -477,11 +482,13 @@ impl Message {
{
if let Some(cache) = cache_http.cache() {
if self.guild_id.is_some() {
let req = Permissions::MANAGE_MESSAGES;

if !utils::user_has_perms(&cache, self.channel_id, self.guild_id, req).await? {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
utils::user_has_perms_cache(
cache,
self.channel_id,
self.guild_id,
Permissions::MANAGE_MESSAGES,
)
.await?;
}
}
}
Expand Down Expand Up @@ -522,11 +529,13 @@ impl Message {
{
if let Some(cache) = cache_http.cache() {
if self.guild_id.is_some() {
let req = Permissions::ADD_REACTIONS;

if !utils::user_has_perms(cache, self.channel_id, self.guild_id, req).await? {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
utils::user_has_perms_cache(
cache,
self.channel_id,
self.guild_id,
Permissions::ADD_REACTIONS,
)
.await?;
}

user_id = Some(cache.current_user().await.id);
Expand Down Expand Up @@ -638,13 +647,13 @@ impl Message {
{
if let Some(cache) = cache_http.cache() {
if self.guild_id.is_some() {
let req = Permissions::SEND_MESSAGES;

if !super::utils::user_has_perms(cache, self.channel_id, self.guild_id, req)
.await?
{
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
utils::user_has_perms_cache(
cache,
self.channel_id,
self.guild_id,
Permissions::SEND_MESSAGES,
)
.await?;
}
}
}
Expand Down Expand Up @@ -680,14 +689,16 @@ impl Message {
#[cfg(feature = "cache")]
{
if let Some(cache) = cache_http.cache() {
let req = Permissions::MANAGE_MESSAGES;
let is_author = self.author.id == cache.current_user().await.id;
let has_perms =
super::utils::user_has_perms(&cache, self.channel_id, self.guild_id, req)
.await?;

if !is_author && !has_perms {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
utils::user_has_perms_cache(
cache,
self.channel_id,
self.guild_id,
Permissions::MANAGE_MESSAGES,
)
.await?;

if !(self.author.id == cache.current_user().await.id) {
return Err(Error::Model(ModelError::NotAuthor));
}
}
}
Expand Down Expand Up @@ -752,13 +763,13 @@ impl Message {
{
if let Some(cache) = cache_http.cache() {
if self.guild_id.is_some() {
let req = Permissions::MANAGE_MESSAGES;

if !super::utils::user_has_perms(cache, self.channel_id, self.guild_id, req)
.await?
{
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
utils::user_has_perms_cache(
cache,
self.channel_id,
self.guild_id,
Permissions::MANAGE_MESSAGES,
)
.await?;
}
}
}
Expand Down Expand Up @@ -1002,7 +1013,7 @@ enum_number!(MessageActivityKind {
JOIN,
SPECTATE,
LISTEN,
JOIN_REQUEST,
JOIN_REQUEST
});

impl MessageActivityKind {
Expand Down
2 changes: 1 addition & 1 deletion src/model/channel/mod.rs
Expand Up @@ -314,7 +314,7 @@ enum_number!(ChannelType {
Voice,
Category,
News,
Store,
Store
});

impl ChannelType {
Expand Down
31 changes: 17 additions & 14 deletions src/model/channel/reaction.rs
Expand Up @@ -84,14 +84,13 @@ impl Reaction {
}

if user_id.is_some() {
let req = Permissions::MANAGE_MESSAGES;

if !utils::user_has_perms(cache, self.channel_id, None, req)
.await
.unwrap_or(true)
{
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
utils::user_has_perms_cache(
cache,
self.channel_id,
self.guild_id,
Permissions::MANAGE_MESSAGES,
)
.await?;
}
}
}
Expand Down Expand Up @@ -120,11 +119,13 @@ impl Reaction {
#[cfg(feature = "cache")]
{
if let Some(cache) = cache_http.cache() {
let req = Permissions::MANAGE_MESSAGES;

if !utils::user_has_perms(cache, self.channel_id, self.guild_id, req).await? {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
utils::user_has_perms_cache(
cache,
self.channel_id,
self.guild_id,
Permissions::MANAGE_MESSAGES,
)
.await?;
}
}
cache_http
Expand Down Expand Up @@ -379,7 +380,9 @@ impl ReactionType {
id,
ref name,
..
} => format!("{}:{}", name.as_ref().map_or("", |s| s.as_str()), id),
} => {
format!("{}:{}", name.as_ref().map_or("", |s| s.as_str()), id)
},
ReactionType::Unicode(ref unicode) => unicode.clone(),
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/model/channel/sticker.rs
Expand Up @@ -39,7 +39,7 @@ pub enum StickerFormatType {
enum_number!(StickerFormatType {
Png,
Apng,
Lottie,
Lottie
});

impl StickerFormatType {
Expand Down
18 changes: 18 additions & 0 deletions src/model/error.rs
Expand Up @@ -145,6 +145,23 @@ pub enum Error {
NameTooShort,
/// Indicates that the webhook name is over the 100 characters limit.
NameTooLong,
/// Indicates that the bot is not author of the message.
NotAuthor,
}

impl Error {
/// Return `true` if the model error is related to an item missing in the
/// cache.
pub fn is_cache_err(&self) -> bool {
match self {
Self::ItemMissing
| Self::ChannelNotFound
| Self::RoleNotFound
| Self::GuildNotFound
| Self::MemberNotFound => true,
_ => false,
}
}
}

impl Display for Error {
Expand All @@ -167,6 +184,7 @@ impl Display for Error {
Error::MessagingBot => f.write_str("Attempted to message another bot user."),
Error::NameTooShort => f.write_str("Name is under the character limit."),
Error::NameTooLong => f.write_str("Name is over the character limit."),
Error::NotAuthor => f.write_str("The bot is not author of this message."),
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/model/gateway.rs
Expand Up @@ -455,7 +455,7 @@ enum_number!(ActivityType {
Streaming,
Listening,
Custom,
Competing,
Competing
});

impl ActivityType {
Expand Down
8 changes: 4 additions & 4 deletions src/model/guild/mod.rs
Expand Up @@ -2394,7 +2394,7 @@ pub enum DefaultMessageNotificationLevel {

enum_number!(DefaultMessageNotificationLevel {
All,
Mentions,
Mentions
});

impl DefaultMessageNotificationLevel {
Expand All @@ -2421,7 +2421,7 @@ pub enum ExplicitContentFilter {
enum_number!(ExplicitContentFilter {
None,
WithoutRole,
All,
All
});

impl ExplicitContentFilter {
Expand All @@ -2446,7 +2446,7 @@ pub enum MfaLevel {

enum_number!(MfaLevel {
None,
Elevated,
Elevated
});

impl MfaLevel {
Expand Down Expand Up @@ -2547,7 +2547,7 @@ enum_number!(VerificationLevel {
Low,
Medium,
High,
Higher,
Higher
});

impl VerificationLevel {
Expand Down
2 changes: 1 addition & 1 deletion src/model/guild/premium_tier.rs
Expand Up @@ -13,7 +13,7 @@ enum_number!(PremiumTier {
Tier0,
Tier1,
Tier2,
Tier3,
Tier3
});

impl PremiumTier {
Expand Down

0 comments on commit 2812236

Please sign in to comment.