forked from jmug/stoatchat
feat: Add Mass Mentions to the backend (#394)
* feat: create base of push daemon Signed-off-by: IAmTomahawkx <iamtomahawkx@gmail.com> * Add outbound senders * Make web_push send to rabbit instead (temp stuff) * feat: stability and friend requests * make vapid fr stuff not suck * swap naming of queue * move pushd into daemons folder * fix cargo file for move into daemons folder * feat: probably working fcm push notifs * comment out fcm webpush stuff since the config keys dont exist * fix fcm, name queues according to their prod status and configure routing keys * add pushd to docker * mix: Remove old code, add stuff to pushd * fix: lockfile * feat: update rocket to 5.0.1 * fix: fix queues and ack bugs * Move rabbit messsage processing into ack queue * chore: update readme * chore: optimizations for ack database hits * pushd flowchart * misc: update flowchart * exit dependancy hell * add rocket_impl flag to authifier * make the tests file of delta actually compile * fix: don't silence every push message * fix: don't silence all messages * add debug logging for sending data to rabbit from message events * validate mentions at a server membership level * put back that import that was actually important * minor fix to lockfile * update delta authifier * feat: proper permissions for push notifications * add unit test for mention sanitization * remove local file dependancy on authifier * update ports to proper defaults * fixTM the node bindings * Theoretically configure docker releases for pushd Signed-off-by: IAmTomahawkx <iamtomahawkx@gmail.com> * declare exchange in pushd and delta * fix createbuckets script Signed-off-by: IAmTomahawkx <iamtomahawkx@gmail.com> * fix: reference db implementation Signed-off-by: IAmTomahawkx <iamtomahawkx@gmail.com> * fix: remove finally redundant code Signed-off-by: IAmTomahawkx <iamtomahawkx@gmail.com> * fix: changes Signed-off-by: IAmTomahawkx <iamtomahawkx@gmail.com> * fix: other changes Signed-off-by: IAmTomahawkx <iamtomahawkx@gmail.com> * fix: make channel name return result Signed-off-by: IAmTomahawkx <iamtomahawkx@gmail.com> * Add role mention parsing * feat: update to mongo 3.1, add member generator. * integrate mass mentions into pushd * patch redis-rs with updated versions * feat: chunk role mentions * move permission bits to 37/38 to avoid livekit conflict * change role mention format to <%id> * fix the lockfile from merge * fix: PR change requests * feat: add tests * fix: i am a dumbass * fix: tests, again --------- Signed-off-by: IAmTomahawkx <iamtomahawkx@gmail.com>
This commit is contained in:
@@ -117,10 +117,11 @@ mod test {
|
||||
use crate::{rocket, util::test::TestHarness};
|
||||
use revolt_database::{
|
||||
util::{idempotency::IdempotencyKey, reference::Reference},
|
||||
Channel, Member, Message, PartialChannel, PartialMember, Role, Server,
|
||||
Channel, Member, Message, MessageFlagsValue, PartialChannel, PartialMember, Role, Server,
|
||||
};
|
||||
use revolt_models::v0::{self, DataCreateServerChannel};
|
||||
use revolt_models::v0::{self, DataCreateServerChannel, MessageFlags};
|
||||
use revolt_permissions::{ChannelPermission, OverrideField};
|
||||
use revolt_result::ErrorType;
|
||||
|
||||
#[rocket::async_test]
|
||||
async fn message_mention_constraints() {
|
||||
@@ -486,4 +487,193 @@ mod test {
|
||||
.await
|
||||
.expect_err("Created message with missing reply and none fail");
|
||||
}
|
||||
|
||||
#[rocket::async_test]
|
||||
async fn mass_mentions_test() {
|
||||
let harness = TestHarness::new().await;
|
||||
let (_, _, user) = harness.new_user().await;
|
||||
let (_, _, other_user) = harness.new_user().await;
|
||||
let (server, _) = harness.new_server(&user).await;
|
||||
let channel = harness.new_channel(&server).await;
|
||||
let (role_id, mut role) = harness
|
||||
.new_role(
|
||||
&server,
|
||||
1,
|
||||
Some(OverrideField {
|
||||
a: (ChannelPermission::MentionEveryone as i64)
|
||||
| (ChannelPermission::MentionRoles as i64),
|
||||
d: 0,
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
let (mut other_member, _) = Member::create(&harness.db, &server, &other_user, None)
|
||||
.await
|
||||
.expect("Failed to add test member");
|
||||
|
||||
// Send a message with an everyone and role mention.
|
||||
// Should fail
|
||||
let bad_message_with_mentions = Message::create_from_api(
|
||||
&harness.db,
|
||||
Some(&harness.amqp),
|
||||
channel.clone(),
|
||||
v0::DataMessageSend {
|
||||
content: Some(format!("Mentioning @everyone and role <%{}>", &role_id)),
|
||||
nonce: None,
|
||||
attachments: None,
|
||||
replies: None,
|
||||
embeds: None,
|
||||
masquerade: None,
|
||||
interactions: None,
|
||||
flags: None,
|
||||
},
|
||||
v0::MessageAuthor::User(
|
||||
&other_user
|
||||
.clone()
|
||||
.into(&harness.db, Some(&other_user))
|
||||
.await,
|
||||
),
|
||||
Some(
|
||||
other_user
|
||||
.clone()
|
||||
.into(&harness.db, Some(&other_user))
|
||||
.await,
|
||||
),
|
||||
Some(other_member.clone().into()),
|
||||
other_user.limits().await,
|
||||
IdempotencyKey::unchecked_from_string("1".to_string()),
|
||||
false,
|
||||
true,
|
||||
)
|
||||
.await
|
||||
.expect_err("Should not have created message with everyone and role pings");
|
||||
|
||||
assert!(
|
||||
matches!(
|
||||
bad_message_with_mentions.error_type,
|
||||
ErrorType::MissingPermission { .. }
|
||||
),
|
||||
"Intentional permissions error did not return MissingPermission"
|
||||
);
|
||||
|
||||
// Send a mass mention inside a codeblock.
|
||||
// Should be undetected and therefor pass
|
||||
let message_with_codeblock = Message::create_from_api(
|
||||
&harness.db,
|
||||
Some(&harness.amqp),
|
||||
channel.clone(),
|
||||
v0::DataMessageSend {
|
||||
content: Some(format!("Mentioning `@everyone` and role `<%{}>`", &role_id)),
|
||||
nonce: None,
|
||||
attachments: None,
|
||||
replies: None,
|
||||
embeds: None,
|
||||
masquerade: None,
|
||||
interactions: None,
|
||||
flags: None,
|
||||
},
|
||||
v0::MessageAuthor::User(
|
||||
&other_user
|
||||
.clone()
|
||||
.into(&harness.db, Some(&other_user))
|
||||
.await,
|
||||
),
|
||||
Some(
|
||||
other_user
|
||||
.clone()
|
||||
.into(&harness.db, Some(&other_user))
|
||||
.await,
|
||||
),
|
||||
Some(other_member.clone().into()),
|
||||
other_user.limits().await,
|
||||
IdempotencyKey::unchecked_from_string("1".to_string()),
|
||||
false,
|
||||
true,
|
||||
)
|
||||
.await
|
||||
.expect("Failed to create message with everyone and role pings in codeblocks");
|
||||
|
||||
assert!(
|
||||
message_with_codeblock.flags.is_none()
|
||||
|| !MessageFlagsValue(message_with_codeblock.flags.unwrap())
|
||||
.has(MessageFlags::MentionsEveryone),
|
||||
"Message flags mentions everyone when inside codeblock",
|
||||
);
|
||||
|
||||
assert!(
|
||||
message_with_codeblock.role_mentions.is_none(),
|
||||
"Role mentions detected when inside codeblock"
|
||||
);
|
||||
|
||||
other_member.roles.push(role_id.clone());
|
||||
harness
|
||||
.db
|
||||
.update_member(
|
||||
&other_member.id,
|
||||
&PartialMember {
|
||||
avatar: None,
|
||||
id: None,
|
||||
joined_at: None,
|
||||
nickname: None,
|
||||
roles: Some(vec![role_id.clone()]),
|
||||
timeout: None,
|
||||
},
|
||||
vec![],
|
||||
)
|
||||
.await
|
||||
.expect("Failed to add role to user");
|
||||
|
||||
// Send a message with an everyone and role mention.
|
||||
// Should succeed
|
||||
let message_with_mentions = Message::create_from_api(
|
||||
&harness.db,
|
||||
Some(&harness.amqp),
|
||||
channel.clone(),
|
||||
v0::DataMessageSend {
|
||||
content: Some(format!("Mentioning @everyone and role <%{}>", &role_id)),
|
||||
nonce: None,
|
||||
attachments: None,
|
||||
replies: None,
|
||||
embeds: None,
|
||||
masquerade: None,
|
||||
interactions: None,
|
||||
flags: None,
|
||||
},
|
||||
v0::MessageAuthor::User(
|
||||
&other_user
|
||||
.clone()
|
||||
.into(&harness.db, Some(&other_user))
|
||||
.await,
|
||||
),
|
||||
Some(
|
||||
other_user
|
||||
.clone()
|
||||
.into(&harness.db, Some(&other_user))
|
||||
.await,
|
||||
),
|
||||
Some(other_member.clone().into()),
|
||||
other_user.limits().await,
|
||||
IdempotencyKey::unchecked_from_string("1".to_string()),
|
||||
false,
|
||||
true,
|
||||
)
|
||||
.await
|
||||
.expect("Failed to create message with everyone and role pings");
|
||||
|
||||
assert!(
|
||||
message_with_mentions.flags.is_some(),
|
||||
"Message flags is None",
|
||||
);
|
||||
|
||||
assert!(
|
||||
MessageFlagsValue(message_with_mentions.flags.unwrap())
|
||||
.has(MessageFlags::MentionsEveryone),
|
||||
"Message flags does not mention everyone. Flag value is {}",
|
||||
message_with_mentions.flags.unwrap()
|
||||
);
|
||||
|
||||
assert!(
|
||||
message_with_mentions.role_mentions.is_some(),
|
||||
"Message has no role mentions"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,11 +5,12 @@ use authifier::{
|
||||
use futures::StreamExt;
|
||||
use rand::Rng;
|
||||
use redis_kiss::redis::aio::PubSub;
|
||||
use revolt_database::util::idempotency::IdempotencyKey;
|
||||
use revolt_database::{
|
||||
events::client::EventV1, Channel, Database, Member, Message, Server, User, AMQP,
|
||||
};
|
||||
use revolt_database::{util::idempotency::IdempotencyKey, Role};
|
||||
use revolt_models::v0;
|
||||
use revolt_permissions::OverrideField;
|
||||
use rocket::http::Header;
|
||||
use rocket::local::asynchronous::{Client, LocalRequest, LocalResponse};
|
||||
|
||||
@@ -122,6 +123,28 @@ impl TestHarness {
|
||||
.expect("Failed to create test server")
|
||||
}
|
||||
|
||||
pub async fn new_role(
|
||||
&self,
|
||||
server: &Server,
|
||||
rank: i64,
|
||||
overrides: Option<OverrideField>,
|
||||
) -> (String, Role) {
|
||||
let role = Role {
|
||||
name: TestHarness::rand_string(),
|
||||
permissions: overrides.unwrap_or(OverrideField { a: 0, d: 0 }),
|
||||
rank,
|
||||
colour: None,
|
||||
hoist: false,
|
||||
};
|
||||
|
||||
let id = role
|
||||
.create(&self.db, &server.id)
|
||||
.await
|
||||
.expect("Failed to create test role");
|
||||
|
||||
(id, role)
|
||||
}
|
||||
|
||||
pub async fn new_channel(&self, server: &Server) -> Channel {
|
||||
Channel::create_server_channel(
|
||||
&self.db,
|
||||
|
||||
Reference in New Issue
Block a user