Prevented users from signing up with an email/username which was already present in the migration database.

This commit is contained in:
rainbow napkin 2025-10-14 02:10:34 -04:00
parent a1b602efdb
commit da9428205f
4 changed files with 79 additions and 7 deletions

View file

@ -43,7 +43,7 @@ module.exports.post = async function(req, res){
//Check to make sure the user is logged in //Check to make sure the user is logged in
if(req.session.user == null){ if(req.session.user == null){
errorHandler(res, "Invalid user!"); return errorHandler(res, "Invalid user!");
} }
//Authenticate and find user model from DB //Authenticate and find user model from DB
@ -51,11 +51,22 @@ module.exports.post = async function(req, res){
//If we have an invalid user //If we have an invalid user
if(userDB == null){ if(userDB == null){
errorHandler(res, "Invalid user!"); return errorHandler(res, "Invalid user!");
} }
if(userDB.email == email){ if(userDB.email == email){
errorHandler(res, "Cannot set current email!"); return errorHandler(res, "Cannot set current email!");
}
//Look through DB and migration cache for existing email
const existingDB = await userModel.findOne({email: new RegExp(email, 'i')});
const needsMigration = userModel.migrationCache.emails.includes(email.toLowerCase());
//If the email is in use
if(existingDB != null || needsMigration){
//Complain
return errorHandler(res, "Email already in use!");
} }
//Generate the password reset link //Generate the password reset link

View file

@ -27,7 +27,6 @@ const permissionModel = require('../permissionSchema');
const tokeModel = require('../tokebot/tokeSchema'); const tokeModel = require('../tokebot/tokeSchema');
const loggerUtils = require('../../utils/loggerUtils'); const loggerUtils = require('../../utils/loggerUtils');
/** /**
* DB Schema for documents representing legacy fore.st migration data for a single user account * DB Schema for documents representing legacy fore.st migration data for a single user account
*/ */
@ -208,7 +207,7 @@ migrationSchema.statics.ingestLegacyUser = async function(rawProfile){
//If we found the user in the database //If we found the user in the database
if(foundMigration != null || foundUser != null){ if(foundMigration != null || foundUser != null){
//Scream //Scream
//loggerUtils.consoleWarn(`Found legacy user ${profileArray[1]} in database, skipping migration!`); loggerUtils.consoleWarn(`Found legacy user ${profileArray[1]} in database, skipping migration!`);
//BAIL! //BAIL!
return; return;
} }
@ -292,4 +291,31 @@ migrationSchema.statics.ingestTokeMaps = async function(rawTokeMaps){
} }
} }
migrationSchema.statics.buildMigrationCache = async function(){
//Pull all profiles from the Legacy Profile Migration DB collection
const legacyProfiles = await this.find();
//For each profile in the migration collection
for(const profile of legacyProfiles){
//Push the username into the migration cache
userModel.migrationCache.users.push(profile.user.toLowerCase());
//If the profile has an email address set
if(profile.email != null && profile.email != ''){
//Add the email to the migration cache
userModel.migrationCache.emails.push(profile.email.toLowerCase());
}
}
}
//Methods
/**
* Consumes a migration profile and creates a new, modern canopy profile from the original.
* @param {String} oldPass - Original password to authenticate migration against
* @param {String} newPass - New password to re-hash with modern hashing algo
* @param {String} confirmPass - Confirmation for the new pass
*/
migrationSchema.methods.consume = async function(oldPass, newPass, confirmPass){
}
module.exports = mongoose.model("migration", migrationSchema); module.exports = mongoose.model("migration", migrationSchema);

View file

@ -226,6 +226,18 @@ userSchema.post('deleteOne', {document: true}, async function (){
}); });
//statics //statics
/**
* Holds cache of usernames of profiles stored in the Legacy Profile Migration collection
*
* We can't directly reference migrationSchema, as it would cause a circular reference
* To deal with this, migration schema caches it's regestered users into this array on startup.
* Bonus pts for improved performance on registration calls
*/
userSchema.statics.migrationCache = {
users: [],
emails: []
};
/** /**
* Registers a new user account with given information * Registers a new user account with given information
* @param {Object} userObj - Object representing user to register, generated by the client * @param {Object} userObj - Object representing user to register, generated by the client
@ -237,11 +249,31 @@ userSchema.statics.register = async function(userObj, ip){
//Check password confirmation matches //Check password confirmation matches
if(pass == passConfirm){ if(pass == passConfirm){
//Setup user query
let userQuery = {user: new RegExp(user, 'i')};
//If we have an email
if(email != null && email != ""){
userQuery = {$or: [
userQuery,
{email: new RegExp(email, 'i')}
]};
}
//Look for a user (case insensitive) //Look for a user (case insensitive)
var userDB = await this.findOne({user: new RegExp(user, 'i')}); var userDB = await this.findOne(userQuery);
//Look for a legacy profile
let needsMigration = this.migrationCache.users.includes(user.toLowerCase());
//If the email isn't null and we didnt hit a migration username
if(email != null && !needsMigration){
//Check for migration email
needsMigration = this.migrationCache.emails.includes(email.toLowerCase());
}
//If the user is found or someones trying to impersonate tokeboi //If the user is found or someones trying to impersonate tokeboi
if(userDB || user.toLowerCase() == "tokebot"){ if(userDB || needsMigration || user.toLowerCase() == "tokebot"){
throw loggerUtils.exceptionSmith("User name/email already taken!", "validation"); throw loggerUtils.exceptionSmith("User name/email already taken!", "validation");
}else{ }else{
//Increment the user count, pulling the id to tattoo to the user //Increment the user count, pulling the id to tattoo to the user

View file

@ -195,6 +195,9 @@ async function asyncKickStart(){
//Run legacy migration //Run legacy migration
await migrationModel.ingestLegacyDump(); await migrationModel.ingestLegacyDump();
//Build migration cache
await migrationModel.buildMigrationCache();
//Calculate Toke Map //Calculate Toke Map
await tokeModel.calculateTokeMap(); await tokeModel.calculateTokeMap();