diff --git a/Cargo.lock b/Cargo.lock index 19dc7f4a..9919d355 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2580,8 +2580,8 @@ dependencies = [ [[package]] name = "rauth" -version = "1.0.3" -source = "git+https://github.com/insertish/rauth?tag=1.0.3#a62eae5076d94730d06e76d438cbca0d70161856" +version = "1.0.4" +source = "git+https://github.com/insertish/rauth?tag=1.0.4#2d3bc59623672e3ff57c49a90c4d3cd20780dbba" dependencies = [ "async-std", "async-trait", @@ -3080,8 +3080,8 @@ dependencies = [ [[package]] name = "rocket_rauth" -version = "1.0.3" -source = "git+https://github.com/insertish/rauth?tag=1.0.3#a62eae5076d94730d06e76d438cbca0d70161856" +version = "1.0.4" +source = "git+https://github.com/insertish/rauth?tag=1.0.4#2d3bc59623672e3ff57c49a90c4d3cd20780dbba" dependencies = [ "iso8601-timestamp", "rauth", diff --git a/crates/delta/src/routes/channels/message_send.rs b/crates/delta/src/routes/channels/message_send.rs index e7dceb4b..59aa03df 100644 --- a/crates/delta/src/routes/channels/message_send.rs +++ b/crates/delta/src/routes/channels/message_send.rs @@ -65,16 +65,20 @@ pub async fn message_send( data.validate() .map_err(|error| Error::FailedValidation { error })?; + // Validate Message is within reasonable length limits Message::validate_sum(&data.content, &data.embeds)?; + // Ensure the request is unique idempotency.consume_nonce(data.nonce).await?; + // Ensure we have permissions to send a message let channel = target.as_channel(db).await?; let mut permissions = perms(&user).channel(&channel); permissions .throw_permission_and_view_channel(db, Permission::SendMessage) .await?; + // 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())) @@ -82,6 +86,22 @@ pub async fn message_send( return Err(Error::EmptyMessage); } + // Ensure restrict_reactions is not specified without reactions list + if let Some(interactions) = &data.interactions { + if interactions.restrict_reactions { + let disallowed = if let Some(list) = &interactions.reactions { + list.len() == 0 + } else { + true + }; + + if disallowed { + return Err(Error::InvalidProperty); + } + } + } + + // Start constructing the message let message_id = Ulid::new().to_string(); let mut message = Message { id: message_id.clone(), diff --git a/crates/quark/src/models/channels/message.rs b/crates/quark/src/models/channels/message.rs index ee9e61cf..2eb91733 100644 --- a/crates/quark/src/models/channels/message.rs +++ b/crates/quark/src/models/channels/message.rs @@ -98,6 +98,8 @@ pub struct Interactions { #[serde(skip_serializing_if = "Option::is_none", default)] pub reactions: Option>, /// Whether reactions should be restricted to the given list + /// + /// Can only be set to true if reactions list is of at least length 1 #[serde(skip_serializing_if = "if_false", default)] pub restrict_reactions: bool, } diff --git a/crates/quark/src/util/result.rs b/crates/quark/src/util/result.rs index 995ad6e2..628c8303 100644 --- a/crates/quark/src/util/result.rs +++ b/crates/quark/src/util/result.rs @@ -20,10 +20,10 @@ pub enum Error { /// This error was not labeled :( LabelMe, - // ? Onboarding related errors. + // ? Onboarding related errors AlreadyOnboarded, - // ? User related errors. + // ? User related errors UsernameTaken, InvalidUsername, UnknownUser, @@ -33,7 +33,7 @@ pub enum Error { BlockedByOther, NotFriends, - // ? Channel related errors. + // ? Channel related errors UnknownChannel, UnknownAttachment, UnknownMessage, @@ -50,7 +50,7 @@ pub enum Error { AlreadyInGroup, NotInGroup, - // ? Server related errors. + // ? Server related errors UnknownServer, InvalidRole, Banned, @@ -59,12 +59,12 @@ pub enum Error { }, TooManyEmoji, - // ? Bot related errors. + // ? Bot related errors ReachedMaximumBots, IsBot, BotIsPrivate, - // ? Permission errors. + // ? Permission errors MissingPermission { permission: Permission, }, @@ -75,7 +75,7 @@ pub enum Error { CannotGiveMissingPermissions, NotOwner, - // ? General errors. + // ? General errors DatabaseError { operation: &'static str, with: &'static str, @@ -83,6 +83,7 @@ pub enum Error { InternalError, InvalidOperation, InvalidCredentials, + InvalidProperty, InvalidSession, DuplicateNonce, VosoUnavailable, @@ -175,6 +176,7 @@ impl<'r> Responder<'r, 'static> for Error { Error::InternalError => Status::InternalServerError, Error::InvalidOperation => Status::BadRequest, Error::InvalidCredentials => Status::Unauthorized, + Error::InvalidProperty => Status::BadRequest, Error::InvalidSession => Status::Unauthorized, Error::DuplicateNonce => Status::Conflict, Error::VosoUnavailable => Status::BadRequest,