feat(core/database): migrate to discriminators

This commit is contained in:
Paul Makles
2023-06-11 09:16:24 +01:00
parent 31c7dc0577
commit 5bbe30edbc
3 changed files with 114 additions and 8 deletions

View File

@@ -29,6 +29,7 @@ revolt-permissions = { version = "0.6.0-rc.2", path = "../permissions", features
# Utility
log = "0.4"
rand = "0.8.5"
ulid = "1.0.0"
nanoid = "0.4.0"
once_cell = "1.17"
@@ -46,6 +47,10 @@ redis-kiss = { version = "0.1.4" }
bson = { optional = true, version = "2.1.0" }
mongodb = { optional = true, version = "2.1.0", default-features = false }
# Database Migration
unicode-segmentation = "1.10.1"
regex = "1"
# Async Language Features
futures = "0.3.19"
async-trait = "0.1.51"

View File

@@ -8,7 +8,9 @@ use crate::{
MongoDb,
};
use futures::StreamExt;
use rand::seq::SliceRandom;
use serde::{Deserialize, Serialize};
use unicode_segmentation::UnicodeSegmentation;
#[derive(Serialize, Deserialize)]
struct MigrationInfo {
@@ -16,7 +18,7 @@ struct MigrationInfo {
revision: i32,
}
pub const LATEST_REVISION: i32 = 24;
pub const LATEST_REVISION: i32 = 25;
pub async fn migrate_database(db: &MongoDb) {
let migrations = db.col::<Document>("migrations");
@@ -769,24 +771,114 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 {
}
if revision <= 23 {
info!("Running migration [revision 23 / 09-06-2023]: Add collection `channel_webhooks` if not exists, update users index.");
db.db()
.create_collection("channel_webhooks", None)
.await
.ok();
info!("Running migration [revision 23 / 10-06-2023]: Generate discriminators for users.");
db.db()
.run_command(
doc! {
"dropIndexes": "users",
"indexes": "username"
"index": "username"
},
None,
)
.await
.expect("Failed to drop existing username index.");
#[derive(Serialize, Deserialize)]
struct UserInformation {
#[serde(rename = "_id")]
id: String,
username: String,
}
let re_username = regex::Regex::new(r"^(\p{L}|[\d_.-])+$").unwrap();
let users: Vec<UserInformation> = db
.col::<UserInformation>("users")
.find(doc! {}, None)
.await
.unwrap()
.map(|doc| doc.expect("id and username"))
.collect()
.await;
let search_space: Vec<String> = (0..9999).map(|v| format!("{:0>4}", v)).collect();
for i in 0..users.len() {
let info = &users[i];
let discriminator = {
let mut rng = rand::thread_rng();
search_space.choose(&mut rng).unwrap()
};
if re_username.is_match(&info.username) {
info!(
"Migrating user \"{}\" to #{} ({i}/{}) - compliant",
info.username,
discriminator,
users.len()
);
db.col::<UserInformation>("users")
.update_one(
doc! {
"_id": &info.id
},
doc! {
"$set": {
"discriminator": discriminator
}
},
None,
)
.await
.unwrap();
} else {
let mut sanitised = info
.username
.graphemes(true)
.filter(|s| re_username.is_match(s))
.collect::<String>();
while sanitised.len() < 2 {
sanitised += "_";
}
info!(
"Migrating user \"{}\" to #{} ({i}/{}) - sanitised: \"{}\"",
info.username,
discriminator,
users.len(),
sanitised
);
db.col::<UserInformation>("users")
.update_one(
doc! {
"_id": &info.id
},
doc! {
"$set": {
"username": &info.username,
"discriminator": discriminator
}
},
None,
)
.await
.unwrap();
}
}
}
if revision <= 24 {
info!("Running migration [revision 24 / 09-06-2023]: Add collection `channel_webhooks` if not exists, update users index.");
db.db()
.create_collection("channel_webhooks", None)
.await
.ok();
db.db()
.run_command(
doc! {