Implemented Profile Migration Backend

This commit is contained in:
rainbow napkin 2025-10-16 05:25:08 -04:00
parent da9428205f
commit 6cbb726764
8 changed files with 228 additions and 17 deletions

View file

@ -25,7 +25,11 @@ const config = require('../../../config.json');
const {userModel} = require('../user/userSchema');
const permissionModel = require('../permissionSchema');
const tokeModel = require('../tokebot/tokeSchema');
const statModel = require('../statSchema');
const emailChangeModel = require('../user/emailChangeSchema');
const loggerUtils = require('../../utils/loggerUtils');
const hashUtils = require('../../utils/hashUtils');
const mailUtils = require('../../utils/mailUtils');
/**
* DB Schema for documents representing legacy fore.st migration data for a single user account
@ -307,15 +311,62 @@ migrationSchema.statics.buildMigrationCache = async function(){
}
}
migrationSchema.statics.consumeByUsername = async function(ip, migration){
//Pull migration doc by case-insensitive username
const migrationDB = await this.findOne({user: new RegExp(migration.user, 'i')});
//Wait on the miration DB token to be consumed
await migrationDB.consume(ip, migration);
}
//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
* @param {String} passConfirm - Confirmation for the new pass
*/
migrationSchema.methods.consume = async function(oldPass, newPass, confirmPass){
migrationSchema.methods.consume = async function(ip, migration){
//If we where handed a bad password
if(!hashUtils.compareLegacyPassword(migration.oldPass, this.pass)){
//Complain
throw loggerUtils.exceptionSmith("Incorrect username/password.", "migration");
}
//If we where handed a mismatched confirmation password
if(migration.newPass != migration.passConfirm){
//Complain
throw loggerUtils.exceptionSmith("New password does not match confirmation password.", "migration");
}
//Increment user count
const id = await statModel.incrementUserCount();
//Create new user from profile info
const newUser = await userModel.create({
id,
user: this.user,
pass: migration.newPass,
rank: permissionModel.rankEnum[this.rank],
bio: this.bio,
img: this.image,
date: this.date,
tokes: new Map([["Legacy Tokes", this.tokes]])
});
//Tattoo hashed IP use to migrate to the new user account
await newUser.tattooIPRecord(ip);
//if we submitted an email
if(this.email != null && this.email != ''){
//Generate new request
const requestDB = await emailChangeModel.create({user: newUser._id, newEmail: this.email, ipHash: ip});
//Send confirmation email
mailUtils.sendAddressVerification(requestDB, newUser, this.email, false, true);
}
await this.deleteOne();
}
module.exports = mongoose.model("migration", migrationSchema);

View file

@ -289,7 +289,7 @@ userSchema.statics.register = async function(userObj, ip){
if(email != null){
const requestDB = await emailChangeModel.create({user: newUser._id, newEmail: email, ipHash: ip});
await mailUtil.sendAddressVerification(requestDB, newUser, email)
await mailUtil.sendAddressVerification(requestDB, newUser, email, true);
}
}
}else{