From 1bd9fcdc8025ce3e1fef01fc91b11c8f47a440cd Mon Sep 17 00:00:00 2001 From: rainbow napkin Date: Wed, 22 Oct 2025 21:53:41 -0400 Subject: [PATCH] High-level rank changes and bad attempts and good Remember-Me tokens now logged. --- .gitignore | 5 +-- src/schemas/user/rememberMeSchema.js | 7 ++-- src/schemas/user/userSchema.js | 5 +++ src/utils/loggerUtils.js | 57 ++++++++++++++++++++-------- src/utils/mailUtils.js | 2 +- 5 files changed, 53 insertions(+), 23 deletions(-) diff --git a/.gitignore b/.gitignore index 9868f22..76cfb45 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,6 @@ node_modules/ -log/crash/* -!log/crash +log/* www/doc/*/* -!www/doc/client -!www/doc/server package-lock.json config.json config.json.old diff --git a/src/schemas/user/rememberMeSchema.js b/src/schemas/user/rememberMeSchema.js index 32df58e..be162fd 100644 --- a/src/schemas/user/rememberMeSchema.js +++ b/src/schemas/user/rememberMeSchema.js @@ -128,14 +128,15 @@ rememberMeToken.statics.authenticate = async function(id, token, failLine = "Bad badLogin(); } + //Populate the user field + await tokenDB.populate('user'); + //Check our password is correct if(await tokenDB.checkToken(token)){ - //Populate the user field - await tokenDB.populate('user'); - //Return the user doc return tokenDB.user; }else{ + loggerUtils.dumpSecurityLog(`Failed attempt at ${tokenDB.user.user}'s Remember-Me token {${tokenDB.id}}... Nuking token!`); //Nuke the token for security await tokenDB.deleteOne(); //if not scream and shout diff --git a/src/schemas/user/userSchema.js b/src/schemas/user/userSchema.js index cc4d364..2d8517c 100644 --- a/src/schemas/user/userSchema.js +++ b/src/schemas/user/userSchema.js @@ -186,6 +186,11 @@ userSchema.pre('save', async function (next){ //If rank was changed if(this.isModified("rank")){ + //If this rank change is above 2 (Mod or above) + if(permissionModel.rankToNum(this.rank) > 2){ + loggerUtils.dumpSecurityLog(`${this.user}'s rank was set to ${this.rank}.`); + } + //force a full log-out await this.killAllSessions("Your site-wide rank has changed. Sign-in required."); } diff --git a/src/utils/loggerUtils.js b/src/utils/loggerUtils.js index 075f9ed..6017a9b 100644 --- a/src/utils/loggerUtils.js +++ b/src/utils/loggerUtils.js @@ -16,6 +16,7 @@ along with this program. If not, see .*/ //Node const fs = require('node:fs/promises'); +const crypto = require('node:crypto'); //Config const config = require('../../config.json'); @@ -172,42 +173,68 @@ module.exports.errorMiddleware = function(err, req, res, next){ * Dumps unexpected server crashes to dedicated log files * @param {Error} err - error to dump to file * @param {Date} date - Date of error, defaults to now + * @param {String} subDir - subdirectory inside the log folder we want to dump to + * @param {Boolean} muzzle - Tells the function to STFU */ -module.exports.dumpError = async function(err, date = new Date(), subDir = ''){ +module.exports.dumpError = async function(err, date = new Date(), subDir = 'crash/', muzzle = false){ + //Generate content from error + const content = `Error Date: ${date.toLocaleString()} (UTC-${date.getTimezoneOffset()/60})\nError Type: ${err.name}\nError Msg:${err.message}\nStack Trace:\n\n${err.stack}`; + + //Dump text to file + module.exports.dumpLog(content, date.getTime(), subDir, muzzle); +} + + +module.exports.dumpSecurityLog = async function(content, date = new Date()){ + module.exports.dumpLog(content, `Incident-{${crypto.randomUUID()}}-${date.getTime()}`, 'security/', true); +} + +/** + * Dumps log file to log folder + * @param {String} content - Text to dump to file + * @param {String} name - file name to save to + * @param {String} subDir - subdirectory inside the log folder we want to dump to + * @param {Boolean} muzzle - Tells the function to STFU + */ +module.exports.dumpLog = async function(content, name, subDir = '/', muzzle = false){ try{ //Crash directory - const dir = `./log/crash/${subDir}` + const dir = `./log/${subDir}` //Double check crash folder exists try{ await fs.stat(dir); //If we caught an error (most likely it's missing) }catch(err){ - //Shout about it - module.exports.consoleWarn("Log folder missing, mking dir!") + if(!muzzle){ + //Shout about it + module.exports.consoleWarn("Log folder missing, mking dir!") + } //Make it if doesn't await fs.mkdir(dir, {recursive: true}); } //Assemble log file path - const path = `${dir}${date.getTime()}.log`; - //Generate error file content - const content = `Error Date: ${date.toLocaleString()} (UTC-${date.getTimezoneOffset()/60})\nError Type: ${err.name}\nError Msg:${err.message}\nStack Trace:\n\n${err.stack}`; + const path = `${dir}${name}.log`; //Write content to file fs.writeFile(path, content); - //Whine about the error - module.exports.consoleWarn(`Warning: Unexpected Server Crash gracefully dumped to '${path}'... SOMETHING MAY BE VERY BROKEN!!!!`); + if(!muzzle){ + //Whine about the error + module.exports.consoleWarn(`Warning: Unexpected Server Crash gracefully dumped to '${path}'... SOMETHING MAY BE VERY BROKEN!!!!`); + } //If somethine went really really wrong }catch(doubleErr){ - //Use humor to cope with the pain - module.exports.consoleWarn("Yo Dawg, I herd you like errors, so I put an error in your error dump, so you can dump while you dump:"); - //Dump the original error to console - module.exports.consoleWarn(err); - //Dump the error we had saving that error to file to console - module.exports.consoleWarn(doubleErr); + if(!muzzle){ + //Use humor to cope with the pain + module.exports.consoleWarn("Yo Dawg, I herd you like errors, so I put an error in your error dump, so you can dump while you dump:"); + //Dump the original error to console + module.exports.consoleWarn(err); + //Dump the error we had saving that error to file to console + module.exports.consoleWarn(doubleErr); + } } } diff --git a/src/utils/mailUtils.js b/src/utils/mailUtils.js index fce92ca..4287160 100644 --- a/src/utils/mailUtils.js +++ b/src/utils/mailUtils.js @@ -78,7 +78,7 @@ module.exports.mailem = async function(to, subject, body, htmlBody = false){ //return the mail info return sentMail; }catch(err){ - loggerUtils.dumpError(err, new Date(), 'mail/'); + loggerUtils.dumpError(err, new Date(), 'crash/mail/'); } }