forked from jmug/stoatchat
feat(core/database): migrate to discriminators
This commit is contained in:
9
Cargo.lock
generated
9
Cargo.lock
generated
@@ -2867,7 +2867,9 @@ dependencies = [
|
||||
"mongodb",
|
||||
"nanoid",
|
||||
"once_cell",
|
||||
"rand 0.8.5",
|
||||
"redis-kiss",
|
||||
"regex",
|
||||
"revolt-models",
|
||||
"revolt-permissions",
|
||||
"revolt-presence",
|
||||
@@ -2878,6 +2880,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"ulid 1.0.0",
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4327,6 +4330,12 @@ dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.0.4"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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! {
|
||||
|
||||
Reference in New Issue
Block a user