Seperated out socket validation/authorization from channel mangement logic.

This commit is contained in:
rainbow napkin 2025-09-18 04:13:19 -04:00
parent d541dce8c4
commit 7da07c8717
4 changed files with 108 additions and 74 deletions

View file

@ -22,6 +22,7 @@ const channelModel = require('../../schemas/channel/channelSchema');
const emoteModel = require('../../schemas/emoteSchema');
const {userModel} = require('../../schemas/user/userSchema');
const userBanModel = require('../../schemas/user/userBanSchema');
const socketUtils = require('../../utils/socketUtils');
const loggerUtils = require('../../utils/loggerUtils');
const csrfUtils = require('../../utils/csrfUtils');
const presenceUtils = require('../../utils/presenceUtils');
@ -68,7 +69,7 @@ class channelManager{
async handleConnection(socket){
try{
//ensure unbanned ip and valid CSRF token
if(!(await this.validateSocket(socket))){
if(!(await socketUtils.validateSocket(socket))){
socket.disconnect();
return;
}
@ -76,7 +77,7 @@ class channelManager{
//Prevent logged out connections and authenticate socket
if(socket.request.session.user != null){
//Authenticate socket
const userDB = await this.authSocket(socket);
const userDB = await socketUtils.authSocket(socket);
//Get the active channel based on the socket
var {activeChan, chanDB} = await this.getActiveChan(socket);
@ -146,71 +147,7 @@ class channelManager{
//Flip a table if something fucks up
return loggerUtils.socketCriticalExceptionHandler(socket, err);
}
}
/**
* Global server-side validation logic for new connections to any channel
* @param {Socket} socket - Requesting Socket
* @returns {Boolean} true on success
*/
async validateSocket(socket){
//If we're proxied use passthrough IP
const ip = config.proxied ? socket.handshake.headers['x-forwarded-for'] : socket.handshake.address;
//Look for ban by IP
const ipBanDB = await userBanModel.checkBanByIP(ip);
//If this ip is randy bobandy
if(ipBanDB != null){
//Make the number a little prettier despite the lack of precision since we're not doing calculations here :P
const expiration = ipBanDB.getDaysUntilExpiration() < 1 ? 0 : ipBanDB.getDaysUntilExpiration();
//If the ban is permanent
if(ipBanDB.permanent){
//tell it to fuck off
socket.emit("kick", {type: "kicked", reason: `The IP address you are trying to connect from has been permanently banned. Your cleartext IP has been saved to the database. Any associated accounts will be nuked in ${expiration} day(s).`});
//Otherwise
}else{
//tell it to fuck off
socket.emit("kick", {type: "kicked", reason: `The IP address you are trying to connect from has been temporarily banned. Your cleartext IP has been saved to the database until the ban expires in ${expiration} day(s).`});
}
return false;
}
//Check for Cross-Site Request Forgery
if(!csrfUtils.isRequestValid(socket.request)){
socket.emit("kick", {type: "disconnected", reason: "Invalid CSRF Token!"});
return false;
}
return true;
}
/**
* Global server-side authorization logic for new connections to any channel
* @param {Socket} socket - Requesting Socket
* @returns {Mongoose.Document} - Authorized User Document upon success
*/
async authSocket(socket){
//Find the user in the Database since the session won't store enough data to fulfill our needs :P
const userDB = await userModel.findOne({user: socket.request.session.user.user});
if(userDB == null){
throw loggerUtils.exceptionSmith("User not found!", "unauthorized");
}
//Set socket user and channel values
socket.user = {
id: userDB.id,
user: userDB.user,
};
return userDB;
}
}
/**
* Gets active channel from a given socket