Finished basic channel ban DB mgmt and ajax calls.
This commit is contained in:
parent
2b52fe7f2f
commit
ef79e9941c
99
src/controllers/api/channel/banController.js
Normal file
99
src/controllers/api/channel/banController.js
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
/*Canopy - The next generation of stoner streaming software
|
||||
Copyright (C) 2024 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 {validationResult, matchedData} = require('express-validator');
|
||||
|
||||
//local imports
|
||||
const {exceptionHandler} = require('../../../utils/loggerUtils.js');
|
||||
const {userModel} = require('../../../schemas/userSchema.js');
|
||||
const channelModel = require('../../../schemas/channel/channelSchema');
|
||||
|
||||
//api account functions
|
||||
module.exports.get = async function(req, res){
|
||||
try{
|
||||
//Get validation result
|
||||
const validResult = validationResult(req);
|
||||
|
||||
//If we data is valid
|
||||
if(validResult.isEmpty()){
|
||||
//Set channel object from sanatized/validated data, and get user document from session data
|
||||
const {chanName} = matchedData(req);
|
||||
const chanDB = await channelModel.findOne({name: chanName});
|
||||
|
||||
res.status(200);
|
||||
return res.send(await chanDB.getChanBans());
|
||||
}else{
|
||||
res.status(400);
|
||||
res.send({errors: validResult.array()})
|
||||
}
|
||||
}catch(err){
|
||||
exceptionHandler(res, err);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports.post = async function(req, res){
|
||||
try{
|
||||
//Get validation result
|
||||
const validResult = validationResult(req);
|
||||
|
||||
//If we data is valid
|
||||
if(validResult.isEmpty()){
|
||||
//Set channel object from sanatized/validated data, and get user document from session data
|
||||
const {chanName, user, expirationDays, banAlts} = matchedData(req);
|
||||
const userDB = await userModel.findOne({user});
|
||||
const chanDB = await channelModel.findOne({name: chanName});
|
||||
|
||||
await chanDB.banByUserDoc(userDB, expirationDays, banAlts);
|
||||
|
||||
res.status(200);
|
||||
return res.send(await chanDB.getChanBans());
|
||||
}else{
|
||||
res.status(400);
|
||||
res.send({errors: validResult.array()})
|
||||
}
|
||||
}catch(err){
|
||||
exceptionHandler(res, err);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports.delete = async function(req, res){
|
||||
try{
|
||||
//Get validation result
|
||||
const validResult = validationResult(req);
|
||||
|
||||
//If we data is valid
|
||||
if(validResult.isEmpty()){
|
||||
//Set channel object from sanatized/validated data, and get user document from session data
|
||||
const {chanName, user} = matchedData(req);
|
||||
const userDB = await userModel.findOne({user});
|
||||
const chanDB = await channelModel.findOne({name: chanName});
|
||||
|
||||
await chanDB.unbanByUserDoc(userDB);
|
||||
|
||||
res.status(200);
|
||||
return res.send(await chanDB.getChanBans());
|
||||
}else{
|
||||
res.status(400);
|
||||
res.send({errors: validResult.array()})
|
||||
}
|
||||
}catch(err){
|
||||
exceptionHandler(res, err);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -15,6 +15,7 @@ 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 { body } = require('express-validator');
|
||||
const { Router } = require('express');
|
||||
|
||||
//local imports
|
||||
|
|
@ -29,6 +30,7 @@ const settingsController = require("../../controllers/api/channel/settingsContro
|
|||
const permissionsController = require("../../controllers/api/channel/permissionsController")
|
||||
const rankController = require("../../controllers/api/channel/rankController");
|
||||
const deleteController = require("../../controllers/api/channel/deleteController");
|
||||
const banController = require("../../controllers/api/channel/banController");
|
||||
|
||||
//globals
|
||||
const router = Router();
|
||||
|
|
@ -38,16 +40,28 @@ router.use("/register",permissionSchema.reqPermCheck("registerChannel"));
|
|||
router.use("/settings", channelValidator.name('chanName'), channelModel.reqPermCheck("manageChannel"));
|
||||
router.use("/permissions", channelValidator.name('chanName'), channelModel.reqPermCheck("manageChannel"));
|
||||
router.use("/rank", channelValidator.name('chanName'), channelModel.reqPermCheck("manageChannel"));
|
||||
router.use("/delete", channelValidator.name('chanName'), channelModel.reqPermCheck("deleteChannel"));
|
||||
router.use("/ban", channelValidator.name('chanName'), channelModel.reqPermCheck("manageChannel"));
|
||||
|
||||
//routing functions
|
||||
//register
|
||||
router.post('/register', channelValidator.name(), channelValidator.description(), channelValidator.thumbnail(), registerController.post);
|
||||
//list
|
||||
router.get('/list', listController.get);
|
||||
//settings
|
||||
router.get('/settings', settingsController.get);
|
||||
router.post('/settings', channelValidator.settingsMap(), settingsController.post);
|
||||
//permissions
|
||||
router.get('/permissions', permissionsController.get);
|
||||
router.post('/permissions', channelPermissionValidator.channelPermissionsMap(), permissionsController.post);
|
||||
//rank
|
||||
router.get('/rank', rankController.get);
|
||||
router.post('/rank', accountValidator.user(), channelValidator.rank(), rankController.post);
|
||||
router.post('/delete', channelValidator.name('chanName'), channelValidator.name('confirm'), channelModel.reqPermCheck("deleteChannel"), deleteController.post);
|
||||
//delete
|
||||
router.post('/delete', channelValidator.name('confirm'), deleteController.post);
|
||||
//ban
|
||||
router.get('/ban', banController.get);
|
||||
router.post('/ban', accountValidator.user(), body("banAlts").isBoolean(), body("expirationDays").isInt(), banController.post);
|
||||
router.delete('/ban', accountValidator.user(), banController.delete);
|
||||
|
||||
module.exports = router;
|
||||
|
|
@ -67,6 +67,29 @@ const channelSchema = new mongoose.Schema({
|
|||
required: true,
|
||||
enum: permissionModel.rankEnum
|
||||
}
|
||||
}],
|
||||
//Thankfully we don't have to keep track of alts, ips, or deleted users so this should be a little easier :P
|
||||
banList: [{
|
||||
user: {
|
||||
type: mongoose.SchemaTypes.ObjectID,
|
||||
required: true,
|
||||
ref: "user"
|
||||
},
|
||||
banDate: {
|
||||
type: mongoose.SchemaTypes.Date,
|
||||
required: true,
|
||||
default: new Date()
|
||||
},
|
||||
expirationDays: {
|
||||
type: mongoose.SchemaTypes.Number,
|
||||
required: true,
|
||||
default: 14
|
||||
},
|
||||
banAlts: {
|
||||
type: mongoose.SchemaTypes.Boolean,
|
||||
required: true,
|
||||
default: false
|
||||
}
|
||||
}]
|
||||
});
|
||||
|
||||
|
|
@ -323,6 +346,113 @@ channelSchema.methods.permCheck = async function (user, perm){
|
|||
return await this.permCheckByUserDoc(userDB, perm)
|
||||
}
|
||||
|
||||
channelSchema.methods.checkBanByUserDoc = async function(userDB){
|
||||
var foundBan = null;
|
||||
|
||||
this.banList.forEach((ban) => {
|
||||
if(ban.user != null){
|
||||
if(ban.user.toString() == userDB._id.toString()){
|
||||
foundBan = ban;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return foundBan;
|
||||
}
|
||||
|
||||
channelSchema.methods.getChanBans = async function(){
|
||||
//Create an empty list to hold our found bans
|
||||
var banList = [];
|
||||
//Populate the users in the banList
|
||||
await this.populate('banList.user');
|
||||
|
||||
//Crawl through known bans
|
||||
this.banList.forEach((ban) => {
|
||||
|
||||
var banObj = {
|
||||
banDate: ban.banDate,
|
||||
expirationDays: ban.expirationDays,
|
||||
}
|
||||
|
||||
//Check if the ban was permanent (expiration set before ban date)
|
||||
if(ban.expirationDays > 0){
|
||||
//if not calculate expiration date
|
||||
var expirationDate = new Date(ban.banDate);
|
||||
expirationDate.setDate(expirationDate.getDate() + ban.expirationDays);
|
||||
|
||||
//Set calculated expiration date
|
||||
banObj.expirationDate = expirationDate;
|
||||
}
|
||||
|
||||
//Setup user object (Do this last to keep it at bottom for human-readibility of json :P)
|
||||
banObj.user = {
|
||||
id: ban.user.id,
|
||||
user: ban.user.user,
|
||||
img: ban.user.img,
|
||||
date: ban.user.date
|
||||
}
|
||||
|
||||
banList.push(banObj);
|
||||
});
|
||||
|
||||
return banList;
|
||||
}
|
||||
|
||||
channelSchema.methods.banByUserDoc = async function(userDB, expirationDays, banAlts){
|
||||
//Throw a shitfit if the user doesn't exist
|
||||
if(userDB == null){
|
||||
throw new Error("Cannot ban non-existant user!");
|
||||
}
|
||||
|
||||
const foundBan = await this.checkBanByUserDoc(userDB);
|
||||
|
||||
if(foundBan != null){
|
||||
throw new Error("User already banned!");
|
||||
}
|
||||
|
||||
//Create a new ban document based on input
|
||||
const banDoc = {
|
||||
user: userDB._id,
|
||||
expirationDays,
|
||||
banAlts
|
||||
}
|
||||
|
||||
//Push the ban to the list
|
||||
this.banList.push(banDoc);
|
||||
|
||||
await this.save();
|
||||
}
|
||||
|
||||
channelSchema.methods.ban = async function(user, expirationDays, banAlts){
|
||||
const userDB = await userModel.find({user});
|
||||
return await this.banByUserDoc(userDB, expirationDays, banAlts);
|
||||
}
|
||||
|
||||
channelSchema.methods.unbanByUserDoc = async function(userDB){
|
||||
//Throw a shitfit if the user doesn't exist
|
||||
if(userDB == null){
|
||||
throw new Error("Cannot ban non-existant user!");
|
||||
}
|
||||
|
||||
const foundBan = await this.checkBanByUserDoc(userDB);
|
||||
|
||||
if(foundBan == null){
|
||||
throw new Error("User already unbanned!");
|
||||
}
|
||||
|
||||
//You know I can't help but feel like an asshole for looking for the index of something I just pulled out of an array using forEach...
|
||||
//Then again this is such an un-used function that the issue of code re-use overshadows performance
|
||||
//I mean how often are we REALLY going to be un-banning users from channels?
|
||||
const banIndex = this.banList.indexOf(foundBan);
|
||||
this.banList.splice(banIndex,1);
|
||||
return await this.save();
|
||||
}
|
||||
|
||||
channelSchema.methods.unban = async function(user){
|
||||
const userDB = await userModel.find({user});
|
||||
return await this.unbanByUserDoc(userDB);
|
||||
}
|
||||
|
||||
channelSchema.methods.nuke = async function(confirm){
|
||||
if(confirm == "" || confirm == null){
|
||||
throw new Error("Empty Confirmation String!");
|
||||
|
|
|
|||
|
|
@ -324,8 +324,8 @@ class canopyAjaxUtils{
|
|||
}
|
||||
}
|
||||
|
||||
async getChannelRank(channel){
|
||||
var response = await fetch(`/api/channel/rank?chanName=${channel}`,{
|
||||
async getChannelRank(chanName){
|
||||
var response = await fetch(`/api/channel/rank?chanName=${chanName}`,{
|
||||
method: "GET"
|
||||
});
|
||||
|
||||
|
|
@ -380,6 +380,53 @@ class canopyAjaxUtils{
|
|||
utils.ux.displayResponseError(await response.json());
|
||||
}
|
||||
}
|
||||
|
||||
async getChanBans(chanName){
|
||||
var response = await fetch(`/api/channel/ban?chanName=${chanName}`,{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
});
|
||||
|
||||
if(response.status == 200){
|
||||
return await response.json();
|
||||
}else{
|
||||
utils.ux.displayResponseError(await response.json());
|
||||
}
|
||||
}
|
||||
|
||||
async chanBan(chanName, user, expirationDays, banAlts){
|
||||
var response = await fetch(`/api/channel/ban`,{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify({chanName, user, expirationDays, banAlts})
|
||||
});
|
||||
|
||||
if(response.status == 200){
|
||||
return await response.json();
|
||||
}else{
|
||||
utils.ux.displayResponseError(await response.json());
|
||||
}
|
||||
}
|
||||
|
||||
async chanUnban(chanName, user){
|
||||
var response = await fetch(`/api/channel/ban`,{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify({chanName, user})
|
||||
});
|
||||
|
||||
if(response.status == 200){
|
||||
return await response.json();
|
||||
}else{
|
||||
utils.ux.displayResponseError(await response.json());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const utils = new canopyUtils()
|
||||
Loading…
Reference in a new issue