/**
* Permission checker
*/
class Permitter {
/**
* Creates a new Permitter instance
* @arg {Client} Client instance
*/
constructor (client) {
this._client = client
}
static get contexts () {
return ['members', 'roles', 'channels']
}
static isBoolean (val) {
return val === true || val === false
}
static hasWildcard (obj) {
return obj !== null && '*' in obj ? this.isBoolean(obj['*']) : false
}
/**
* Verifies if a command has permission to be executed
* @arg {String} node The permission node
* @arg {external:"Eris.Message"} message The command message
* @arg {Object} perms The permissions map
* @arg {Boolean} [defaultValue=true] The default result
*/
static verifyMessage (node, msg, perms = {}, defVal = true) {
if (!msg.channel.guild) return true
let res = this.check(`${msg.channel.id}.${msg.author.id}.${node}`, perms)
if (this.isBoolean(res)) return res
for (const perm of msg.member.roles.map(r => `${msg.channel.id}.${r}.${node}`)) {
res = this.check(perm, perms)
if (this.isBoolean(res)) return res
}
res = this.check(`*.${msg.author.id}.${node}`, perms)
if (this.isBoolean(res)) return res
for (const perm of msg.member.roles.map(r => `*.${r}.${node}`)) {
res = this.check(perm, perms)
if (this.isBoolean(res)) return res
}
res = this.check(`${msg.channel.id}.${node}`, perms)
if (this.isBoolean(res)) return res
res = this.check(`*.*.${node}`, perms)
if (this.isBoolean(res)) return res
return defVal
}
/**
* Checks if a node is allowed
* @arg {String} node The permission node
* @arg {Object} perms THe permissions map
*/
check (node, perms = {}) {
const res = node.split('.').reduce((obj, idx) => {
if (obj === null || this.isBoolean(obj)) return obj
if (idx in obj) return obj[idx]
else if ('*' in obj) return obj['*']
return null
}, perms)
if (res === true || res === false) return res
return null
}
/**
* Allows a permission node
* @arg {String} node The permission node
* @arg {Object} perms THe permissions map
*/
static allow (node, perms) {
return this.grant(node, true, perms)
}
/**
* Denies a permission node
* @arg {String} node The permission node
* @arg {Object} perms THe permissions map
*/
static deny (node, perms) {
return this.grant(node, false, perms)
}
/**
* Grants a permission node allow or deny
* @arg {String} node The permission node
* @arg {Boolean} value The value of the node
* @arg {Object} perms THe permissions map
*/
static grant (node, val = true, rawPerms = {}) {
const nodes = node.split('.')
const last = nodes.length - 1
nodes.reduce((o, c, i) => {
if (i >= last) {
if (typeof o['*'] === 'undefined') o['*'] = null
if (o[c] === true || o[c] === false && o[c] !== val) {
o[c] = null
} else {
o[c] = val
}
} else if (typeof o[c] === 'undefined') {
o[c] = {}
} else if (o[c] === true || o[c] === false) {
o[c] = { '*': o[c] }
}
return o[c]
}, rawPerms)
return rawPerms
}
}
module.exports = Permitter