diff --git a/Cargo.lock b/Cargo.lock index 7bdf672b..188c0419 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2837,7 +2837,7 @@ dependencies = [ [[package]] name = "revolt-bonfire" -version = "0.5.21" +version = "0.5.22" dependencies = [ "async-std", "async-tungstenite", @@ -2882,7 +2882,7 @@ dependencies = [ [[package]] name = "revolt-delta" -version = "0.5.21" +version = "0.5.22" dependencies = [ "async-channel", "async-std", @@ -2955,7 +2955,7 @@ dependencies = [ [[package]] name = "revolt-quark" -version = "0.5.21" +version = "0.5.22" dependencies = [ "async-lock", "async-recursion", diff --git a/crates/bonfire/Cargo.toml b/crates/bonfire/Cargo.toml index 9828f03d..e4d7d19e 100644 --- a/crates/bonfire/Cargo.toml +++ b/crates/bonfire/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "revolt-bonfire" -version = "0.5.21" +version = "0.5.22" license = "AGPL-3.0-or-later" edition = "2021" diff --git a/crates/delta/Cargo.toml b/crates/delta/Cargo.toml index 99b1d7c4..bb5a445f 100644 --- a/crates/delta/Cargo.toml +++ b/crates/delta/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "revolt-delta" -version = "0.5.21" +version = "0.5.22" license = "AGPL-3.0-or-later" authors = ["Paul Makles "] edition = "2018" diff --git a/crates/delta/src/routes/channels/message_edit.rs b/crates/delta/src/routes/channels/message_edit.rs index 228bbb87..cf6e6b74 100644 --- a/crates/delta/src/routes/channels/message_edit.rs +++ b/crates/delta/src/routes/channels/message_edit.rs @@ -44,8 +44,6 @@ pub async fn req( .throw_permission_and_view_channel(db, Permission::SendMessage) .await?; - Message::validate_sum(&edit.content, &edit.embeds)?; - let mut message = msg.as_message(db).await?; if message.channel != channel.id() { return Err(Error::NotFound); @@ -55,6 +53,12 @@ pub async fn req( return Err(Error::CannotEditMessage); } + if let Some(new_embeds) = &edit.embeds { + Message::validate_sum(&edit.content, new_embeds)?; + } else { + Message::validate_sum(&edit.content, &vec![])?; + } + message.edited = Some(Timestamp::now_utc()); let mut partial = PartialMessage { edited: message.edited, diff --git a/crates/delta/src/routes/channels/message_send.rs b/crates/delta/src/routes/channels/message_send.rs index 9645fffc..ef25699e 100644 --- a/crates/delta/src/routes/channels/message_send.rs +++ b/crates/delta/src/routes/channels/message_send.rs @@ -1,11 +1,9 @@ use revolt_quark::{ - models::{ - message::DataMessageSend, - Message, User, - }, + models::{message::DataMessageSend, Message, User}, perms, + types::push::MessageAuthor, web::idempotency::IdempotencyKey, - Db, Error, Permission, Ref, Result, types::push::MessageAuthor, + Db, Error, Permission, Ref, Result, }; use rocket::serde::json::Json; @@ -35,7 +33,7 @@ pub async fn message_send( .throw_permission_and_view_channel(db, Permission::SendMessage) .await?; - // Verify permissions for masquerade. + // Verify permissions for masquerade if let Some(masq) = &data.masquerade { permissions .throw_permission(db, Permission::Masquerade) @@ -48,8 +46,37 @@ pub async fn message_send( } } + // Check permissions for embeds + if !data.embeds.is_empty() { + permissions + .throw_permission(db, Permission::SendEmbeds) + .await?; + } + + // Check permissions for files + if !data.attachments.is_empty() { + permissions + .throw_permission(db, Permission::UploadFiles) + .await?; + } + + // Ensure interactions information is correct + if let Some(interactions) = &data.interactions { + interactions.validate(db, &mut permissions).await?; + } + // Create the message - let message = channel.send_message(db, data, MessageAuthor::User(&user), idempotency).await?; + let message = channel + .send_message( + db, + data, + MessageAuthor::User(&user), + idempotency, + permissions + .has_permission(db, Permission::SendEmbeds) + .await?, + ) + .await?; Ok(Json(message)) } diff --git a/crates/delta/src/routes/webhooks/webhook_execute.rs b/crates/delta/src/routes/webhooks/webhook_execute.rs index 94772d6a..60a56f93 100644 --- a/crates/delta/src/routes/webhooks/webhook_execute.rs +++ b/crates/delta/src/routes/webhooks/webhook_execute.rs @@ -33,6 +33,9 @@ pub async fn webhook_execute( 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 + let channel = legacy_db.fetch_channel(&webhook.channel_id).await?; let message = channel .send_message( @@ -40,6 +43,7 @@ pub async fn webhook_execute( data, MessageAuthor::Webhook(&webhook.into()), idempotency, + true, ) .await?; diff --git a/crates/quark/Cargo.toml b/crates/quark/Cargo.toml index da6a6e85..27fdd07a 100644 --- a/crates/quark/Cargo.toml +++ b/crates/quark/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "revolt-quark" -version = "0.5.21" +version = "0.5.22" edition = "2021" license = "AGPL-3.0-or-later" diff --git a/crates/quark/src/impl/generic/channels/channel.rs b/crates/quark/src/impl/generic/channels/channel.rs index 7c650f5a..cfcb7ce5 100644 --- a/crates/quark/src/impl/generic/channels/channel.rs +++ b/crates/quark/src/impl/generic/channels/channel.rs @@ -409,6 +409,7 @@ impl Channel { data: DataMessageSend, author: MessageAuthor<'_>, mut idempotency: IdempotencyKey, + generate_embeds: bool, ) -> Result { Message::validate_sum(&data.content, &data.embeds)?; @@ -416,8 +417,8 @@ impl Channel { // Check the message is not empty if (data.content.as_ref().map_or(true, |v| v.is_empty())) - && (data.attachments.as_ref().map_or(true, |v| v.is_empty())) - && (data.embeds.as_ref().map_or(true, |v| v.is_empty())) + && (data.attachments.is_empty()) + && (data.embeds.is_empty()) { return Err(Error::EmptyMessage); } @@ -496,10 +497,8 @@ impl Channel { // Process included embeds. let mut embeds = vec![]; - if let Some(sendable_embeds) = data.embeds { - for sendable_embed in sendable_embeds { - embeds.push(sendable_embed.into_embed(db, message_id.clone()).await?) - } + for sendable_embed in data.embeds { + embeds.push(sendable_embed.into_embed(db, message_id.clone()).await?) } if !embeds.is_empty() { @@ -508,24 +507,17 @@ impl Channel { // Add attachments to message. let mut attachments = vec![]; - if let Some(ids) = &data.attachments { - if ids.len() > *MAX_ATTACHMENT_COUNT { - return Err(Error::TooManyAttachments { - max: *MAX_ATTACHMENT_COUNT, - }); - } + if data.attachments.len() > *MAX_ATTACHMENT_COUNT { + return Err(Error::TooManyAttachments { + max: *MAX_ATTACHMENT_COUNT, + }); + } - for attachment_id in ids { - attachments.push( - db.find_and_use_attachment( - attachment_id, - "attachments", - "message", - &message_id, - ) + for attachment_id in data.attachments { + attachments.push( + db.find_and_use_attachment(&attachment_id, "attachments", "message", &message_id) .await?, - ); - } + ); } if !attachments.is_empty() { @@ -541,13 +533,15 @@ impl Channel { message.create(db, self, Some(author)).await?; // Queue up a task for processing embeds - if let Some(content) = &message.content { - process_embeds::queue( - self.id().to_string(), - message.id.to_string(), - content.clone(), - ) - .await; + if generate_embeds { + if let Some(content) = &message.content { + process_embeds::queue( + self.id().to_string(), + message.id.to_string(), + content.clone(), + ) + .await; + } } Ok(message) diff --git a/crates/quark/src/impl/generic/channels/message.rs b/crates/quark/src/impl/generic/channels/message.rs index 5655606e..dcf56de3 100644 --- a/crates/quark/src/impl/generic/channels/message.rs +++ b/crates/quark/src/impl/generic/channels/message.rs @@ -18,7 +18,7 @@ use crate::{ tasks::ack::AckEvent, types::{ january::{Embed, Text}, - push::{PushNotification, MessageAuthor}, + push::{MessageAuthor, PushNotification}, }, Database, Error, Permission, Result, }; @@ -170,20 +170,15 @@ impl Message { } /// Validate the sum of content of a message is under threshold - pub fn validate_sum( - content: &Option, - embeds: &Option>, - ) -> Result<()> { + pub fn validate_sum(content: &Option, embeds: &Vec) -> Result<()> { let mut running_total = 0; if let Some(content) = content { running_total += content.len(); } - if let Some(embeds) = embeds { - for embed in embeds { - if let Some(desc) = &embed.description { - running_total += desc.len(); - } + for embed in embeds { + if let Some(desc) = &embed.description { + running_total += desc.len(); } } diff --git a/crates/quark/src/models/channels/message.rs b/crates/quark/src/models/channels/message.rs index 917e35d1..3aa2c8c6 100644 --- a/crates/quark/src/models/channels/message.rs +++ b/crates/quark/src/models/channels/message.rs @@ -268,15 +268,16 @@ pub struct DataMessageSend { #[validate(length(min = 0, max = 2000))] pub content: Option, /// Attachments to include in message - #[validate(length(min = 1, max = 128))] - pub attachments: Option>, + #[serde(default)] + pub attachments: Vec, /// Messages to reply to pub replies: Option>, /// Embeds to include in message /// /// Text embed content contributes to the content length cap + #[serde(default)] #[validate(length(min = 1, max = 10))] - pub embeds: Option>, + pub embeds: Vec, /// Masquerade to apply to this message #[validate] pub masquerade: Option,