fix: conflict resolution in migration

fix: write new username and display name
chore: restrict discriminator search space
This commit is contained in:
Paul Makles
2023-06-11 09:53:41 +01:00
parent 5bbe30edbc
commit c7a04e4559
3 changed files with 71 additions and 13 deletions

View File

@@ -1,11 +1,11 @@
use std::{ops::BitXor, time::Duration}; use std::{collections::HashSet, ops::BitXor, time::Duration};
use crate::{ use crate::{
mongodb::{ mongodb::{
bson::{doc, from_bson, from_document, to_document, Bson, DateTime, Document}, bson::{doc, from_bson, from_document, to_document, Bson, DateTime, Document},
options::FindOptions, options::FindOptions,
}, },
MongoDb, MongoDb, DISCRIMINATOR_SEARCH_SPACE,
}; };
use futures::StreamExt; use futures::StreamExt;
use rand::seq::SliceRandom; use rand::seq::SliceRandom;
@@ -802,21 +802,38 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 {
.collect() .collect()
.await; .await;
let search_space: Vec<String> = (0..9999).map(|v| format!("{:0>4}", v)).collect(); let search_space: Vec<String> = DISCRIMINATOR_SEARCH_SPACE.iter().cloned().collect();
let mut claimed: HashSet<String> = HashSet::new();
for i in 0..users.len() { for i in 0..users.len() {
let info = &users[i]; let info = &users[i];
let discriminator = { let mut discriminator = {
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
search_space.choose(&mut rng).unwrap() search_space.choose(&mut rng).unwrap()
}; };
if re_username.is_match(&info.username) { if re_username.is_match(&info.username) {
while claimed.contains(&format!("{}#{}", info.username, discriminator)) {
let new_discriminator = {
let mut rng = rand::thread_rng();
search_space.choose(&mut rng).unwrap()
};
info!(
"Re-rolled {} to {new_discriminator} from {discriminator}",
info.username
);
discriminator = new_discriminator;
}
claimed.insert(format!("{}#{}", info.username, discriminator));
info!( info!(
"Migrating user \"{}\" to #{} ({i}/{}) - compliant", "({i}/{}) Migrating user \"{}\" to #{} - compliant",
users.len(),
info.username, info.username,
discriminator, discriminator
users.len()
); );
db.col::<UserInformation>("users") db.col::<UserInformation>("users")
@@ -844,11 +861,23 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 {
sanitised += "_"; sanitised += "_";
} }
while claimed.contains(&format!("{}#{}", sanitised, discriminator)) {
let new_discriminator = {
let mut rng = rand::thread_rng();
search_space.choose(&mut rng).unwrap()
};
info!("Re-rolled {sanitised} to {new_discriminator} from {discriminator}");
discriminator = new_discriminator;
}
claimed.insert(format!("{}#{}", sanitised, discriminator));
info!( info!(
"Migrating user \"{}\" to #{} ({i}/{}) - sanitised: \"{}\"", "({i}/{}) Migrating user \"{}\" to #{} - sanitised: \"{}\"",
users.len(),
info.username, info.username,
discriminator, discriminator,
users.len(),
sanitised sanitised
); );
@@ -859,8 +888,9 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 {
}, },
doc! { doc! {
"$set": { "$set": {
"username": &info.username, "username": sanitised,
"discriminator": discriminator "discriminator": discriminator,
"display_name": &info.username
} }
}, },
None, None,

View File

@@ -1,5 +1,8 @@
use std::collections::HashSet;
use crate::{Database, File}; use crate::{Database, File};
use once_cell::sync::Lazy;
use revolt_result::{Error, ErrorType, Result}; use revolt_result::{Error, ErrorType, Result};
auto_derived_partial!( auto_derived_partial!(
@@ -199,3 +202,15 @@ impl User {
.await .await
} }
} }
pub static DISCRIMINATOR_SEARCH_SPACE: Lazy<HashSet<String>> = Lazy::new(|| {
let mut set = (2..9999)
.map(|v| format!("{:0>4}", v))
.collect::<HashSet<String>>();
for discrim in [1111, 2222, 3333, 4444, 5555, 6666, 7777, 8888, 9999] {
set.remove(&discrim.to_string());
}
set.into_iter().collect()
});

View File

@@ -8,6 +8,7 @@ use crate::{perms, Database, Error, Result};
use futures::try_join; use futures::try_join;
use impl_ops::impl_op_ex_commutative; use impl_ops::impl_op_ex_commutative;
use once_cell::sync::Lazy;
use rand::seq::SliceRandom; use rand::seq::SliceRandom;
use revolt_presence::filter_online; use revolt_presence::filter_online;
use std::collections::HashSet; use std::collections::HashSet;
@@ -202,7 +203,7 @@ impl User {
username: &str, username: &str,
preferred: Option<String>, preferred: Option<String>,
) -> Result<String> { ) -> Result<String> {
let search_space: HashSet<String> = (0..9999).map(|v| format!("{:0>4}", v)).collect(); let search_space: &HashSet<String> = &DISCRIMINATOR_SEARCH_SPACE_QUARK;
let used_discriminators: HashSet<String> = db let used_discriminators: HashSet<String> = db
.fetch_discriminators_in_use(username) .fetch_discriminators_in_use(username)
.await? .await?
@@ -218,7 +219,7 @@ impl User {
if let Some(preferred) = preferred { if let Some(preferred) = preferred {
if available_discriminators.contains(&&preferred) { if available_discriminators.contains(&&preferred) {
return Ok(preferred.to_string()); return Ok(preferred);
} }
} }
@@ -450,3 +451,15 @@ impl User {
} }
} }
} }
pub static DISCRIMINATOR_SEARCH_SPACE_QUARK: Lazy<HashSet<String>> = Lazy::new(|| {
let mut set = (2..9999)
.map(|v| format!("{:0>4}", v))
.collect::<HashSet<String>>();
for discrim in [1111, 2222, 3333, 4444, 5555, 6666, 7777, 8888, 9999] {
set.remove(&discrim.to_string());
}
set.into_iter().collect()
});