forked from jmug/stoatchat
fix: db migration for webhooks does not consider missing channels
fixes #378
This commit is contained in:
@@ -11,6 +11,7 @@ use bson::oid::ObjectId;
|
|||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use rand::seq::SliceRandom;
|
use rand::seq::SliceRandom;
|
||||||
use revolt_permissions::DEFAULT_WEBHOOK_PERMISSIONS;
|
use revolt_permissions::DEFAULT_WEBHOOK_PERMISSIONS;
|
||||||
|
use revolt_result::{Error, ErrorType};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use unicode_segmentation::UnicodeSegmentation;
|
use unicode_segmentation::UnicodeSegmentation;
|
||||||
|
|
||||||
@@ -20,7 +21,7 @@ struct MigrationInfo {
|
|||||||
revision: i32,
|
revision: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const LATEST_REVISION: i32 = 30;
|
pub const LATEST_REVISION: i32 = 31;
|
||||||
|
|
||||||
pub async fn migrate_database(db: &MongoDb) {
|
pub async fn migrate_database(db: &MongoDb) {
|
||||||
let migrations = db.col::<Document>("migrations");
|
let migrations = db.col::<Document>("migrations");
|
||||||
@@ -1139,53 +1140,7 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 {
|
|||||||
.expect("Failed to create attachment_hashes index.");
|
.expect("Failed to create attachment_hashes index.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if revision <= 29 {
|
// Revision 29 omitted due to bug.
|
||||||
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::<WebhookShell>("channel_webhooks")
|
|
||||||
.find(doc! {}, None)
|
|
||||||
.await
|
|
||||||
.expect("webhooks")
|
|
||||||
.filter_map(|s| async { s.ok() })
|
|
||||||
.collect::<Vec<WebhookShell>>()
|
|
||||||
.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::<Document>("channel_webhooks")
|
|
||||||
.update_one(
|
|
||||||
doc! {
|
|
||||||
"_id": invite._id,
|
|
||||||
},
|
|
||||||
doc! {
|
|
||||||
"$set" : {
|
|
||||||
"creator_id": creator_id
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.expect("update webhook");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if revision <= 30 {
|
if revision <= 30 {
|
||||||
info!("Running migration [revision 30 / 29-09-2024]: Add index for used_for.id to attachments.");
|
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.");
|
.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::<WebhookShell>("channel_webhooks")
|
||||||
|
.find(doc! {}, None)
|
||||||
|
.await
|
||||||
|
.expect("webhooks")
|
||||||
|
.filter_map(|s| async { s.ok() })
|
||||||
|
.collect::<Vec<WebhookShell>>()
|
||||||
|
.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::<Document>("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::<WebhookShell>("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.
|
// Reminder to update LATEST_REVISION when adding new migrations.
|
||||||
LATEST_REVISION.max(revision)
|
LATEST_REVISION.max(revision)
|
||||||
|
|||||||
Reference in New Issue
Block a user