Skip to content

Commit

Permalink
feat: add webhook permissions
Browse files Browse the repository at this point in the history
  • Loading branch information
Zomatree authored and insertish committed Jul 2, 2023
1 parent 6e4798f commit 54878e8
Show file tree
Hide file tree
Showing 11 changed files with 81 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::{
};
use futures::StreamExt;
use rand::seq::SliceRandom;
use revolt_permissions::DEFAULT_WEBHOOK_PERMISSIONS;
use serde::{Deserialize, Serialize};
use unicode_segmentation::UnicodeSegmentation;

Expand Down Expand Up @@ -945,6 +946,23 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 {
)
.await
.expect("Failed to create username index.");
};

if revision <= 25 {
info!("Running migration [revision 25 / 11-06-2023]: Add permissions to webhooks.");

db.col::<Document>("webhooks")
.update_many(
doc! {},
doc! {
"$set": {
"permissions": *DEFAULT_WEBHOOK_PERMISSIONS as i64
}
},
None,
)
.await
.expect("Failed to update webhooks.");
}

if revision <= 25 {
Expand Down
3 changes: 3 additions & 0 deletions crates/core/database/src/models/channel_webhooks/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ auto_derived_partial!(
/// The channel this webhook belongs to
pub channel_id: String,

/// The permissions of the webhook
pub permissions: u64,

/// The private token for the webhook
pub token: Option<String>,
},
Expand Down
2 changes: 2 additions & 0 deletions crates/core/database/src/util/bridge/v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ impl From<crate::Webhook> for Webhook {
avatar: value.avatar.map(|file| file.into()),
channel_id: value.channel_id,
token: value.token,
permissions: value.permissions
}
}
}
Expand All @@ -64,6 +65,7 @@ impl From<crate::PartialWebhook> for PartialWebhook {
avatar: value.avatar.map(|file| file.into()),
channel_id: value.channel_id,
token: value.token,
permissions: value.permissions
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions crates/core/models/src/v0/channel_webhooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ auto_derived_partial!(
/// The channel this webhook belongs to
pub channel_id: String,

/// The permissions for the webhook
pub permissions: u64,

/// The private token for the webhook
pub token: Option<String>,
},
Expand Down Expand Up @@ -43,6 +46,9 @@ auto_derived!(
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 128)))]
pub avatar: Option<String>,

/// Webhook permissions
pub permissions: Option<u64>,

/// Fields to remove from webhook
#[cfg_attr(feature = "serde", serde(default))]
pub remove: Vec<FieldsWebhook>,
Expand All @@ -61,6 +67,9 @@ auto_derived!(

/// The channel this webhook belongs to
pub channel_id: String,

/// The permissions for the webhook
pub permissions: u64
}

/// Optional fields on webhook object
Expand All @@ -85,6 +94,7 @@ impl From<Webhook> for ResponseWebhook {
name: value.name,
avatar: value.avatar.map(|file| file.id),
channel_id: value.channel_id,
permissions: value.permissions
}
}
}
2 changes: 2 additions & 0 deletions crates/core/permissions/src/models/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,5 @@ pub static DEFAULT_PERMISSION_SERVER: Lazy<u64> = Lazy::new(|| {
+ ChannelPermission::ChangeAvatar,
)
});

pub static DEFAULT_WEBHOOK_PERMISSIONS: Lazy<u64> = Lazy::new(|| ChannelPermission::SendMessage + ChannelPermission::SendEmbeds + ChannelPermission::Masquerade + ChannelPermission::React);
2 changes: 2 additions & 0 deletions crates/delta/src/routes/channels/webhook_create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use revolt_database::{Database, Webhook};
use revolt_quark::{
models::{Channel, User},
perms, Db, Error, Permission, Ref, Result,
DEFAULT_WEBHOOK_PERMISSIONS,
};
use rocket::{serde::json::Json, State};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -60,6 +61,7 @@ pub async fn req(
name: data.name,
avatar,
channel_id: channel.id().to_string(),
permissions: *DEFAULT_WEBHOOK_PERMISSIONS,
token: Some(nanoid::nanoid!(64)),
};

