Finished up with IP-Ban functionality on the back-end. Just need to finish up with UI.
This commit is contained in:
parent
756c42ceaa
commit
977e8e1e2e
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"instanceName": "Canopy",
|
||||
"verbose": false,
|
||||
"port": 8080,
|
||||
"protocol": "http",
|
||||
"domain": "localhost",
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
|||
const channelModel = require('../../schemas/channel/channelSchema');
|
||||
const emoteModel = require('../../schemas/emoteSchema');
|
||||
const {userModel} = require('../../schemas/user/userSchema');
|
||||
const userBanModel = require('../../schemas/user/userBanSchema');
|
||||
const loggerUtils = require('../../utils/loggerUtils');
|
||||
const csrfUtils = require('../../utils/csrfUtils');
|
||||
const activeChannel = require('./activeChannel');
|
||||
|
|
@ -39,23 +40,29 @@ module.exports = class{
|
|||
}
|
||||
|
||||
async handleConnection(socket){
|
||||
//Prevent logged out connections and authenticate socket
|
||||
if(socket.request.session.user != null){
|
||||
try{
|
||||
try{
|
||||
//ensure unbanned ip and valid CSRF token
|
||||
if(!(await this.validateSocket(socket))){
|
||||
socket.disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
//Prevent logged out connections and authenticate socket
|
||||
if(socket.request.session.user != null){
|
||||
//Authenticate socket
|
||||
const userDB = await this.authSocket(socket);
|
||||
|
||||
//Get the active channel based on the socket
|
||||
var {activeChan, chanDB} = await this.getActiveChan(socket);
|
||||
|
||||
//Check for ban
|
||||
//Check for chan ban
|
||||
const ban = await chanDB.checkBanByUserDoc(userDB);
|
||||
if(ban != null){
|
||||
//Toss out banned user's
|
||||
if(ban.expirationDays < 0){
|
||||
socket.emit("kick", {type: "Banned", reason: "You have been permanently banned from this channel!"});
|
||||
socket.emit("kick", {type: "kicked", reason: "You have been permanently banned from this channel!"});
|
||||
}else{
|
||||
socket.emit("kick", {type: "Banned", reason: `You have been temporarily banned from this channel, and will be unbanned in ${ban.getDaysUntilExpiration()} day(s)!`});
|
||||
socket.emit("kick", {type: "kicked", reason: `You have been temporarily banned from this channel, and will be unbanned in ${ban.getDaysUntilExpiration()} day(s)!`});
|
||||
}
|
||||
socket.disconnect();
|
||||
return;
|
||||
|
|
@ -68,24 +75,41 @@ module.exports = class{
|
|||
//Connect the socket to it's given channel
|
||||
//Lil' hacky to pass chanDB like that, but why double up on DB calls?
|
||||
activeChan.handleConnection(userDB, chanDB, socket);
|
||||
}catch(err){
|
||||
//Flip a table if something fucks up
|
||||
return loggerUtils.socketCriticalExceptionHandler(socket, err);
|
||||
}else{
|
||||
//Toss out anon's
|
||||
socket.emit("kick", {type: "disconnected", reason: "You must log-in to join this channel!"});
|
||||
socket.disconnect();
|
||||
return;
|
||||
}
|
||||
}else{
|
||||
//Toss out anon's
|
||||
socket.emit("kick", {type: "Disconnected", reason: "You must log-in to join this channel!"});
|
||||
socket.disconnect();
|
||||
return;
|
||||
}catch(err){
|
||||
//Flip a table if something fucks up
|
||||
return loggerUtils.socketCriticalExceptionHandler(socket, err);
|
||||
}
|
||||
}
|
||||
|
||||
async validateSocket(socket){
|
||||
//Look for ban by IP
|
||||
const ipBanDB = await userBanModel.checkBanByIP(socket.handshake.address);
|
||||
|
||||
//If this ip is randy bobandy
|
||||
if(ipBanDB != null){
|
||||
//tell it to fuck off
|
||||
socket.emit("kick", {type: "kicked", reason: "The IP address you are trying to connect from has been banned!"});
|
||||
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;
|
||||
}
|
||||
|
||||
async authSocket(socket){
|
||||
//Check for Cross-Site Request Forgery
|
||||
if(!csrfUtils.isRequestValid(socket.request)){
|
||||
throw new Error("Invalid CSRF Token!");
|
||||
}
|
||||
|
||||
//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});
|
||||
|
||||
|
|
|
|||
|
|
@ -71,7 +71,6 @@ module.exports.post = async function(req, res){
|
|||
return res.send({errors: validResult.array()});
|
||||
}
|
||||
}catch(err){
|
||||
console.log(err)
|
||||
return exceptionHandler(res, err);
|
||||
}
|
||||
}
|
||||
|
|
@ -52,6 +52,22 @@ module.exports.post = async function(req, res){
|
|||
return errorHandler(res, 'Cannot re-create banned account!', 'unauthorized');
|
||||
}
|
||||
|
||||
//Look for ban by IP
|
||||
const ipBanDB = await userBanModel.checkBanByIP(req.ip);
|
||||
|
||||
//If this ip is randy bobandy
|
||||
if(ipBanDB != null){
|
||||
//Make the code and message look pretty (kinda) at the same time
|
||||
const banMsg = [
|
||||
'The IP address you are trying to register an account from has been banned.',
|
||||
'If you beleive this to be an error feel free to reach out to your server administrator.',
|
||||
'Otherwise, fuck off :)'
|
||||
];
|
||||
|
||||
//tell it to fuck off
|
||||
return errorHandler(res, banMsg.join('<br>'), 'unauthorized');
|
||||
}
|
||||
|
||||
await userModel.register(user, req.ip);
|
||||
return res.sendStatus(200);
|
||||
}else{
|
||||
|
|
@ -59,7 +75,6 @@ module.exports.post = async function(req, res){
|
|||
return res.send({errors: validResult.array()});
|
||||
}
|
||||
}catch(err){
|
||||
console.log(err);
|
||||
return exceptionHandler(res, err);
|
||||
}
|
||||
}
|
||||
|
|
@ -40,7 +40,7 @@ module.exports.post = async function(req, res){
|
|||
try{
|
||||
const validResult = validationResult(req);
|
||||
if(validResult.isEmpty()){
|
||||
const {user, permanent, expirationDays} = matchedData(req);
|
||||
const {user, permanent, ipBan, expirationDays} = matchedData(req);
|
||||
const userDB = await userModel.findOne({user});
|
||||
|
||||
if(userDB == null){
|
||||
|
|
@ -54,7 +54,7 @@ module.exports.post = async function(req, res){
|
|||
return errorHandler(res, 'You cannot ban peer/outranking users', 'Unauthorized', 401);
|
||||
}
|
||||
|
||||
await banModel.banByUserDoc(userDB, permanent, expirationDays);
|
||||
await banModel.banByUserDoc(userDB, permanent, expirationDays, ipBan);
|
||||
|
||||
res.status(200);
|
||||
return res.send(await banModel.getBans());
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ router.post('/changeRank', permissionSchema.reqPermCheck("changeRank"), account
|
|||
//Ban
|
||||
router.get('/ban', permissionSchema.reqPermCheck("adminPanel"), banController.get);
|
||||
//Sometimes they're so simple you don't need to put your validators in their own special place :P
|
||||
router.post('/ban', permissionSchema.reqPermCheck("banUser"), accountValidator.user(), body("permanent").isBoolean(), body("expirationDays").isInt(), banController.post);
|
||||
router.post('/ban', permissionSchema.reqPermCheck("banUser"), accountValidator.user(), body("permanent").isBoolean(), body("ipBan").isBoolean(), body("expirationDays").isInt(), banController.post);
|
||||
router.delete('/ban', permissionSchema.reqPermCheck("banUser"), accountValidator.user(), banController.delete);
|
||||
//TokeCommands
|
||||
router.get('/tokeCommands', permissionSchema.reqPermCheck("adminPanel"), tokeCommandController.get);
|
||||
|
|
|
|||
|
|
@ -328,17 +328,9 @@ channelSchema.methods.rankCrawl = async function(userDB,cb){
|
|||
//TODO: replace this with rank check function shared with setRank
|
||||
this.rankList.forEach(async (rankObj, rankIndex) => {
|
||||
//check against user ID to speed things up
|
||||
if(rankObj.user.user == null){
|
||||
if(rankObj.user.toString() == userDB._id.toString()){
|
||||
//If we found a match, call back
|
||||
cb(rankObj, rankIndex);
|
||||
}
|
||||
}else{
|
||||
//in case someone populated the users
|
||||
if(rankObj.user.user == userDB.user){
|
||||
//If we found a match, call back
|
||||
cb(rankObj, rankIndex);
|
||||
}
|
||||
if(rankObj.user != null && rankObj.user._id.toString() == userDB._id.toString()){
|
||||
//If we found a match, call back
|
||||
cb(rankObj, rankIndex);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -379,14 +371,22 @@ channelSchema.methods.setRank = async function(userDB,rank){
|
|||
channelSchema.methods.getRankList = async function(){
|
||||
//Create an empty array to hold the user list
|
||||
const rankList = new Map()
|
||||
//Create temp rank list to replace the current one in the advant we have busted users
|
||||
let tempRankList = [];
|
||||
//Flag that lets us know we gotta save
|
||||
let reqSave = false;
|
||||
|
||||
//Populate the user objects in our ranklist based off of their DB ID's
|
||||
await this.populate('rankList.user');
|
||||
|
||||
//For each rank object in the rank list
|
||||
this.rankList.forEach(async (rankObj, rankObjIndex) => {
|
||||
for(rankObjIndex in this.rankList){
|
||||
const rankObj = this.rankList[rankObjIndex];
|
||||
//If the use still exists
|
||||
if(rankObj.user != null){
|
||||
//Push current rank object to the temp rank list in the advant that it doesn't get saved
|
||||
tempRankList.push(rankObj);
|
||||
|
||||
//Create a new user object from rank object data
|
||||
const userObj = {
|
||||
id: rankObj.user.id,
|
||||
|
|
@ -397,12 +397,20 @@ channelSchema.methods.getRankList = async function(){
|
|||
|
||||
//Add our user object to the list
|
||||
rankList.set(rankObj.user.user, userObj);
|
||||
//Otherwise if it's an invalid rank for a deleted user
|
||||
}else{
|
||||
//Otherwise clean deleted users out of list
|
||||
this.rankList.splice(rankObjIndex,1);
|
||||
await this.save();
|
||||
//Ignore the rank object and throw the save flag to save the temporary rank list
|
||||
reqSave = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//if we need to save the temp rank list
|
||||
if(reqSave){
|
||||
//set rank list
|
||||
this.rankList = tempRankList;
|
||||
//save
|
||||
await this.save();
|
||||
}
|
||||
|
||||
//return userList
|
||||
return rankList;
|
||||
|
|
|
|||
|
|
@ -75,7 +75,6 @@ emoteSchema.statics.loadDefaults = async function(){
|
|||
|
||||
}catch(err){
|
||||
if(emote != null){
|
||||
console.log(err);
|
||||
console.log(`Error loading emote [${emote.name}]:`);
|
||||
}else{
|
||||
console.log("Error, null emote:");
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@ flairSchema.statics.loadDefaults = async function(){
|
|||
|
||||
}catch(err){
|
||||
if(flair != null){
|
||||
console.log(err);
|
||||
console.log(`Error loading flair '${flair.name}':`);
|
||||
}else{
|
||||
console.log("Error, null flair:");
|
||||
|
|
|
|||
|
|
@ -93,7 +93,6 @@ tokeCommandSchema.statics.loadDefaults = async function(){
|
|||
|
||||
}catch(err){
|
||||
if(toke != null){
|
||||
console.log(err);
|
||||
console.log(`Error loading toke command: '!${toke}'`);
|
||||
}else{
|
||||
console.log("Error, null toke!");
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
|||
const {mongoose} = require('mongoose');
|
||||
|
||||
//Local Imports
|
||||
const hashUtil = require('../../utils/hashUtils');
|
||||
const {userModel} = require('./userSchema');
|
||||
|
||||
const userBanSchema = new mongoose.Schema({
|
||||
|
|
@ -25,16 +26,20 @@ const userBanSchema = new mongoose.Schema({
|
|||
type: mongoose.SchemaTypes.ObjectID,
|
||||
ref: "user"
|
||||
},
|
||||
//To be used in future when ip-hashing/better session tracking is implemented
|
||||
ips: {
|
||||
type: [mongoose.SchemaTypes.String],
|
||||
required: false
|
||||
plaintext: {
|
||||
type: [mongoose.SchemaTypes.String],
|
||||
required: false
|
||||
},
|
||||
hashed: {
|
||||
type: [mongoose.SchemaTypes.String],
|
||||
required: false
|
||||
}
|
||||
},
|
||||
//To be used in future when alt-detection has been implemented
|
||||
alts: {
|
||||
alts: [{
|
||||
type: mongoose.SchemaTypes.ObjectID,
|
||||
ref: "user"
|
||||
},
|
||||
}],
|
||||
deletedNames: {
|
||||
type: [mongoose.SchemaTypes.String],
|
||||
required: false
|
||||
|
|
@ -58,15 +63,92 @@ const userBanSchema = new mongoose.Schema({
|
|||
}
|
||||
});
|
||||
|
||||
userBanSchema.statics.checkBanByIP = async function(ip){
|
||||
//Get hash of ip
|
||||
const ipHash = hashUtil.hashIP(ip);
|
||||
//Get all bans
|
||||
const banDB = await this.find({});
|
||||
//Create null variable to hold any found ban
|
||||
let foundBan = null;
|
||||
|
||||
//For every ban
|
||||
for(ban of banDB){
|
||||
//Create empty list to hold unmatched hashes in the advent that we match one
|
||||
let tempHashes = [];
|
||||
//Create flag to throw to save tempHashes in the advent that we have matches we dont want to save as hashes
|
||||
let saveBan = false;
|
||||
|
||||
|
||||
//For every plaintext IP in the ban
|
||||
for(ipIndex in ban.ips.plaintext){
|
||||
//Get the current ip
|
||||
const curIP = ban.ips.plaintext[ipIndex];
|
||||
|
||||
//Check the current IP against the given ip
|
||||
if(ip == curIP){
|
||||
//If it matches we found the ban
|
||||
foundBan = ban;
|
||||
}
|
||||
}
|
||||
|
||||
//For every hashed IP in the ban
|
||||
for(ipIndex in ban.ips.hashed){
|
||||
//Get the current ip hash
|
||||
const curHash = ban.ips.hashed[ipIndex];
|
||||
|
||||
//Check the current hash against the given hash
|
||||
if(ipHash == curHash){
|
||||
//If it matches we found the ban
|
||||
foundBan = ban;
|
||||
|
||||
//Push the match to plaintext IPs so we know who the fucker is
|
||||
ban.ips.plaintext.push(ip);
|
||||
|
||||
//Throw the save ban flag to save the ban
|
||||
saveBan = true;
|
||||
//Otherwise
|
||||
}else{
|
||||
//Keep the hash since it hasn't been matched yet
|
||||
tempHashes.push(curHash);
|
||||
}
|
||||
}
|
||||
|
||||
//If we matched a hashed ip and we need to save it as plaintext
|
||||
if(saveBan){
|
||||
//Keep unmatched hashes
|
||||
ban.ips.hashed = tempHashes;
|
||||
|
||||
//Save the current ban
|
||||
await ban.save();
|
||||
}
|
||||
}
|
||||
|
||||
return foundBan;
|
||||
}
|
||||
|
||||
userBanSchema.statics.checkBanByUserDoc = async function(userDB){
|
||||
const banDB = await this.find({});
|
||||
var foundBan = null;
|
||||
|
||||
banDB.forEach((ban) => {
|
||||
if(ban.user != null){
|
||||
//if we found a match
|
||||
if(ban.user.toString() == userDB._id.toString()){
|
||||
//Set found ban
|
||||
foundBan = ban;
|
||||
}
|
||||
|
||||
//For each banned alt
|
||||
for(altIndex in ban.alts){
|
||||
//get current alt
|
||||
const alt = ban.alts[altIndex];
|
||||
|
||||
//if the alt matches our user
|
||||
if(alt._id.toString() == userDB._id.toString()){
|
||||
//Set found ban
|
||||
foundBan = ban;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -99,7 +181,7 @@ userBanSchema.statics.checkProcessedBans = async function(user){
|
|||
return foundBan;
|
||||
}
|
||||
|
||||
userBanSchema.statics.banByUserDoc = async function(userDB, permanent, expirationDays){
|
||||
userBanSchema.statics.banByUserDoc = async function(userDB, permanent, expirationDays, ipBan = false){
|
||||
//Prevent missing users
|
||||
if(userDB == null){
|
||||
throw new Error("User not found")
|
||||
|
|
@ -110,6 +192,7 @@ userBanSchema.statics.banByUserDoc = async function(userDB, permanent, expiratio
|
|||
throw new Error("User already banned");
|
||||
}
|
||||
|
||||
//Verify time to expire/delete depending on action
|
||||
if(expirationDays < 0){
|
||||
throw new Error("Expiration Days must be a positive integer!");
|
||||
}else if(expirationDays < 30 && permanent){
|
||||
|
|
@ -118,20 +201,65 @@ userBanSchema.statics.banByUserDoc = async function(userDB, permanent, expiratio
|
|||
throw new Error("Expiration/Deletion date cannot be longer than half a year out from the original ban date.");
|
||||
}
|
||||
|
||||
//Log the user out
|
||||
if(permanent){
|
||||
await userDB.killAllSessions(`Your account has been permanently banned, and will be nuked from the database in ${expirationDays} day(s).`);
|
||||
}else{
|
||||
await userDB.killAllSessions(`Your account has been temporarily banned, and will be reinstated in: ${expirationDays} day(s).`);
|
||||
}
|
||||
await banSessions(userDB);
|
||||
|
||||
//Add the ban to the database
|
||||
return await this.create({user: userDB._id, permanent, expirationDays});
|
||||
const banDB = await this.create({user: userDB._id, permanent, expirationDays});
|
||||
|
||||
//If we're banning the users IP
|
||||
if(ipBan){
|
||||
//Scrape IP's from current user into the ban record
|
||||
await scrapeUserIPs(userDB);
|
||||
|
||||
//Populate the users alts
|
||||
await userDB.populate('alts');
|
||||
|
||||
//For each of the users alts
|
||||
for(altIndex in userDB.alts){
|
||||
//Add the current alt to the ban record
|
||||
banDB.alts.push(userDB.alts[altIndex]._id);
|
||||
|
||||
//Scrape out the IPs from the current alt into the ban record
|
||||
await scrapeUserIPs(userDB.alts[altIndex]);
|
||||
|
||||
//Kill all of alts sessions
|
||||
await banSessions(userDB.alts[altIndex]);
|
||||
}
|
||||
|
||||
//Save commited IP information to the ban record
|
||||
await banDB.save();
|
||||
|
||||
async function scrapeUserIPs(curRecord){
|
||||
//For each hashed ip on record for this user
|
||||
for(hashIndex in curRecord.recentIPs){
|
||||
//Look for any occurance of the current hash
|
||||
const foundHash = banDB.ips.hashed.indexOf(curRecord.recentIPs[hashIndex].ipHash);
|
||||
|
||||
//If its not listed in the ban record
|
||||
if(foundHash == -1){
|
||||
//Add it to the list of hashed IPs for this ban
|
||||
banDB.ips.hashed.push(curRecord.recentIPs[hashIndex].ipHash);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//return the ban record
|
||||
return banDB;
|
||||
|
||||
async function banSessions(user){
|
||||
//Log the user out
|
||||
if(permanent){
|
||||
await user.killAllSessions(`Your account has been permanently banned, and will be nuked from the database in ${expirationDays} day(s).`);
|
||||
}else{
|
||||
await user.killAllSessions(`Your account has been temporarily banned, and will be reinstated in: ${expirationDays} day(s).`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
userBanSchema.statics.ban = async function(user, permanent, expirationDays){
|
||||
userBanSchema.statics.ban = async function(user, permanent, expirationDays, ipBan){
|
||||
const userDB = await userModel.findOne({user: user.user});
|
||||
return this.banByUserDoc(userDB, permanent, expirationDays);
|
||||
return this.banByUserDoc(userDB, permanent, expirationDays, ipBan);
|
||||
}
|
||||
|
||||
userBanSchema.statics.unbanByUserDoc = async function(userDB){
|
||||
|
|
@ -217,6 +345,7 @@ userBanSchema.statics.getBans = async function(){
|
|||
userBanSchema.statics.processExpiredBans = async function(){
|
||||
const banDB = await this.find({});
|
||||
|
||||
//Firem all off all at once seperately without waiting for one another
|
||||
banDB.forEach(async (ban) => {
|
||||
//This ban was already processed, and it's user has been deleted. There is no more to be done...
|
||||
if(ban.user == null){
|
||||
|
|
@ -227,14 +356,27 @@ userBanSchema.statics.processExpiredBans = async function(){
|
|||
if(ban.getDaysUntilExpiration() <= 0){
|
||||
//If the ban is permanent
|
||||
if(ban.permanent){
|
||||
//Populate the user field
|
||||
//Populate the user and alt fields
|
||||
await ban.populate('user');
|
||||
await ban.populate('alts');
|
||||
//Add the name to our deleted names list
|
||||
ban.deletedNames.push(ban.user.user);
|
||||
//Hey hey hey, goodbye!
|
||||
await userModel.deleteOne({_id: ban.user._id});
|
||||
//Empty out the reference
|
||||
ban.user = null;
|
||||
|
||||
//For every alt
|
||||
for(alt of ban.alts){
|
||||
//Add the alts name to the deleted names list
|
||||
ban.deletedNames.push(alt.user);
|
||||
//Motherfuckin' Kablewie!
|
||||
await userModel.deleteOne({_id: alt._id});
|
||||
}
|
||||
|
||||
//Clear out the alts array
|
||||
ban.alts = [];
|
||||
|
||||
//Save the ban
|
||||
await ban.save();
|
||||
}else{
|
||||
|
|
@ -242,7 +384,7 @@ userBanSchema.statics.processExpiredBans = async function(){
|
|||
await this.deleteOne({_id: ban._id});
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
//methods
|
||||
|
|
|
|||
|
|
@ -14,6 +14,9 @@ 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/>.*/
|
||||
|
||||
//Config
|
||||
const config = require('../../config.json');
|
||||
|
||||
//At some point this will be a bit more advanced, right now it's just a placeholder :P
|
||||
module.exports.errorHandler = function(res, msg, type = "Generic", status = 400){
|
||||
//Some controllers do things after sending headers, for those, we should remain silent
|
||||
|
|
@ -24,11 +27,23 @@ module.exports.errorHandler = function(res, msg, type = "Generic", status = 400)
|
|||
}
|
||||
|
||||
module.exports.exceptionHandler = function(res, err){
|
||||
//If we're being verbose
|
||||
if(config.verbose){
|
||||
//Log the error
|
||||
console.log(err)
|
||||
}
|
||||
|
||||
//if not yell at the browser for fucking up, and tell it what it did wrong.
|
||||
module.exports.errorHandler(res, err.message, "Caught Exception");
|
||||
}
|
||||
|
||||
module.exports.socketExceptionHandler = function(socket, err){
|
||||
//If we're being verbose
|
||||
if(config.verbose){
|
||||
//Log the error
|
||||
console.log(err)
|
||||
}
|
||||
|
||||
//if not yell at the browser for fucking up, and tell it what it did wrong.
|
||||
return socket.emit("error", {errors: [{type: "Caught Exception", msg: err.message, date: new Date()}]});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,15 @@ module.exports.authenticateSession = async function(user, pass, req){
|
|||
//Grab previous attempts
|
||||
const attempt = failedAttempts.get(user);
|
||||
|
||||
//Look for ban by IP
|
||||
const ipBanDB = await userBanModel.checkBanByIP(req.ip);
|
||||
|
||||
//If this ip is randy bobandy
|
||||
if(ipBanDB != null){
|
||||
//tell it to fuck off
|
||||
throw new Error(`The IP address you are trying to login from has been banned.`);
|
||||
}
|
||||
|
||||
//If we have failed attempts
|
||||
if(attempt != null){
|
||||
//If we have more failed attempts than allowed
|
||||
|
|
@ -53,13 +62,15 @@ module.exports.authenticateSession = async function(user, pass, req){
|
|||
|
||||
//Authenticate the session
|
||||
const userDB = await userModel.authenticate(user, pass);
|
||||
const banDB = await userBanModel.checkBanByUserDoc(userDB);
|
||||
|
||||
//Check for user ban
|
||||
const userBanDB = await userBanModel.checkBanByUserDoc(userDB);
|
||||
|
||||
//If the user is banned
|
||||
if(banDB){
|
||||
if(userBanDB){
|
||||
//Make the number a little prettier despite the lack of precision since we're not doing calculations here :P
|
||||
const expiration = banDB.getDaysUntilExpiration() < 1 ? 0 : banDB.getDaysUntilExpiration();
|
||||
if(banDB.permanent){
|
||||
const expiration = userBanDB.getDaysUntilExpiration() < 1 ? 0 : userBanDB.getDaysUntilExpiration();
|
||||
if(userBanDB.permanent){
|
||||
throw new Error(`Your account has been permanently banned, and will be nuked from the database in: ${expiration} day(s)`);
|
||||
}else{
|
||||
throw new Error(`Your account has been temporarily banned, and will be reinstated in: ${expiration} day(s)`);
|
||||
|
|
|
|||
|
|
@ -150,6 +150,10 @@ p.navbar-item, input.navbar-item{
|
|||
margin-top: 0;
|
||||
}
|
||||
|
||||
.popup-plaintext-content{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* tooltip */
|
||||
div.tooltip{
|
||||
position: fixed;
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ class canopyAdminUtils{
|
|||
}
|
||||
}
|
||||
|
||||
async banUser(user, permanent, expirationDays){
|
||||
async banUser(user, permanent, ipBan, expirationDays){
|
||||
var response = await fetch(`/api/admin/ban`,{
|
||||
method: "POST",
|
||||
headers: {
|
||||
|
|
@ -147,7 +147,7 @@ class canopyAdminUtils{
|
|||
"x-csrf-token": utils.ajax.getCSRFToken()
|
||||
},
|
||||
//Unfortunately JSON doesn't natively handle ES6 maps, and god forbid someone update the standard in a way that's backwards compatible...
|
||||
body: JSON.stringify({user, permanent, expirationDays})
|
||||
body: JSON.stringify({user, permanent, ipBan, expirationDays})
|
||||
});
|
||||
|
||||
if(response.status == 200){
|
||||
|
|
|
|||
|
|
@ -234,6 +234,7 @@ class canopyUXUtils{
|
|||
this.contentDiv.innerHTML = await utils.ajax.getPopup(this.content);
|
||||
}else{
|
||||
this.contentDiv.innerHTML = this.content;
|
||||
this.contentDiv.classList.add('popup-plaintext-content');
|
||||
}
|
||||
|
||||
//display popup nodes
|
||||
|
|
|
|||
Loading…
Reference in a new issue