Added more granular permissions.

This commit is contained in:
rainbow napkin 2024-12-02 20:33:18 -05:00
parent ef4894e409
commit 2dbf3b97d5
11 changed files with 179 additions and 75 deletions

View file

@ -98,7 +98,6 @@ module.exports.post = async function(req, res){
res.send({errors: validResult.array()}) res.send({errors: validResult.array()})
} }
}catch(err){ }catch(err){
console.log(err);
return exceptionHandler(res, err); return exceptionHandler(res, err);
} }
} }

View file

@ -41,7 +41,6 @@ module.exports.post = async function(req, res){
res.send({errors: validResult.array()}) res.send({errors: validResult.array()})
} }
}catch(err){ }catch(err){
console.log(err);
exceptionHandler(res, err); exceptionHandler(res, err);
} }

View file

@ -107,7 +107,6 @@ module.exports.post = async function(req, res){
res.send({errors: validResult.array()}) res.send({errors: validResult.array()})
} }
}catch(err){ }catch(err){
console.log(err);
return exceptionHandler(res, err); return exceptionHandler(res, err);
} }
} }

View file

@ -32,18 +32,15 @@ const banController = require("../../controllers/api/admin/banController");
//globals //globals
const router = Router(); const router = Router();
//Use authentication middleware
router.use(permissionSchema.reqPermCheck("adminAPI"));
//routing functions //routing functions
router.get('/listUsers', listUsersController.get); router.get('/listUsers', permissionSchema.reqPermCheck("adminPanel"), listUsersController.get);
router.get('/listChannels', listChannelsController.get); router.get('/listChannels', permissionSchema.reqPermCheck("adminPanel"), listChannelsController.get);
router.get('/permissions', permissionsController.get); router.get('/permissions', permissionSchema.reqPermCheck("adminPanel"), permissionsController.get);
router.post('/permissions', checkExact([permissionsValidator.permissionsMap(), channelPermissionValidator.channelPermissionsMap()]), permissionsController.post); router.post('/permissions', permissionSchema.reqPermCheck("changePerms"), checkExact([permissionsValidator.permissionsMap(), channelPermissionValidator.channelPermissionsMap()]), permissionsController.post);
router.post('/changeRank', accountValidator.user(), accountValidator.rank(), changeRankController.post); router.post('/changeRank', permissionSchema.reqPermCheck("changeRank"), accountValidator.user(), accountValidator.rank(), changeRankController.post);
router.get('/ban', banController.get); 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 //Sometimes they're so simple you don't need to put your validators in their own special place :P
router.post('/ban', accountValidator.user(), body("permanent").isBoolean(), body("expirationDays").isInt(), banController.post); router.post('/ban', permissionSchema.reqPermCheck("banUser"), accountValidator.user(), body("permanent").isBoolean(), body("expirationDays").isInt(), banController.post);
router.delete('/ban', accountValidator.user(), banController.delete); router.delete('/ban', permissionSchema.reqPermCheck("banUser"), accountValidator.user(), banController.delete);
module.exports = router; module.exports = router;

View file

