Finished adding JSDoc for src/utils
This commit is contained in:
parent
2303c89bcf
commit
7b8c44158f
|
|
@ -20,11 +20,21 @@ const config = require('../../config.json');
|
||||||
//NPM imports
|
//NPM imports
|
||||||
const { createChallenge, verifySolution } = require('altcha-lib');
|
const { createChallenge, verifySolution } = require('altcha-lib');
|
||||||
|
|
||||||
//Create empty array to hold cache of spent payloades to protect against replay attacks
|
/**
|
||||||
|
* Create empty array to hold cache of spent payloads to protect against replay attacks
|
||||||
|
*/
|
||||||
const spent = [];
|
const spent = [];
|
||||||
//Captcha lifetime in minutes
|
/**
|
||||||
|
* Captcha lifetime in minutes
|
||||||
|
*/
|
||||||
const lifetime = 2;
|
const lifetime = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates captcha challenges to send down to the browser
|
||||||
|
* @param {Number} difficulty - Challange Difficulty (x100K internally)
|
||||||
|
* @param {String} uniqueSecret - Secret to salt the challange hash with
|
||||||
|
* @returns {String} Altcha Challenge hash
|
||||||
|
*/
|
||||||
module.exports.genCaptcha = async function(difficulty = 2, uniqueSecret = ''){
|
module.exports.genCaptcha = async function(difficulty = 2, uniqueSecret = ''){
|
||||||
//Set altcha expiration date
|
//Set altcha expiration date
|
||||||
const expiration = new Date();
|
const expiration = new Date();
|
||||||
|
|
@ -40,8 +50,14 @@ module.exports.genCaptcha = async function(difficulty = 2, uniqueSecret = ''){
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies completed altcha challenges handed over from the user
|
||||||
|
* @param {String} payload - Completed Altcha Payload
|
||||||
|
* @param {String} uniqueSecret - Server-side Unique Secret to verify payload came from server-generated challenge
|
||||||
|
* @returns {boolean} True if payload is a valid and unique altcha challenge which originated from this server
|
||||||
|
*/
|
||||||
module.exports.verify = async function(payload, uniqueSecret = ''){
|
module.exports.verify = async function(payload, uniqueSecret = ''){
|
||||||
//If we already checked this payload
|
//If this payload is already spent
|
||||||
if(spent.indexOf(payload) != -1){
|
if(spent.indexOf(payload) != -1){
|
||||||
//Fuck off and die
|
//Fuck off and die
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,10 @@ const loggerUtil = require('./loggerUtils');
|
||||||
//NPM Imports
|
//NPM Imports
|
||||||
const validator = require('validator');//We need validators for express-less code too!
|
const validator = require('validator');//We need validators for express-less code too!
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic security check which runs on startup.
|
||||||
|
* Warns server admin against unsafe config options.
|
||||||
|
*/
|
||||||
module.exports.securityCheck = function(){
|
module.exports.securityCheck = function(){
|
||||||
//Check Protocol
|
//Check Protocol
|
||||||
if(config.protocol.toLowerCase() != 'https'){
|
if(config.protocol.toLowerCase() != 'https'){
|
||||||
|
|
|
||||||
|
|
@ -23,15 +23,33 @@ const crypto = require('node:crypto');
|
||||||
//NPM Imports
|
//NPM Imports
|
||||||
const bcrypt = require('bcrypt');
|
const bcrypt = require('bcrypt');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sitewide function for hashing passwords
|
||||||
|
* @param {String} pass - Password to hash
|
||||||
|
* @returns {String} Hashed/Salted password
|
||||||
|
*/
|
||||||
module.exports.hashPassword = function(pass){
|
module.exports.hashPassword = function(pass){
|
||||||
const salt = bcrypt.genSaltSync();
|
const salt = bcrypt.genSaltSync();
|
||||||
return bcrypt.hashSync(pass, salt);
|
return bcrypt.hashSync(pass, salt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sitewide password for authenticating/comparing passwords agianst hashes
|
||||||
|
* @param {String} pass - Plaintext Password
|
||||||
|
* @param {String} hash - Salty Hash
|
||||||
|
* @returns {Boolean} True if authentication success
|
||||||
|
*/
|
||||||
module.exports.comparePassword = function(pass, hash){
|
module.exports.comparePassword = function(pass, hash){
|
||||||
return bcrypt.compareSync(pass, hash);
|
return bcrypt.compareSync(pass, hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Site-wide IP hashing/salting function
|
||||||
|
*
|
||||||
|
* Provides a basic level of privacy by only logging salted hashes of IP's
|
||||||
|
* @param {String} ip - IP to hash
|
||||||
|
* @returns {String} Hashed/Salted IP Adress
|
||||||
|
*/
|
||||||
module.exports.hashIP = function(ip){
|
module.exports.hashIP = function(ip){
|
||||||
//Create hash object
|
//Create hash object
|
||||||
const hashObj = crypto.createHash('md5');
|
const hashObj = crypto.createHash('md5');
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,16 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
||||||
const validator = require('validator');//No express here, so regular validator it is!
|
const validator = require('validator');//No express here, so regular validator it is!
|
||||||
|
|
||||||
//Create link cache
|
//Create link cache
|
||||||
|
/**
|
||||||
|
* Basic RAM-Based cache of links, so we don't have to re-pull things after we get them
|
||||||
|
*/
|
||||||
module.exports.cache = new Map();
|
module.exports.cache = new Map();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates links and returns a marked link object that can be returned to the client to format/embed accordingly
|
||||||
|
* @param {String} link - URL to Validate
|
||||||
|
* @returns {Object} Marked link object
|
||||||
|
*/
|
||||||
module.exports.markLink = async function(link){
|
module.exports.markLink = async function(link){
|
||||||
//Check link cache for the requested link
|
//Check link cache for the requested link
|
||||||
const cachedLink = module.exports.cache.get(link);
|
const cachedLink = module.exports.cache.get(link);
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,15 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
||||||
//Config
|
//Config
|
||||||
const config = require('../../config.json');
|
const config = require('../../config.json');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and returns a custom exception, tagged as a 'custom' exception, using the 'custom' boolean property.
|
||||||
|
* This is used to denote that this error was generated on purpose, with a human readable message, that can be securely sent to the client.
|
||||||
|
* Unexpected exceptions should only be logged internally, however, as they may contain sensitive data.
|
||||||
|
*
|
||||||
|
* @param {String} msg - Error message to send the client
|
||||||
|
* @param {String} type - Error type to send back to the client
|
||||||
|
* @returns {Error} The exception to smith
|
||||||
|
*/
|
||||||
module.exports.exceptionSmith = function(msg, type){
|
module.exports.exceptionSmith = function(msg, type){
|
||||||
//Create the new error with the given message
|
//Create the new error with the given message
|
||||||
const exception = new Error(msg);
|
const exception = new Error(msg);
|
||||||
|
|
@ -31,6 +40,14 @@ module.exports.exceptionSmith = function(msg, type){
|
||||||
return exception;
|
return exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main error handling function
|
||||||
|
* @param {Express.Response} res - Response being sent out to the client who caused the issue
|
||||||
|
* @param {String} msg - Error message to send the client
|
||||||
|
* @param {String} type - Error type to send back to the client
|
||||||
|
* @param {Number} status - HTTP(s) Status Code to send back to the client
|
||||||
|
* @returns {Express.Response} If we have a usable Express Response object, return it back after it's been cashed
|
||||||
|
*/
|
||||||
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){
|
||||||
|
|
@ -39,6 +56,10 @@ module.exports.errorHandler = function(res, msg, type = "Generic", status = 400)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles local exceptions which where not directly created by user interaction
|
||||||
|
* @param {Error} err - Exception to handle
|
||||||
|
*/
|
||||||
module.exports.localExceptionHandler = function(err){
|
module.exports.localExceptionHandler = function(err){
|
||||||
//If we're being verbose
|
//If we're being verbose
|
||||||
if(config.verbose){
|
if(config.verbose){
|
||||||
|
|
@ -47,6 +68,11 @@ module.exports.localExceptionHandler = function(err){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles exceptions which where directly the fault of user action >:(
|
||||||
|
* @param {Express.Response} res - Express Response object to bitch at
|
||||||
|
* @param {Error} err - Error created by the jerk in question
|
||||||
|
*/
|
||||||
module.exports.exceptionHandler = function(res, err){
|
module.exports.exceptionHandler = function(res, err){
|
||||||
//If this is a self-made problem
|
//If this is a self-made problem
|
||||||
if(err.custom){
|
if(err.custom){
|
||||||
|
|
@ -60,14 +86,27 @@ module.exports.exceptionHandler = function(res, err){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic error-handling for socket.io so we don't just silently swallow errors.
|
||||||
|
* @param {Socket} socket - Socket error originated from
|
||||||
|
* @param {String} msg - Error message to send the client
|
||||||
|
* @param {String} type - Error type to send back to the client
|
||||||
|
* @returns {Boolean} - Passthrough from socket.emit
|
||||||
|
*/
|
||||||
module.exports.socketErrorHandler = function(socket, msg, type = "Generic"){
|
module.exports.socketErrorHandler = function(socket, msg, type = "Generic"){
|
||||||
return socket.emit("error", {errors: [{type, msg, date: new Date()}]});
|
return socket.emit("error", {errors: [{type, msg, date: new Date()}]});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates error messages for simple errors generated by socket.io interaction
|
||||||
|
* @param {Socket} socket - Socket error originated from
|
||||||
|
* @param {Error} err - Error created by the jerk in question
|
||||||
|
* @returns {Boolean} - Passthrough from socket.emit
|
||||||
|
*/
|
||||||
module.exports.socketExceptionHandler = function(socket, err){
|
module.exports.socketExceptionHandler = function(socket, err){
|
||||||
//If this is a self made problem
|
//If this is a self made problem
|
||||||
if(err.custom){
|
if(err.custom){
|
||||||
//at the browser for fucking up, and tell it what it did wrong.
|
//yell at the browser for fucking up, and tell it what it did wrong.
|
||||||
return module.exports.socketErrorHandler(socket, err.message, err.type);
|
return module.exports.socketErrorHandler(socket, err.message, err.type);
|
||||||
}else{
|
}else{
|
||||||
//Locally handle the exception
|
//Locally handle the exception
|
||||||
|
|
@ -78,6 +117,12 @@ module.exports.socketExceptionHandler = function(socket, err){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates error messages and drops connection for critical errors caused by socket.io interaction
|
||||||
|
* @param {Socket} socket - Socket error originated from
|
||||||
|
* @param {Error} err - Error created by the jerk in question
|
||||||
|
* @returns {Boolean} - Passthrough from socket.disconnect
|
||||||
|
*/
|
||||||
module.exports.socketCriticalExceptionHandler = function(socket, err){
|
module.exports.socketCriticalExceptionHandler = function(socket, err){
|
||||||
//If this is a self made problem
|
//If this is a self made problem
|
||||||
if(err.custom){
|
if(err.custom){
|
||||||
|
|
@ -93,11 +138,21 @@ module.exports.socketCriticalExceptionHandler = function(socket, err){
|
||||||
return socket.disconnect();
|
return socket.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints warning text to server console
|
||||||
|
* @param {String} string - String to print to console
|
||||||
|
*/
|
||||||
module.exports.consoleWarn = function(string){
|
module.exports.consoleWarn = function(string){
|
||||||
console.warn('\x1b[31m\x1b[4m%s\x1b[0m',string);
|
console.warn('\x1b[31m\x1b[4m%s\x1b[0m',string);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Basic error-handling middleware to ensure we're not dumping stack traces
|
/**
|
||||||
|
* Basic error-handling middleware to ensure we're not dumping stack traces to the client, as that would be insecure
|
||||||
|
* @param {Error} err - Error to handle
|
||||||
|
* @param {Express.Request} req - Express Request
|
||||||
|
* @param {Express.Response} res - Express Response
|
||||||
|
* @param {Function} next - Next function in the Express middleware chain (Not that it's getting called XP)
|
||||||
|
*/
|
||||||
module.exports.errorMiddleware = function(err, req, res, next){
|
module.exports.errorMiddleware = function(err, req, res, next){
|
||||||
//Set generic error
|
//Set generic error
|
||||||
var reason = "Server Error";
|
var reason = "Server Error";
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,9 @@ const config = require('../../config.json');
|
||||||
const nodeMailer = require("nodemailer");
|
const nodeMailer = require("nodemailer");
|
||||||
|
|
||||||
//Setup mail transport
|
//Setup mail transport
|
||||||
|
/**
|
||||||
|
* nodemailer transport object, generated from options specific in our config file
|
||||||
|
*/
|
||||||
const transporter = nodeMailer.createTransport({
|
const transporter = nodeMailer.createTransport({
|
||||||
host: config.mail.host,
|
host: config.mail.host,
|
||||||
port: config.mail.port,
|
port: config.mail.port,
|
||||||
|
|
@ -31,6 +34,14 @@ const transporter = nodeMailer.createTransport({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends an email as tokebot to the requested user w/ the requested body and signature
|
||||||
|
* @param {String} to - String containing the email address to send to
|
||||||
|
* @param {String} subject - Subject line of the email to send
|
||||||
|
* @param {String} body - Body contents, either HTML or Plaintext
|
||||||
|
* @param {Boolean} htmlBody - Whether or not Body contents should be sent as HTML or Plaintext
|
||||||
|
* @returns {Object} Sent mail info
|
||||||
|
*/
|
||||||
module.exports.mailem = async function(to, subject, body, htmlBody = false){
|
module.exports.mailem = async function(to, subject, body, htmlBody = false){
|
||||||
//Create mail object
|
//Create mail object
|
||||||
const mailObj = {
|
const mailObj = {
|
||||||
|
|
@ -56,6 +67,12 @@ module.exports.mailem = async function(to, subject, body, htmlBody = false){
|
||||||
return sentMail;
|
return sentMail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends address verification email
|
||||||
|
* @param {Mongoose.Document} requestDB - DB Document Object for the current email change request token
|
||||||
|
* @param {Mongoose.Document} userDB - DB Document Object for the user we're verifying email against
|
||||||
|
* @param {String} newEmail - New email address to send to
|
||||||
|
*/
|
||||||
module.exports.sendAddressVerification = async function(requestDB, userDB, newEmail){
|
module.exports.sendAddressVerification = async function(requestDB, userDB, newEmail){
|
||||||
//Send the reset url via email
|
//Send the reset url via email
|
||||||
await module.exports.mailem(
|
await module.exports.mailem(
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,12 @@ const media = require('../../app/channel/media/media.js');
|
||||||
const regexUtils = require('../regexUtils.js');
|
const regexUtils = require('../regexUtils.js');
|
||||||
const loggerUtils = require('../loggerUtils.js')
|
const loggerUtils = require('../loggerUtils.js')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pulls metadate for a given archive.org item
|
||||||
|
* @param {String} fullID - Full path of the requested upload
|
||||||
|
* @param {String} title - Title to add to media object
|
||||||
|
* @returns {Array} Generated list of media objects from given upload path
|
||||||
|
*/
|
||||||
module.exports.fetchMetadata = async function(fullID, title){
|
module.exports.fetchMetadata = async function(fullID, title){
|
||||||
//Split fullID by first slash
|
//Split fullID by first slash
|
||||||
const [itemID, requestedPath] = decodeURIComponent(fullID).split(/\/(.*)/);
|
const [itemID, requestedPath] = decodeURIComponent(fullID).split(/\/(.*)/);
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,12 @@ const validator = require('validator');//No express here, so regular validator i
|
||||||
const iaUtil = require('./internetArchiveUtils');
|
const iaUtil = require('./internetArchiveUtils');
|
||||||
const ytdlpUtil = require('./ytdlpUtils');
|
const ytdlpUtil = require('./ytdlpUtils');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks a given URL and runs the proper metadata fetching function to create a media object from any supported URL
|
||||||
|
* @param {String} url - URL to yank media against
|
||||||
|
* @param {String} title - Title to apply to yanked media
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
module.exports.yankMedia = async function(url, title){
|
module.exports.yankMedia = async function(url, title){
|
||||||
//Get pull type
|
//Get pull type
|
||||||
const pullType = await this.getMediaType(url);
|
const pullType = await this.getMediaType(url);
|
||||||
|
|
@ -50,6 +56,13 @@ module.exports.yankMedia = async function(url, title){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refreshes raw links on relevant media objects
|
||||||
|
*
|
||||||
|
* Useful for sources like youtube, who only provide expiring raw links
|
||||||
|
* @param {ScheduledMedia} mediaObj - Media Object to refresh
|
||||||
|
* @returns {ScheduledMedia} Refreshed media object
|
||||||
|
*/
|
||||||
module.exports.refreshRawLink = async function(mediaObj){
|
module.exports.refreshRawLink = async function(mediaObj){
|
||||||
switch(mediaObj.type){
|
switch(mediaObj.type){
|
||||||
case 'yt':
|
case 'yt':
|
||||||
|
|
@ -76,10 +89,16 @@ module.exports.refreshRawLink = async function(mediaObj){
|
||||||
//Return null to tell the calling function there is no refresh required for this media type
|
//Return null to tell the calling function there is no refresh required for this media type
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
//I'd be lying if this didn't take at least some inspiration/regex patterns from extractQueryParam() in cytube/forest's browser-side 'util.js'
|
* Detects media type by URL
|
||||||
//Still this has some improvements like url pre-checks and the fact that it's handled serverside, recuing possibility of bad requests.
|
*
|
||||||
//Some of the regex expressions for certain services have also been improved, such as youtube, and the fore.st-unique archive.org
|
* I'd be lying if this didn't take at least some inspiration/regex patterns from extractQueryParam() in cytube/forest's browser-side 'util.js'
|
||||||
|
* Still this has some improvements like url pre-checks and the fact that it's handled serverside, recuing possibility of bad requests.
|
||||||
|
* Some of the regex expressions for certain services have also been improved, such as youtube, and the fore.st-unique archive.org
|
||||||
|
*
|
||||||
|
* @param {String} url - URL to determine media type of
|
||||||
|
* @returns {Object} containing URL type and clipped ID string
|
||||||
|
*/
|
||||||
module.exports.getMediaType = async function(url){
|
module.exports.getMediaType = async function(url){
|
||||||
//Check if we have a valid url, encode it on the fly in case it's too humie-friendly
|
//Check if we have a valid url, encode it on the fly in case it's too humie-friendly
|
||||||
if(!validator.isURL(encodeURI(url))){
|
if(!validator.isURL(encodeURI(url))){
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,12 @@ const media = require('../../app/channel/media/media.js');
|
||||||
const regexUtils = require('../regexUtils.js');
|
const regexUtils = require('../regexUtils.js');
|
||||||
const loggerUtils = require('../loggerUtils.js')
|
const loggerUtils = require('../loggerUtils.js')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pulls metadata for a single youtube video via YT-DLP
|
||||||
|
* @param {String} id - Youtube Video ID
|
||||||
|
* @param {String} title - Title to add to the given media object
|
||||||
|
* @returns {Media} Media object containing relevant metadata
|
||||||
|
*/
|
||||||
module.exports.fetchYoutubeMetadata = async function(id, title){
|
module.exports.fetchYoutubeMetadata = async function(id, title){
|
||||||
try{
|
try{
|
||||||
//Try to pull media from youtube id
|
//Try to pull media from youtube id
|
||||||
|
|
@ -50,6 +56,12 @@ module.exports.fetchYoutubeMetadata = async function(id, title){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pulls metadata for a playlist of youtube videos via YT-DLP
|
||||||
|
* @param {String} id - Youtube Playlist ID
|
||||||
|
* @param {String} title - Title to add to the given media objects
|
||||||
|
* @returns {Array} Array of Media objects containing relevant metadata
|
||||||
|
*/
|
||||||
module.exports.fetchYoutubePlaylistMetadata = async function(id, title){
|
module.exports.fetchYoutubePlaylistMetadata = async function(id, title){
|
||||||
try{
|
try{
|
||||||
//Try to pull media from youtube id
|
//Try to pull media from youtube id
|
||||||
|
|
@ -71,15 +83,23 @@ module.exports.fetchYoutubePlaylistMetadata = async function(id, title){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This requires HLS embeds which, in-turn, require daily motion to add us to their CORS exception list
|
||||||
|
* Not gonna happen, so we need to use their API for this, or proxy the video
|
||||||
module.exports.fetchDailymotionMetadata = async function(id, title){
|
module.exports.fetchDailymotionMetadata = async function(id, title){
|
||||||
//Pull media from dailymotion link
|
//Pull media from dailymotion link
|
||||||
const media = await fetchVideoMetadata(`https://dailymotion.com/video/${id}`, title, 'dm');
|
const media = await fetchVideoMetadata(`https://dailymotion.com/video/${id}`, title, 'dm');
|
||||||
|
|
||||||
//Return found media;
|
//Return found media;
|
||||||
return media;
|
return media;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
//Generic single video YTDLP function meant to be used by service-sepecific fetchers which will then be used to fetch video metadata
|
/**
|
||||||
|
* Generic single video YTDLP function meant to be used by service-sepecific fetchers which will then be used to fetch video metadata
|
||||||
|
* @param {String} link - Link to video in question
|
||||||
|
* @param {String} title - Title to add to the given media objects
|
||||||
|
* @param {String} type - Link type to attach to the resulting media object
|
||||||
|
* @returns {Array} Array of Media objects containing relevant metadata
|
||||||
|
*/
|
||||||
async function fetchVideoMetadata(link, title, type, format = 'b'){
|
async function fetchVideoMetadata(link, title, type, format = 'b'){
|
||||||
//Create media list
|
//Create media list
|
||||||
const mediaList = [];
|
const mediaList = [];
|
||||||
|
|
@ -110,6 +130,12 @@ async function fetchVideoMetadata(link, title, type, format = 'b'){
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
//Wrapper function for YT-DLP NPM package with pre-set cli-flags
|
//Wrapper function for YT-DLP NPM package with pre-set cli-flags
|
||||||
|
/**
|
||||||
|
* Basic async YT-DLP Fetch wrapper, ensuring config
|
||||||
|
* @param {String} link - Link to fetch using YT-DLP
|
||||||
|
* @param {String} format - Format string to hand YT-DLP, defaults to 'b'
|
||||||
|
* @returns {Object} Metadata dump from YT-DLP
|
||||||
|
*/
|
||||||
async function ytdlpFetch(link, format = 'b'){
|
async function ytdlpFetch(link, format = 'b'){
|
||||||
//return promise from ytdlp
|
//return promise from ytdlp
|
||||||
return ytdlp(link, {
|
return ytdlp(link, {
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,15 @@ 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/>.*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* I won't lie this line was whole-sale ganked from stack overflow like a fucking skid
|
||||||
|
* In my defense I only did it because js-runtime-devs are taking fucking eons to implement RegExp.escape()
|
||||||
|
* This should be replaced once that function becomes available in mainline versions of node.js:
|
||||||
|
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/escape
|
||||||
|
*
|
||||||
|
* @param {String} string - Regex string to escape
|
||||||
|
* @returns {String} The Escaped String
|
||||||
|
*/
|
||||||
module.exports.escapeRegex = function(string){
|
module.exports.escapeRegex = function(string){
|
||||||
/* I won't lie this line was whole-sale ganked from stack overflow like a fucking skid
|
|
||||||
In my defense I only did it because js-runtime-devs are taking fucking eons to implement RegExp.escape()
|
|
||||||
This should be replaced once that function becomes available in mainline versions of node.js:
|
|
||||||
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/escape */
|
|
||||||
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||||
}
|
}
|
||||||
|
|
@ -26,6 +26,9 @@ const channelModel = require('../schemas/channel/channelSchema');
|
||||||
const sessionUtils = require('./sessionUtils');
|
const sessionUtils = require('./sessionUtils');
|
||||||
const { email } = require('../validators/accountValidator');
|
const { email } = require('../validators/accountValidator');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules all timed jobs accross the server
|
||||||
|
*/
|
||||||
module.exports.schedule = function(){
|
module.exports.schedule = 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
|
||||||
cron.schedule('0 0 * * *', ()=>{userModel.processAgedIPRecords()},{scheduled: true, timezone: "UTC"});
|
cron.schedule('0 0 * * *', ()=>{userModel.processAgedIPRecords()},{scheduled: true, timezone: "UTC"});
|
||||||
|
|
@ -41,6 +44,9 @@ module.exports.schedule = function(){
|
||||||
cron.schedule('0 0 * * *', ()=>{emailChangeModel.processExpiredRequests()},{scheduled: true, timezone: "UTC"});
|
cron.schedule('0 0 * * *', ()=>{emailChangeModel.processExpiredRequests()},{scheduled: true, timezone: "UTC"});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kicks off first run of scheduled functions before scheduling functions for regular callback
|
||||||
|
*/
|
||||||
module.exports.kickoff = function(){
|
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();
|
||||||
|
|
|
||||||
|
|
@ -19,15 +19,33 @@ const config = require('../../config.json');
|
||||||
const {userModel} = require('../schemas/user/userSchema.js');
|
const {userModel} = require('../schemas/user/userSchema.js');
|
||||||
const userBanModel = require('../schemas/user/userBanSchema.js')
|
const userBanModel = require('../schemas/user/userBanSchema.js')
|
||||||
const altchaUtils = require('../utils/altchaUtils.js');
|
const altchaUtils = require('../utils/altchaUtils.js');
|
||||||
const loggerUtils = require('../utils/loggerUtils.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
|
/**
|
||||||
//Server restarts are far and few between. It would take multiple during a single bruteforce attempt for this to become an issue.
|
* 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.
|
||||||
|
*/
|
||||||
const failedAttempts = new Map();
|
const failedAttempts = new Map();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How many failed attempts required to throttle with altcha
|
||||||
|
*/
|
||||||
const throttleAttempts = 5;
|
const throttleAttempts = 5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How many attempts to lock user account out for the day
|
||||||
|
*/
|
||||||
const maxAttempts = 200;
|
const maxAttempts = 200;
|
||||||
|
|
||||||
//this module is good for keeping wrappers for userModel and other shit in that does more session handling than database access/modification.
|
/**
|
||||||
|
* Sole and Singular Session Authentication method.
|
||||||
|
* All logins should happen through here, all other site-wide authentication should happen by sessions authenticated by this model.
|
||||||
|
* This is important, as reducing authentication endpoints reduces attack surface.
|
||||||
|
* @param {String} user - Username to login as
|
||||||
|
* @param {String} pass - Password to authenticat session with
|
||||||
|
* @param {express.Request} req - Express request object w/ session to authenticate
|
||||||
|
* @returns Username of authticated user upon success
|
||||||
|
*/
|
||||||
module.exports.authenticateSession = async function(user, pass, req){
|
module.exports.authenticateSession = async function(user, pass, req){
|
||||||
//Fuck you yoda
|
//Fuck you yoda
|
||||||
try{
|
try{
|
||||||
|
|
@ -137,15 +155,27 @@ module.exports.authenticateSession = async function(user, pass, req){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs user out and destroys all server-side traces of a given session
|
||||||
|
* @param {express-session.session} session
|
||||||
|
*/
|
||||||
module.exports.killSession = async function(session){
|
module.exports.killSession = async function(session){
|
||||||
session.destroy();
|
session.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns how many failed login attempts within the past day or so since the last login has occured for a given user
|
||||||
|
* @param {String} user - User to check map against
|
||||||
|
* @returns {Number} of failed login attempts
|
||||||
|
*/
|
||||||
module.exports.getLoginAttempts = function(user){
|
module.exports.getLoginAttempts = function(user){
|
||||||
//Read the code, i'm not explaining this
|
//Read the code, i'm not explaining this
|
||||||
return failedAttempts.get(user);
|
return failedAttempts.get(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Nightly Function Call which iterates through the failed login attempts map, removing any which haven't been attempted in over a da yeahy
|
||||||
|
*/
|
||||||
module.exports.processExpiredAttempts = function(){
|
module.exports.processExpiredAttempts = function(){
|
||||||
for(user of failedAttempts.keys()){
|
for(user of failedAttempts.keys()){
|
||||||
//Get attempt by user
|
//Get attempt by user
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue