Feat: Push notification server (#387)

* 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>

---------

Signed-off-by: IAmTomahawkx <iamtomahawkx@gmail.com>
This commit is contained in:
Tom
2024-11-28 13:34:17 -08:00
committed by GitHub
parent ed5ded5e45
commit b55765d7c7
71 changed files with 3463 additions and 1059 deletions

View File

@@ -1,5 +1,6 @@
use revolt_database::{
util::{permissions::DatabasePermissionQuery, reference::Reference}, Database, FieldsMessage, PartialMessage, SystemMessage, User
util::{permissions::DatabasePermissionQuery, reference::Reference},
Database, FieldsMessage, PartialMessage, SystemMessage, User, AMQP,
};
use revolt_models::v0::MessageAuthor;
use revolt_permissions::{calculate_channel_permissions, ChannelPermission};
@@ -14,6 +15,7 @@ use rocket_empty::EmptyResponse;
#[delete("/<target>/messages/<msg>/pin")]
pub async fn message_unpin(
db: &State<Database>,
amqp: &State<AMQP>,
user: User,
target: Reference,
msg: Reference,
@@ -28,27 +30,31 @@ pub async fn message_unpin(
let mut message = msg.as_message_in_channel(db, channel.id()).await?;
if !message.pinned.unwrap_or_default() {
return Err(create_error!(NotPinned))
return Err(create_error!(NotPinned));
}
message.update(db, PartialMessage::default(), vec![FieldsMessage::Pinned]).await?;
message
.update(db, PartialMessage::default(), vec![FieldsMessage::Pinned])
.await?;
SystemMessage::MessageUnpinned {
id: message.id.clone(),
by: user.id.clone()
by: user.id.clone(),
}
.into_message(channel.id().to_string())
.send(
db,
Some(amqp),
MessageAuthor::System {
username: &user.username,
avatar: user.avatar.as_ref().map(|file| file.id.as_ref())
avatar: user.avatar.as_ref().map(|file| file.id.as_ref()),
},
None,
None,
&channel,
false
).await?;
false,
)
.await?;
Ok(EmptyResponse)
}
@@ -56,7 +62,11 @@ pub async fn message_unpin(
#[cfg(test)]
mod test {
use crate::{rocket, util::test::TestHarness};
use revolt_database::{events::client::EventV1, util::{idempotency::IdempotencyKey, reference::Reference}, Member, Message, PartialMessage, Server};
use revolt_database::{
events::client::EventV1,
util::{idempotency::IdempotencyKey, reference::Reference},
Member, Message, PartialMessage, Server,
};
use revolt_models::v0::{self, FieldsMessage, SystemMessage};
use rocket::http::{Header, Status};
@@ -72,26 +82,34 @@ mod test {
..Default::default()
},
&user,
true
).await.expect("Failed to create test server");
true,
)
.await
.expect("Failed to create test server");
let channel = &channels[0];
Member::create(&harness.db, &server, &user, Some(channels.clone())).await.expect("Failed to create member");
let member = Reference::from_unchecked(user.id.clone()).as_member(&harness.db, &server.id).await.expect("Failed to get member");
Member::create(&harness.db, &server, &user, Some(channels.clone()))
.await
.expect("Failed to create member");
let member = Reference::from_unchecked(user.id.clone())
.as_member(&harness.db, &server.id)
.await
.expect("Failed to get member");
let message = Message::create_from_api(
&harness.db,
None,
channel.clone(),
v0::DataMessageSend {
content:Some("Test message".to_string()),
content: Some("Test message".to_string()),
nonce: None,
attachments: None,
replies: None,
embeds: None,
masquerade: None,
interactions: None,
flags: None
flags: None,
},
v0::MessageAuthor::User(&user.clone().into(&harness.db, Some(&user)).await),
Some(user.clone().into(&harness.db, Some(&user)).await),
@@ -99,23 +117,31 @@ mod test {
user.limits().await,
IdempotencyKey::unchecked_from_string("0".to_string()),
false,
false
false,
)
.await
.expect("Failed to create message");
harness.db.update_message(
&message.id,
&PartialMessage {
pinned: Some(true),
..Default::default()
},
vec![]
).await.expect("Failed to update message");
harness
.db
.update_message(
&message.id,
&PartialMessage {
pinned: Some(true),
..Default::default()
},
vec![],
)
.await
.expect("Failed to update message");
let response = harness
.client
.delete(format!("/channels/{}/messages/{}/pin", channel.id(), &message.id))
.delete(format!(
"/channels/{}/messages/{}/pin",
channel.id(),
&message.id
))
.header(Header::new("x-session-token", session.token.to_string()))
.dispatch()
.await;
@@ -123,33 +149,31 @@ mod test {
assert_eq!(response.status(), Status::NoContent);
drop(response);
harness.wait_for_event(channel.id(), |event| {
match event {
EventV1::Message(message) => {
match &message.system {
Some(SystemMessage::MessageUnpinned { by, .. }) => {
assert_eq!(by, &user.id);
harness
.wait_for_event(channel.id(), |event| match event {
EventV1::Message(message) => match &message.system {
Some(SystemMessage::MessageUnpinned { by, .. }) => {
assert_eq!(by, &user.id);
true
},
_ => false
true
}
_ => false,
},
_ => false
}
}).await;
_ => false,
})
.await;
harness.wait_for_event(channel.id(), |event| {
match event {
harness
.wait_for_event(channel.id(), |event| match event {
EventV1::MessageUpdate { id, clear, .. } => {
assert_eq!(&message.id, id);
assert_eq!(clear, &[FieldsMessage::Pinned]);
true
},
_ => false
}
}).await;
}
_ => false,
})
.await;
let updated_message = Reference::from_unchecked(message.id)
.as_message(&harness.db)