From acb4190f70f990c73a252769658808f7fdd7f18a Mon Sep 17 00:00:00 2001 From: Paul Makles Date: Sun, 7 Apr 2024 22:24:23 +0100 Subject: [PATCH] fix: delete associated server objects --- .../core/database/src/models/servers/model.rs | 2 - .../src/models/servers/ops/mongodb.rs | 81 ++++++++++++++++++- 2 files changed, 80 insertions(+), 3 deletions(-) diff --git a/crates/core/database/src/models/servers/model.rs b/crates/core/database/src/models/servers/model.rs index 8e427fb4..75a022cd 100644 --- a/crates/core/database/src/models/servers/model.rs +++ b/crates/core/database/src/models/servers/model.rs @@ -214,8 +214,6 @@ impl Server { .p(self.id.clone()) .await; - // TODO: missing functionality - db.delete_server(&self.id).await } diff --git a/crates/core/database/src/models/servers/ops/mongodb.rs b/crates/core/database/src/models/servers/ops/mongodb.rs index 0c679e5f..24bb65da 100644 --- a/crates/core/database/src/models/servers/ops/mongodb.rs +++ b/crates/core/database/src/models/servers/ops/mongodb.rs @@ -1,4 +1,4 @@ -use bson::{to_document, Document}; +use bson::{to_document, Bson, Document}; use futures::StreamExt; use revolt_result::Result; @@ -67,6 +67,7 @@ impl AbstractServers for MongoDb { /// Delete a server by its id async fn delete_server(&self, id: &str) -> Result<()> { + self.delete_associated_server_objects(id).await?; query!(self, delete_one_by_id, COL, id).map(|_| ()) } @@ -181,3 +182,81 @@ impl IntoDocumentPath for FieldsRole { }) } } + +impl MongoDb { + pub async fn delete_associated_server_objects(&self, server_id: &str) -> Result<()> { + // Find all channels + let channels: Vec = self + .col::("channels") + .find( + doc! { + "server": server_id + }, + None, + ) + .await + .map_err(|_| create_database_error!("find", "channels"))? + .filter_map(|s| async { + s.map(|d| d.get_str("_id").map(|s| s.to_string()).ok()) + .ok() + .flatten() + }) + .collect() + .await; + + // Check if there are any attachments we need to delete. + self.delete_bulk_messages(doc! { + "channel": { + "$in": &channels + } + }) + .await?; + + // Delete all emoji. + self.col::("emojis") + .delete_many( + doc! { + "parent.id": &server_id + }, + None, + ) + .await + .map_err(|_| create_database_error!("delete_many", "emojis"))?; + + // Delete all channels. + self.col::("channels") + .delete_many( + doc! { + "server": &server_id + }, + None, + ) + .await + .map_err(|_| create_database_error!("delete_many", "channels"))?; + + // Delete any associated objects, e.g. unreads and invites. + self.delete_associated_channel_objects(Bson::Document(doc! { "$in": &channels })) + .await?; + + // Delete members and bans. + for with in &["server_members", "server_bans"] { + self.col::(with) + .delete_many( + doc! { + "_id.server": &server_id + }, + None, + ) + .await + .map_err(|_| create_database_error!("delete_many", with))?; + } + + // Update many attachments with parent id. + self.delete_many_attachments(doc! { + "object_id": &server_id + }) + .await?; + + Ok(()) + } +}