Improved exception handling, started work on improving error messages for IP bans

This commit is contained in:
rainbow napkin 2025-05-29 09:48:48 -04:00
parent 7d3c31f0aa
commit 853f67fe15
15 changed files with 118 additions and 77 deletions

View file

@ -122,7 +122,7 @@ module.exports = class{
const userDB = await userModel.findOne({user: socket.request.session.user.user}); const userDB = await userModel.findOne({user: socket.request.session.user.user});
if(userDB == null){ if(userDB == null){
throw new Error("User not found!"); throw loggerUtils.exceptionSmith("User not found!", "unauthorized");
} }
//Set socket user and channel values //Set socket user and channel values
@ -140,7 +140,7 @@ module.exports = class{
//Check if channel exists //Check if channel exists
if(chanDB == null){ if(chanDB == null){
throw new Error("Channel not found!"); throw loggerUtils.exceptionSmith("Channel not found", "validation");
} }
//Check if current channel is active //Check if current channel is active

View file

@ -312,7 +312,7 @@ module.exports = class{
//If we couldn't find the channel //If we couldn't find the channel
if(chanDB == null){ if(chanDB == null){
//FUCK //FUCK
throw new Error(`Unable to find channel document ${this.channel.name} while queue item!`); throw loggerUtils.exceptionSmith(`Unable to find channel document ${this.channel.name} while queue item!`, "queue");
} }
//For each item //For each item
@ -409,7 +409,7 @@ module.exports = class{
//If we couldn't find the channel //If we couldn't find the channel
if(chanDB == null){ if(chanDB == null){
//FUCK //FUCK
throw new Error(`Unable to find channel document ${this.channel.name} while queue item!`); throw loggerUtils.exceptionSmith(`Unable to find channel document ${this.channel.name} while queue item!`, "queue");
} }
//Keep a copy of the archive that hasn't been changed //Keep a copy of the archive that hasn't been changed
@ -470,7 +470,7 @@ module.exports = class{
//If we couldn't find the channel //If we couldn't find the channel
if(chanDB == null){ if(chanDB == null){
//FUCK //FUCK
throw new Error(`Unable to find channel document ${this.channel.name} while queue item!`); throw loggerUtils.exceptionSmith(`Unable to find channel document ${this.channel.name} while queue item!`, "queue");
} }
//Filter media out by UUID //Filter media out by UUID
@ -611,7 +611,7 @@ module.exports = class{
//If we couldn't find the channel //If we couldn't find the channel
if(chanDB == null){ if(chanDB == null){
//FUCK //FUCK
throw new Error(`Unable to find channel document ${this.channel.name} while saving item to queue!`); throw loggerUtils.exceptionSmith(`Unable to find channel document ${this.channel.name} while saving item to queue!`, "queue");
} }
//Add media to the persistant schedule //Add media to the persistant schedule
@ -766,7 +766,7 @@ module.exports = class{
//If we couldn't find the channel //If we couldn't find the channel
if(chanDB == null){ if(chanDB == null){
//FUCK //FUCK
throw new Error(`Unable to find channel document ${this.channel.name} while ending queue item!`); throw loggerUtils.exceptionSmith(`Unable to find channel document ${this.channel.name} while ending queue item!`, "queue");
} }
//If we haven't changed 'nowPlaying' in the play list //If we haven't changed 'nowPlaying' in the play list
@ -909,7 +909,7 @@ module.exports = class{
//If we couldn't find the channel //If we couldn't find the channel
if(chanDB == null){ if(chanDB == null){
//FUCK //FUCK
throw new Error(`Unable to find channel document ${this.channel.name} while rehydrating queue!`); throw loggerUtils.exceptionSmith(`Unable to find channel document ${this.channel.name} while rehydrating queue!`, "queue");
} }
//Create an empty array to hold our schedule //Create an empty array to hold our schedule
@ -957,7 +957,7 @@ module.exports = class{
//If we couldn't find the channel //If we couldn't find the channel
if(chanDB == null){ if(chanDB == null){
//FUCK //FUCK
throw new Error(`Unable to find channel document ${this.channel.name} while rehydrating queue!`); throw loggerUtils.exceptionSmith(`Unable to find channel document ${this.channel.name} while rehydrating queue!`, "queue");
} }
const now = new Date().getTime(); const now = new Date().getTime();

View file

@ -31,7 +31,7 @@ module.exports.post = async function(req, res){
const channel = await channelModel.findOne({name: data.chanName}); const channel = await channelModel.findOne({name: data.chanName});
if(channel == null){ if(channel == null){
throw new Error("Chanenl does not exist!"); throw loggerUtils.exceptionSmith("Chanenl does not exist!", "validation");
} }
await channel.nuke(data.confirm); await channel.nuke(data.confirm);

View file

@ -33,7 +33,7 @@ module.exports.get = async function(req, res){
if(channel == null){ if(channel == null){
throw new Error("Channel not found."); throw loggerUtils.exceptionSmith("Channel not found.", "validation");
} }
res.status(200); res.status(200);
@ -64,7 +64,7 @@ module.exports.post = async function(req, res){
var permError = null; var permError = null;
if(chanDB == null){ if(chanDB == null){
throw new Error("Channel not found."); throw loggerUtils.exceptionSmith("Channel not found.", "validation");
} }
//For each permission submitted //For each permission submitted

View file

@ -31,7 +31,7 @@ module.exports.get = async function(req, res){
const channel = await channelModel.findOne({name: data.chanName}); const channel = await channelModel.findOne({name: data.chanName});
if(channel == null){ if(channel == null){
throw new Error("Channel not found."); throw loggerUtils.exceptionSmith("Channel not found.", "validation");
} }
res.status(200); res.status(200);
@ -56,7 +56,7 @@ module.exports.post = async function(req, res){
const settingsMap = new Map(Object.entries(data.settingsMap)); const settingsMap = new Map(Object.entries(data.settingsMap));
if(channel == null){ if(channel == null){
throw new Error("Channel not found."); throw loggerUtils.exceptionSmith("Channel not found.", "validation");
} }
res.status(200); res.status(200);

View file

@ -36,7 +36,7 @@ module.exports.get = async function(req, res){
delete chanDB.permissions._doc._id; delete chanDB.permissions._doc._id;
if(chanDB == null){ if(chanDB == null){
throw new Error("Channel not found."); throw loggerUtils.exceptionSmith("Channel not found.", "queue");
} }
return res.render('channelSettings', {instance: config.instanceName, user: req.session.user, channel: chanDB, reqRank, rankEnum: permissionModel.rankEnum, csrfToken: csrfUtils.generateToken(req)}); return res.render('channelSettings', {instance: config.instanceName, user: req.session.user, channel: chanDB, reqRank, rankEnum: permissionModel.rankEnum, csrfToken: csrfUtils.generateToken(req)});

View file

@ -115,7 +115,7 @@ const channelSchema = new mongoose.Schema({
channelSchema.pre('save', async function (next){ channelSchema.pre('save', async function (next){
if(this.isModified("name")){ if(this.isModified("name")){
if(this.name.match(/^[a-z0-9_\-.]+$/i) == null){ if(this.name.match(/^[a-z0-9_\-.]+$/i) == null){
throw new Error("Username must only contain alpha-numerics and the following symbols: '-_.'"); throw loggerUtils.exceptionSmith("Username must only contain alpha-numerics and the following symbols: '-_.'", "validation");
} }
} }
@ -221,7 +221,7 @@ channelSchema.statics.register = async function(channelObj, ownerObj){
const chanDB = await this.findOne({ name }); const chanDB = await this.findOne({ name });
if(chanDB){ if(chanDB){
throw new Error("Channel name already taken!"); throw loggerUtils.exceptionSmith("Channel name already taken!", "validation");
}else{ }else{
const id = await statModel.incrementChannelCount(); const id = await statModel.incrementChannelCount();
const rankList = [{ const rankList = [{
@ -334,7 +334,7 @@ channelSchema.statics.processExpiredBans = async function(){
channelSchema.methods.updateSettings = async function(settingsMap){ channelSchema.methods.updateSettings = async function(settingsMap){
settingsMap.forEach((value, key) => { settingsMap.forEach((value, key) => {
if(this.settings[key] == null){ if(this.settings[key] == null){
throw new Error("Invalid channel setting."); throw loggerUtils.exceptionSmith("Invalid channel setting.", "validation");
} }
this.settings[key] = value; this.settings[key] = value;
@ -661,13 +661,13 @@ channelSchema.methods.getChanBans = async function(){
channelSchema.methods.banByUserDoc = async function(userDB, expirationDays, banAlts){ channelSchema.methods.banByUserDoc = async function(userDB, expirationDays, banAlts){
//Throw a shitfit if the user doesn't exist //Throw a shitfit if the user doesn't exist
if(userDB == null){ if(userDB == null){
throw new Error("Cannot ban non-existant user!"); throw loggerUtils.exceptionSmith("Cannot ban non-existant user!", "validation");
} }
const foundBan = await this.checkBanByUserDoc(userDB); const foundBan = await this.checkBanByUserDoc(userDB);
if(foundBan != null){ if(foundBan != null){
throw new Error("User already banned!"); throw loggerUtils.exceptionSmith("User already banned!", "validation");
} }
//Create a new ban document based on input //Create a new ban document based on input
@ -703,13 +703,13 @@ channelSchema.methods.ban = async function(user, expirationDays, banAlts){
channelSchema.methods.unbanByUserDoc = async function(userDB){ channelSchema.methods.unbanByUserDoc = async function(userDB){
//Throw a shitfit if the user doesn't exist //Throw a shitfit if the user doesn't exist
if(userDB == null){ if(userDB == null){
throw new Error("Cannot ban non-existant user!"); throw loggerUtils.exceptionSmith("Cannot ban non-existant user!", "validation");
} }
const foundBan = await this.checkBanByUserDoc(userDB); const foundBan = await this.checkBanByUserDoc(userDB);
if(foundBan == null){ if(foundBan == null){
throw new Error("User already unbanned!"); throw loggerUtils.exceptionSmith("User already unbanned!", "validation");
} }
//You know I can't help but feel like an asshole for looking for the index of something I just pulled out of an array using forEach... //You know I can't help but feel like an asshole for looking for the index of something I just pulled out of an array using forEach...
@ -727,16 +727,16 @@ channelSchema.methods.unban = async function(user){
channelSchema.methods.nuke = async function(confirm){ channelSchema.methods.nuke = async function(confirm){
if(confirm == "" || confirm == null){ if(confirm == "" || confirm == null){
throw new Error("Empty Confirmation String!"); throw loggerUtils.exceptionSmith("Empty Confirmation String!", "validation");
}else if(confirm != this.name){ }else if(confirm != this.name){
throw new Error("Bad Confirmation String!"); throw loggerUtils.exceptionSmith("Bad Confirmation String!", "validation");
} }
//Annoyingly there isnt a good way to do this from 'this' //Annoyingly there isnt a good way to do this from 'this'
var oldChan = await this.deleteOne(); var oldChan = await this.deleteOne();
if(oldChan.deletedCount == 0){ if(oldChan.deletedCount == 0){
throw new Error("Server Error: Unable to delete channel! Please report this error to your server administrator, and with timestamp."); throw loggerUtils.exceptionSmith("Server Error: Unable to delete channel! Please report this error to your server administrator, and with timestamp.", "internal");
} }
} }

View file

@ -201,7 +201,7 @@ permissionSchema.methods.permCheckByUserDoc = function(userDB, perm){
return (userRank >= requiredRank); return (userRank >= requiredRank);
}else{ }else{
//if not scream and shout //if not scream and shout
throw new Error(`Permission check '${perm}' not found!`); throw loggerUtils.exceptionSmith(`Permission check '${perm}' not found!`, "Validation");
} }
} }
@ -223,7 +223,7 @@ permissionSchema.methods.overrideCheckByUserDoc = function(userDB, perm){
return (userRank >= requiredRank); return (userRank >= requiredRank);
}else{ }else{
//if not scream and shout //if not scream and shout
throw new Error(`Permission check '${perm}' not found!`); throw loggerUtils.exceptionSmith(`Permission check '${perm}' not found!`, "validation");
} }
} }

View file

@ -27,7 +27,8 @@ const crypto = require("node:crypto");
const {mongoose} = require('mongoose'); const {mongoose} = require('mongoose');
//Local Imports //Local Imports
const hashUtil = require('../../utils/hashUtils'); const hashUtil = require('../../utils/hashUtils.js');
const loggerUtils = require('../../utils/loggerUtils.js')
const daysToExpire = 7; const daysToExpire = 7;
@ -85,7 +86,7 @@ passwordResetSchema.statics.processExpiredRequests = async function(){
passwordResetSchema.methods.consume = async function(pass, confirmPass){ passwordResetSchema.methods.consume = async function(pass, confirmPass){
//Check confirmation pass //Check confirmation pass
if(pass != confirmPass){ if(pass != confirmPass){
throw new Error("Confirmation password does not match!"); throw loggerUtils.exceptionSmith("Confirmation password does not match!", "validation");
} }
//Populate the user reference //Populate the user reference

View file

@ -18,8 +18,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.*/
const {mongoose} = require('mongoose'); const {mongoose} = require('mongoose');
//Local Imports //Local Imports
const hashUtil = require('../../utils/hashUtils'); const hashUtil = require('../../utils/hashUtils.js');
const {userModel} = require('./userSchema'); const {userModel} = require('./userSchema.js');
const loggerUtils = require('../../utils/loggerUtils.js');
const userBanSchema = new mongoose.Schema({ const userBanSchema = new mongoose.Schema({
user: { user: {
@ -184,21 +185,21 @@ userBanSchema.statics.checkProcessedBans = async function(user){
userBanSchema.statics.banByUserDoc = async function(userDB, permanent, expirationDays, ipBan = false){ userBanSchema.statics.banByUserDoc = async function(userDB, permanent, expirationDays, ipBan = false){
//Prevent missing users //Prevent missing users
if(userDB == null){ if(userDB == null){
throw new Error("User not found") throw loggerUtils.exceptionSmith("User not found", "validation");
} }
//Ensure the user isn't already banned //Ensure the user isn't already banned
if(await this.checkBanByUserDoc(userDB) != null){ if(await this.checkBanByUserDoc(userDB) != null){
throw new Error("User already banned"); throw loggerUtils.exceptionSmith("User already banned", "validation");
} }
//Verify time to expire/delete depending on action //Verify time to expire/delete depending on action
if(expirationDays < 0){ if(expirationDays < 0){
throw new Error("Expiration Days must be a positive integer!"); throw loggerUtils.exceptionSmith("Expiration Days must be a positive integer!", "validation");
}else if(expirationDays < 30 && permanent){ }else if(expirationDays < 30 && permanent){
throw new Error("Permanent bans must be given at least 30 days before automatic account deletion!"); throw loggerUtils.exceptionSmith("Permanent bans must be given at least 30 days before automatic account deletion!", "validation");
}else if(expirationDays > 185){ }else if(expirationDays > 185){
throw new Error("Expiration/Deletion date cannot be longer than half a year out from the original ban date."); throw loggerUtils.exceptionSmith("Expiration/Deletion date cannot be longer than half a year out from the original ban date.", "validation");
} }
await banSessions(userDB); await banSessions(userDB);
@ -266,13 +267,13 @@ userBanSchema.statics.unbanByUserDoc = async function(userDB){
//Prevent missing users //Prevent missing users
if(userDB == null){ if(userDB == null){
throw new Error("User not found") throw loggerUtils.exceptionSmith("User not found", "validation");
} }
const banDB = await this.checkBanByUserDoc(userDB); const banDB = await this.checkBanByUserDoc(userDB);
if(!banDB){ if(!banDB){
throw new Error("User already un-banned"); throw loggerUtils.exceptionSmith("User already un-banned", "validation");
} }
//Use _id in-case mongoose wants to be a cunt //Use _id in-case mongoose wants to be a cunt
@ -284,7 +285,7 @@ userBanSchema.statics.unbanDeleted = async function(user){
const banDB = await this.checkProcessedBans(user); const banDB = await this.checkProcessedBans(user);
if(!banDB){ if(!banDB){
throw new Error("User already un-banned"); throw loggerUtils.exceptionSmith("User already un-banned", "validation");
} }
const oldBan = await this.deleteOne({_id: banDB._id}); const oldBan = await this.deleteOne({_id: banDB._id});

View file

@ -14,9 +14,6 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.*/ along with this program. If not, see <https://www.gnu.org/licenses/>.*/
//Node Imports
const { profile } = require('console');
//NPM Imports //NPM Imports
const {mongoose} = require('mongoose'); const {mongoose} = require('mongoose');
@ -33,6 +30,7 @@ const playlistSchema = require('../channel/media/playlistSchema');
//Utils //Utils
const hashUtil = require('../../utils/hashUtils'); const hashUtil = require('../../utils/hashUtils');
const mailUtil = require('../../utils/mailUtils'); const mailUtil = require('../../utils/mailUtils');
const loggerUtils = require('../../utils/loggerUtils')
const userSchema = new mongoose.Schema({ const userSchema = new mongoose.Schema({
@ -161,7 +159,7 @@ userSchema.pre('save', async function (next){
await this.populate('flair'); await this.populate('flair');
if(permissionModel.rankToNum(this.rank) < permissionModel.rankToNum(this.flair.rank)){ if(permissionModel.rankToNum(this.rank) < permissionModel.rankToNum(this.flair.rank)){
throw new Error(`User '${this.user}' does not have a high enough rank for flair '${this.flair.displayName}'!`); throw loggerUtils.exceptionSmith(`User '${this.user}' does not have a high enough rank for flair '${this.flair.displayName}'!`, "unauthorized");
} }
} }
@ -223,7 +221,7 @@ userSchema.statics.register = async function(userObj, ip){
//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 || user.toLowerCase() == "tokebot"){
throw new Error("User name/email already taken!"); 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
const id = await statModel.incrementUserCount(); const id = await statModel.incrementUserCount();
@ -242,14 +240,14 @@ userSchema.statics.register = async function(userObj, ip){
} }
} }
}else{ }else{
throw new Error("Confirmation password doesn't match!"); throw loggerUtils.exceptionSmith("Confirmation password doesn't match!", "validation");
} }
} }
userSchema.statics.authenticate = async function(user, pass, failLine = "Bad Username or Password."){ userSchema.statics.authenticate = async function(user, pass, failLine = "Bad Username or Password."){
//check for missing pass //check for missing pass
if(!user || !pass){ if(!user || !pass){
throw new Error("Missing user/pass."); throw loggerUtils.exceptionSmith("Missing user/pass.", "validation");
} }
//get the user if it exists //get the user if it exists
@ -268,9 +266,9 @@ userSchema.statics.authenticate = async function(user, pass, failLine = "Bad Use
badLogin(); badLogin();
} }
//standardize bad login response so it's unknowin which is bad for security reasons. //standardize bad login response so it's unknown which is bad for security reasons.
function badLogin(){ function badLogin(){
throw new Error(failLine); throw loggerUtils.exceptionSmith(failLine, "unauthorized");
} }
} }
@ -688,11 +686,11 @@ userSchema.methods.changePassword = async function(passChange){
await this.killAllSessions("Your password has been reset."); await this.killAllSessions("Your password has been reset.");
}else{ }else{
//confirmation pass doesn't match //confirmation pass doesn't match
throw new Error("Mismatched confirmation password!"); throw loggerUtils.exceptionSmith("Mismatched confirmation password!", "validation");
} }
}else{ }else{
//Old password wrong //Old password wrong
throw new Error("Incorrect Password!"); throw loggerUtils.exceptionSmith("Incorrect Password!", "validation");
} }
} }
@ -716,7 +714,7 @@ userSchema.methods.nuke = async function(pass){
//Check we have a confirmation password //Check we have a confirmation password
if(pass == "" || pass == null){ if(pass == "" || pass == null){
//scream and shout //scream and shout
throw new Error("No confirmation password!"); throw loggerUtils.exceptionSmith("No confirmation password!", "validation");
} }
//Check that the password is correct //Check that the password is correct
@ -725,7 +723,7 @@ userSchema.methods.nuke = async function(pass){
var oldUser = await this.deleteOne(); var oldUser = await this.deleteOne();
}else{ }else{
//complain about a bad pass //complain about a bad pass
throw new Error("Bad pass."); throw loggerUtils.exceptionSmith("Bad pass.", "unauthorized");
} }
} }

View file

@ -17,7 +17,20 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.*/
//Config //Config
const config = require('../../config.json'); const config = require('../../config.json');
//At some point this will be a bit more advanced, right now it's just a placeholder :P module.exports.exceptionSmith = function(msg, type){
//Create the new error with the given message
const exception = new Error(msg);
//Set the error type
exception.type = type;
//Mark the error as a custom error
exception.custom = true;
//Return the error
return exception;
}
module.exports.errorHandler = function(res, msg, type = "Generic", status = 400){ module.exports.errorHandler = function(res, msg, type = "Generic", status = 400){
//Some controllers do things after sending headers, for those, we should remain silent //Some controllers do things after sending headers, for those, we should remain silent
if(!res.headersSent){ if(!res.headersSent){
@ -35,11 +48,16 @@ module.exports.localExceptionHandler = function(err){
} }
module.exports.exceptionHandler = function(res, err){ module.exports.exceptionHandler = function(res, err){
//Locally handle the exception //If this is a self-made problem
module.exports.localExceptionHandler(err); if(err.custom){
module.exports.errorHandler(res, err.message, err.type);
}else{
//Locally handle the exception
module.exports.localExceptionHandler(err);
//if not yell at the browser for fucking up, and tell it what it did wrong. //if not yell at the browser for fucking up, and tell it what it did wrong.
module.exports.errorHandler(res, err.message, "Caught Exception"); module.exports.errorHandler(res, "An unexpected server crash was just prevented. You should probably report this to an admin.", "Caught Exception");
}
} }
module.exports.socketErrorHandler = function(socket, msg, type = "Generic"){ module.exports.socketErrorHandler = function(socket, msg, type = "Generic"){
@ -47,16 +65,28 @@ module.exports.socketErrorHandler = function(socket, msg, type = "Generic"){
} }
module.exports.socketExceptionHandler = function(socket, err){ module.exports.socketExceptionHandler = function(socket, err){
//Locally handle the exception //If this is a self made problem
module.exports.localExceptionHandler(err); if(err.custom){
//at the browser for fucking up, and tell it what it did wrong.
return module.exports.socketErrorHandler(socket, err.message, err.type);
}else{
//Locally handle the exception
module.exports.localExceptionHandler(err);
//if not yell at the browser for fucking up, and tell it what it did wrong. //if not yell at the browser for fucking up
return module.exports.socketErrorHandler(socket, err.msg, "Caught Exception"); return module.exports.socketErrorHandler(socket, "Caught Exception", "Caught Exception");
}
} }
module.exports.socketCriticalExceptionHandler = function(socket, err){ module.exports.socketCriticalExceptionHandler = function(socket, err){
//if not yell at the browser for fucking up, and tell it what it did wrong. //If this is a self made problem
socket.emit("kick", {type: "Disconnected", reason: `Server Error: ${err.message}`}); if(err.custom){
//yell at the browser for fucking up, and tell it what it did wrong.
socket.emit("kick", {type: "Disconnected", reason: `Server Error: ${err.message}`});
}else{
//yell at the browser for fucking up
socket.emit("kick", {type: "Disconnected", reason: "An unexpected server crash was just prevented. You should probably report this to an admin."});
}
return socket.disconnect(); return socket.disconnect();
} }

View file

@ -19,8 +19,9 @@ const url = require("node:url");
const validator = require('validator'); const validator = require('validator');
//Local Imports //Local Imports
const regexUtils = require('../regexUtils'); const media = require('../../app/channel/media/media.js');
const media = require('../../app/channel/media/media'); const regexUtils = require('../regexUtils.js');
const loggerUtils = require('../loggerUtils.js')
module.exports.fetchMetadata = async function(link, title){ module.exports.fetchMetadata = async function(link, title){
//Parse link //Parse link
@ -52,7 +53,7 @@ module.exports.fetchMetadata = async function(link, title){
if(!response.ok){ if(!response.ok){
//Scream and shout //Scream and shout
const errorBody = await response.text(); const errorBody = await response.text();
throw new Error(`Internet Archive Error '${response.status}': ${errorBody}`); throw loggerUtils.exceptionSmith(`Internet Archive Error '${response.status}': ${errorBody}`, "queue");
} }
//Collect our metadata //Collect our metadata

View file

@ -45,7 +45,7 @@ module.exports.kickoff = function(){
//Process Hashed IP Records that haven't been recorded in a week or more //Process Hashed IP Records that haven't been recorded in a week or more
userModel.processAgedIPRecords(); userModel.processAgedIPRecords();
//Process expired global bans that may have expired since last restart //Process expired global bans that may have expired since last restart
userBanModel.processExpiredBans() userBanModel.processExpiredBans();
//Process expired channel bans that may have expired since last restart //Process expired channel bans that may have expired since last restart
channelModel.processExpiredBans(); channelModel.processExpiredBans();
//Process expired password reset requests that may have expired since last restart //Process expired password reset requests that may have expired since last restart

View file

@ -16,9 +16,10 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.*/
//Local Imports //Local Imports
const config = require('../../config.json'); const config = require('../../config.json');
const {userModel} = require('../schemas/user/userSchema'); const {userModel} = require('../schemas/user/userSchema.js');
const userBanModel = require('../schemas/user/userBanSchema') const userBanModel = require('../schemas/user/userBanSchema.js')
const altchaUtils = require('../utils/altchaUtils'); const altchaUtils = require('../utils/altchaUtils.js');
const loggerUtils = require('../utils/loggerUtils.js')
//Create failed sign-in cache since it's easier and more preformant to implement it this way than adding extra burdon to the database //Create failed sign-in cache since it's easier and more preformant to implement it this way than adding extra burdon to the database
//Server restarts are far and few between. It would take multiple during a single bruteforce attempt for this to become an issue. //Server restarts are far and few between. It would take multiple during a single bruteforce attempt for this to become an issue.
@ -41,15 +42,24 @@ module.exports.authenticateSession = async function(user, pass, req){
//If this ip is randy bobandy //If this ip is randy bobandy
if(ipBanDB != null){ if(ipBanDB != null){
//tell it to fuck off //Make the number a little prettier despite the lack of precision since we're not doing calculations here :P
throw new Error(`The IP address you are trying to login from has been banned.`); const expiration = ipBanDB.getDaysUntilExpiration() < 1 ? 0 : ipBanDB.getDaysUntilExpiration();
//If the ban is permanent
if(ipBanDB.permanent){
//tell it to fuck off
throw loggerUtils.exceptionSmith(`The IP address you are trying to login from has been permanently banned. Your cleartext IP has been saved to the database. Any associated accounts will be nuked in ${expiration} day(s).`, "unauthorized");
}else{
//tell it to fuck off
throw loggerUtils.exceptionSmith(`The IP address you are trying to login from has been temporarily banned. Your cleartext IP has been saved to the database until the ban expires in ${expiration} day(s).`, "unauthorized");
}
} }
//If we have failed attempts //If we have failed attempts
if(attempt != null){ if(attempt != null){
//If we have more failed attempts than allowed //If we have more failed attempts than allowed
if(attempt.count > maxAttempts){ if(attempt.count > maxAttempts){
throw new Error("This account has been locked for at 24 hours due to a large amount of failed log-in attempts"); throw loggerUtils.exceptionSmith("This account has been locked for at 24 hours due to a large amount of failed log-in attempts", "unauthorized");
} }
//If we're throttling logins //If we're throttling logins
@ -57,9 +67,9 @@ module.exports.authenticateSession = async function(user, pass, req){
//Verification doesnt get sanatized or checked since that would most likely break the cryptography //Verification doesnt get sanatized or checked since that would most likely break the cryptography
//Since we've already got access to the request and dont need to import anything, why bother getting it from a parameter? //Since we've already got access to the request and dont need to import anything, why bother getting it from a parameter?
if(req.body.verification == null){ if(req.body.verification == null){
throw new Error("Verification failed!"); throw loggerUtils.exceptionSmith("Verification failed!", "unauthorized");
}else if(!altchaUtils.verify(req.body.verification, user)){ }else if(!altchaUtils.verify(req.body.verification, user)){
throw new Error("Verification failed!"); throw loggerUtils.exceptionSmith("Verification failed!", "");
} }
} }
} }
@ -75,9 +85,9 @@ module.exports.authenticateSession = async function(user, pass, req){
//Make the number a little prettier despite the lack of precision since we're not doing calculations here :P //Make the number a little prettier despite the lack of precision since we're not doing calculations here :P
const expiration = userBanDB.getDaysUntilExpiration() < 1 ? 0 : userBanDB.getDaysUntilExpiration(); const expiration = userBanDB.getDaysUntilExpiration() < 1 ? 0 : userBanDB.getDaysUntilExpiration();
if(userBanDB.permanent){ if(userBanDB.permanent){
throw new Error(`Your account has been permanently banned, and will be nuked from the database in: ${expiration} day(s)`); throw loggerUtils.exceptionSmith(`Your account has been permanently banned, and will be nuked from the database in: ${expiration} day(s)`, "unauthorized");
}else{ }else{
throw new Error(`Your account has been temporarily banned, and will be reinstated in: ${expiration} day(s)`); throw loggerUtils.exceptionSmith(`Your account has been temporarily banned, and will be reinstated in: ${expiration} day(s)`, "unauthorized");
} }
} }