Added '/api/admin/permissions' post & ajax helper

This commit is contained in:
rainbownapkin 2024-11-18 08:18:02 -05:00
parent 8c4d9693f5
commit bd24aae381
9 changed files with 172 additions and 43 deletions

View file

@ -22,7 +22,7 @@ const {exceptionHandler} = require('../../../utils/loggerUtils');
const permissionModel = require('../../../schemas/permissionSchema');
const userModel = require('../../../schemas/userSchema');
//api account functions
//api change rank functions
module.exports.post = async function(req, res){
try{
const validResult = validationResult(req);

View file

@ -18,7 +18,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.*/
const {exceptionHandler} = require('../../../utils/loggerUtils.js');
const channelModel = require('../../../schemas/channelSchema.js');
//api account functions
//api list channel functions
module.exports.get = async function(req, res){
try{
const chanGuide = await channelModel.getChannelList(true);

View file

@ -1,31 +0,0 @@
/*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/>.*/
//local imports
const {exceptionHandler} = require('../../../utils/loggerUtils.js');
const permissionModel = require('../../../schemas/permissionSchema.js');
//api account functions
module.exports.get = async function(req, res){
try{
const perms = await permissionModel.getPerms();
res.status(200);
return res.send(perms);
}catch(err){
return exceptionHandler(res, err);
}
}

View file

@ -18,7 +18,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.*/
const {exceptionHandler} = require('../../../utils/loggerUtils.js');
const userModel = require('../../../schemas/userSchema');
//api account functions
//api list account functions
module.exports.get = async function(req, res){
try{
const userList = await userModel.getUserList(true);

View file

@ -0,0 +1,85 @@
/*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 permissionModel = require('../../../schemas/permissionSchema.js');
//api permissions functions
module.exports.get = async function(req, res){
try{
const perms = await permissionModel.getPerms();
res.status(200);
return res.send(perms);
}catch(err){
return exceptionHandler(res, err);
}
}
module.exports.post = async function(req, res){
try{
//check for validation errors
const validResult = validationResult(req);
//if none
if(validResult.isEmpty()){
//grab validated/sanatized data
const {permissionsMap} = matchedData(req);
const perms = await permissionModel.getPerms();
var permError = false;
//For each permission submitted
Object.keys(permissionsMap).forEach((perm) => {
//Check to make sure no one is jumping perms (this should be admins only, but just in-case)
//Setting a boolean inside of an if statement seems fucked, until you realize it won't set it back false on the next loop :P
if(permissionModel.rankToNum(perms[perm]) > permissionModel.rankToNum(req.session.user.rank) || permissionModel.rankToNum(permissionsMap[perm]) > permissionModel.rankToNum(req.session.user.rank)){
permError = true;
}
//Set permissions in the permissions model
perms[perm] = permissionsMap[perm];
});
//Flip our shit if something's wrong.
if(permError){
res.status(401);
return res.send({errors:[{type: "Unauthorized", msg: "New rank must be equal to or below that of the user changing it.", date: new Date()}]});
}
await perms.save();
//Cleanup return object
var returnObj = perms.toObject();
delete returnObj._id
delete returnObj.__v
//send successful response
res.status(200);
return res.send(returnObj);
//otherwise scream
}else{
res.status(400);
res.send({errors: validResult.array()})
}
}catch(err){
return exceptionHandler(res, err);
}
}

View file

@ -20,11 +20,12 @@ const { Router } = require('express');
//local imports
const accountValidator = require("../../validators/accountValidator");
const {permissionsValidator} = require("../../validators/permissionsValidator");
const permissionSchema = require("../../schemas/permissionSchema");
const listUsersController = require("../../controllers/api/admin/listUsersController");
const listChannelsController = require("../../controllers/api/admin/listChannelsController");
const changeRankController = require("../../controllers/api/admin/changeRankController");
const listPermissionsController = require("../../controllers/api/admin/listPermissionsController");
const permissionsController = require("../../controllers/api/admin/permissionsController");
//globals
const router = Router();
@ -35,7 +36,8 @@ router.use(permissionSchema.reqPermCheck("adminAPI"));
//routing functions
router.get('/listUsers', listUsersController.get);
router.get('/listChannels', listChannelsController.get);
router.get('/listPermissions', listPermissionsController.get);
router.get('/permissions', permissionsController.get);
router.post('/permissions', permissionsValidator.permissionsMap(), permissionsController.post);
router.post('/changeRank', accountValidator.user(), accountValidator.rank(), changeRankController.post);
module.exports = router;

View file

@ -18,13 +18,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.*/
const { check, body, checkSchema, checkExact} = require('express-validator');
//local imports
const permissionSchema = require("../schemas/permissionSchema");
function isRank(value){
rankVal = permissionSchema.rankToNum(value);
return rankVal != -1;
}
const {isRank} = require('./permissionsValidator');
module.exports = {
user: (field = 'user') => body(field).escape().trim().isLength({min: 1, max: 22}),

View file

@ -0,0 +1,62 @@
/*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 { check, body, checkSchema, checkExact} = require('express-validator');
//local imports
const permissionSchema = require("../schemas/permissionSchema");
module.exports.isRank = function(value){
rankVal = permissionSchema.rankToNum(value);
return rankVal != -1;
}
module.exports.permissionsValidator = {
permissionsMap: () => checkExact(checkSchema({
'permissionsMap.adminPanel': {
optional: true,
custom: {
options: module.exports.isRank
},
},
'permissionsMap.adminAPI': {
optional: true,
custom: {
options: module.exports.isRank
},
},
'permissionsMap.registerChannel': {
optional: true,
custom: {
options: module.exports.isRank
},
},
'permissionsMap.manageChannel': {
optional: true,
custom: {
options: module.exports.isRank
},
},
'permissionsMap.deleteChannel': {
optional: true,
custom: {
options: module.exports.isRank
},
}
}))
}

View file

@ -35,6 +35,23 @@ class canopyAdminUtils{
utils.ux.displayResponseError(await response.json());
}
}
async setPermission(permObj){
var response = await fetch(`/api/admin/permissions`,{
method: "POST",
headers: {
"Content-Type": "application/json"
},
//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({permissionsMap: Object.fromEntries(permObj)})
});
if(response.status == 200){
return await response.json();
}else{
utils.ux.displayResponseError(await response.json());
}
}
}
class adminUserList{