/*Canopy - The next generation of stoner streaming software Copyright (C) 2024-2025 Rainbownapkin and the TTN Community This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 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 .*/ //NPM Imports const { checkSchema } = require('express-validator'); const {sanitizeUrl} = require("@braintree/sanitize-url"); //local imports const {isRank} = require('./permissionsValidator'); module.exports.user = function(field = 'user'){ return checkSchema({ [field]: { escape: true, trim: true, //Caution: Nerd Rant //isAlphanumerics only takes locale for the option flag in schemas for some reason... matches: { //See this is the shit I'm talking about, WHY IS THIS CALLED OPTIONS? IT SHOULD BE PATTERN //OPTIONS IS SUPPOSED TO BE AN OBJECT THAT PASSES EXTRA VALUES THATS LITERALLY HOW EVERYTHING ELSE IN THIS FUCKING LIBRARY WORKS //WHO FUCKING WROTE THIS SHIT!?!?!?!?! //HOW IS THIS ACCEPTED ON ONE OF THE MOST WIDELY USED VALIDATION LIBRARIES ON THE WEB!??!?!?!!? //IT'S NOT EVEN FUCKING DOCUMENTED ANYWHERE!!!!!!!!!!!! //WEBDEVS, GET YOUR FUCKING SHIT TOGETHER, FUCK! options: [/^[A-Za-z0-9-_]+$/], errorMessage: "Usernames can only contain numbers, letters, underscores, and dashes." }, //matches: /^[A-Za-z0-9-_]+$/, isLength: { options: { min: 1, max: 22 }, errorMessage: "Usernames must be between 1 and 22 characters." }, } }); } function getPassSchema(field = 'pass'){ //Heavily simplified from previous versions. //Trimming passwords is iffy, and escaping them is a down-right bad idea return { [field]: { notEmpty: true, } } } module.exports.pass = function(field = 'pass'){ return checkSchema(getPassSchema(field)); } module.exports.securePass = function(field = 'pass'){ const schema = getPassSchema(field); schema[field].isStrongPassword = { options: { minLength: 8, minLowercase: 1, minUppercase: 1, minNumbers: 1, minSymbols: 1 }, errorMessage: "Passwords must contain 8 characters, including at least one: Upper, Lower, Number, and Special char." } return checkSchema(schema); } module.exports.email = function(field = 'email'){ return checkSchema({ [field]: { optional: true, isEmail: { errorMessage: "Invalid E-Mail Address" }, normalizeEmail: true } }); } module.exports.img = function(field = 'img'){ return checkSchema({ [field]: { optional: true, isURL: { options: { require_tld: false, require_host: false, require_valid_protocol: true }, errorMessage: "Invalid URL." }, trim: true, customSanitizer: { options: sanitizeUrl } } }); } module.exports.pronouns = function(field = 'pronouns'){ return checkSchema({ [field]: { optional: true, trim: true, isLength: { options: { min: 0, max: 15 }, errorMessage: "Pronouns must be under 15 characters." }, escape: true } }); } module.exports.signature = function(field = 'signature'){ return checkSchema({ [field]: { optional: true, trim: true, isLength: { options: { min: 1, max: 25 }, errorMessage: "Signature must be between 1 and 25 characters." }, escape: true } }); } module.exports.bio = function(field = 'bio'){ return checkSchema({ [field]: { optional: true, trim: true, isLength: { options: { min: 1, max: 1000 }, errorMessage: "Bio must be between 1 and 1000 characters." }, escape: true } }); } module.exports.rank = function(field = 'rank'){ return checkSchema({ [field]: { escape: true, trim: true, custom: { options: isRank, }, errorMessage: "Invalid rank." } }); } const securityTokenSchema = { escape: true, trim: true, isHexadecimal: true, isLength: { options: { min: 64, max: 64 } }, errorMessage: "Invalid security token." } module.exports.securityToken = function(field = 'token'){ return checkSchema({[field]:securityTokenSchema}); } module.exports.rememberMeID = function(field = 'rememberme.id'){ return checkSchema({ [field]:{ in: ['cookies'], optional: true, isUUID: true } }) } module.exports.rememberMeToken = function(field = 'rememberme.token'){ //Create our own schema with blackjack and hookers const tokenSchema = structuredClone(securityTokenSchema); //Modify as needed tokenSchema.in = ['cookies']; tokenSchema.optional = true; //Return the validator return checkSchema({[field]:tokenSchema}); }