Channel Rank/Auth base backend functional
This commit is contained in:
parent
057537341a
commit
61fab57a6d
|
|
@ -27,16 +27,18 @@ module.exports = class{
|
|||
this.userList = new Map();
|
||||
}
|
||||
|
||||
async handleConnection(userDB, socket){
|
||||
async handleConnection(userDB, chanDB, socket){
|
||||
//get current user object from the userlist
|
||||
var userObj = this.userList.get(userDB.user);
|
||||
//get channel rank for current user
|
||||
const chanRank = await chanDB.getChannelRankByUserDoc(userDB);
|
||||
|
||||
//If user is already connected
|
||||
if(userObj){
|
||||
//Add this socket on to the userobject
|
||||
userObj.sockets.push(socket.id);
|
||||
}else{
|
||||
userObj = new connectedUser(userDB.user, userDB.id, userDB.rank, userDB.flair, this, socket);
|
||||
userObj = new connectedUser(userDB.user, userDB.id, userDB.rank, chanRank, userDB.flair, this, socket);
|
||||
}
|
||||
|
||||
//Set user entry in userlist
|
||||
|
|
@ -49,6 +51,8 @@ module.exports = class{
|
|||
//await this.sendClientMetadata(userDB, socket);
|
||||
await userObj.sendClientMetadata();
|
||||
|
||||
console.log(userObj);
|
||||
|
||||
//Send out the userlist
|
||||
this.broadcastUserList(socket.chan);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,14 +45,15 @@ module.exports = class{
|
|||
const userDB = await this.authSocket(socket);
|
||||
|
||||
//Get the active channel based on the socket
|
||||
var activeChan = await this.getActiveChan(socket);
|
||||
var {activeChan, chanDB} = await this.getActiveChan(socket);
|
||||
|
||||
//Define listeners
|
||||
this.defineListeners(socket);
|
||||
this.chatHandler.defineListeners(socket);
|
||||
|
||||
//Connect the socket to it's given channel
|
||||
activeChan.handleConnection(userDB, socket);
|
||||
//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);
|
||||
|
|
@ -83,10 +84,11 @@ module.exports = class{
|
|||
|
||||
async getActiveChan(socket){
|
||||
socket.chan = socket.handshake.headers.referer.split('/c/')[1];
|
||||
const chanDB = (await channelModel.findOne({name: socket.chan}))
|
||||
|
||||
//Check if channel exists
|
||||
if(await channelModel.findOne({name: socket.chan}) == null){
|
||||
throw new Error("Channel not found!")
|
||||
if(chanDB == null){
|
||||
throw new Error("Channel not found!");
|
||||
}
|
||||
|
||||
//Check if current channel is active
|
||||
|
|
@ -99,7 +101,8 @@ module.exports = class{
|
|||
}
|
||||
|
||||
//Return whatever the active channel is (new or old)
|
||||
return activeChan;
|
||||
return {activeChan, chanDB};
|
||||
//return activeChan;
|
||||
}
|
||||
|
||||
defineListeners(socket){
|
||||
|
|
|
|||
|
|
@ -19,10 +19,11 @@ const flairModel = require('../../schemas/flairSchema');
|
|||
const permissionModel = require('../../schemas/permissionSchema');
|
||||
|
||||
module.exports = class{
|
||||
constructor(id, name, rank, flair, channel, socket){
|
||||
constructor(id, name, rank, chanRank, flair, channel, socket){
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.rank = rank;
|
||||
this.chanRank = chanRank;
|
||||
this.flair = flair;
|
||||
this.channel = channel;
|
||||
this.sockets = [socket.id];
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ const {validationResult, matchedData} = require('express-validator');
|
|||
//local imports
|
||||
const {exceptionHandler} = require('../../../utils/loggerUtils.js');
|
||||
const channelModel = require('../../../schemas/channel/channelSchema.js');
|
||||
const permissionModel = require('../../../schemas/permissionSchema.js');
|
||||
|
||||
//api account functions
|
||||
module.exports.get = async function(req, res){
|
||||
|
|
@ -53,15 +54,41 @@ module.exports.post = async function(req, res){
|
|||
|
||||
if(validResult.isEmpty()){
|
||||
const data = matchedData(req);
|
||||
const channel = await channelModel.findOne({name: data.chanName});
|
||||
const permissionsMap = new Map(Object.entries(data.channelPermissionsMap));
|
||||
//get channel document based on sanatized/validated input
|
||||
const chanDB = await channelModel.findOne({name: data.chanName});
|
||||
//get permissions map based on sanatized/validated input
|
||||
const permissionsMap = data.channelPermissionsMap;
|
||||
//get chanRank off off session user
|
||||
const chanRank = await chanDB.getChannelRank(req.session.user);
|
||||
//setup flag for permissions errors
|
||||
var permError = null;
|
||||
|
||||
if(channel == null){
|
||||
if(chanDB == null){
|
||||
throw new Error("Channel not found.");
|
||||
}
|
||||
|
||||
//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(chanDB.permissions[perm]) > permissionModel.rankToNum(chanRank) || permissionModel.rankToNum(permissionsMap[perm]) > permissionModel.rankToNum(chanRank)){
|
||||
permError = true;
|
||||
}
|
||||
|
||||
//Set permissions in the permissions model
|
||||
chanDB.permissions[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 chanDB.save();
|
||||
|
||||
res.status(200);
|
||||
return res.send(await channel.updateChannelPerms(permissionsMap));
|
||||
return res.send(chanDB.permissions);
|
||||
}else{
|
||||
res.status(400);
|
||||
res.send({errors: validResult.array()})
|
||||
|
|
|
|||
|
|
@ -34,24 +34,19 @@ module.exports.get = async function(req, res){
|
|||
//Get channel document from validated/sanatized chanName querystring
|
||||
const data = matchedData(req);
|
||||
const chanDB = await channelModel.findOne({name: data.chanName});
|
||||
//Setup empty array for our return data
|
||||
const userList = [];
|
||||
|
||||
//Populate the user objects in our ranklist based off of their DB ID's
|
||||
await chanDB.populate('rankList.user');
|
||||
|
||||
//For each rank object in the rank list
|
||||
chanDB.rankList.forEach(async (rankObj) => {
|
||||
//Create a new user object from rank object data
|
||||
const userObj = {
|
||||
id: rankObj.user.id,
|
||||
user: rankObj.user.user,
|
||||
rank: rankObj.rank
|
||||
//get userDB from session
|
||||
if(req.session.user != null){
|
||||
var userDB = await userModel.findOne({user: req.session.user.user});
|
||||
}
|
||||
|
||||
//Add our user object to the list
|
||||
userList.push(userObj);
|
||||
});
|
||||
//If for some reason there isn't any user found
|
||||
if(userDB == null){
|
||||
var userDB = {rank: "anon"};
|
||||
}
|
||||
|
||||
//Setup empty array for our return data
|
||||
const userList = await chanDB.getRankList();
|
||||
|
||||
//Send out the userlist we created
|
||||
res.status(200);
|
||||
|
|
@ -66,3 +61,53 @@ module.exports.get = async function(req, res){
|
|||
}
|
||||
}
|
||||
|
||||
module.exports.post = async function(req, res){
|
||||
try{
|
||||
//Get validation results
|
||||
const validResult = validationResult(req);
|
||||
|
||||
//If we don't have any validation errors
|
||||
if(validResult.isEmpty()){
|
||||
const data = matchedData(req);
|
||||
//Get channel document from sanatized/validated data
|
||||
const chanDB = await channelModel.findOne({name: data.chanName});
|
||||
//Get user document from sanatized/validated data
|
||||
const userDB = await userModel.findOne({user: data.user});
|
||||
//Get requesting user rank from sanatized/validated data
|
||||
const chanRank = await chanDB.getChannelRank(req.session.user);
|
||||
//Get target user rank from sanatized/validated data
|
||||
const targetChanRank = await chanDB.getChannelRankByUserDoc(userDB);
|
||||
|
||||
if(data.user == null || userDB == null){
|
||||
//If the user is null, scream and shout
|
||||
res.status(400);
|
||||
return res.send({errors:[{type: "Bad Query", msg: "User not found.", date: new Date()}]});
|
||||
}else if(data.user == req.session.user.user){
|
||||
//If some smart-ass is trying self-privelege escalation
|
||||
res.status(401);
|
||||
return res.send({errors:[{type: "Unauthorized", msg: "No, you can't change your own rank. Fuck off.", date: new Date()}]});
|
||||
}else if(permissionModel.rankToNum(data.rank) >= permissionModel.rankToNum(chanRank)){
|
||||
//If the user is below the new rank of the user they're setting, scream and shout
|
||||
res.status(401);
|
||||
return res.send({errors:[{type: "Unauthorized", msg: "New rank must be below that of the user changing it.", date: new Date()}]});
|
||||
}else if(permissionModel.rankToNum(targetChanRank) >= permissionModel.rankToNum(chanRank)){
|
||||
//If the user is below the original rank of the user they're setting, scream and shout
|
||||
res.status(401);
|
||||
return res.send({errors:[{type: "Unauthorized", msg: "You cannot promote/demote peer/outranking users.", date: new Date()}]});
|
||||
}
|
||||
|
||||
//Set rank
|
||||
var rankList = await chanDB.setRank(userDB, data.rank);
|
||||
|
||||
res.status(200);
|
||||
res.send(rankList);
|
||||
}else{
|
||||
//If we received bad input, we have only one action: bitch, moan, and complain!
|
||||
res.status(400);
|
||||
res.send({errors: validResult.array()})
|
||||
}
|
||||
}catch(err){
|
||||
console.log(err);
|
||||
return exceptionHandler(res, err);
|
||||
}
|
||||
}
|
||||
|
|
@ -19,7 +19,9 @@ const { Router } = require('express');
|
|||
|
||||
//local imports
|
||||
const permissionSchema = require("../../schemas/permissionSchema");
|
||||
const channelModel = require("../../schemas/channel/channelSchema");
|
||||
const {channelValidator} = require("../../validators/channelValidator");
|
||||
const {accountValidator} = require("../../validators/accountValidator");
|
||||
const {channelPermissionValidator} = require("../../validators/permissionsValidator");
|
||||
const registerController = require("../../controllers/api/channel/registerController");
|
||||
const listController = require("../../controllers/api/channel/listController");
|
||||
|
|
@ -33,17 +35,19 @@ const router = Router();
|
|||
|
||||
//user authentication middleware
|
||||
router.use("/register",permissionSchema.reqPermCheck("registerChannel"));
|
||||
router.use("/delete",permissionSchema.reqPermCheck("deleteChannel"));
|
||||
router.use("/settings",permissionSchema.reqPermCheck("manageChannel"));
|
||||
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"));
|
||||
|
||||
//routing functions
|
||||
router.post('/register', channelValidator.name(), channelValidator.description(), channelValidator.thumbnail(), registerController.post);
|
||||
router.get('/list', listController.get);
|
||||
router.get('/settings', channelValidator.name('chanName'), settingsController.get);
|
||||
router.post('/settings', channelValidator.name('chanName'), channelValidator.settingsMap(), settingsController.post);
|
||||
router.get('/permissions', channelValidator.name('chanName'), permissionsController.get);
|
||||
router.post('/permissions', channelValidator.name('chanName'), channelPermissionValidator.channelPermissionsMap(), permissionsController.post);
|
||||
router.get('/rank', channelValidator.name('chanName'), rankController.get);
|
||||
router.post('/delete', channelValidator.name('chanName'), channelValidator.name('confirm'),deleteController.post);
|
||||
router.get('/settings', settingsController.get);
|
||||
router.post('/settings', channelValidator.settingsMap(), settingsController.post);
|
||||
router.get('/permissions', permissionsController.get);
|
||||
router.post('/permissions', channelPermissionValidator.channelPermissionsMap(), permissionsController.post);
|
||||
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);
|
||||
|
||||
module.exports = router;
|
||||
|
|
@ -19,7 +19,7 @@ const { Router } = require('express');
|
|||
|
||||
|
||||
//local imports
|
||||
const permissionSchema = require("../schemas/permissionSchema");
|
||||
const channelModel = require("../schemas/channel/channelSchema");
|
||||
const channelController = require("../controllers/channelController");
|
||||
const channelSettingsController = require("../controllers/channelSettingsController");
|
||||
|
||||
|
|
@ -27,7 +27,7 @@ const channelSettingsController = require("../controllers/channelSettingsControl
|
|||
const router = Router();
|
||||
|
||||
//User authentication middleware
|
||||
router.use("/*/settings",permissionSchema.reqPermCheck("manageChannel"));
|
||||
router.use("/*/settings",channelModel.reqPermCheck("manageChannel","/c/"));
|
||||
|
||||
//routing functions
|
||||
router.get('/*/settings', channelSettingsController.get);
|
||||
|
|
|
|||
|
|
@ -16,11 +16,14 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
|||
|
||||
//NPM Imports
|
||||
const {mongoose} = require('mongoose');
|
||||
const {validationResult, matchedData} = require('express-validator');
|
||||
|
||||
//Local Imports
|
||||
const statModel = require('../statSchema.js');
|
||||
const userModel = require('../userSchema.js');
|
||||
const permissionModel = require('../permissionSchema.js');
|
||||
const channelPermissionSchema = require('./channelPermissionSchema.js');
|
||||
const { exceptionHandler } = require('../../utils/loggerUtils.js');
|
||||
|
||||
const channelSchema = new mongoose.Schema({
|
||||
id: {
|
||||
|
|
@ -118,6 +121,56 @@ channelSchema.statics.getChannelList = async function(includeHidden = false){
|
|||
return chanGuide;
|
||||
}
|
||||
|
||||
//Middleware for rank checks
|
||||
//Man, it would be really nice if express middleware actually supported async functions, you know, as if it where't still 2015 >:(
|
||||
//Also holy shit, sharing a function between two middleware functions is a nightmare
|
||||
//I'd rather just have this check chanField for '/c/' to handle channels in URL, fuck me this was obnoxious to write
|
||||
channelSchema.statics.reqPermCheck = function(perm, chanField = "chanName"){
|
||||
return (req, res, next)=>{
|
||||
try{
|
||||
//Check validation result
|
||||
const validResult = validationResult(req);
|
||||
|
||||
//if our chan field is set to '/c/', telling us to check the URL
|
||||
if(chanField == '/c/'){
|
||||
//Rip the chan name out of the URL
|
||||
var chanName = (req.originalUrl.split('/c/')[1].replace('/settings',''));
|
||||
}else if(validResult.isEmpty()){
|
||||
//otherwise if our input is valid, use that
|
||||
var chanName = matchedData(req)[chanField];
|
||||
}else{
|
||||
//We didn't get /c/ and we got a bad input, time for shit to hit the fan!
|
||||
res.status(400);
|
||||
return res.send({errors: validResult.array()})
|
||||
}
|
||||
|
||||
//Find the related channel document, and handle it using a then() block
|
||||
this.findOne({name: chanName}).then((chanDB) => {
|
||||
//If we didnt find a channel
|
||||
if(chanDB == null){
|
||||
//FUCK
|
||||
res.status(401);
|
||||
return res.send({error:`Cannot perm check non-existant channel!.`});
|
||||
}
|
||||
|
||||
//Run a perm check against the current user and permission
|
||||
chanDB.permCheck(req.session.user, perm).then((permitted) => {
|
||||
if(permitted){
|
||||
//if we're permitted, go on to fulfill the request
|
||||
next();
|
||||
}else{
|
||||
//If not, prevent the request from going through and tell them why
|
||||
res.status(401);
|
||||
return res.send({error:`You do not have a high enough rank to access this resource.`});
|
||||
}
|
||||
});
|
||||
});
|
||||
}catch(err){
|
||||
return exceptionHandler(res, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//methods
|
||||
channelSchema.methods.updateSettings = async function(settingsMap){
|
||||
settingsMap.forEach((value, key) => {
|
||||
|
|
@ -133,37 +186,140 @@ channelSchema.methods.updateSettings = async function(settingsMap){
|
|||
return this.settings;
|
||||
}
|
||||
|
||||
channelSchema.methods.updateChannelPerms = async function(permissionsMap){
|
||||
permissionsMap.forEach((value, key) => {
|
||||
if(this.permissions[key] == null){
|
||||
throw new Error("Invalid channel permission.");
|
||||
channelSchema.methods.rankCrawl = async function(userDB,cb){
|
||||
//Crawl through channel rank list
|
||||
//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);
|
||||
}
|
||||
|
||||
this.permissions[key] = value;
|
||||
})
|
||||
|
||||
await this.save();
|
||||
|
||||
return this.permissions;
|
||||
}else{
|
||||
//in case someone populated the users
|
||||
if(rankObj.user.user == userDB.user){
|
||||
//If we found a match, call back
|
||||
cb(rankObj, rankIndex);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
channelSchema.methods.setUserRank = async function(userDB,rank){
|
||||
channelSchema.methods.setRank = async function(userDB,rank){
|
||||
//Create variable to store found ranks
|
||||
var foundRankIndex = null;
|
||||
|
||||
//Crawl through ranks to find matching index
|
||||
this.rankCrawl(userDB,(rankObj, rankIndex)=>{foundRankIndex = rankIndex});
|
||||
|
||||
//If we found an existing rank object
|
||||
if(foundRankIndex != null){
|
||||
if(rank == "user"){
|
||||
this.rankList.splice(foundRankIndex,1);
|
||||
}else{
|
||||
//otherwise, set the users rank
|
||||
this.rankList[foundRankIndex].rank = rank;
|
||||
}
|
||||
}else if(rank != "user"){
|
||||
//if the user rank object doesn't exist, and we're not setting to user
|
||||
//Create rank object based on input
|
||||
const rankObj = {
|
||||
user: userDB._id,
|
||||
rank: rank
|
||||
}
|
||||
|
||||
//Add it to rank list
|
||||
this.rankList.push(rankObj);
|
||||
}
|
||||
|
||||
|
||||
//Save our channel and return rankList
|
||||
await this.save();
|
||||
return this.rankList;
|
||||
}
|
||||
|
||||
channelSchema.methods.getChannelRankFromUser = async function(userDB){
|
||||
channelSchema.methods.getRankList = async function(){
|
||||
//Create an empty array to hold the user list
|
||||
const rankList = [];
|
||||
|
||||
//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) => {
|
||||
//Create a new user object from rank object data
|
||||
const userObj = {
|
||||
id: rankObj.user.id,
|
||||
user: rankObj.user.user,
|
||||
rank: rankObj.rank
|
||||
}
|
||||
|
||||
//Add our user object to the list
|
||||
rankList.push(userObj);
|
||||
});
|
||||
|
||||
//return userList
|
||||
return rankList;
|
||||
}
|
||||
|
||||
channelSchema.methods.channelPermCheck = async function(user, perm){
|
||||
channelSchema.methods.getChannelRankByUserDoc = async function(userDB = null){
|
||||
var foundRank = null;
|
||||
|
||||
//Check to make sure userDB exists before going forward
|
||||
if(userDB == null){
|
||||
//If so this user is probably not signed in
|
||||
return "anon"
|
||||
}
|
||||
|
||||
//Crawl through ranks to find matching rank
|
||||
this.rankCrawl(userDB,(rankObj)=>{foundRank = rankObj});
|
||||
|
||||
//If we found an existing rank object
|
||||
if(foundRank != null){
|
||||
//return rank
|
||||
return foundRank.rank;
|
||||
}else{
|
||||
//default to "user" for registered users, and "anon" for anonymous
|
||||
if(userDB.rank == "anon"){
|
||||
return "anon";
|
||||
}else{
|
||||
return "user";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
channelSchema.methods.getChannelRank = async function(user){
|
||||
const userDB = await userModel.findOne({user: user.user});
|
||||
return await this.getChannelRankByUserDoc(userDB);
|
||||
}
|
||||
|
||||
channelSchema.methods.permCheckByUserDoc = async function(userDB, perm){
|
||||
//Get site-wide rank as number, default to anon for anonymous users
|
||||
const rank = userDB ? permissionModel.rankToNum(userDB.rank) : permissionModel.rankToNum("anon");
|
||||
//Get channel rank as number
|
||||
const chanRank = permissionModel.rankToNum(await this.getChannelRankByUserDoc(userDB));
|
||||
//Get channel permission rank requirement as number
|
||||
const permRank = permissionModel.rankToNum(this.permissions[perm]);
|
||||
//Get site-wide rank requirement to override as number
|
||||
const overrideRank = permissionModel.rankToNum((await permissionModel.getPerms()).channelOverrides[perm]);
|
||||
//Get channel perm check result
|
||||
const permCheck = (chanRank >= permRank);
|
||||
//Get site-wide override perm check result
|
||||
const overrideCheck = (rank >= overrideRank);
|
||||
|
||||
return (permCheck || overrideCheck);
|
||||
}
|
||||
|
||||
channelSchema.methods.permCheck = async function (user, perm){
|
||||
//Set userDB to null if we wheren't passed a real user
|
||||
if(user != null){
|
||||
var userDB = await userModel.findOne({user: user.user});
|
||||
}else{
|
||||
var userDB = null;
|
||||
}
|
||||
|
||||
return await this.permCheckByUserDoc(userDB, perm)
|
||||
}
|
||||
|
||||
channelSchema.methods.nuke = async function(confirm){
|
||||
|
|
|
|||
|
|
@ -43,18 +43,6 @@ const permissionSchema = new mongoose.Schema({
|
|||
default: "admin",
|
||||
required: true
|
||||
},
|
||||
manageChannel: {
|
||||
type: mongoose.SchemaTypes.String,
|
||||
enum: rankEnum,
|
||||
default: "admin",
|
||||
required: true
|
||||
},
|
||||
deleteChannel: {
|
||||
type: mongoose.SchemaTypes.String,
|
||||
enum: rankEnum,
|
||||
default: "admin",
|
||||
required: true
|
||||
},
|
||||
channelOverrides: {
|
||||
type: channelPermissionSchema,
|
||||
default: () => ({})
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ module.exports.channelValidator = {
|
|||
|
||||
thumbnail: (field = 'thumbnail') => accountValidator.img(field),
|
||||
|
||||
rank: (field = 'rank') => accountValidator.rank(field),
|
||||
|
||||
settingsMap: () => checkExact(checkSchema({
|
||||
'settingsMap.hidden': {
|
||||
optional: true,
|
||||
|
|
|
|||
|
|
@ -45,18 +45,6 @@ module.exports.permissionsValidator = {
|
|||
custom: {
|
||||
options: module.exports.isRank
|
||||
},
|
||||
},
|
||||
'permissionsMap.manageChannel': {
|
||||
optional: true,
|
||||
custom: {
|
||||
options: module.exports.isRank
|
||||
},
|
||||
},
|
||||
'permissionsMap.deleteChannel': {
|
||||
optional: true,
|
||||
custom: {
|
||||
options: module.exports.isRank
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -253,6 +253,23 @@ class canopyAjaxUtils{
|
|||
}
|
||||
}
|
||||
|
||||
async setChannelRank(chanName, user, rank){
|
||||
var response = await fetch(`/api/channel/rank`,{
|
||||
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({chanName, user, rank})
|
||||
});
|
||||
|
||||
if(response.status == 200){
|
||||
return await response.json();
|
||||
}else{
|
||||
utils.ux.displayResponseError(await response.json());
|
||||
}
|
||||
}
|
||||
|
||||
async deleteChannel(chanName, confirm){
|
||||
var response = await fetch(`/api/channel/delete`,{
|
||||
method: "POST",
|
||||
|
|
|
|||
Loading…
Reference in a new issue