From 23ceb748834967501f96531d9852478524f6f657 Mon Sep 17 00:00:00 2001 From: rainbow napkin Date: Tue, 29 Apr 2025 07:05:38 -0400 Subject: [PATCH] Finished up with improvements to error handling. --- src/schemas/channel/channelSchema.js | 3 +- src/schemas/emoteSchema.js | 3 +- src/validators/accountValidator.js | 2 +- src/validators/channelValidator.js | 51 ++++++++++++---- src/validators/emoteValidator.js | 80 +++++++++++++++++++------- src/validators/permissionsValidator.js | 2 +- src/validators/tokebotValidator.js | 21 ++++++- www/js/utils.js | 6 +- 8 files changed, 128 insertions(+), 40 deletions(-) diff --git a/src/schemas/channel/channelSchema.js b/src/schemas/channel/channelSchema.js index 590d964..f98332e 100644 --- a/src/schemas/channel/channelSchema.js +++ b/src/schemas/channel/channelSchema.js @@ -49,7 +49,8 @@ const channelSchema = new mongoose.Schema({ description: { type: mongoose.SchemaTypes.String, required: true, - maxLength: 1000, + //Calculate max length by the validator max length and the size of an escaped character + maxLength: 1000 * 6, default: 0 }, thumbnail: { diff --git a/src/schemas/emoteSchema.js b/src/schemas/emoteSchema.js index dafda2a..9afb512 100644 --- a/src/schemas/emoteSchema.js +++ b/src/schemas/emoteSchema.js @@ -26,7 +26,8 @@ const typeEnum = ["image", "video"]; const emoteSchema = new mongoose.Schema({ name:{ type: mongoose.SchemaTypes.String, - required: true + required: true, + maxLength: 14, }, link:{ type: mongoose.SchemaTypes.String, diff --git a/src/validators/accountValidator.js b/src/validators/accountValidator.js index 4fc9d32..1e021a4 100644 --- a/src/validators/accountValidator.js +++ b/src/validators/accountValidator.js @@ -15,7 +15,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see .*/ //NPM Imports -const {checkSchema} = require('express-validator'); +const { checkSchema } = require('express-validator'); //local imports const {isRank} = require('./permissionsValidator'); diff --git a/src/validators/channelValidator.js b/src/validators/channelValidator.js index 0032ad8..b0390a3 100644 --- a/src/validators/channelValidator.js +++ b/src/validators/channelValidator.js @@ -15,30 +15,24 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see .*/ //NPM Imports -const { check, body, checkSchema, checkExact} = require('express-validator'); +const { checkSchema, checkExact } = require('express-validator'); //local imports const accountValidator = require('./accountValidator'); module.exports = { - description: (field = 'description') => body(field).escape().trim().isLength({min: 1, max: 1000}), - - thumbnail: (field = 'thumbnail') => accountValidator.img(field), - - rank: (field = 'rank') => accountValidator.rank(field), settingsMap: () => checkExact(checkSchema({ 'settingsMap.hidden': { optional: true, isBoolean: true, - } - })) + } })) } module.exports.name = function(field = 'name'){ return checkSchema({ [field]: { - esacpe: true, + escape: true, isAlphanumeric: { errorMessage: "Channel names must be alphanumeric." }, @@ -47,9 +41,46 @@ module.exports.name = function(field = 'name'){ min: 1, max: 50 }, - errorMessage: "Channel numes must be between 1 and 50 characters." + errorMessage: "Channel names must be between 1 and 50 characters." }, trim: true } }); +} + +module.exports.description = function(field = 'description'){ + return checkSchema({ + [field]:{ + escape: true, + trim: true, + isLength: { + options: { + min: 1, + max: 1000 + }, + errorMessage: "Description must be between 1 and 1000 characters." + }, + } + }); +} + +module.exports.thumbnail = function(field = 'thumbnail'){ + return accountValidator.img(field); +} + + +module.exports.rank = function(field = 'rank'){ + return accountValidator.rank(field); +} + +module.exports.settingsMap = function(){ + return checkExact( + checkSchema({ + 'settingsMap.hidden': { + optional: true, + isBoolean: true, + errorMessage: "Bad channel settings map." + } + }) + ); } \ No newline at end of file diff --git a/src/validators/emoteValidator.js b/src/validators/emoteValidator.js index 806536f..3c4ee74 100644 --- a/src/validators/emoteValidator.js +++ b/src/validators/emoteValidator.js @@ -15,35 +15,71 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see .*/ //NPM Imports -const { check } = require('express-validator'); +const { checkSchema } = require('express-validator'); const validator = require('validator');//We need validators for express-less code too! +const { errorMiddleware } = require('../utils/loggerUtils'); module.exports = { - name: (field = 'name') => check(field).escape().trim().isAlphanumeric().isLength({min: 1, max: 14}), - link: (field = 'link') => check(field).trim().isURL(), - manualName: (input) => { - //Trim and sanatize input - const clean = validator.trim(validator.escape(input)); - //if cleaned input is a proper emote name - if(validator.isLength(clean, {min: 1, max: 14}) && validator.isAlphanumeric(clean)){ - //return cleaned input - return clean; +} + +module.exports.name = function(field = 'name'){ + return checkSchema({ + [field]: { + escape: true, + trim: true, + isAlphanumeric: { + errorMessage: "Emote names must be alphanumeric." + }, + isLength: { + options: { + min: 1, + max: 14 + }, + errorMessage: "Emote name must be between 1 and 14 characters." + }, } + }) +} - //otherwise return false - return false; - }, - manualLink: (input) => { - //Trim the input - const clean = validator.trim(input) - - //If we have a URL return the trimmed input - if(validator.isURL(clean)){ - return clean; +module.exports.link = function(field = 'link'){ + return checkSchema({ + [field]: { + isURL: { + options: { + require_tld: false, + require_host: false + }, + errorMessage: "Invalid URL." + }, + trim: true } + }) +} - //otherwise return false - return false; +module.exports.manualName = function(input){ + //Trim and sanatize input + const clean = validator.trim(validator.escape(input)); + + //if cleaned input is a proper emote name + if(validator.isLength(clean, {min: 1, max: 14}) && validator.isAlphanumeric(clean)){ + //return cleaned input + return clean; } + + //otherwise return false + return false; +} + +module.exports.manualLink = function(input){ + //Trim the input + const clean = validator.trim(input) + + //If we have a URL return the trimmed input + if(validator.isURL(clean)){ + return clean; + } + + //otherwise return false + return false; } \ No newline at end of file diff --git a/src/validators/permissionsValidator.js b/src/validators/permissionsValidator.js index c304406..baa04ae 100644 --- a/src/validators/permissionsValidator.js +++ b/src/validators/permissionsValidator.js @@ -15,7 +15,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see .*/ //NPM Imports -const { check, body, checkSchema, checkExact} = require('express-validator'); +const { checkSchema } = require('express-validator'); //local imports const permissionModel = require("../schemas/permissionSchema"); diff --git a/src/validators/tokebotValidator.js b/src/validators/tokebotValidator.js index a4edec3..02a7008 100644 --- a/src/validators/tokebotValidator.js +++ b/src/validators/tokebotValidator.js @@ -15,8 +15,23 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see .*/ //NPM Imports -const { check } = require('express-validator'); +const { check, checkSchema } = require('express-validator'); -module.exports = { - command: (field = 'command') => check(field).escape().trim().isAlphanumeric().isLength({min: 1, max: 30}), +module.exports.command = function(field = 'command'){ + return checkSchema({ + [field]: { + escape: true, + trim: true, + isAlphanumeric: { + errorMessage: "Toke commands must be alphanumeric." + }, + isLength: { + options: { + min: 1, + max: 30 + }, + errorMessage: "Toke commands must be between 1 and 30 characters." + } + } + }); } \ No newline at end of file diff --git a/www/js/utils.js b/www/js/utils.js index 24da23d..f93e2b7 100644 --- a/www/js/utils.js +++ b/www/js/utils.js @@ -105,7 +105,11 @@ class canopyUXUtils{ try{ const errors = body.errors; errors.forEach((err)=>{ - new canopyUXUtils.popup(`

${err.type} Error:


${err.msg}

`); + //Capitalize the first letter of the type + const type = `${err.type[0].toUpperCase()}${err.type.slice(1)}` + + //Display our error + new canopyUXUtils.popup(`

${type} Error:


${err.msg}

`); }); }catch(err){ console.error("Display Error Body:");