mirror of https://gitgud.io/fatchan/jschan.git
commit
475c0df8fc
147 changed files with 2376 additions and 842 deletions
@ -0,0 +1,48 @@ |
||||
'use strict'; |
||||
|
||||
const addStaff = require(__dirname+'/../../models/forms/addstaff.js') |
||||
, dynamicResponse = require(__dirname+'/../../helpers/dynamic.js') |
||||
, config = require(__dirname+'/../../config.js') |
||||
, { Accounts } = require(__dirname+'/../../db/') |
||||
, paramConverter = require(__dirname+'/../../helpers/paramconverter.js') |
||||
, { checkSchema, lengthBody, numberBody, minmaxBody, numberBodyVariable, |
||||
inArrayBody, arrayInBody, existsBody } = require(__dirname+'/../../helpers/schema.js'); |
||||
|
||||
module.exports = { |
||||
|
||||
paramConverter: paramConverter({ |
||||
trimFields: ['username'], |
||||
}), |
||||
|
||||
controller: async (req, res, next) => { |
||||
|
||||
const { globalLimits } = config.get; |
||||
|
||||
const errors = await checkSchema([ |
||||
{ result: existsBody(req.body.username), expected: true, error: 'Missing staff username' }, |
||||
{ result: lengthBody(req.body.username, 0, 50), expected: false, error: 'Username must be 50 characters or less' }, |
||||
{ result: (res.locals.board.owner === req.body.username), expected: false, blocking: true, error: 'User is already board owner' }, |
||||
{ result: (res.locals.board.staff[req.body.username] != null), expected: false, blocking: true, error: 'User is already staff' }, |
||||
{ result: async () => { |
||||
const numAccounts = await Accounts.countUsers([req.body.username]); |
||||
return numAccounts > 0; |
||||
}, expected: true, error: 'User does not exist' }, |
||||
]); |
||||
|
||||
if (errors.length > 0) { |
||||
return dynamicResponse(req, res, 400, 'message', { |
||||
'title': 'Bad request', |
||||
'errors': errors, |
||||
'redirect': req.headers.referer || `/${req.params.board}/manage/staff.html`, |
||||
}); |
||||
} |
||||
|
||||
try { |
||||
await addStaff(req, res, next); |
||||
} catch (err) { |
||||
return next(err); |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
@ -0,0 +1,42 @@ |
||||
'use strict'; |
||||
|
||||
const deleteStaff = require(__dirname+'/../../models/forms/deletestaff.js') |
||||
, dynamicResponse = require(__dirname+'/../../helpers/dynamic.js') |
||||
, paramConverter = require(__dirname+'/../../helpers/paramconverter.js') |
||||
, Permissions = require(__dirname+'/../../helpers/permissions.js') |
||||
, { checkSchema, lengthBody, numberBody, minmaxBody, numberBodyVariable, |
||||
inArrayBody, arrayInBody, existsBody } = require(__dirname+'/../../helpers/schema.js'); |
||||
|
||||
module.exports = { |
||||
|
||||
paramConverter: paramConverter({ |
||||
allowedArrays: ['checkedstaff'], |
||||
}), |
||||
|
||||
controller: async (req, res, next) => { |
||||
|
||||
const errors = await checkSchema([ |
||||
{ result: lengthBody(req.body.checkedstaff, 1), expected: false, error: 'Must select at least one staff to delete' }, |
||||
{ result: existsBody(req.body.checkedstaff) && req.body.checkedstaff.some(s => !res.locals.board.staff[s]), expected: false, error: 'Invalid staff selection' }, |
||||
{ result: existsBody(req.body.checkedstaff) && req.body.checkedstaff.some(s => s === res.locals.board.owner), expected: false, permission: Permissions.ROOT, error: "You can't delete the board owner" }, |
||||
//not really necessary, but its a bit retarded to "delete yourself" as staff this way
|
||||
{ result: existsBody(req.body.checkedstaff) && req.body.checkedstaff.some(s => s === res.locals.user.username), expected: false, error: 'Resign from the accounts page instead' }, |
||||
]); |
||||
|
||||
if (errors.length > 0) { |
||||
return dynamicResponse(req, res, 400, 'message', { |
||||
'title': 'Bad request', |
||||
'errors': errors, |
||||
'redirect': req.headers.referer || `/${req.params.board}/manage/staff.html`, |
||||
}) |
||||
} |
||||
|
||||
try { |
||||
await deleteStaff(req, res, next); |
||||
} catch (err) { |
||||
return next(err); |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
@ -0,0 +1,52 @@ |
||||
'use strict'; |
||||
|
||||
const editAccount = require(__dirname+'/../../models/forms/editaccount.js') |
||||
, { Accounts } = require(__dirname+'/../../db/') |
||||
, alphaNumericRegex = require(__dirname+'/../../helpers/checks/alphanumregex.js') |
||||
, dynamicResponse = require(__dirname+'/../../helpers/dynamic.js') |
||||
, paramConverter = require(__dirname+'/../../helpers/paramconverter.js') |
||||
, Permissions = require(__dirname+'/../../helpers/permissions.js') |
||||
, roleManager = require(__dirname+'/../../helpers/rolemanager.js') |
||||
, { checkSchema, lengthBody, numberBody, minmaxBody, numberBodyVariable, |
||||
inArrayBody, arrayInBody, existsBody } = require(__dirname+'/../../helpers/schema.js'); |
||||
|
||||
module.exports = { |
||||
|
||||
paramConverter: paramConverter({ |
||||
trimFields: ['username'], |
||||
}), |
||||
|
||||
controller: async (req, res, next) => { |
||||
|
||||
const errors = await checkSchema([ |
||||
{ result: existsBody(req.body.username), expected: true, error: 'Missing username' }, |
||||
{ result: lengthBody(req.body.username, 1, 50), expected: false, error: 'Username must be 50 characters or less' }, |
||||
{ result: alphaNumericRegex.test(req.body.username), expected: true, error: 'Username must contain a-z 0-9 only' }, |
||||
{ result: async () => { |
||||
res.locals.editingAccount = await Accounts.findOne(req.body.username); |
||||
return res.locals.editingAccount != null; |
||||
}, expected: true, error: 'Invalid account username' }, |
||||
{ result: (res.locals.user.username === req.body.username), expected: false, error: "You can't edit your own permissions" }, |
||||
{ result: !existsBody(req.body.template) //no template, OR the template is a valid one
|
||||
|| inArrayBody(req.body.template, [roleManager.roles.ANON.base64, roleManager.roles.GLOBAL_STAFF.base64, |
||||
roleManager.roles.ADMIN.base64, roleManager.roles.BOARD_STAFF.base64, roleManager.roles.BOARD_OWNER.base64]), |
||||
expected: true, error: "Invalid template selection" }, |
||||
]); |
||||
|
||||
if (errors.length > 0) { |
||||
return dynamicResponse(req, res, 400, 'message', { |
||||
'title': 'Bad request', |
||||
'errors': errors, |
||||
'redirect': req.headers.referer || `/${req.params.board}/manage/staff.html`, |
||||
}); |
||||
} |
||||
|
||||
try { |
||||
await editAccount(req, res, next); |
||||
} catch (err) { |
||||
return next(err); |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
@ -0,0 +1,42 @@ |
||||
'use strict'; |
||||
|
||||
const editRole = require(__dirname+'/../../models/forms/editrole.js') |
||||
, { Roles } = require(__dirname+'/../../db/') |
||||
, dynamicResponse = require(__dirname+'/../../helpers/dynamic.js') |
||||
, paramConverter = require(__dirname+'/../../helpers/paramconverter.js') |
||||
, { checkSchema, lengthBody, numberBody, minmaxBody, numberBodyVariable, |
||||
inArrayBody, arrayInBody, existsBody } = require(__dirname+'/../../helpers/schema.js'); |
||||
|
||||
module.exports = { |
||||
|
||||
paramConverter: paramConverter({ |
||||
objectIdFields: ['roleid'], |
||||
}), |
||||
|
||||
controller: async (req, res, next) => { |
||||
|
||||
const errors = await checkSchema([ |
||||
{ result: existsBody(req.body.roleid), expected: true, error: 'Missing role id' }, |
||||
{ result: async () => { |
||||
res.locals.editingRole = await Roles.findOne(req.body.roleid); |
||||
return res.locals.editingRole != null && res.locals.editingRole.name !== 'ROOT'; |
||||
}, blocking: true, expected: true, error: "You can't edit this role" }, |
||||
]); |
||||
|
||||
if (errors.length > 0) { |
||||
return dynamicResponse(req, res, 400, 'message', { |
||||
'title': 'Bad request', |
||||
'errors': errors, |
||||
'redirect': req.headers.referer || `/${req.params.board}/manage/roles.html`, |
||||
}); |
||||
} |
||||
|
||||
try { |
||||
await editRole(req, res, next); |
||||
} catch (err) { |
||||
return next(err); |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
@ -0,0 +1,45 @@ |
||||
'use strict'; |
||||
|
||||
const editStaff = require(__dirname+'/../../models/forms/editstaff.js') |
||||
, { Accounts } = require(__dirname+'/../../db/') |
||||
, alphaNumericRegex = require(__dirname+'/../../helpers/checks/alphanumregex.js') |
||||
, dynamicResponse = require(__dirname+'/../../helpers/dynamic.js') |
||||
, paramConverter = require(__dirname+'/../../helpers/paramconverter.js') |
||||
, Permissions = require(__dirname+'/../../helpers/permissions.js') |
||||
, { checkSchema, lengthBody, numberBody, minmaxBody, numberBodyVariable, |
||||
inArrayBody, arrayInBody, existsBody } = require(__dirname+'/../../helpers/schema.js'); |
||||
|
||||
module.exports = { |
||||
|
||||
paramConverter: paramConverter({ |
||||
trimFields: ['username'], |
||||
}), |
||||
|
||||
controller: async (req, res, next) => { |
||||
|
||||
const errors = await checkSchema([ |
||||
{ result: existsBody(req.body.username), expected: true, error: 'Missing username' }, |
||||
{ result: lengthBody(req.body.username, 1, 50), expected: false, error: 'Username must be 50 characters or less' }, |
||||
{ result: alphaNumericRegex.test(req.body.username), expected: true, error: 'Username must contain a-z 0-9 only' }, |
||||
{ result: (res.locals.board.staff[req.body.username] != null), expected: true, error: 'Invalid staff username' }, |
||||
{ result: (req.body.username === res.locals.board.owner), expected: false, error: "You can't edit the permissions of the board owner" }, |
||||
{ result: (res.locals.user.username === req.body.username), expected: false, error: "You can't edit your own permissions" }, |
||||
]); |
||||
|
||||
if (errors.length > 0) { |
||||
return dynamicResponse(req, res, 400, 'message', { |
||||
'title': 'Bad request', |
||||
'errors': errors, |
||||
'redirect': req.headers.referer || `/${req.params.board}/manage/staff.html`, |
||||
}); |
||||
} |
||||
|
||||
try { |
||||
await editStaff(req, res, next); |
||||
} catch (err) { |
||||
return next(err); |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
@ -0,0 +1,46 @@ |
||||
'use strict'; |
||||
|
||||
const Mongo = require(__dirname+'/db.js') |
||||
, db = Mongo.db.collection('roles') |
||||
, cache = require(__dirname+'/../redis.js'); |
||||
|
||||
module.exports = { |
||||
|
||||
db, |
||||
|
||||
findOne: async (id) => { |
||||
//is there any point even caching
|
||||
let role = await cache.get(`role:${id}`); |
||||
if (role) { |
||||
return role; |
||||
} else { |
||||
role = await db.findOne({ '_id': id }); |
||||
if (role) { |
||||
role.permissions = role.permissions.toString('base64'); |
||||
cache.set(`role:${id}`, role); |
||||
} |
||||
} |
||||
return role; |
||||
}, |
||||
|
||||
find: () => { |
||||
return db.find({}).toArray(); |
||||
}, |
||||
|
||||
updateOne: async (id, permissions) => { |
||||
const res = await db.updateOne({ |
||||
'_id': id |
||||
}, { |
||||
'$set': { |
||||
'permissions': Mongo.Binary(permissions.array), |
||||
}, |
||||
}); |
||||
cache.del(`role:${id}`); |
||||
return res; |
||||
}, |
||||
|
||||
deleteAll: () => { |
||||
return db.deleteMany({}); |
||||
}, |
||||
|
||||
}; |
@ -1,26 +1,34 @@ |
||||
'use strict'; |
||||
|
||||
const { Bans } = require(__dirname+'/../../db/') |
||||
, hasPerms = require(__dirname+'/hasperms.js') |
||||
, dynamicResponse = require(__dirname+'/../dynamic.js'); |
||||
, dynamicResponse = require(__dirname+'/../dynamic.js') |
||||
, Permissions = require(__dirname+'/../permissions.js'); |
||||
|
||||
module.exports = async (req, res, next) => { |
||||
|
||||
if (res.locals.permLevel > 1) {//global staff or admin bypass
|
||||
const bans = await Bans.find(res.locals.ip, res.locals.board ? res.locals.board._id : null); |
||||
if (bans && bans.length > 0) { |
||||
const globalBans = bans.filter(ban => { return ban.board === null }); |
||||
if (globalBans.length > 0 || (res.locals.permLevel >= 4 && globalBans.length !== bans.length)) { |
||||
//board staff bypass bans on their own board, but not global bans
|
||||
const unseenBans = bans.filter(b => !b.seen).map(b => b._id); |
||||
await Bans.markSeen(unseenBans); //mark bans as seen
|
||||
bans.forEach(ban => ban.seen = true); //mark seen as true in memory for user viewed ban page
|
||||
return res.status(403).render('ban', { |
||||
bans: bans, |
||||
}); |
||||
} |
||||
} |
||||
//bypass all bans, special permission
|
||||
if (res.locals.permissions.get(Permissions.BYPASS_BANS)) { |
||||
return next(); |
||||
} |
||||
next(); |
||||
|
||||
//fetch bans
|
||||
const banBoard = res.locals.board ? res.locals.board._id : null; //if no board, global bans or "null" board.
|
||||
let bans = await Bans.find(res.locals.ip, banBoard); |
||||
//board staff still bypass bans on their board by default
|
||||
if (res.locals.permissions.get(Permissions.MANAGE_BOARD_GENERAL)) { |
||||
//filter bans to leave only global bans remaining
|
||||
bans = bans.filter(ban => ban.board !== res.locals.board); |
||||
} |
||||
if (bans && bans.length > 0) { |
||||
const unseenBans = bans.filter(b => !b.seen).map(b => b._id); |
||||
await Bans.markSeen(unseenBans); //mark bans as seen
|
||||
bans.forEach(ban => ban.seen = true); //mark seen as true in memory for user viewed ban page
|
||||
//todo: make a dynamicresponse, handle in frontend modal.
|
||||
return res.status(403).render('ban', { |
||||
bans: bans, |
||||
}); |
||||
} |
||||
|
||||
next(); //no bans found
|
||||
|
||||
} |
||||
|
@ -0,0 +1,48 @@ |
||||
'use strict'; |
||||
|
||||
const Permissions = require(__dirname+'/../permissions.js') //needs rename
|
||||
, Permission = require(__dirname+'/../permission.js') |
||||
, roleManager = require(__dirname+'/../rolemanager.js'); |
||||
|
||||
module.exports = (req, res) => { |
||||
|
||||
let calculatedPermissions; |
||||
|
||||
if (req.session && res.locals && res.locals.user) { |
||||
|
||||
//has a session and user, not anon, so their permissions from the db/user instead.
|
||||
const { user } = res.locals; |
||||
calculatedPermissions = new Permission(user.permissions); |
||||
|
||||
//if they are on a board endpoint, also apply the board perms.
|
||||
if (res.locals.board != null) { |
||||
if (res.locals.board.owner === user.username) { |
||||
//they are board owner, give them board owner perms, in this board context
|
||||
calculatedPermissions.set(Permissions.MANAGE_BOARD_OWNER); |
||||
} else if (res.locals.board.staff[user.username] != null) { |
||||
//they are board staff, give them their board level staff perms, OR'd with account/global perms
|
||||
const boardPermissions = new Permission(res.locals.board.staff[user.username].permissions); |
||||
for (let bit of Permissions._MANAGE_BOARD_BITS) { |
||||
const inheritOrGlobal = calculatedPermissions.get(bit) || boardPermissions.get(bit); |
||||
calculatedPermissions.set(bit, inheritOrGlobal); |
||||
} |
||||
} |
||||
//and note, in future since we might need multiple-boards permission checks, we will have to change this.
|
||||
//could even build it with a map for each board, based on their stored permissions in that board, maybe like:
|
||||
//res.locals.boardPermissions[board] = new Permission(res.locals.board.settings.staff[user.username].permissions);
|
||||
//and then the MANAGE_BOARD_OWNER inheritance could be removed, since it should be set immutable
|
||||
//inside the board perms instead. and the existing code would make it for "global" BOs to have the permissions.
|
||||
//so we would remove the "...permissions.set(Permissions.MANAGE_BOARD_OWNER)..." above
|
||||
} |
||||
|
||||
//give ROOT all permission, BOARD_OWNER all MANAGE_BOARD*, etc
|
||||
calculatedPermissions.applyInheritance(); |
||||
|
||||
} else { |
||||
//not logged in, gets default anon permission
|
||||
calculatedPermissions = new Permission(roleManager.roles.ANON.base64); |
||||
} |
||||
|
||||
return calculatedPermissions; |
||||
|
||||
} |
@ -1,8 +1,8 @@ |
||||
'use strict'; |
||||
|
||||
const hasPerms = require(__dirname+'/hasperms.js'); |
||||
const calcPerms = require(__dirname+'/calcperms.js'); |
||||
|
||||
module.exports = (req, res, next) => { |
||||
res.locals.permLevel = hasPerms(req, res); |
||||
res.locals.permissions = calcPerms(req, res); |
||||
next(); |
||||
} |
||||
|
@ -1,20 +0,0 @@ |
||||
'use strict'; |
||||
|
||||
module.exports = (req, res) => { |
||||
if (req.session) { |
||||
const { user } = res.locals; |
||||
if (user != null) { |
||||
if (user.authLevel < 4) { //assigned levels
|
||||
return user.authLevel; |
||||
} |
||||
if (res.locals.board != null) { |
||||
if (res.locals.board.owner === user.username) { |
||||
return 2; //board owner 2
|
||||
} else if (res.locals.board.settings.moderators.includes(user.username) === true) { |
||||
return 3; //board staff 3
|
||||
} |
||||
} |
||||
} |
||||
} |
||||
return 4; //not logged in, not staff or moderator
|
||||
} |
@ -1,18 +1,53 @@ |
||||
'use strict'; |
||||
|
||||
const cache = {}; |
||||
//todo: refactor
|
||||
const Permissions = require(__dirname+'/../permissions.js') |
||||
, dynamicResponse = require(__dirname+'/../dynamic.js') |
||||
, cache = { |
||||
one: {}, all: {}, any: {}, |
||||
}; |
||||
|
||||
module.exports = (requiredLevel) => { |
||||
module.exports = { |
||||
|
||||
return cache[requiredLevel] || (cache[requiredLevel] = function(req, res, next) { |
||||
if (res.locals.permLevel > requiredLevel) { |
||||
return res.status(403).render('message', { |
||||
'title': 'Forbidden', |
||||
'message': 'No Permission', |
||||
'redirect': req.headers.referer || '/' |
||||
}); |
||||
} |
||||
next(); |
||||
}); |
||||
one: (requiredPermission) => { |
||||
return cache.one[requiredPermission] || (cache.one[requiredPermission] = function(req, res, next) { |
||||
if (!res.locals.permissions.get(requiredPermission)) { |
||||
return res.status(403).render('message', { |
||||
'title': 'Forbidden', |
||||
'message': 'No Permission', |
||||
'redirect': req.headers.referer || '/', |
||||
}); |
||||
} |
||||
next(); |
||||
}); |
||||
}, |
||||
|
||||
} |
||||
all: (...requiredPermissions) => { |
||||
//these caches working as intended with arrays?
|
||||
return cache.all[requiredPermissions] || (cache.all[requiredPermissions] = function(req, res, next) { |
||||
if (!res.locals.permissions.hasAll(...requiredPermissions)) { |
||||
return res.status(403).render('message', { |
||||
'title': 'Forbidden', |
||||
'message': 'No Permission', |
||||
'redirect': req.headers.referer || '/', |
||||
}); |
||||
} |
||||
next(); |
||||
}); |
||||
}, |
||||
|
||||
any: (...requiredPermissions) => { |
||||
//these caches working as intended with arrays?
|
||||
return cache.any[requiredPermissions] || (cache.any[requiredPermissions] = function(req, res, next) { |
||||
if (!res.locals.permissions.hasAny(...requiredPermissions)) { |
||||
return res.status(403).render('message', { |
||||
'title': 'Forbidden', |
||||
'message': 'No Permission', |
||||
'redirect': req.headers.referer || '/', |
||||
}); |
||||
} |
||||
next(); |
||||
}); |
||||
}, |
||||
|
||||
}; |
||||
|
@ -0,0 +1,43 @@ |
||||
'use strict'; |
||||
|
||||
const Permissions = require(__dirname+'/permissions.js') |
||||
, PermissionText = require(__dirname+'/permissiontext.js') //todo:combine^
|
||||
, BigBitfield = require('big-bitfield'); |
||||
|
||||
class Permission extends BigBitfield { |
||||
|
||||
constructor(data) { |
||||
super(data); |
||||
} |
||||
|
||||
static permissionEntries = Object.entries(Permissions) |
||||
.filter(e => typeof e[1] === 'number'); |
||||
|
||||
static allPermissions = this.permissionEntries |
||||
.map(e => e[1]); |
||||
|
||||
toJSON() { |
||||
return this.constructor.permissionEntries |
||||
.reduce((acc, entry) => { |
||||
acc[entry[0]] = { |
||||
bit: entry[1], |
||||
state: this.get(entry[1]), |
||||
label: PermissionText[entry[0]].label, |
||||
desc: PermissionText[entry[0]].desc, |
||||
title: PermissionText[entry[0]].title, |
||||
}; |
||||
return acc; |
||||
}, {}); |
||||
} |
||||
|
||||
applyInheritance() { |
||||
if (this.get(Permissions.ROOT)){ //root gets all perms
|
||||
this.setAll(this.constructor.allPermissions); |
||||
} else if (this.get(Permissions.MANAGE_BOARD_OWNER)) { //BOs and "global staff"
|
||||
this.setAll(Permissions._MANAGE_BOARD_BITS); |
||||
} |
||||
} |
||||
|
||||
}; |
||||
|
||||
module.exports = Permission; |
@ -0,0 +1,44 @@ |
||||
'use strict'; |
||||
|
||||
const Permissions = { |
||||
ROOT: 0, |
||||
VIEW_RAW_IP: 1, |
||||
CREATE_BOARD: 2, |
||||
CREATE_ACCOUNT: 3, |
||||
BYPASS_BANS: 4, |
||||
BYPASS_SPAMCHECK: 5, |
||||
BYPASS_RATELIMITS: 6, |
||||
BYPASS_FILTERS: 7, |
||||
MANAGE_GLOBAL_GENERAL: 10, |
||||
MANAGE_GLOBAL_BANS: 11, |
||||
MANAGE_GLOBAL_LOGS: 12, |
||||
MANAGE_GLOBAL_NEWS: 13, |
||||
MANAGE_GLOBAL_BOARDS: 14, |
||||
MANAGE_GLOBAL_SETTINGS: 15, |
||||
MANAGE_GLOBAL_ACCOUNTS: 16, |
||||
MANAGE_GLOBAL_ROLES: 17, |
||||
MANAGE_BOARD_OWNER: 20, |
||||
MANAGE_BOARD_GENERAL: 21, |
||||
MANAGE_BOARD_BANS: 22, |
||||
MANAGE_BOARD_LOGS: 23, |
||||
MANAGE_BOARD_SETTINGS: 24, |
||||
MANAGE_BOARD_CUSTOMISATION: 25, |
||||
MANAGE_BOARD_STAFF: 26, |
||||
_MANAGE_BOARD_BITS: [20,21,22,23,24,25,26], |
||||
USE_MARKDOWN_PINKTEXT: 35, |
||||
USE_MARKDOWN_GREENTEXT: 36, |
||||
USE_MARKDOWN_BOLD: 37, |
||||
USE_MARKDOWN_UNDERLINE: 38, |
||||
USE_MARKDOWN_STRIKETHROUGH: 39, |
||||
USE_MARKDOWN_TITLE: 40, |
||||
USE_MARKDOWN_ITALIC: 41, |
||||
USE_MARKDOWN_SPOILER: 42, |
||||
USE_MARKDOWN_MONO: 43, |
||||
USE_MARKDOWN_CODE: 44, |
||||
USE_MARKDOWN_DETECTED: 45, |
||||
USE_MARKDOWN_LINK: 46, |
||||
USE_MARKDOWN_DICE: 47, |
||||
USE_MARKDOWN_FORTUNE: 48, |
||||
}; |
||||
|
||||
module.exports = Object.seal(Object.freeze(Object.preventExtensions(Permissions))); |
@ -0,0 +1,42 @@ |
||||
'use strict'; |
||||
|
||||
//todo: merge in permissions.js
|
||||
module.exports = { |
||||
ROOT: { title: 'Root', label: 'Root', desc: 'Full control. Use with caution!' }, |
||||
VIEW_RAW_IP: { title: 'Raw IPs', label: 'View Raw IPs', desc: 'Ability to see raw IPs in moderation interfaces.' }, |
||||
CREATE_BOARD: { title: 'Create', label: 'Create Board', desc: 'Ability to create new boards.' }, |
||||
CREATE_ACCOUNT: { label: 'Create Account', desc: 'Ability to register an account.' }, |
||||
BYPASS_BANS: { title: 'Bypasses', label: 'Bypass Bans', desc: 'Bypass all bans.' }, |
||||
BYPASS_SPAMCHECK: { label: 'Bypass Spamcheck', desc: 'Bypass the basic anti-flood spamcheck for too frequent similar posting.' }, |
||||
BYPASS_RATELIMITS: { label: 'Bypass Ratelimits', desc: 'Bypass ratelimits for getting new captchas, editing posts, editing board settings, etc.' }, |
||||
BYPASS_FILTERS: { label: 'Bypass Filters', desc: 'Bypass all post filters.' }, |
||||
MANAGE_GLOBAL_GENERAL: { title: 'Global Management',label: 'Global Staff', desc: 'General global staff permission. Access to recent posts and reports. Ability to submit global actions.' }, |
||||
MANAGE_GLOBAL_BANS: { label: 'Global Bans', desc: 'Access global bans. Ability to unban, edit, or deny appeals.' }, |
||||
MANAGE_GLOBAL_LOGS: { label: 'Global Logs', desc: 'Access global logs. Ability to search/filter' }, |
||||
MANAGE_GLOBAL_NEWS: { label: 'News', desc: 'Access news posting. Ability to add, edit, or delete newsposts.' }, |
||||
MANAGE_GLOBAL_BOARDS: { label: 'Boards', desc: 'Access the global board list. Ability to search/filter. Also grants the ability to transfer or delete any board.' }, |
||||
MANAGE_GLOBAL_SETTINGS: { label: 'Global Settings', desc: 'Access global settings. Ability to change any settings.' }, |
||||
MANAGE_GLOBAL_ACCOUNTS: { label: 'Accounts', desc: 'Access the accounts list. Ability to search/sort. Ability to edit permissions of any user. Can only be given by somebody else with "Root" permission.' }, //view, delete, change account permissions
|
||||
MANAGE_GLOBAL_ROLES: { label: 'Roles', desc: 'Access roles list. Ability to edit roles. Can only be given by somebody else with "Root" permission.' }, //view and edit roles
|
||||
MANAGE_BOARD_OWNER: { title: 'Board Management', label: 'Board Owner', desc: 'Full control of the board, equivalent to the BO. Can delete and/or transfer the board. Can only be given by somebody else with "Board Owner" permission. Use with caution!' }, |
||||
MANAGE_BOARD_GENERAL: { label: 'Board Staff', desc: 'General board staff permission. Access mod index, catalog, recent posts and reports. Ability to submit mod actions. Bypass board-specific bans and post filters.' }, |
||||
MANAGE_BOARD_BANS: { label: 'Bans', desc: 'Access board bans. Ability to unban, edit, or deny appeals.' }, |
||||
MANAGE_BOARD_LOGS: { label: 'Logs', desc: 'Access board logs. Ability to search/filter.' }, |
||||
MANAGE_BOARD_SETTINGS: { label: 'Settings', desc: 'Access board settings. Ability to change any settings. Settings page will show transfer/delete forms for those with "Board Owner" permission.' }, |
||||
MANAGE_BOARD_CUSTOMISATION: { label: 'Customisation', desc: 'Access to board assets and custompages. Ability to upload, create, edit, delete.' }, |
||||
MANAGE_BOARD_STAFF: { label: 'Staff', desc: 'Access to staff management, and ability to add or remove permissions from others. Can only be given by somebody else with "Board Owner" permission. Use with caution!' }, |
||||
USE_MARKDOWN_PINKTEXT: { title: 'Post styling', label: 'Pinktext', desc: 'Use pinktext' }, |
||||
USE_MARKDOWN_GREENTEXT: { label: 'Greentext', desc: 'Use greentext' }, |
||||
USE_MARKDOWN_BOLD: { label: 'Bold', desc: 'Use bold' }, |
||||
USE_MARKDOWN_UNDERLINE: { label: 'Underline', desc: 'Use underline' }, |
||||
USE_MARKDOWN_STRIKETHROUGH: { label: 'Strikethrough', desc: 'Use strikethrough' }, |
||||
USE_MARKDOWN_TITLE: { label: 'Title', desc: 'Use titles' }, |
||||
USE_MARKDOWN_ITALIC: { label: 'Italic', desc: 'Use italics' }, |
||||
USE_MARKDOWN_SPOILER: { label: 'Spoiler', desc: 'Use spoilers' }, |
||||
USE_MARKDOWN_MONO: { label: 'Inline Monospace', desc: 'Use inline monospace' }, |
||||
USE_MARKDOWN_CODE: { label: 'Code Block', desc: 'Use code blocks' }, |
||||
USE_MARKDOWN_DETECTED: { label: 'Detected', desc: 'Use detected' }, |
||||
USE_MARKDOWN_LINK: { label: 'Links', desc: 'Make links clickable' }, |
||||
USE_MARKDOWN_DICE: { label: 'Dice Roll', desc: 'Use dice rolls' }, |
||||
USE_MARKDOWN_FORTUNE: { label: 'Fortune', desc: 'Use fortunes' }, |
||||
}; |
@ -0,0 +1,39 @@ |
||||
'use strict'; |
||||
|
||||
const { Roles } = require(__dirname+'/../db/') |
||||
, { Binary } = require(__dirname+'/../db/db.js') |
||||
, redis = require(__dirname+'/../redis.js') |
||||
, Permissions = require(__dirname+'/permissions.js') |
||||
, Permission = require(__dirname+'/permission.js'); |
||||
|
||||
const load = async () => { |
||||
|
||||
//todo: take a message argument from callback
|
||||
//maybe make it a separate func just for reloading single role?
|
||||
|
||||
let roles = await Roles.find(); |
||||
roles = roles.reduce((acc, r) => { |
||||
acc[r.name] = new Permission(r.permissions.toString('base64')); |
||||
return acc; |
||||
}, {}); |
||||
|
||||
module.exports.roles = roles; |
||||
|
||||
module.exports.roleNameMap = { |
||||
[roles.ANON.base64]: 'Regular User', |
||||
[roles.BOARD_STAFF.base64]: 'Board Staff', |
||||
[roles.BOARD_OWNER.base64]: 'Board Owner', |
||||
[roles.GLOBAL_STAFF.base64]: 'Global Staff', |
||||
[roles.ADMIN.base64]: 'Admin', |
||||
[roles.ROOT.base64]: 'Root', |
||||
}; |
||||
|
||||
}; |
||||
|
||||
redis.addCallback('roles', load); |
||||
|
||||
module.exports = { |
||||
roles: {}, |
||||
roleNameMap: {}, |
||||
load, |
||||
}; |
@ -0,0 +1,20 @@ |
||||
'use strict'; |
||||
|
||||
const { Boards, Accounts } = require(__dirname+'/../../db/') |
||||
, dynamicResponse = require(__dirname+'/../../helpers/dynamic.js') |
||||
, roleManager = require(__dirname+'/../../helpers/rolemanager.js'); |
||||
|
||||
module.exports = async (req, res, next) => { |
||||
|
||||
await Promise.all([ |
||||
Accounts.addStaffBoard([req.body.username], res.locals.board._id), |
||||
Boards.addStaff(res.locals.board._id, req.body.username, roleManager.roles.BOARD_STAFF) |
||||
]); |
||||
|
||||
return dynamicResponse(req, res, 200, 'message', { |
||||
'title': 'Success', |
||||
'message': 'Added staff', |
||||
'redirect': `/${req.params.board}/manage/staff.html`, |
||||
}); |
||||
|
||||
} |
@ -0,0 +1,66 @@ |
||||
'use strict'; |
||||
|
||||
const { Accounts, Boards } = require(__dirname+'/../../db/') |
||||
, dynamicResponse = require(__dirname+'/../../helpers/dynamic.js') |
||||
, cache = require(__dirname+'/../../redis.js'); |
||||
|
||||
module.exports = async (req, res, next) => { |
||||
|
||||
const accountsWithBoards = await Accounts.getOwnedOrStaffBoards(req.body.checkedaccounts); |
||||
if (accountsWithBoards.length > 0) { |
||||
const bulkWrites = []; |
||||
for (let i = 0; i < accountsWithBoards.length; i++) { |
||||
const acc = accountsWithBoards[i]; |
||||
if (acc.staffBoards.length > 0) { |
||||
//remove from staff of any boards they are mod on
|
||||
bulkWrites.push({ |
||||
'updateMany': { |
||||
'filter': { |
||||
'_id': { |
||||
'$in': acc.staffBoards |
||||
} |
||||
}, |
||||
'update': { |
||||
'$unset': { |
||||
[`staff.${acc.username}`]: "", |
||||
} |
||||
} |
||||
} |
||||
}); |
||||
cache.del(acc.staffBoards.map(b => `board:${b}`)); |
||||
} |
||||
if (acc.ownedBoards.length > 0) { |
||||
//remove as owner of any boards they own
|
||||
bulkWrites.push({ |
||||
'updateMany': { |
||||
'filter': { |
||||
'_id': { |
||||
'$in': acc.ownedBoards |
||||
} |
||||
}, |
||||
'update': { |
||||
'$set': { |
||||
'owner': null, |
||||
}, |
||||
'$unset': { |
||||
[`staff.${acc.username}`]: "", |
||||
}, |
||||
} |
||||
} |
||||
}); |
||||
cache.del(acc.ownedBoards.map(b => `board:${b}`)); |
||||
//todo: use list of board with no owners for claims
|
||||
} |
||||
} |
||||
await Boards.db.bulkWrite(bulkWrites); |
||||
} |
||||
|
||||
const amount = await Accounts.deleteMany(req.body.checkedaccounts).then(res => res.deletedCount); |
||||
|
||||
return dynamicResponse(req, res, 200, 'message', { |
||||
'title': 'Success', |
||||
'message': `${req.body.delete_account ? 'Deleted' : 'Edited'} ${amount} accounts`, |
||||
'redirect': '/globalmanage/accounts.html' |
||||
}); |
||||
|
||||
} |
@ -0,0 +1,24 @@ |
||||
'use strict'; |
||||
|
||||
const { Boards, Accounts } = require(__dirname+'/../../db/') |
||||
, dynamicResponse = require(__dirname+'/../../helpers/dynamic.js'); |
||||
|
||||
module.exports = async (req, res, next) => { |
||||
|
||||
//only a ROOT could do this, per the permission bypass in the controller
|
||||
const deletingBoardOwner = req.body.checkedstaff.some(s => s === res.locals.board.owner); |
||||
|
||||
await Promise.all([ |
||||
Accounts.removeStaffBoard(req.body.checkedstaff, res.locals.board._id), |
||||
Boards.removeStaff(res.locals.board._id, req.body.checkedstaff), |
||||
deletingBoardOwner ? Accounts.removeOwnedBoard(res.locals.board.owner, res.locals.board._id) : void 0, |
||||
deletingBoardOwner ? Boards.setOwner(res.locals.board._id, null) : void 0, |
||||
]); |
||||
|
||||
return dynamicResponse(req, res, 200, 'message', { |
||||
'title': 'Success', |
||||
'message': 'Deleted staff', |
||||
'redirect': `/${req.params.board}/manage/staff.html`, |
||||
}); |
||||
|
||||
} |
@ -0,0 +1,74 @@ |
||||
'use strict'; |
||||
|
||||
const { Accounts } = require(__dirname+'/../../db/') |
||||
, dynamicResponse = require(__dirname+'/../../helpers/dynamic.js') |
||||
, Permissions = require(__dirname+'/../../helpers/permissions.js') |
||||
, Permission = require(__dirname+'/../../helpers/permission.js'); |
||||
|
||||
module.exports = async (req, res, next) => { |
||||
|
||||
let updatingPermissions; |
||||
|
||||
if (req.body.template) { |
||||
updatingPermissions = new Permission(req.body.template); |
||||
} else { |
||||
updatingPermissions = new Permission(res.locals.editingAccount.permissions); |
||||
updatingPermissions.set(Permissions.VIEW_RAW_IP, (req.body.VIEW_RAW_IP != null)); |
||||
updatingPermissions.set(Permissions.CREATE_BOARD, (req.body.CREATE_BOARD != null)); |
||||
updatingPermissions.set(Permissions.CREATE_ACCOUNT, (req.body.CREATE_ACCOUNT != null)); |
||||
updatingPermissions.set(Permissions.BYPASS_BANS, (req.body.BYPASS_BANS != null)); |
||||
updatingPermissions.set(Permissions.BYPASS_SPAMCHECK, (req.body.BYPASS_SPAMCHECK != null)); |
||||
updatingPermissions.set(Permissions.BYPASS_RATELIMITS, (req.body.BYPASS_RATELIMITS != null)); |
||||
updatingPermissions.set(Permissions.BYPASS_FILTERS, (req.body.BYPASS_FILTERS != null)); |
||||
updatingPermissions.set(Permissions.MANAGE_GLOBAL_GENERAL, (req.body.MANAGE_GLOBAL_GENERAL != null)); |
||||
updatingPermissions.set(Permissions.MANAGE_GLOBAL_BANS, (req.body.MANAGE_GLOBAL_BANS != null)); |
||||
updatingPermissions.set(Permissions.MANAGE_GLOBAL_LOGS, (req.body.MANAGE_GLOBAL_LOGS != null)); |
||||
updatingPermissions.set(Permissions.MANAGE_GLOBAL_NEWS, (req.body.MANAGE_GLOBAL_NEWS != null)); |
||||
updatingPermissions.set(Permissions.MANAGE_GLOBAL_BOARDS, (req.body.MANAGE_GLOBAL_BOARDS != null)); |
||||
updatingPermissions.set(Permissions.MANAGE_GLOBAL_SETTINGS, (req.body.MANAGE_GLOBAL_SETTINGS != null)); |
||||
updatingPermissions.set(Permissions.MANAGE_BOARD_GENERAL, (req.body.MANAGE_BOARD_GENERAL != null)); |
||||
updatingPermissions.set(Permissions.MANAGE_BOARD_OWNER, (req.body.MANAGE_BOARD_OWNER != null)); |
||||
updatingPermissions.set(Permissions.MANAGE_BOARD_BANS, (req.body.MANAGE_BOARD_BANS != null)); |
||||
updatingPermissions.set(Permissions.MANAGE_BOARD_LOGS, (req.body.MANAGE_BOARD_LOGS != null)); |
||||
updatingPermissions.set(Permissions.MANAGE_BOARD_SETTINGS, (req.body.MANAGE_BOARD_SETTINGS != null)); |
||||
updatingPermissions.set(Permissions.MANAGE_BOARD_CUSTOMISATION, (req.body.MANAGE_BOARD_CUSTOMISATION != null)); |
||||
updatingPermissions.set(Permissions.MANAGE_BOARD_STAFF, (req.body.MANAGE_BOARD_STAFF != null)); |
||||
updatingPermissions.set(Permissions.USE_MARKDOWN_PINKTEXT, (req.body.USE_MARKDOWN_PINKTEXT != null)); |
||||
updatingPermissions.set(Permissions.USE_MARKDOWN_GREENTEXT, (req.body.USE_MARKDOWN_GREENTEXT != null)); |
||||
updatingPermissions.set(Permissions.USE_MARKDOWN_BOLD, (req.body.USE_MARKDOWN_BOLD != null)); |
||||
updatingPermissions.set(Permissions.USE_MARKDOWN_UNDERLINE, (req.body.USE_MARKDOWN_UNDERLINE != null)); |
||||
updatingPermissions.set(Permissions.USE_MARKDOWN_STRIKETHROUGH, (req.body.USE_MARKDOWN_STRIKETHROUGH != null)); |
||||
updatingPermissions.set(Permissions.USE_MARKDOWN_TITLE, (req.body.USE_MARKDOWN_TITLE != null)); |
||||
updatingPermissions.set(Permissions.USE_MARKDOWN_ITALIC, (req.body.USE_MARKDOWN_ITALIC != null)); |
||||
updatingPermissions.set(Permissions.USE_MARKDOWN_SPOILER, (req.body.USE_MARKDOWN_SPOILER != null)); |
||||
updatingPermissions.set(Permissions.USE_MARKDOWN_MONO, (req.body.USE_MARKDOWN_MONO != null)); |
||||
updatingPermissions.set(Permissions.USE_MARKDOWN_CODE, (req.body.USE_MARKDOWN_CODE != null)); |
||||
updatingPermissions.set(Permissions.USE_MARKDOWN_DETECTED, (req.body.USE_MARKDOWN_DETECTED != null)); |
||||
updatingPermissions.set(Permissions.USE_MARKDOWN_LINK, (req.body.USE_MARKDOWN_LINK != null)); |
||||
updatingPermissions.set(Permissions.USE_MARKDOWN_DICE, (req.body.USE_MARKDOWN_DICE != null)); |
||||
updatingPermissions.set(Permissions.USE_MARKDOWN_FORTUNE, (req.body.USE_MARKDOWN_FORTUNE != null)); |
||||
if (res.locals.permissions.get(Permissions.ROOT)) { |
||||
updatingPermissions.set(Permissions.MANAGE_GLOBAL_ACCOUNTS, (req.body.MANAGE_GLOBAL_ACCOUNTS != null)) |
||||
updatingPermissions.set(Permissions.MANAGE_GLOBAL_ROLES, (req.body.MANAGE_GLOBAL_ROLES != null)) |
||||
updatingPermissions.set(Permissions.ROOT, (req.body.ROOT != null)); |
||||
} |
||||
} |
||||
updatingPermissions.applyInheritance(); |
||||
|
||||
const updated = await Accounts.setAccountPermissions(req.body.username, updatingPermissions).then(r => r.matchedCount); |
||||
|
||||
if (updated === 0) { |
||||
return dynamicResponse(req, res, 400, 'message', { |
||||
'title': 'Bad request', |
||||
'errors': 'Account does not exist', |
||||
'redirect': req.headers.referer || `/globalmanage/accounts.html`, |
||||
}); |
||||
} |
||||
|
||||
return dynamicResponse(req, res, 200, 'message', { |
||||
'title': 'Success', |
||||
'message': 'Edited account', |
||||
'redirect': `/globalmanage/editaccount/${req.body.username}.html`, |
||||
}); |
||||
|
||||
} |
@ -1,68 +0,0 @@ |
||||
'use strict'; |
||||
|
||||
const { Accounts, Boards } = require(__dirname+'/../../db/') |
||||
, dynamicResponse = require(__dirname+'/../../helpers/dynamic.js') |
||||
, cache = require(__dirname+'/../../redis.js') |
||||
|
||||
module.exports = async (req, res, next) => { |
||||
|
||||
//edit the accounts
|
||||
let amount = 0; |
||||
if (req.body.delete_account) { |
||||
const accountsWithBoards = await Accounts.getOwnedOrModBoards(req.body.checkedaccounts); |
||||
if (accountsWithBoards.length > 0) { |
||||
const bulkWrites = []; |
||||
for (let i = 0; i < accountsWithBoards.length; i++) { |
||||
const acc = accountsWithBoards[i]; |
||||
if (acc.modBoards.length > 0) { |
||||
//remove from moderators of any boards they are mod on
|
||||
bulkWrites.push({ |
||||
'updateMany': { |
||||
'filter': { |
||||
'_id': { |
||||
'$in': acc.modBoards |
||||
} |
||||
}, |
||||
'update': { |
||||
'$pull': { |
||||
'settings.moderators': acc._id |
||||
} |
||||
} |
||||
} |
||||
}); |
||||
cache.del(acc.modBoards.map(b => `board:${b}`)); |
||||
} |
||||
if (acc.ownedBoards.length > 0) { |
||||
//remove from moderators of any boards they are mod on
|
||||
bulkWrites.push({ |
||||
'updateMany': { |
||||
'filter': { |
||||
'_id': { |
||||
'$in': acc.ownedBoards |
||||
} |
||||
}, |
||||
'update': { |
||||
'$set': { |
||||
'owner': null //board has no owner
|
||||
} |
||||
} |
||||
} |
||||
}); |
||||
cache.del(acc.ownedBoards.map(b => `board:${b}`)); |
||||
//todo: use list of board with no owners for claims
|
||||
} |
||||
} |
||||
await Boards.db.bulkWrite(bulkWrites); |
||||
} |
||||
amount = await Accounts.deleteMany(req.body.checkedaccounts).then(res => res.deletedCount); |
||||
} else { |
||||
amount = await Accounts.setLevel(req.body.checkedaccounts, req.body.auth_level).then(res => res.modifiedCount); |
||||
} |
||||
|
||||
return dynamicResponse(req, res, 200, 'message', { |
||||
'title': 'Success', |
||||
'message': `${req.body.delete_account ? 'Deleted' : 'Edited'} ${amount} accounts`, |
||||
'redirect': '/globalmanage/accounts.html' |
||||
}); |
||||
|
||||
} |
@ -0,0 +1,85 @@ |
||||
'use strict'; |
||||
|
||||
const { Roles, Accounts } = require(__dirname+'/../../db/') |
||||
, { Binary } = require(__dirname+'/../../db/db.js') |
||||
, redis = require(__dirname+'/../../redis.js') |
||||
, dynamicResponse = require(__dirname+'/../../helpers/dynamic.js') |
||||
, roleManager = require(__dirname+'/../../helpers/rolemanager.js') |
||||
, Permissions = require(__dirname+'/../../helpers/permissions.js') |
||||
, Permission = require(__dirname+'/../../helpers/permission.js'); |
||||
|
||||
module.exports = async (req, res, next) => { |
||||
|
||||
let rolePermissions = new Permission(res.locals.editingRole.permissions); |
||||
rolePermissions.set(Permissions.VIEW_RAW_IP, (req.body.VIEW_RAW_IP != null)); |
||||
rolePermissions.set(Permissions.CREATE_BOARD, (req.body.CREATE_BOARD != null)); |
||||
rolePermissions.set(Permissions.CREATE_ACCOUNT, (req.body.CREATE_ACCOUNT != null)); |
||||
rolePermissions.set(Permissions.BYPASS_BANS, (req.body.BYPASS_BANS != null)); |
||||
rolePermissions.set(Permissions.BYPASS_SPAMCHECK, (req.body.BYPASS_SPAMCHECK != null)); |
||||
rolePermissions.set(Permissions.BYPASS_RATELIMITS, (req.body.BYPASS_RATELIMITS != null)); |
||||
rolePermissions.set(Permissions.BYPASS_FILTERS, (req.body.BYPASS_FILTERS != null)); |
||||
rolePermissions.set(Permissions.MANAGE_GLOBAL_GENERAL, (req.body.MANAGE_GLOBAL_GENERAL != null)); |
||||
rolePermissions.set(Permissions.MANAGE_GLOBAL_BANS, (req.body.MANAGE_GLOBAL_BANS != null)); |
||||
rolePermissions.set(Permissions.MANAGE_GLOBAL_LOGS, (req.body.MANAGE_GLOBAL_LOGS != null)); |
||||
rolePermissions.set(Permissions.MANAGE_GLOBAL_NEWS, (req.body.MANAGE_GLOBAL_NEWS != null)); |
||||
rolePermissions.set(Permissions.MANAGE_GLOBAL_BOARDS, (req.body.MANAGE_GLOBAL_BOARDS != null)); |
||||
rolePermissions.set(Permissions.MANAGE_GLOBAL_SETTINGS, (req.body.MANAGE_GLOBAL_SETTINGS != null)); |
||||
rolePermissions.set(Permissions.MANAGE_BOARD_GENERAL, (req.body.MANAGE_BOARD_GENERAL != null)); |
||||
rolePermissions.set(Permissions.MANAGE_BOARD_OWNER, (req.body.MANAGE_BOARD_OWNER != null)); |
||||
rolePermissions.set(Permissions.MANAGE_BOARD_BANS, (req.body.MANAGE_BOARD_BANS != null)); |
||||
rolePermissions.set(Permissions.MANAGE_BOARD_LOGS, (req.body.MANAGE_BOARD_LOGS != null)); |
||||
rolePermissions.set(Permissions.MANAGE_BOARD_SETTINGS, (req.body.MANAGE_BOARD_SETTINGS != null)); |
||||
rolePermissions.set(Permissions.MANAGE_BOARD_CUSTOMISATION, (req.body.MANAGE_BOARD_CUSTOMISATION != null)); |
||||
rolePermissions.set(Permissions.MANAGE_BOARD_STAFF, (req.body.MANAGE_BOARD_STAFF != null)); |
||||
rolePermissions.set(Permissions.USE_MARKDOWN_PINKTEXT, (req.body.USE_MARKDOWN_PINKTEXT != null)); |
||||
rolePermissions.set(Permissions.USE_MARKDOWN_GREENTEXT, (req.body.USE_MARKDOWN_GREENTEXT != null)); |
||||
rolePermissions.set(Permissions.USE_MARKDOWN_BOLD, (req.body.USE_MARKDOWN_BOLD != null)); |
||||
rolePermissions.set(Permissions.USE_MARKDOWN_UNDERLINE, (req.body.USE_MARKDOWN_UNDERLINE != null)); |
||||
rolePermissions.set(Permissions.USE_MARKDOWN_STRIKETHROUGH, (req.body.USE_MARKDOWN_STRIKETHROUGH != null)); |
||||
rolePermissions.set(Permissions.USE_MARKDOWN_TITLE, (req.body.USE_MARKDOWN_TITLE != null)); |
||||
rolePermissions.set(Permissions.USE_MARKDOWN_ITALIC, (req.body.USE_MARKDOWN_ITALIC != null)); |
||||
rolePermissions.set(Permissions.USE_MARKDOWN_SPOILER, (req.body.USE_MARKDOWN_SPOILER != null)); |
||||
rolePermissions.set(Permissions.USE_MARKDOWN_MONO, (req.body.USE_MARKDOWN_MONO != null)); |
||||
rolePermissions.set(Permissions.USE_MARKDOWN_CODE, (req.body.USE_MARKDOWN_CODE != null)); |
||||
rolePermissions.set(Permissions.USE_MARKDOWN_DETECTED, (req.body.USE_MARKDOWN_DETECTED != null)); |
||||
rolePermissions.set(Permissions.USE_MARKDOWN_LINK, (req.body.USE_MARKDOWN_LINK != null)); |
||||
rolePermissions.set(Permissions.USE_MARKDOWN_DICE, (req.body.USE_MARKDOWN_DICE != null)); |
||||
rolePermissions.set(Permissions.USE_MARKDOWN_FORTUNE, (req.body.USE_MARKDOWN_FORTUNE != null)); |
||||
if (res.locals.permissions.get(Permissions.ROOT)) { |
||||
rolePermissions.set(Permissions.MANAGE_GLOBAL_ACCOUNTS, (req.body.MANAGE_GLOBAL_ACCOUNTS != null)) |
||||
rolePermissions.set(Permissions.MANAGE_GLOBAL_ROLES, (req.body.MANAGE_GLOBAL_ROLES != null)) |
||||
rolePermissions.set(Permissions.ROOT, (req.body.ROOT != null)); |
||||
} |
||||
rolePermissions.applyInheritance(); |
||||
|
||||
const existingRoleName = roleManager.roleNameMap[rolePermissions.base64] |
||||
if (existingRoleName) { |
||||
return dynamicResponse(req, res, 409, 'message', { |
||||
'title': 'Conflict', |
||||
'error': `Another role already exists with those same permissions: "${existingRoleName}"`, |
||||
'redirect': req.headers.referer || `/globalmanage/roles.html`, |
||||
}); |
||||
} |
||||
|
||||
const updated = await Roles.updateOne(req.body.roleid, rolePermissions).then(r => r.matchedCount); |
||||
|
||||
if (updated === 0) { |
||||
return dynamicResponse(req, res, 400, 'message', { |
||||
'title': 'Bad request', |
||||
'error': 'Role does not exist', |
||||
'redirect': req.headers.referer || `/globalmanage/roles.html`, |
||||
}); |
||||
} |
||||
|
||||
const oldPermissions = new Permission(res.locals.editingRole.permissions); |
||||
await Accounts.setNewRolePermissions(oldPermissions, rolePermissions) |
||||
|
||||
redis.redisPublisher.publish('roles', null); |
||||
|
||||
return dynamicResponse(req, res, 200, 'message', { |
||||
'title': 'Success', |
||||
'message': 'Edited role', |
||||
'redirect': `/globalmanage/editrole/${req.body.roleid}.html`, |
||||
}); |
||||
|
||||
} |
@ -0,0 +1,40 @@ |
||||
'use strict'; |
||||
|
||||
const { Boards } = require(__dirname+'/../../db/') |
||||
, dynamicResponse = require(__dirname+'/../../helpers/dynamic.js') |
||||
, Permissions = require(__dirname+'/../../helpers/permissions.js') |
||||
, Permission = require(__dirname+'/../../helpers/permission.js'); |
||||
|
||||
module.exports = async (req, res, next) => { |
||||
|
||||
let updatingPermissions = new Permission(res.locals.board.staff[req.body.username].permissions); |
||||
|
||||
//maybe these can be changed
|
||||
//updatingPermissions.set(Permissions.MANAGE_BOARD_GENERSL, (req.body.MANAGE_BOARD_GENERAL != null))
|
||||
updatingPermissions.set(Permissions.MANAGE_BOARD_BANS, (req.body.MANAGE_BOARD_BANS != null)) |
||||
updatingPermissions.set(Permissions.MANAGE_BOARD_LOGS, (req.body.MANAGE_BOARD_LOGS != null)) |
||||
updatingPermissions.set(Permissions.MANAGE_BOARD_SETTINGS, (req.body.MANAGE_BOARD_SETTINGS != null)) |
||||
updatingPermissions.set(Permissions.MANAGE_BOARD_CUSTOMISATION, (req.body.MANAGE_BOARD_CUSTOMISATION != null)) |
||||
if (res.locals.permissions.get(Permissions.MANAGE_BOARD_OWNER)) { |
||||
//be careful giving others manage_board_owner!
|
||||
updatingPermissions.set(Permissions.MANAGE_BOARD_OWNER, (req.body.MANAGE_BOARD_OWNER != null)) |
||||
updatingPermissions.set(Permissions.MANAGE_BOARD_STAFF, (req.body.MANAGE_BOARD_STAFF != null)) |
||||
} |
||||
|
||||
const updated = await Boards.setStaffPermissions(req.params.board, req.body.username, updatingPermissions).then(r => r.matchedCount); |
||||
|
||||
if (updated === 0) { |
||||
return dynamicResponse(req, res, 400, 'message', { |
||||
'title': 'Bad request', |
||||
'errors': 'Staff does not exist', |
||||
'redirect': req.headers.referer || `/${req.params.board}/manage/staff.html`, |
||||
}); |
||||
} |
||||
|
||||
return dynamicResponse(req, res, 200, 'message', { |
||||
'title': 'Success', |
||||
'message': 'Edited staff', |
||||
'redirect': `/${req.params.board}/manage/editstaff/${req.body.username}.html`, |
||||
}); |
||||
|
||||
} |
@ -0,0 +1,29 @@ |
||||
'use strict'; |
||||
|
||||
const { Accounts } = require(__dirname+'/../../../db/') |
||||
, roleManager = require(__dirname+'/../../../helpers/rolemanager.js') |
||||
, Permission = require(__dirname+'/../../../helpers/permission.js'); |
||||
|
||||
module.exports = async (req, res, next) => { |
||||
|
||||
const editingAccount = await Accounts.findOne(req.params.accountusername); |
||||
|
||||
if (editingAccount == null) { |
||||
//account does not exist
|
||||
return next(); |
||||
} |
||||
|
||||
const accountPermissions = new Permission(editingAccount.permissions); |
||||
//accountPermissions.applyInheritance();
|
||||
|
||||
res |
||||
.set('Cache-Control', 'private, max-age=5') |
||||
.render('editaccount', { |
||||
csrf: req.csrfToken(), |
||||
board: res.locals.board, |
||||
accountUsername: req.params.accountusername, |
||||
accountPermissions, |
||||
roles: roleManager.roles, |
||||
}); |
||||
|
||||
} |
@ -0,0 +1,25 @@ |
||||
'use strict'; |
||||
|
||||
const { Roles } = require(__dirname+'/../../../db/') |
||||
, roleManager = require(__dirname+'/../../../helpers/rolemanager.js') |
||||
, Permission = require(__dirname+'/../../../helpers/permission.js'); |
||||
|
||||
module.exports = async (req, res, next) => { |
||||
|
||||
const role = await Roles.findOne(req.params.roleid); |
||||
|
||||
if (role == null) { |
||||
//role does not exist
|
||||
return next(); |
||||
} |
||||
|
||||
res |
||||
.set('Cache-Control', 'private, max-age=5') |
||||
.render('editrole', { |
||||
csrf: req.csrfToken(), |
||||
role, |
||||
rolePermissions: new Permission(role.permissions), |
||||
roleNameMap: roleManager.roleNameMap, |
||||
}); |
||||
|
||||
} |
@ -0,0 +1,19 @@ |
||||
'use strict'; |
||||
|
||||
const { Roles } = require(__dirname+'/../../../db/') |
||||
, roleManager = require(__dirname+'/../../../helpers/rolemanager.js'); |
||||
|
||||
module.exports = async (req, res, next) => { |
||||
|
||||
const allRoles = await Roles.find(); |
||||
|
||||
res |
||||
.set('Cache-Control', 'private, max-age=5') |
||||
.render('globalmanageroles', { |
||||
csrf: req.csrfToken(), |
||||
permissions: res.locals.permissions, |
||||
allRoles, |
||||
roleNameMap: roleManager.roleNameMap, |
||||
}); |
||||
|
||||
} |
@ -0,0 +1,24 @@ |
||||
'use strict'; |
||||
|
||||
const Permission = require(__dirname+'/../../../helpers/permission.js'); |
||||
|
||||
module.exports = async (req, res, next) => { |
||||
|
||||
let staffData = res.locals.board.staff[req.params.staffusername]; |
||||
|
||||
if (staffData == null) { |
||||
//staff does not exist
|
||||
return next(); |
||||
} |
||||
|
||||
res |
||||
// .set('Cache-Control', 'private, max-age=5')
|
||||
.render('editstaff', { |
||||
csrf: req.csrfToken(), |
||||
board: res.locals.board, |
||||
permissions: res.locals.permissions, |
||||
staffUsername: req.params.staffusername, |
||||
staffPermissions: new Permission(staffData.permissions), |
||||
}); |
||||
|
||||
} |
@ -0,0 +1,13 @@ |
||||
'use strict'; |
||||
|
||||
module.exports = async (req, res, next) => { |
||||
|
||||
res |
||||
.set('Cache-Control', 'private, max-age=5') |
||||
.render('managemypermissions', { |
||||
user: res.locals.user, |
||||
board: res.locals.board, |
||||
permissions: res.locals.permissions, |
||||
}); |
||||
|
||||
} |
@ -0,0 +1,11 @@ |
||||
'use strict'; |
||||
|
||||
module.exports = async (req, res, next) => { |
||||
|
||||
res |
||||
.set('Cache-Control', 'private, max-age=5') |
||||
.render('managemypermissions', { |
||||
permissions: res.locals.permissions, |
||||
}); |
||||
|
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue