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

@ -115,7 +115,7 @@ const channelSchema = new mongoose.Schema({
channelSchema.pre('save', async function (next){
if(this.isModified("name")){
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 });
if(chanDB){
throw new Error("Channel name already taken!");
throw loggerUtils.exceptionSmith("Channel name already taken!", "validation");
}else{
const id = await statModel.incrementChannelCount();
const rankList = [{
@ -334,7 +334,7 @@ channelSchema.statics.processExpiredBans = async function(){
channelSchema.methods.updateSettings = async function(settingsMap){
settingsMap.forEach((value, key) => {
if(this.settings[key] == null){
throw new Error("Invalid channel setting.");
throw loggerUtils.exceptionSmith("Invalid channel setting.", "validation");
}
this.settings[key] = value;
@ -661,13 +661,13 @@ channelSchema.methods.getChanBans = async function(){
channelSchema.methods.banByUserDoc = async function(userDB, expirationDays, banAlts){
//Throw a shitfit if the user doesn't exist
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);
if(foundBan != null){
throw new Error("User already banned!");
throw loggerUtils.exceptionSmith("User already banned!", "validation");
}
//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){
//Throw a shitfit if the user doesn't exist
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);
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...
@ -727,16 +727,16 @@ channelSchema.methods.unban = async function(user){
channelSchema.methods.nuke = async function(confirm){
if(confirm == "" || confirm == null){
throw new Error("Empty Confirmation String!");
throw loggerUtils.exceptionSmith("Empty Confirmation String!", "validation");
}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'
var oldChan = await this.deleteOne();
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);
}else{
//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);
}else{
//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');
//Local Imports
const hashUtil = require('../../utils/hashUtils');
const hashUtil = require('../../utils/hashUtils.js');
const loggerUtils = require('../../utils/loggerUtils.js')
const daysToExpire = 7;
@ -85,7 +86,7 @@ passwordResetSchema.statics.processExpiredRequests = async function(){
passwordResetSchema.methods.consume = async function(pass, confirmPass){
//Check confirmation pass
if(pass != confirmPass){
throw new Error("Confirmation password does not match!");
throw loggerUtils.exceptionSmith("Confirmation password does not match!", "validation");
}
//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');
//Local Imports
const hashUtil = require('../../utils/hashUtils');
const {userModel} = require('./userSchema');
const hashUtil = require('../../utils/hashUtils.js');
const {userModel} = require('./userSchema.js');
const loggerUtils = require('../../utils/loggerUtils.js');
const userBanSchema = new mongoose.Schema({
user: {
@ -184,21 +185,21 @@ userBanSchema.statics.checkProcessedBans = async function(user){
userBanSchema.statics.banByUserDoc = async function(userDB, permanent, expirationDays, ipBan = false){
//Prevent missing users
if(userDB == null){
throw new Error("User not found")
throw loggerUtils.exceptionSmith("User not found", "validation");
}
//Ensure the user isn't already banned
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
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){
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){
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);
@ -266,13 +267,13 @@ userBanSchema.statics.unbanByUserDoc = async function(userDB){
//Prevent missing users
if(userDB == null){
throw new Error("User not found")
throw loggerUtils.exceptionSmith("User not found", "validation");
}
const banDB = await this.checkBanByUserDoc(userDB);
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
@ -284,7 +285,7 @@ userBanSchema.statics.unbanDeleted = async function(user){
const banDB = await this.checkProcessedBans(user);
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});

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
along with this program. If not, see <https://www.gnu.org/licenses/>.*/
//Node Imports
const { profile } = require('console');
//NPM Imports
const {mongoose} = require('mongoose');
@ -33,6 +30,7 @@ const playlistSchema = require('../channel/media/playlistSchema');
//Utils
const hashUtil = require('../../utils/hashUtils');
const mailUtil = require('../../utils/mailUtils');
const loggerUtils = require('../../utils/loggerUtils')
const userSchema = new mongoose.Schema({
@ -161,7 +159,7 @@ userSchema.pre('save', async function (next){
await this.populate('flair');
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(userDB || user.toLowerCase() == "tokebot"){
throw new Error("User name/email already taken!");
throw loggerUtils.exceptionSmith("User name/email already taken!", "validation");
}else{
//Increment the user count, pulling the id to tattoo to the user
const id = await statModel.incrementUserCount();
@ -242,14 +240,14 @@ userSchema.statics.register = async function(userObj, ip){
}
}
}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."){
//check for missing pass
if(!user || !pass){
throw new Error("Missing user/pass.");
throw loggerUtils.exceptionSmith("Missing user/pass.", "validation");
}
//get the user if it exists
@ -268,9 +266,9 @@ userSchema.statics.authenticate = async function(user, pass, failLine = "Bad Use
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(){
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.");
}else{
//confirmation pass doesn't match
throw new Error("Mismatched confirmation password!");
throw loggerUtils.exceptionSmith("Mismatched confirmation password!", "validation");
}
}else{
//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
if(pass == "" || pass == null){
//scream and shout
throw new Error("No confirmation password!");
throw loggerUtils.exceptionSmith("No confirmation password!", "validation");
}
//Check that the password is correct
@ -725,7 +723,7 @@ userSchema.methods.nuke = async function(pass){
var oldUser = await this.deleteOne();
}else{
//complain about a bad pass
throw new Error("Bad pass.");
throw loggerUtils.exceptionSmith("Bad pass.", "unauthorized");
}
}