From 8f4d6c864bf55c6539cb6e3c7b4d50edf90395e1 Mon Sep 17 00:00:00 2001 From: Paul Makles Date: Sat, 10 Feb 2024 01:04:52 +0000 Subject: [PATCH] feat: block mentions from low trust users (account created < 12 hours) --- .../database/src/models/messages/model.rs | 13 +++++++----- crates/core/database/src/util/permissions.rs | 20 +++++++++++++++++++ .../delta/src/routes/channels/message_send.rs | 19 ++++++++++++++++++ .../src/routes/webhooks/webhook_execute.rs | 1 + 4 files changed, 48 insertions(+), 5 deletions(-) diff --git a/crates/core/database/src/models/messages/model.rs b/crates/core/database/src/models/messages/model.rs index 0cc4f069..1973aac1 100644 --- a/crates/core/database/src/models/messages/model.rs +++ b/crates/core/database/src/models/messages/model.rs @@ -212,6 +212,7 @@ impl Message { author: MessageAuthor<'_>, mut idempotency: IdempotencyKey, generate_embeds: bool, + allow_mentions: bool, ) -> Result { let config = config().await; @@ -272,10 +273,12 @@ impl Message { // Parse mentions in message. let mut mentions = HashSet::new(); - if let Some(content) = &data.content { - for capture in RE_MENTION.captures_iter(content) { - if let Some(mention) = capture.get(1) { - mentions.insert(mention.as_str().to_string()); + if allow_mentions { + if let Some(content) = &data.content { + for capture in RE_MENTION.captures_iter(content) { + if let Some(mention) = capture.get(1) { + mentions.insert(mention.as_str().to_string()); + } } } } @@ -292,7 +295,7 @@ impl Message { for ReplyIntent { id, mention } in entries { let message = db.fetch_message(&id).await?; - if mention { + if mention && allow_mentions { mentions.insert(message.author.to_owned()); } diff --git a/crates/core/database/src/util/permissions.rs b/crates/core/database/src/util/permissions.rs index ae6634a2..28972c06 100644 --- a/crates/core/database/src/util/permissions.rs +++ b/crates/core/database/src/util/permissions.rs @@ -444,6 +444,26 @@ impl<'a> DatabasePermissionQuery<'a> { ..self } } + + /// Access the underlying user + pub fn user_ref(&self) -> &Option> { + &self.user + } + + /// Access the underlying server + pub fn channel_ref(&self) -> &Option> { + &self.channel + } + + /// Access the underlying server + pub fn server_ref(&self) -> &Option> { + &self.server + } + + /// Access the underlying member + pub fn member_ref(&self) -> &Option> { + &self.member + } } /// Short-hand for creating a permission calculator diff --git a/crates/delta/src/routes/channels/message_send.rs b/crates/delta/src/routes/channels/message_send.rs index a194fc9d..ea403371 100644 --- a/crates/delta/src/routes/channels/message_send.rs +++ b/crates/delta/src/routes/channels/message_send.rs @@ -1,3 +1,4 @@ +use chrono::{Duration, Utc}; use revolt_database::util::permissions::DatabasePermissionQuery; use revolt_database::{ util::idempotency::IdempotencyKey, util::reference::Reference, Database, User, @@ -61,6 +62,23 @@ pub async fn message_send( interactions.validate(db, &permissions).await?; } + // Disallow mentions for new users (TRUST-0: <12 hours age) in public servers + let allow_mentions = if let Some(server) = query.server_ref() { + if server.discoverable { + if (Utc::now() - ulid::Ulid::from_string(&user.id).unwrap().datetime()) + < Duration::hours(12) + { + false + } else { + true + } + } else { + true + } + } else { + true + }; + // Create the message let author: v0::User = user.clone().into(db, Some(&user)).await; Ok(Json( @@ -71,6 +89,7 @@ pub async fn message_send( v0::MessageAuthor::User(&author), idempotency, permissions.has_channel_permission(ChannelPermission::SendEmbeds), + allow_mentions, ) .await? .into(), diff --git a/crates/delta/src/routes/webhooks/webhook_execute.rs b/crates/delta/src/routes/webhooks/webhook_execute.rs index 0b8e1b07..f370b186 100644 --- a/crates/delta/src/routes/webhooks/webhook_execute.rs +++ b/crates/delta/src/routes/webhooks/webhook_execute.rs @@ -60,6 +60,7 @@ pub async fn webhook_execute( v0::MessageAuthor::Webhook(&webhook.into()), idempotency, true, + true, ) .await? .into(),