@ -15,7 +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/>.*/ along with this program. If not, see <https://www.gnu.org/licenses/>.*/
//npm imports //npm imports
const { body } = require('express-validator'); const { body, checkExact } = require('express-validator');
const { Router } = require('express'); const { Router } = require('express');
//local imports //local imports
@ -37,31 +37,31 @@ const router = Router();
//user authentication middleware //user authentication middleware
router.use("/register",permissionSchema.reqPermCheck("registerChannel")); router.use("/register",permissionSchema.reqPermCheck("registerChannel"));
router.use("/settings", channelValidator.name('chanName'), channelModel.reqPermCheck("manageChannel")); router.use("/settings", channelValidator.name('chanName'));
router.use("/permissions", channelValidator.name('chanName'), channelModel.reqPermCheck("manageChannel")); router.use("/permissions", channelValidator.name('chanName'));
router.use("/rank", channelValidator.name('chanName'), channelModel.reqPermCheck("manageChannel")); router.use("/rank", channelValidator.name('chanName'));
router.use("/delete", channelValidator.name('chanName'), channelModel.reqPermCheck("deleteChannel")); router.use("/delete", channelValidator.name('chanName'));
router.use("/ban", channelValidator.name('chanName'), channelModel.reqPermCheck("manageChannel")); router.use("/ban", channelValidator.name('chanName'));
//routing functions //routing functions
//register //register
router.post('/register', channelValidator.name(), channelValidator.description(), channelValidator.thumbnail(), registerController.post); router.post('/register', channelValidator.name(), channelValidator.description(), channelValidator.thumbnail(), registerController.post);
//list //list
router.get('/list', listController.get); router.get('/list', channelModel.reqPermCheck("manageChannel"), listController.get);
//settings //settings
router.get('/settings', settingsController.get); router.get('/settings', channelModel.reqPermCheck("manageChannel"), settingsController.get);
router.post('/settings', channelValidator.settingsMap(), settingsController.post); router.post('/settings', channelModel.reqPermCheck("changeSettings"), channelValidator.settingsMap(), settingsController.post);
//permissions //permissions
router.get('/permissions', permissionsController.get); router.get('/permissions', channelModel.reqPermCheck("manageChannel"), permissionsController.get);
router.post('/permissions', channelPermissionValidator.channelPermissionsMap(), permissionsController.post); router.post('/permissions', channelModel.reqPermCheck("changePerms"), checkExact(channelPermissionValidator.channelPermissionsMap()), permissionsController.post);
//rank //rank
router.get('/rank', rankController.get); router.get('/rank', channelModel.reqPermCheck("manageChannel"), rankController.get);
router.post('/rank', accountValidator.user(), channelValidator.rank(), rankController.post); router.post('/rank', channelModel.reqPermCheck("changeRank"), accountValidator.user(), channelValidator.rank(), rankController.post);
//delete //delete
router.post('/delete', channelValidator.name('confirm'), deleteController.post); router.post('/delete', channelModel.reqPermCheck("deleteChannel"), channelValidator.name('confirm'), deleteController.post);
//ban //ban
router.get('/ban', banController.get); router.get('/ban', channelModel.reqPermCheck("manageChannel"), banController.get);
router.post('/ban', accountValidator.user(), body("banAlts").isBoolean(), body("expirationDays").isInt(), banController.post); router.post('/ban', channelModel.reqPermCheck("banUser"), accountValidator.user(), body("banAlts").isBoolean(), body("expirationDays").isInt(), banController.post);
router.delete('/ban', accountValidator.user(), banController.delete); router.delete('/ban', channelModel.reqPermCheck("banUser"), accountValidator.user(), banController.delete);
module.exports = router; module.exports = router;

View file

@ -28,6 +28,36 @@ const channelPermissionSchema = new mongoose.Schema({
default: "admin", default: "admin",
required: true required: true
}, },
changeRank: {
type: mongoose.SchemaTypes.String,
enum: rankEnum,
default: "admin",
required: true
},
changePerms: {
type: mongoose.SchemaTypes.String,
enum: rankEnum,
default: "admin",
required: true
},
changeSettings: {
type: mongoose.SchemaTypes.String,
enum: rankEnum,
default: "admin",
required: true
},
kickUser: {
type: mongoose.SchemaTypes.String,
enum: rankEnum,
default: "admin",
required: true
},
banUser: {
type: mongoose.SchemaTypes.String,
enum: rankEnum,
default: "admin",
required: true
},
deleteChannel: { deleteChannel: {
type: mongoose.SchemaTypes.String, type: mongoose.SchemaTypes.String,
enum: rankEnum, enum: rankEnum,

View file

@ -84,55 +84,56 @@ channelSchema.pre('save', async function (next){
//Getting the affected user would be a million times easier elsewhere //Getting the affected user would be a million times easier elsewhere
//But this ensures it happens every time channel rank gets changed no matter what //But this ensures it happens every time channel rank gets changed no matter what
if(this.isModified('rankList')){ if(this.isModified('rankList') && this.rankList != null){
//Get the rank list before it was modified (gross but works, find a better way if you dont like it :P) //Get the rank list before it was modified (gross but works, find a better way if you dont like it :P)
var chanDB = await module.exports.findOne({_id: this._id}); var chanDB = await module.exports.findOne({_id: this._id});
//Create empty variable for the found rank object //Create empty variable for the found rank object
var foundRank = null; var foundRank = null;
if(chanDB != null){
//If we're removing one //If we're removing one
if(chanDB.rankList.length > this.rankList.length){ if(chanDB.rankList.length > this.rankList.length){
//Child/Parent is *WAY* to atomic family for my tastes :P //Child/Parent is *WAY* to atomic family for my tastes :P
var top = chanDB; var top = chanDB;
var bottom = this; var bottom = this;
}else{ }else{
//otherwise reverse the loops //otherwise reverse the loops
var top = this; var top = this;
var bottom = chanDB; var bottom = chanDB;
}
//Populate the top doc
await top.populate('rankList.user');
top.rankList.forEach((topObj) => {
//Create empty variable for the matched rank
var matchedRank = null;
//For each rank in the old copy of the rank list
bottom.rankList.forEach((bottomObj) => {
if(topObj.user._id.toString() == bottomObj.user._id.toString()){
matchedRank = bottomObj;
}
});
if(matchedRank == null || matchedRank.rank != topObj.rank){
foundRank = topObj;
} }
}); //Populate the top doc
await top.populate('rankList.user');
//get relevant active channel
const activeChan = server.channelManager.activeChannels.get(this.name);
//if the channel is online top.rankList.forEach((topObj) => {
if(activeChan != null){ //Create empty variable for the matched rank
//Get the relevant user connection var matchedRank = null;
const userConn = activeChan.userList.get(foundRank.user.user); //For each rank in the old copy of the rank list
//if the user is online bottom.rankList.forEach((bottomObj) => {
if(userConn != null){ if(topObj.user._id.toString() == bottomObj.user._id.toString()){
//kick the user matchedRank = bottomObj;
userConn.disconnect("Your channel rank has changed!"); }
});
if(matchedRank == null || matchedRank.rank != topObj.rank){
foundRank = topObj;
}
});
//get relevant active channel
const activeChan = server.channelManager.activeChannels.get(this.name);
//if the channel is online
if(activeChan != null){
//Get the relevant user connection
const userConn = activeChan.userList.get(foundRank.user.user);
//if the user is online
if(userConn != null){
//kick the user
userConn.disconnect("Your channel rank has changed!");
}
} }
} }
} }