Expand Down
2 changes: 2 additions & 0 deletions crates/delta/src/routes/webhooks/webhook_edit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@ pub async fn webhook_edit(
let DataEditWebhook {
name,
avatar,
permissions,
remove,
} = data;

let mut partial = PartialWebhook {
name,
permissions,
..Default::default()
};

Expand Down
4 changes: 3 additions & 1 deletion crates/delta/src/routes/webhooks/webhook_edit_token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@ pub async fn webhook_edit_token(
let DataEditWebhook {
name,
avatar,
remove,
permissions,
remove
} = data;

let mut partial = PartialWebhook {
name,
permissions,
..Default::default()
};

Expand Down
3 changes: 1 addition & 2 deletions crates/delta/src/routes/webhooks/webhook_execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ pub async fn webhook_execute(
let webhook = webhook_id.as_webhook(db).await.map_err(Error::from_core)?;
webhook.assert_token(&token).map_err(Error::from_core)?;

// TODO: webhooks can currently always send masquerades, files, embeds, reactions (interactions)
// TODO: they can also mention anyone
data.validate_webhook_permissions(webhook.permissions)?;

let channel = legacy_db.fetch_channel(&webhook.channel_id).await?;
let message = channel
Expand Down
38 changes: 37 additions & 1 deletion crates/quark/src/impl/generic/channels/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{
models::{
message::{
AppendMessage, BulkMessageResponse, Interactions, PartialMessage, SendableEmbed,
SystemMessage,
SystemMessage, DataMessageSend,
},
Channel, Emoji, Message, User,
},
Expand Down Expand Up @@ -451,3 +451,39 @@ impl Interactions {
!self.restrict_reactions && self.reactions.is_none()
}
}


fn throw_permission(permissions: u64, permission: Permission) -> Result<()> {
if (permission as u64) & permissions == (permission as u64) {
Ok(())
} else {
Err(Error::MissingPermission { permission })
}
}

impl DataMessageSend {
pub fn validate_webhook_permissions(
&self,
permissions: u64,
) -> Result<()> {
throw_permission(permissions, Permission::SendMessage)?;

if self.attachments.as_ref().map_or(false, |v| !v.is_empty()) {
throw_permission(permissions, Permission::UploadFiles)?;
};

if self.embeds.as_ref().map_or(false, |v| !v.is_empty()) {
throw_permission(permissions, Permission::SendEmbeds)?;
};

if self.masquerade.is_some() {
throw_permission(permissions, Permission::Masquerade)?;
};

if self.interactions.is_some() {
throw_permission(permissions, Permission::React)?;
};

Ok(())
}
}
1 change: 1 addition & 0 deletions crates/quark/src/permissions/defn/permission.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ pub static DEFAULT_PERMISSION: Lazy<u64> = Lazy::new(|| DEFAULT_PERMISSION_VIEW_
pub static DEFAULT_PERMISSION_SAVED_MESSAGES: u64 = Permission::GrantAllSafe as u64;
pub static DEFAULT_PERMISSION_DIRECT_MESSAGE: Lazy<u64> = Lazy::new(|| DEFAULT_PERMISSION.add(Permission::ManageChannel + Permission::React));
pub static DEFAULT_PERMISSION_SERVER: Lazy<u64> = Lazy::new(|| DEFAULT_PERMISSION.add(Permission::React + Permission::ChangeNickname + Permission::ChangeAvatar));
pub static DEFAULT_WEBHOOK_PERMISSIONS: Lazy<u64> = Lazy::new(|| Permission::SendMessage + Permission::SendEmbeds + Permission::Masquerade + Permission::React);

bitfield! {
#[derive(Default)]
Expand Down

0 comments on commit 54878e8

Please sign in to comment.