From 705e517871af5ed3308af33dd6164685e623b259 Mon Sep 17 00:00:00 2001 From: Paul Makles Date: Thu, 31 Oct 2024 20:31:09 +0000 Subject: [PATCH] fix: db migration for webhooks does not consider missing channels fixes #378 --- .../admin_migrations/ops/mongodb/scripts.rs | 114 ++++++++++-------- 1 file changed, 65 insertions(+), 49 deletions(-) diff --git a/crates/core/database/src/models/admin_migrations/ops/mongodb/scripts.rs b/crates/core/database/src/models/admin_migrations/ops/mongodb/scripts.rs index 5a22cd6d..7780037e 100644 --- a/crates/core/database/src/models/admin_migrations/ops/mongodb/scripts.rs +++ b/crates/core/database/src/models/admin_migrations/ops/mongodb/scripts.rs @@ -11,6 +11,7 @@ use bson::oid::ObjectId; use futures::StreamExt; use rand::seq::SliceRandom; use revolt_permissions::DEFAULT_WEBHOOK_PERMISSIONS; +use revolt_result::{Error, ErrorType}; use serde::{Deserialize, Serialize}; use unicode_segmentation::UnicodeSegmentation; @@ -20,7 +21,7 @@ struct MigrationInfo { revision: i32, } -pub const LATEST_REVISION: i32 = 30; +pub const LATEST_REVISION: i32 = 31; pub async fn migrate_database(db: &MongoDb) { let migrations = db.col::("migrations"); @@ -1139,53 +1140,7 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { .expect("Failed to create attachment_hashes index."); } - if revision <= 29 { - info!("Running migration [revision 29 / 29-09-2024]: Add creator_id to webhooks."); - - #[derive(serde::Serialize, serde::Deserialize)] - struct WebhookShell { - _id: String, - channel_id: String, - } - - let invites = db - .db() - .collection::("channel_webhooks") - .find(doc! {}, None) - .await - .expect("webhooks") - .filter_map(|s| async { s.ok() }) - .collect::>() - .await; - - for invite in invites { - let channel = db.fetch_channel(&invite.channel_id).await.expect("channel"); - let creator_id = match channel { - Channel::Group { owner, .. } => owner, - Channel::TextChannel { server, .. } | Channel::VoiceChannel { server, .. } => { - let server = db.fetch_server(&server).await.expect("server"); - server.owner - } - _ => unreachable!("not server or group channel!"), - }; - - db.db() - .collection::("channel_webhooks") - .update_one( - doc! { - "_id": invite._id, - }, - doc! { - "$set" : { - "creator_id": creator_id - } - }, - None, - ) - .await - .expect("update webhook"); - } - } + // Revision 29 omitted due to bug. if revision <= 30 { info!("Running migration [revision 30 / 29-09-2024]: Add index for used_for.id to attachments."); @@ -1209,7 +1164,68 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { .expect("Failed to create attachments index."); } - // Need to migrate fields on attachments, change `user_id`, `object_id`, etc to `parent`. + if revision <= 31 { + info!("Running migration [revision 31 / 31-10-2024]: Add creator_id to webhooks and delete those whose channels don't exist."); + + #[derive(serde::Serialize, serde::Deserialize)] + struct WebhookShell { + _id: String, + channel_id: String, + } + + let webhooks = db + .db() + .collection::("channel_webhooks") + .find(doc! {}, None) + .await + .expect("webhooks") + .filter_map(|s| async { s.ok() }) + .collect::>() + .await; + + for webhook in webhooks { + match db.fetch_channel(&webhook.channel_id).await { + Ok(channel) => { + let creator_id = match channel { + Channel::Group { owner, .. } => owner, + Channel::TextChannel { server, .. } + | Channel::VoiceChannel { server, .. } => { + let server = db.fetch_server(&server).await.expect("server"); + server.owner + } + _ => unreachable!("not server or group channel!"), + }; + + db.db() + .collection::("channel_webhooks") + .update_one( + doc! { + "_id": webhook._id, + }, + doc! { + "$set" : { + "creator_id": creator_id + } + }, + None, + ) + .await + .expect("update webhook"); + } + Err(Error { + error_type: ErrorType::NotFound, + .. + }) => { + db.db() + .collection::("channel_webhooks") + .delete_one(doc! { "_id": webhook._id }, None) + .await + .expect("failed to delete invalid webhook"); + } + Err(err) => panic!("{err:?}"), + } + } + } // Reminder to update LATEST_REVISION when adding new migrations. LATEST_REVISION.max(revision)