View file

@ -58,7 +58,6 @@ flairSchema.statics.loadDefaults = async function(){
}else{ }else{
console.log("Error, null flair:"); console.log("Error, null flair:");
} }
console.log(err);
} }
}); });
} }

View file

@ -31,7 +31,31 @@ const permissionSchema = new mongoose.Schema({
default: "admin", default: "admin",
required: true required: true
}, },
adminAPI: { changeRank: {
type: mongoose.SchemaTypes.String,
enum: rankEnum,
default: "admin",
required: true
},
changePerms: {
type: mongoose.SchemaTypes.String,
enum: rankEnum,
default: "admin",
required: true
},
banUser: {
type: mongoose.SchemaTypes.String,
enum: rankEnum,
default: "admin",
required: true
},
nukeUser: {
type: mongoose.SchemaTypes.String,
enum: rankEnum,
default: "admin",
required: true
},
genPasswordReset: {
type: mongoose.SchemaTypes.String, type: mongoose.SchemaTypes.String,
enum: rankEnum, enum: rankEnum,
default: "admin", default: "admin",

View file

@ -34,7 +34,31 @@ module.exports.permissionsValidator = {
options: module.exports.isRank options: module.exports.isRank
}, },
}, },
'permissionsMap.adminAPI': { 'permissionsMap.changeRank': {
optional: true,
custom: {
options: module.exports.isRank
},
},
'permissionsMap.changePerms': {
optional: true,
custom: {
options: module.exports.isRank
},
},
'permissionsMap.banUser': {
optional: true,
custom: {
options: module.exports.isRank
},
},
'permissionsMap.nukeUser': {
optional: true,
custom: {
options: module.exports.isRank
},
},
'permissionsMap.genPasswordReset': {
optional: true, optional: true,
custom: { custom: {
options: module.exports.isRank options: module.exports.isRank
@ -57,6 +81,36 @@ module.exports.channelPermissionValidator = {
options: module.exports.isRank options: module.exports.isRank
}, },
}, },
'channelPermissionsMap.changeRank': {
optional: true,
custom: {
options: module.exports.isRank
},
},
'channelPermissionsMap.changePerms': {
optional: true,
custom: {
options: module.exports.isRank
},
},
'channelPermissionsMap.changeSettings': {
optional: true,
custom: {
options: module.exports.isRank
},
},
'channelPermissionsMap.kickUser': {
optional: true,
custom: {
options: module.exports.isRank
},
},
'channelPermissionsMap.banUser': {
optional: true,
custom: {
options: module.exports.isRank
},
},
'channelPermissionsMap.deleteChannel': { 'channelPermissionsMap.deleteChannel': {
optional: true, optional: true,
custom: { custom: {

View file

@ -275,6 +275,8 @@ class prefrenceList{
constructor(channel){ constructor(channel){
this.channel = channel; this.channel = channel;
this.inputs = document.querySelectorAll(".channel-preference-list-item"); this.inputs = document.querySelectorAll(".channel-preference-list-item");
this.setupInput();
} }
setupInput(){ setupInput(){