217 lines
6.1 KiB
JavaScript
217 lines
6.1 KiB
JavaScript
/*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 <https://www.gnu.org/licenses/>.*/
|
|
|
|
//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});
|
|
} |