From 1b2c7b2fa1b9873e3ffdfd305413826356ae95ab Mon Sep 17 00:00:00 2001 From: Zomatree Date: Thu, 5 Jun 2025 22:37:10 +0100 Subject: [PATCH] feat: add roles migration --- .../admin_migrations/ops/mongodb/scripts.rs | 42 +++++++++++++++++-- crates/delta/src/routes/servers/mod.rs | 2 +- .../routes/servers/roles_edit_positions.rs | 4 +- 3 files changed, 42 insertions(+), 6 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 0f58082a..e671e43d 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 @@ -4,8 +4,7 @@ use crate::{ mongodb::{ bson::{doc, from_bson, from_document, to_document, Bson, DateTime, Document}, options::FindOptions, - }, - AbstractChannels, AbstractServers, Channel, Invite, MongoDb, User, DISCRIMINATOR_SEARCH_SPACE, + }, AbstractChannels, AbstractServers, Channel, Invite, MongoDb, Server, User, DISCRIMINATOR_SEARCH_SPACE }; use bson::{oid::ObjectId, to_bson}; use futures::StreamExt; @@ -22,7 +21,7 @@ struct MigrationInfo { revision: i32, } -pub const LATEST_REVISION: i32 = 41; // MUST BE +1 to last migration +pub const LATEST_REVISION: i32 = 42; // MUST BE +1 to last migration pub async fn migrate_database(db: &MongoDb) { let migrations = db.col::("migrations"); @@ -1165,6 +1164,43 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { .expect("failed to update users"); } + if revision <= 41 { + info!("Running migration [revision 41 / 05-06-2025]: convert role ranks to uniform numbers."); + + let mut servers = db.db() + .collection::("servers") + .find(doc! { + "roles": { + "$exists": true, + "$ne": [] + } + }) + .await + .unwrap() + .filter_map(|s| async { s.ok() }) + .boxed(); + + while let Some(mut server) = servers.next().await { + let mut ordered_roles = server.roles.clone().into_iter().collect::>(); + ordered_roles.sort_by(|(_, role_a), (_, role_b)| role_a.rank.cmp(&role_b.rank)); + let ordered_roles = ordered_roles.into_iter().map(|(id, _)| id).collect::>(); + + for (id, role) in server.roles.iter_mut() { + role.rank = ordered_roles.iter().position(|x| id == x).unwrap() as i64; + } + + db.db().collection::("servers") + .update_one( + doc! { "_id": &server.id }, + doc! { "$set": { + "roles": bson::to_bson(&server.roles).unwrap() + } } + ) + .await + .unwrap(); + } + } + // Reminder to update LATEST_REVISION when adding new migrations. LATEST_REVISION.max(revision) } diff --git a/crates/delta/src/routes/servers/mod.rs b/crates/delta/src/routes/servers/mod.rs index b656b401..066fd32a 100644 --- a/crates/delta/src/routes/servers/mod.rs +++ b/crates/delta/src/routes/servers/mod.rs @@ -49,6 +49,6 @@ pub fn routes() -> (Vec, OpenApi) { permissions_set::set_role_permission, permissions_set_default::set_default_permissions, emoji_list::list_emoji, - roles_edit_positions::edit_role_positions + roles_edit_positions::edit_role_ranks ] } diff --git a/crates/delta/src/routes/servers/roles_edit_positions.rs b/crates/delta/src/routes/servers/roles_edit_positions.rs index 5a7e4438..8edc8d7f 100644 --- a/crates/delta/src/routes/servers/roles_edit_positions.rs +++ b/crates/delta/src/routes/servers/roles_edit_positions.rs @@ -8,7 +8,7 @@ use revolt_models::v0; /// /// Edit's server role's ranks. #[openapi(tag = "Server Permissions")] -#[patch("//roles/ranks", data = "")] +#[patch("//roles/ranks", data = "", rank = 1)] pub async fn edit_role_ranks( db: &State, user: User, @@ -36,7 +36,7 @@ pub async fn edit_role_ranks( // find all roles above the member which we should not be able to reorder let cant_modify = server.roles.clone() .into_iter() - .filter(|(_, role)| if let Some(top_rank) = member_top_rank { role.rank >= top_rank } else { true }) + .filter(|(_, role)| if let Some(top_rank) = member_top_rank { role.rank <= top_rank } else { true }) .collect::>(); // check if any roles which we cant reorder have tried to been reordered