Skip to content

Commit

Permalink
Overhaul Permissions utilities (EvaluatedPermissions no more)
Browse files Browse the repository at this point in the history
  • Loading branch information
Gawdl3y committed Mar 6, 2017
1 parent 055775d commit 16fe48d
Show file tree
Hide file tree
Showing 11 changed files with 280 additions and 212 deletions.
3 changes: 2 additions & 1 deletion src/client/Client.js
@@ -1,6 +1,7 @@
const os = require('os');
const EventEmitter = require('events').EventEmitter;
const Constants = require('../util/Constants');
const Permissions = require('../util/Permissions');
const Util = require('../util/Util');
const RESTManager = require('./rest/RESTManager');
const ClientDataManager = require('./ClientDataManager');
Expand Down Expand Up @@ -398,7 +399,7 @@ class Client extends EventEmitter {
*/
generateInvite(permissions) {
if (permissions) {
if (permissions instanceof Array) permissions = this.resolver.resolvePermissions(permissions);
if (permissions instanceof Array) permissions = Permissions.resolve(permissions);
} else {
permissions = 0;
}
Expand Down
76 changes: 0 additions & 76 deletions src/client/ClientDataResolver.js
Expand Up @@ -155,82 +155,6 @@ class ClientDataResolver {
return data;
}

/**
* Data that can be resolved to give a permission number. This can be:
* * A string
* * A permission number
*
* Possible strings:
* ```js
* [
* 'CREATE_INSTANT_INVITE',
* 'KICK_MEMBERS',
* 'BAN_MEMBERS',
* 'ADMINISTRATOR',
* 'MANAGE_CHANNELS',
* 'MANAGE_GUILD',
* 'ADD_REACTIONS', // add reactions to messages
* 'READ_MESSAGES',
* 'SEND_MESSAGES',
* 'SEND_TTS_MESSAGES',
* 'MANAGE_MESSAGES',
* 'EMBED_LINKS',
* 'ATTACH_FILES',
* 'READ_MESSAGE_HISTORY',
* 'MENTION_EVERYONE',
* 'EXTERNAL_EMOJIS', // use external emojis
* 'CONNECT', // connect to voice
* 'SPEAK', // speak on voice
* 'MUTE_MEMBERS', // globally mute members on voice
* 'DEAFEN_MEMBERS', // globally deafen members on voice
* 'MOVE_MEMBERS', // move member's voice channels
* 'USE_VAD', // use voice activity detection
* 'CHANGE_NICKNAME',
* 'MANAGE_NICKNAMES', // change nicknames of others
* 'MANAGE_ROLES_OR_PERMISSIONS',
* 'MANAGE_WEBHOOKS',
* 'MANAGE_EMOJIS'
* ]
* ```
* @typedef {string|number} PermissionResolvable
*/

/**
* Resolves a PermissionResolvable to a permission number
* @param {PermissionResolvable} permission The permission resolvable to resolve
* @returns {number}
*/
resolvePermission(permission) {
if (typeof permission === 'string') permission = Constants.PermissionFlags[permission];
if (typeof permission !== 'number' || permission < 1) throw new Error(Constants.Errors.NOT_A_PERMISSION);
return permission;
}

/**
* Turn an array of permissions into a valid Discord permission bitfield
* @param {PermissionResolvable[]} permissions Permissions to resolve together
* @returns {number}
*/
resolvePermissions(permissions) {
let bitfield = 0;
for (const permission of permissions) bitfield |= this.resolvePermission(permission);
return bitfield;
}

hasPermission(bitfield, name, explicit = false) {
const permission = this.resolvePermission(name);
if (!explicit && (bitfield & Constants.PermissionFlags.ADMINISTRATOR) > 0) return true;
return (bitfield & permission) > 0;
}

serializePermissions(bitfield) {
const serializedPermissions = {};
for (const name in Constants.PermissionFlags) {
serializedPermissions[name] = this.hasPermission(bitfield, name);
}
return serializedPermissions;
}

/**
* Data that can be resolved to give a string. This can be:
* * A string
Expand Down
3 changes: 2 additions & 1 deletion src/client/rest/RESTMethods.js
@@ -1,5 +1,6 @@
const querystring = require('querystring');
const long = require('long');
const Permissions = require('../../util/Permissions');
const Constants = require('../../util/Constants');
const Collection = require('../../util/Collection');
const Snowflake = require('../../util/Snowflake');
Expand Down Expand Up @@ -581,7 +582,7 @@ class RESTMethods {
if (_data.permissions) {
let perms = 0;
for (let perm of _data.permissions) {
if (typeof perm === 'string') perm = Constants.PermissionFlags[perm];
if (typeof perm === 'string') perm = Permissions.FLAGS[perm];
perms |= perm;
}
data.permissions = perms;
Expand Down
3 changes: 2 additions & 1 deletion src/index.js
Expand Up @@ -11,6 +11,8 @@ module.exports = {
// Utilities
Collection: require('./util/Collection'),
Constants: require('./util/Constants'),
EvaluatedPermissions: require('./util/Permissions'),
Permissions: require('./util/Permissions'),
Snowflake: require('./util/Snowflake'),
SnowflakeUtil: require('./util/Snowflake'),
Util: Util,
Expand All @@ -27,7 +29,6 @@ module.exports = {
ClientUser: require('./structures/ClientUser'),
DMChannel: require('./structures/DMChannel'),
Emoji: require('./structures/Emoji'),
EvaluatedPermissions: require('./structures/EvaluatedPermissions'),
Game: require('./structures/Presence').Game,
GroupDMChannel: require('./structures/GroupDMChannel'),
Guild: require('./structures/Guild'),
Expand Down
67 changes: 0 additions & 67 deletions src/structures/EvaluatedPermissions.js

This file was deleted.

27 changes: 13 additions & 14 deletions src/structures/GuildChannel.js
@@ -1,8 +1,7 @@
const Channel = require('./Channel');
const Role = require('./Role');
const PermissionOverwrites = require('./PermissionOverwrites');
const EvaluatedPermissions = require('./EvaluatedPermissions');
const Constants = require('../util/Constants');
const Permissions = require('../util/Permissions');
const Collection = require('../util/Collection');

/**
Expand Down Expand Up @@ -51,12 +50,12 @@ class GuildChannel extends Channel {
* Gets the overall set of permissions for a user in this channel, taking into account roles and permission
* overwrites.
* @param {GuildMemberResolvable} member The user that you want to obtain the overall permissions for
* @returns {?EvaluatedPermissions}
* @returns {?Permissions}
*/
permissionsFor(member) {
member = this.client.resolver.resolveGuildMember(this.guild, member);
if (!member) return null;
if (member.id === this.guild.ownerID) return new EvaluatedPermissions(member, Constants.ALL_PERMISSIONS);
if (member.id === this.guild.ownerID) return new Permissions(member, Permissions.ALL);

let permissions = 0;

Expand All @@ -71,10 +70,10 @@ class GuildChannel extends Channel {
}
permissions |= allow;

const admin = Boolean(permissions & Constants.PermissionFlags.ADMINISTRATOR);
if (admin) permissions = Constants.ALL_PERMISSIONS;
const admin = Boolean(permissions & Permissions.FLAGS.ADMINISTRATOR);
if (admin) permissions = Permissions.ALL;

return new EvaluatedPermissions(member, permissions);
return new Permissions(member, permissions);
}

overwritesFor(member, verified = false, roles = null) {
Expand Down Expand Up @@ -151,14 +150,14 @@ class GuildChannel extends Channel {

for (const perm in options) {
if (options[perm] === true) {
payload.allow |= Constants.PermissionFlags[perm] || 0;
payload.deny &= ~(Constants.PermissionFlags[perm] || 0);
payload.allow |= Permissions.FLAGS[perm] || 0;
payload.deny &= ~(Permissions.FLAGS[perm] || 0);
} else if (options[perm] === false) {
payload.allow &= ~(Constants.PermissionFlags[perm] || 0);
payload.deny |= Constants.PermissionFlags[perm] || 0;
payload.allow &= ~(Permissions.FLAGS[perm] || 0);
payload.deny |= Permissions.FLAGS[perm] || 0;
} else if (options[perm] === null) {
payload.allow &= ~(Constants.PermissionFlags[perm] || 0);
payload.deny &= ~(Constants.PermissionFlags[perm] || 0);
payload.allow &= ~(Permissions.FLAGS[perm] || 0);
payload.deny &= ~(Permissions.FLAGS[perm] || 0);
}
}

Expand Down Expand Up @@ -294,7 +293,7 @@ class GuildChannel extends Channel {
*/
get deletable() {
return this.id !== this.guild.id &&
this.permissionsFor(this.client.user).hasPermission(Constants.PermissionFlags.MANAGE_CHANNELS);
this.permissionsFor(this.client.user).hasPermission(Permissions.FLAGS.MANAGE_CHANNELS);
}

/**
Expand Down
17 changes: 7 additions & 10 deletions src/structures/GuildMember.js
@@ -1,6 +1,6 @@
const TextBasedChannel = require('./interface/TextBasedChannel');
const Role = require('./Role');
const EvaluatedPermissions = require('./EvaluatedPermissions');
const Permissions = require('../util/Permissions');
const Constants = require('../util/Constants');
const Collection = require('../util/Collection');
const Presence = require('./Presence').Presence;
Expand Down Expand Up @@ -241,20 +241,17 @@ class GuildMember {

/**
* The overall set of permissions for the guild member, taking only roles into account
* @type {EvaluatedPermissions}
* @type {Permissions}
* @readonly
*/
get permissions() {
if (this.user.id === this.guild.ownerID) return new EvaluatedPermissions(this, Constants.ALL_PERMISSIONS);
if (this.user.id === this.guild.ownerID) return new Permissions(this, Permissions.ALL);

let permissions = 0;
const roles = this.roles;
for (const role of roles.values()) permissions |= role.permissions;

const admin = Boolean(permissions & Constants.PermissionFlags.ADMINISTRATOR);
if (admin) permissions = Constants.ALL_PERMISSIONS;

return new EvaluatedPermissions(this, permissions);
return new Permissions(this, permissions);
}

/**
Expand All @@ -266,7 +263,7 @@ class GuildMember {
if (this.user.id === this.guild.ownerID) return false;
if (this.user.id === this.client.user.id) return false;
const clientMember = this.guild.member(this.client.user);
if (!clientMember.hasPermission(Constants.PermissionFlags.KICK_MEMBERS)) return false;
if (!clientMember.hasPermission(Permissions.FLAGS.KICK_MEMBERS)) return false;
return clientMember.highestRole.comparePositionTo(this.highestRole) > 0;
}

Expand All @@ -279,14 +276,14 @@ class GuildMember {
if (this.user.id === this.guild.ownerID) return false;
if (this.user.id === this.client.user.id) return false;
const clientMember = this.guild.member(this.client.user);
if (!clientMember.hasPermission(Constants.PermissionFlags.BAN_MEMBERS)) return false;
if (!clientMember.hasPermission(Permissions.FLAGS.BAN_MEMBERS)) return false;
return clientMember.highestRole.comparePositionTo(this.highestRole) > 0;
}

/**
* Returns `channel.permissionsFor(guildMember)`. Returns evaluated permissions for a member in a guild channel.
* @param {ChannelResolvable} channel Guild channel to use as context
* @returns {?EvaluatedPermissions}
* @returns {?Permissions}
*/
permissionsIn(channel) {
channel = this.client.resolver.resolveChannel(channel);
Expand Down
5 changes: 3 additions & 2 deletions src/structures/Message.js
Expand Up @@ -4,6 +4,7 @@ const MessageReaction = require('./MessageReaction');
const Util = require('../util/Util');
const Collection = require('../util/Collection');
const Constants = require('../util/Constants');
const Permissions = require('../util/Permissions');
let GuildMember;

/**
Expand Down Expand Up @@ -334,7 +335,7 @@ class Message {
*/
get deletable() {
return this.author.id === this.client.user.id || (this.guild &&
this.channel.permissionsFor(this.client.user).hasPermission(Constants.PermissionFlags.MANAGE_MESSAGES)
this.channel.permissionsFor(this.client.user).hasPermission(Permissions.FLAGS.MANAGE_MESSAGES)
);
}

Expand All @@ -345,7 +346,7 @@ class Message {
*/
get pinnable() {
return !this.guild ||
this.channel.permissionsFor(this.client.user).hasPermission(Constants.PermissionFlags.MANAGE_MESSAGES);
this.channel.permissionsFor(this.client.user).hasPermission(Permissions.FLAGS.MANAGE_MESSAGES);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/structures/Role.js
@@ -1,4 +1,4 @@
const Constants = require('../util/Constants');
const Permissions = require('../util/Permissions');

/**
* Represents a role on Discord
Expand Down Expand Up @@ -118,7 +118,7 @@ class Role {
get editable() {
if (this.managed) return false;
const clientMember = this.guild.member(this.client.user);
if (!clientMember.hasPermission(Constants.PermissionFlags.MANAGE_ROLES_OR_PERMISSIONS)) return false;
if (!clientMember.hasPermission(Permissions.FLAGS.MANAGE_ROLES_OR_PERMISSIONS)) return false;
return clientMember.highestRole.comparePositionTo(this) > 0;
}

Expand Down

0 comments on commit 16fe48d

Please sign in to comment.