diff --git a/src/app/channel/channelManager.js b/src/app/channel/channelManager.js
index cddc5dd..894cc4c 100644
--- a/src/app/channel/channelManager.js
+++ b/src/app/channel/channelManager.js
@@ -16,7 +16,7 @@ along with this program. If not, see .*/
//Local Imports
const channelModel = require('../../schemas/channel/channelSchema');
-const userModel = require('../../schemas/userSchema');
+const {userModel} = require('../../schemas/userSchema');
const loggerUtils = require('../../utils/loggerUtils');
const activeChannel = require('./activeChannel');
const chatHandler = require('./chatHandler');
diff --git a/src/app/channel/chatHandler.js b/src/app/channel/chatHandler.js
index c6c2955..64bbb21 100644
--- a/src/app/channel/chatHandler.js
+++ b/src/app/channel/chatHandler.js
@@ -19,7 +19,7 @@ const validator = require('validator');//No express here, so regular validator i
//local imports
const loggerUtils = require('../../utils/loggerUtils');
-const userModel = require('../../schemas/userSchema');
+const {userModel} = require('../../schemas/userSchema');
module.exports = class{
constructor(server){
diff --git a/src/controllers/adminPanelController.js b/src/controllers/adminPanelController.js
index 098f62f..42ba146 100644
--- a/src/controllers/adminPanelController.js
+++ b/src/controllers/adminPanelController.js
@@ -16,7 +16,7 @@ along with this program. If not, see .*/
//Config
const config = require('../../config.json');
-const userModel = require('../schemas/userSchema');
+const {userModel} = require('../schemas/userSchema');
const permissionModel = require('../schemas/permissionSchema');
const channelModel = require('../schemas/channel/channelSchema');
const {exceptionHandler} = require("../utils/loggerUtils");
diff --git a/src/controllers/api/account/deleteController.js b/src/controllers/api/account/deleteController.js
index a930b4d..45ed2c7 100644
--- a/src/controllers/api/account/deleteController.js
+++ b/src/controllers/api/account/deleteController.js
@@ -18,7 +18,7 @@ along with this program. If not, see .*/
const {validationResult, matchedData} = require('express-validator');
//local imports
-const userModel = require('../../../schemas/userSchema');
+const {userModel} = require('../../../schemas/userSchema');
const accountUtils = require('../../../utils/sessionUtils.js');
const {exceptionHandler} = require('../../../utils/loggerUtils.js');
diff --git a/src/controllers/api/account/registerController.js b/src/controllers/api/account/registerController.js
index e294dc4..ee07654 100644
--- a/src/controllers/api/account/registerController.js
+++ b/src/controllers/api/account/registerController.js
@@ -18,7 +18,7 @@ along with this program. If not, see .*/
const {validationResult, matchedData} = require('express-validator');
//local imports
-const userModel = require('../../../schemas/userSchema');
+const {userModel} = require('../../../schemas/userSchema');
const {exceptionHandler} = require('../../../utils/loggerUtils.js');
module.exports.post = async function(req, res){
diff --git a/src/controllers/api/account/updateController.js b/src/controllers/api/account/updateController.js
index 8cc5d3b..50ffd0e 100644
--- a/src/controllers/api/account/updateController.js
+++ b/src/controllers/api/account/updateController.js
@@ -18,7 +18,7 @@ along with this program. If not, see .*/
const {validationResult, matchedData} = require('express-validator');
//local imports
-const userModel = require('../../../schemas/userSchema');
+const {userModel} = require('../../../schemas/userSchema');
const accountUtils = require('../../../utils/sessionUtils.js');
const {exceptionHandler} = require('../../../utils/loggerUtils.js');
diff --git a/src/controllers/api/admin/banController.js b/src/controllers/api/admin/banController.js
new file mode 100644
index 0000000..63fc1a2
--- /dev/null
+++ b/src/controllers/api/admin/banController.js
@@ -0,0 +1,59 @@
+/*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 .*/
+
+//NPM Imports
+const {validationResult, matchedData} = require('express-validator');
+
+//local imports
+const banModel = require('../../../schemas/userBanSchema');
+const {userModel} = require('../../../schemas/userSchema');
+const {exceptionHandler} = require('../../../utils/loggerUtils');
+
+module.exports.get = async function(req, res){
+ try{
+ //get bans
+ const bans = await banModel.getBans();
+
+ //send bans
+ res.status(200);
+ return res.send(bans);
+ }catch(err){
+ return exceptionHandler(res, err);
+ }
+}
+
+module.exports.post = async function(req, res){
+ try{
+ const validResult = validationResult(req);
+ if(validResult.isEmpty()){
+ const {user} = matchedData(req);
+ const userDB = await userModel.findOne({user});
+
+ if(userDB == null){
+ res.status(400);
+ res.send({errors:[{type: "Bad Query", msg: "User not found.", date: new Date()}]});
+ }
+
+ await banModel.banByUserDoc(userDB);
+
+ }else{
+ res.status(400);
+ return res.send({errors: validResult.array()})
+ }
+ }catch(err){
+ return exceptionHandler(res, err);
+ }
+}
\ No newline at end of file
diff --git a/src/controllers/api/admin/changeRankController.js b/src/controllers/api/admin/changeRankController.js
index 2ba0ea8..d509be1 100644
--- a/src/controllers/api/admin/changeRankController.js
+++ b/src/controllers/api/admin/changeRankController.js
@@ -20,7 +20,7 @@ const {validationResult, matchedData} = require('express-validator');
//local imports
const {exceptionHandler} = require('../../../utils/loggerUtils');
const permissionModel = require('../../../schemas/permissionSchema');
-const userModel = require('../../../schemas/userSchema');
+const {userModel} = require('../../../schemas/userSchema');
//api change rank functions
module.exports.post = async function(req, res){
diff --git a/src/controllers/api/admin/listUsersController.js b/src/controllers/api/admin/listUsersController.js
index 4f057e8..217c3ef 100644
--- a/src/controllers/api/admin/listUsersController.js
+++ b/src/controllers/api/admin/listUsersController.js
@@ -16,7 +16,7 @@ along with this program. If not, see .*/
//local imports
const {exceptionHandler} = require('../../../utils/loggerUtils.js');
-const userModel = require('../../../schemas/userSchema');
+const {userModel} = require('../../../schemas/userSchema');
//api list account functions
module.exports.get = async function(req, res){
diff --git a/src/controllers/api/channel/rankController.js b/src/controllers/api/channel/rankController.js
index e779c7a..5f9eb9c 100644
--- a/src/controllers/api/channel/rankController.js
+++ b/src/controllers/api/channel/rankController.js
@@ -20,7 +20,7 @@ const {validationResult, matchedData} = require('express-validator');
//local imports
const {exceptionHandler} = require('../../../utils/loggerUtils');
const permissionModel = require('../../../schemas/permissionSchema');
-const userModel = require('../../../schemas/userSchema');
+const {userModel} = require('../../../schemas/userSchema');
const channelModel = require('../../../schemas/channel/channelSchema');
//api channel rank functions
diff --git a/src/controllers/api/channel/registerController.js b/src/controllers/api/channel/registerController.js
index 1a2a390..d299e09 100644
--- a/src/controllers/api/channel/registerController.js
+++ b/src/controllers/api/channel/registerController.js
@@ -19,7 +19,7 @@ const {validationResult, matchedData} = require('express-validator');
//local imports
const {exceptionHandler} = require('../../../utils/loggerUtils.js');
-const userModel = require('../../../schemas/userSchema.js');
+const {userModel} = require('../../../schemas/userSchema.js');
const channelModel = require('../../../schemas/channel/channelSchema');
//api account functions
diff --git a/src/controllers/profileController.js b/src/controllers/profileController.js
index c6248c6..322891e 100644
--- a/src/controllers/profileController.js
+++ b/src/controllers/profileController.js
@@ -15,7 +15,7 @@ You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .*/
//Local Imports
-const userModel = require('../schemas/userSchema');
+const {userModel} = require('../schemas/userSchema');
const {exceptionHandler} = require('../utils/loggerUtils.js');
//Config
diff --git a/src/routers/api/adminRouter.js b/src/routers/api/adminRouter.js
index 771c582..aa96d7a 100644
--- a/src/routers/api/adminRouter.js
+++ b/src/routers/api/adminRouter.js
@@ -27,6 +27,7 @@ const listUsersController = require("../../controllers/api/admin/listUsersContro
const listChannelsController = require("../../controllers/api/admin/listChannelsController");
const changeRankController = require("../../controllers/api/admin/changeRankController");
const permissionsController = require("../../controllers/api/admin/permissionsController");
+const banController = require("../../controllers/api/admin/banController");
//globals
const router = Router();
@@ -40,5 +41,7 @@ router.get('/listChannels', listChannelsController.get);
router.get('/permissions', permissionsController.get);
router.post('/permissions', checkExact([permissionsValidator.permissionsMap(), channelPermissionValidator.channelPermissionsMap()]), permissionsController.post);
router.post('/changeRank', accountValidator.user(), accountValidator.rank(), changeRankController.post);
+router.get('/ban', banController.get);
+router.post('/ban', accountValidator.user(), banController.post);
module.exports = router;
diff --git a/src/schemas/channel/channelSchema.js b/src/schemas/channel/channelSchema.js
index 9dcb4b4..089b441 100644
--- a/src/schemas/channel/channelSchema.js
+++ b/src/schemas/channel/channelSchema.js
@@ -20,7 +20,7 @@ const {validationResult, matchedData} = require('express-validator');
//Local Imports
const statModel = require('../statSchema.js');
-const userModel = require('../userSchema.js');
+const {userModel} = require('../userSchema.js');
const permissionModel = require('../permissionSchema.js');
const channelPermissionSchema = require('./channelPermissionSchema.js');
const { exceptionHandler } = require('../../utils/loggerUtils.js');
diff --git a/src/schemas/userBanSchema.js b/src/schemas/userBanSchema.js
new file mode 100644
index 0000000..0068f95
--- /dev/null
+++ b/src/schemas/userBanSchema.js
@@ -0,0 +1,121 @@
+/*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 .*/
+
+//NPM Imports
+const {mongoose} = require('mongoose');
+
+//Local Imports
+const {userSchema} = require('./userSchema');
+
+const userBanSchema = new mongoose.Schema({
+ user: {
+ type: mongoose.SchemaTypes.ObjectID,
+ required: true,
+ ref: "user"
+ },
+ //To be used in future when ip-hashing/better session tracking is implemented
+ ips: {
+ type: [mongoose.SchemaTypes.String],
+ required: false
+ },
+ //To be used in future when alt-detection has been implemented
+ alts: {
+ type: [userSchema],
+ required: false
+ },
+ banDate: {
+
+ type: mongoose.SchemaTypes.Date,
+ required: true,
+ default: new Date()
+ },
+ expirationDays: {
+ type: mongoose.SchemaTypes.Number,
+ required: true,
+ default: 30
+ },
+ //If true, then expiration date deletes associated accounts instead of deleting the ban record
+ deleteAccountOnExpire: {
+ type: mongoose.SchemaTypes.Boolean,
+ required: true,
+ default: false
+ }
+});
+
+userBanSchema.statics.checkBanByUserDoc = async function(userDB){
+ const banDB = await this.find({});
+ var foundBan = null;
+
+ banDB.forEach((ban) => {
+ if(ban.user.toString() == userDB._id.toString()){
+ foundBan = ban;
+ }
+ });
+
+ return foundBan;
+}
+
+userBanSchema.statics.checkBan = async function(user){
+ const userDB = await userModel.findOne({user: user.user});
+ return this.checkBanByUserDoc(userDB);
+}
+
+userBanSchema.statics.banByUserDoc = async function(userDB){
+ if(await this.checkBanByUserDoc(userDB) != null){
+ throw new Error("User already banned");
+ }
+
+ return await this.create({user: userDB._id});
+}
+
+userBanSchema.statics.ban = async function(user){
+ const userDB = await userModel.findOne({user: user.user});
+ return this.banByUserDoc(userDB);
+}
+
+userBanSchema.statics.getBans = async function(){
+ const banDB = await this.find({}).populate('user');
+ var bans = [];
+
+ banDB.forEach((ban) => {
+ //Calcualte expiration date
+ var expirationDate = new Date(ban.banDate);
+ expirationDate.setDate(expirationDate.getDate() + ban.expirationDays);
+
+ const userObj = {
+ id: ban.user.id,
+ user: ban.user.user,
+ img: ban.user.img,
+ date: ban.user.date
+ }
+
+ const banObj = {
+ banDate: ban.banDate,
+ expirationDays: ban.expirationDays,
+ expirationDate: expirationDate,
+ user: userObj,
+ ips: ban.ips,
+ alts: ban.alts,
+ deleteAccountOnExpire: ban.deleteAccountOnExpire
+ }
+
+ bans.push(banObj);
+ });
+
+ return bans;
+}
+
+module.exports = mongoose.model("userBan", userBanSchema);
\ No newline at end of file
diff --git a/src/schemas/userSchema.js b/src/schemas/userSchema.js
index ebd5b7e..c18c578 100644
--- a/src/schemas/userSchema.js
+++ b/src/schemas/userSchema.js
@@ -282,4 +282,5 @@ userSchema.methods.nuke = async function(pass){
}
}
-module.exports = mongoose.model("user", userSchema);
\ No newline at end of file
+module.exports.userSchema = userSchema;
+module.exports.userModel = mongoose.model("user", userSchema);
\ No newline at end of file
diff --git a/src/utils/sessionUtils.js b/src/utils/sessionUtils.js
index ec3fe87..cc2f0f1 100644
--- a/src/utils/sessionUtils.js
+++ b/src/utils/sessionUtils.js
@@ -15,7 +15,7 @@ You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .*/
//local imports
-const userModel = require('../schemas/userSchema.js');
+const {userModel} = require('../schemas/userSchema.js');
//this module is good for keeping wrappers for userModel and other shit in that does more session handling than database access/modification.
diff --git a/src/views/adminPanel.ejs b/src/views/adminPanel.ejs
index f53f4d0..7c4aa62 100644
--- a/src/views/adminPanel.ejs
+++ b/src/views/adminPanel.ejs
@@ -26,6 +26,7 @@ along with this program. If not, see .-->
<%- include('partial/adminPanel/channelList', {chanGuide}) %>
<%- include('partial/adminPanel/userList', {user, userList, rankEnum}) %>
<%- include('partial/adminPanel/permList', {permList, rankEnum}) %>
+ <%- include('partial/adminPanel/userBanList') %>