diff --git a/src/schemas/user/migrationSchema.js b/src/schemas/user/migrationSchema.js index 6c4bad9..aab54bb 100644 --- a/src/schemas/user/migrationSchema.js +++ b/src/schemas/user/migrationSchema.js @@ -24,6 +24,7 @@ const {mongoose} = require('mongoose'); const config = require('../../../config.json'); const {userModel} = require('../user/userSchema'); const permissionModel = require('../permissionSchema'); +const loggerUtils = require('../../utils/loggerUtils'); /** @@ -66,41 +67,49 @@ const migrationSchema = new mongoose.Schema({ }, }); +//TODO: before next commit, add error checking to the ingestLegacy statics down below +//Also add a warning for the fail condition in ingestLegacyDump that bails out when missing files + //statics /** * Static method for ingesting data dump from legacy cytube/fore.st server */ migrationSchema.statics.ingestLegacyDump = async function(){ - //If migration is disabled - if(!config.migrate){ - //BAIL! - return; - } - - //Crash directory - const dir = "./migration/" - const userDump = `${dir}users.sql` - - //Double check migration files try{ - //Pull dump stats - await fs.stat(userDump); - //If we caught an error (most likely it's missing) + //If migration is disabled + if(!config.migrate){ + //BAIL! + return; + } + + //Crash directory + const dir = "./migration/" + const userDump = `${dir}users.sql` + + //Double check migration files + try{ + //Pull dump stats + await fs.stat(userDump); + //If we caught an error (most likely it's missing) + }catch(err){ + loggerUtils.consoleWarn("No migration files detected! Pleas provide legacy migration files or disable migration from config.json!"); + //BAIL! + return; + } + + //Pull raw dump from file + const rawDump = await fs.readFile(userDump, 'binary'); + + //Split dump by line + const splitDump = rawDump.split('\n'); + + //For each line in the user dump + for(const line of splitDump){ + //Ingest the legacy user profile + this.ingestLegacyUser(line); + } }catch(err){ - //BAIL! - return; - } - - //Pull raw dump from file - const rawDump = await fs.readFile(userDump, 'binary'); - - //Split dump by line - const splitDump = rawDump.split('\n'); - - //For each line in the user dump - for(const line of splitDump){ - //Ingest the legacy user profile - this.ingestLegacyUser(line); + return loggerUtils.localExceptionHandler(err); } } @@ -109,82 +118,90 @@ migrationSchema.statics.ingestLegacyDump = async function(){ * @param {String} rawProfile - Line of text contianing raw profile dump */ migrationSchema.statics.ingestLegacyUser = async function(rawProfile){ - //If migration is disabled - if(!config.migrate){ - //BAIL! - return; + try{ + //If migration is disabled + if(!config.migrate){ + //BAIL! + return; + } + + //Filter out the entry from any extra guff on the line + const profileMatches = rawProfile.match(/^\((.*?(?=,),){9}.*?(?=\))\)/g); + + //If we have an invalid line + if(profileMatches <= 0){ + loggerUtils.consoleWarn('Bad profile detected in legacy dump:'); + loggerUtils.consoleWarn(rawProfile); + //BAIL! + return; + } + + //Set filtered profile to the match we found + let filteredProfile = profileMatches[0]; + + //cook the filtered profile in order to trick the JSON interpreter into thinking it's an array + filteredProfile = `[${filteredProfile.substring(1, filteredProfile.length - 1)}]`; + + //Replace single qoutes with double to match JSON strings + filteredProfile = filteredProfile.replaceAll(",'",',"'); + filteredProfile = filteredProfile.replaceAll("',",'",'); + + //Make sure single qoutes are escaped + filteredProfile = filteredProfile.replaceAll("\'",'\\\''); + + + //Dupe the JSON interpreter like the rube that it is + const profileArray = JSON.parse(filteredProfile); + + //If profile array is the wrong length + if(profileArray.length != 10){ + loggerUtils.consoleWarn('Bad profile detected in legacy dump:'); + loggerUtils.consoleWarn(profileArray); + //BAIL! + return; + } + + //Look for user in migration table + const foundMigration = await this.findOne({user:profileArray[1]}); + const foundUser = await userModel.findOne({user: profileArray[1]}); + + //If we found the user in the database + if(foundMigration != null || foundUser != null){ + //Scream + loggerUtils.consoleWarn(`Found legacy user ${profileArray[1]} in database, skipping migration!`); + //BAIL! + return; + } + + + //Create migration profile object from scraped info + const migrationProfile = new this({ + user: profileArray[1], + pass: profileArray[2], + //Clamp rank to 0 and the max setting allowed by the rank enum + rank: Math.min(Math.max(0, profileArray[3]), permissionModel.rankEnum.length - 1), + email: profileArray[4], + date: profileArray[7], + }) + + //If our profile array isn't empty + if(profileArray[5] != ''){ + //Make sure single qoutes are escaped, and parse bio JSON + const bioObject = JSON.parse(profileArray[5].replaceAll("\'",'\\\'')); + + //Inject bio information into migration profile, only if they're present; + migrationProfile.bio = bioObject.text == '' ? undefined : bioObject.text; + migrationProfile.image = bioObject.image == '' ? undefined : bioObject.image; + } + + //Build DB Doc from migration Profile hashtable and dump it into the DB + await this.create(migrationProfile); + + //Let the world know of our triumph! + console.log(`Legacy user profile ${migrationProfile.user} migrated successfully!`); + }catch(err){ + return loggerUtils.localExceptionHandler(err); } - - //Filter out the entry from any extra guff on the line - const profileMatches = rawProfile.match(/^\((.*?(?=,),){9}.*?(?=\))\)/g); - - //If we have an invalid line - if(profileMatches <= 0){ - //BAIL! - return; - } - - //Set filtered profile to the match we found - let filteredProfile = profileMatches[0]; - - //cook the filtered profile in order to trick the JSON interpreter into thinking it's an array - filteredProfile = `[${filteredProfile.substring(1, filteredProfile.length - 1)}]`; - - //Replace single qoutes with double to match JSON strings - filteredProfile = filteredProfile.replaceAll(",'",',"'); - filteredProfile = filteredProfile.replaceAll("',",'",'); - - //Make sure single qoutes are escaped - filteredProfile = filteredProfile.replaceAll("\'",'\\\''); - - - //Dupe the JSON interpreter like the rube that it is - const profileArray = JSON.parse(filteredProfile); - - //If profile array is the wrong length - if(profileArray.length != 10){ - //BAIL! - return; - } - - //Look for user in migration table - const foundMigration = await this.findOne({user:profileArray[1]}); - const foundUser = await userModel.findOne({user: profileArray[1]}); - - //If we found the user in the database - if(foundMigration != null || foundUser != null){ - //Scream - console.log(`Found legacy user ${profileArray[1]} in database, skipping migration!`); - //BAIL! - return; - } - - - //Create migration profile object from scraped info - const migrationProfile = new this({ - user: profileArray[1], - pass: profileArray[2], - //Clamp rank to 0 and the max setting allowed by the rank enum - rank: Math.min(Math.max(0, profileArray[3]), permissionModel.rankEnum.length - 1), - email: profileArray[4], - date: profileArray[7], - }) - - //If our profile array isn't empty - if(profileArray[5] != ''){ - //Make sure single qoutes are escaped, and parse bio JSON - const bioObject = JSON.parse(profileArray[5].replaceAll("\'",'\\\'')); - - //Inject bio information into migration profile, only if they're present; - migrationProfile.bio = bioObject.text == '' ? undefined : bioObject.text; - migrationProfile.image = bioObject.image == '' ? undefined : bioObject.image; - } - - //Build DB Doc from migration Profile hashtable and dump it into the DB - await this.create(migrationProfile); - - //Let the world know of our triumph! - console.log(`Legacy user profile ${migrationProfile.user} migrated successfully!`); } module.exports = mongoose.model("migration", migrationSchema); \ No newline at end of file