Added Permission evaluation for channels and EvaluatedPermissions class.

This commit is contained in:
hydrabolt
2016-04-18 19:31:36 +01:00
parent 00327a5776
commit da42b422f0
8 changed files with 200 additions and 2 deletions

View File

@@ -6,6 +6,7 @@ const Constants = require('../util/Constants');
const RESTManager = require('./rest/RestManager');
const ClientDataStore = require('../structures/DataStore/ClientDataStore');
const ClientManager = require('./ClientManager');
const ClientDataResolver = require('./ClientDataResolver');
const WebSocketManager = require('./websocket/WebSocketManager');
class Client extends EventEmitter{
@@ -17,6 +18,7 @@ class Client extends EventEmitter{
this.store = new ClientDataStore(this);
this.manager = new ClientManager(this);
this.ws = new WebSocketManager(this);
this.resolver = new ClientDataResolver(this);
}
login(email, password) {

View File

@@ -0,0 +1,59 @@
'use strict';
const Structure = name => require(`../structures/${name}`);
const User = Structure('User');
const Message = Structure('Message');
const Guild = Structure('Guild');
const ServerChannel = Structure('ServerChannel');
const TextChannel = Structure('TextChannel');
const VoiceChannel = Structure('VoiceChannel');
const GuildMember = Structure('GuildMember');
function $string(obj) {
return (typeof obj === 'string' || obj instanceof String);
}
class ClientDataResolver {
constructor(client) {
this.client = client;
}
ResolveUser(user) {
if (user instanceof User) {
return user;
}else if ($string(user)) {
return this.client.store.get('users', user);
}else if (user instanceof Message) {
return user.author;
}else if (user instanceof Guild) {
return user.owner;
}
return null;
}
ResolveGuild(guild) {
if (guild instanceof Guild) {
return guild;
}
}
ResolveGuildMember(guild, user) {
if (user instanceof GuildMember) {
return user;
}
guild = this.ResolveGuild(guild);
user = this.ResolveUser(user);
if (!guild || !user) {
return null;
}
return guild.store.get('members', user.id);
}
}
module.exports = ClientDataResolver;

View File

@@ -0,0 +1,39 @@
'use strict';
const Constants = require('../Util/Constants');
class EvaluatedPermissions {
constructor(member, permissions) {
this.member = member;
this.permissions = permissions;
}
serialize() {
let serializedPermissions = {};
for (let permissionName in Constants.PermissionFlags) {
serializedPermissions[permissionName] = this.hasPermission(permissionName);
}
return serializedPermissions;
}
hasPermission(permission, explicit) {
if (permission instanceof String || typeof permission === 'string') {
permission = Constants.PermissionFlags[permission];
}
if (!permission) {
throw Constants.Errors.NOT_A_PERMISSION;
}
if (!explicit) {
if ((this.permissions & Constants.PermissionFlags.MANAGE_ROLES) > 0) {
return true;
}
}
return ((this.permissions & permission) > 0);
}
}
module.exports = EvaluatedPermissions;

View File

@@ -60,12 +60,15 @@ class Guild {
return this.name;
}
member(user) {
return this.client.resolver.ResolveGuildMember(this, user);
}
setup(data) {
this.id = data.id;
this.available = !data.unavailable;
this.splash = data.splash;
this.region = data.region;
this.ownerID = data.owner_id;
this.name = data.name;
this.memberCount = data.member_count;
this.large = data.large;
@@ -87,6 +90,8 @@ class Guild {
}
}
this.owner = this.store.get('members', data.owner_id);
if (data.channels) {
this.store.clear('channels');
for (let channel of data.channels) {
@@ -125,6 +130,18 @@ class Guild {
}
}
}
get channels() { return this.store.getAsArray('channels'); }
get $channels() { return this.store.data.channels; }
get roles() { return this.store.getAsArray('roles'); }
get $roles() { return this.store.data.roles; }
get members() { return this.store.getAsArray('members'); }
get $members() { return this.store.data.members; }
}
module.exports = Guild;

View File

@@ -25,6 +25,12 @@ class GuildMember {
get roles() {
let list = [];
let everyoneRole = this.guild.store.get('roles', this.guild.id);
if (everyoneRole) {
list.push(everyoneRole);
}
for (let roleID of this._roles) {
let role = this.guild.store.get('roles', roleID);
if (role) {

View File

@@ -2,6 +2,8 @@
const Channel = require('./Channel');
const PermissionOverwrites = require('./PermissionOverwrites');
const EvaluatedPermissions = require('./EvaluatedPermissions');
const Constants = require('../util/Constants');
class ServerChannel extends Channel{
constructor(guild, data) {
@@ -15,7 +17,7 @@ class ServerChannel extends Channel{
this.position = data.position;
this.name = data.name;
this.lastMessageID = data.last_message_id;
this.ow = data.permission_overwrites;
if (data.permission_overwrites) {
this.permissionOverwrites = [];
for (let overwrite of data.permission_overwrites) {
@@ -24,6 +26,62 @@ class ServerChannel extends Channel{
}
}
permissionsFor(member) {
member = this.client.resolver.ResolveGuildMember(this.guild, member);
if (member) {
if (this.guild.owner.id === member.id) {
return new EvaluatedPermissions(member, Constants.ALL_PERMISSIONS);
}
let roles = member.roles;
let permissions = 0;
let overwrites = this.overwritesFor(member, true);
for (let role of roles) {
permissions |= role.permissions;
}
for (let overwrite of overwrites.role.concat(overwrites.member)) {
permissions = permissions & ~overwrite.denyData;
permissions = permissions | overwrite.allowData;
}
if (!!(permissions & (Constants.PermissionFlags.MANAGE_ROLES))) {
permissions = Constants.ALL_PERMISSIONS;
}
return new EvaluatedPermissions(member, permissions);
}
}
overwritesFor(member, verified) {
// for speed
if (!verified)
member = this.client.resolver.ResolveGuildMember(this.guild, member);
if (member) {
let found = [];
let memberRoles = member._roles;
let roleOverwrites = [];
let memberOverwrites = [];
for (let overwrite of this.permissionOverwrites) {
if (overwrite.id === member.id) {
memberOverwrites.push(overwrite);
} else if (memberRoles.indexOf(overwrite.id) > -1) {
roleOverwrites.push(overwrite);
}
}
return {
role: roleOverwrites,
member: memberOverwrites,
};
}
return [];
}
toString() {
return this.name;
}

View File

@@ -1,3 +1,5 @@
'use strict';
const DefaultOptions = exports.DefaultOptions = {
ws: {
large_threshold: 250,
@@ -157,4 +159,12 @@ const PermissionFlags = exports.PermissionFlags = {
USE_VAD: 1 << 25,
};
let _ALL_PERMISSIONS = 0;
for (let key in PermissionFlags) {
_ALL_PERMISSIONS |= PermissionFlags[key];
}
const ALL_PERMISSIONS = exports.ALL_PERMISSIONS = _ALL_PERMISSIONS;
const DEFAULT_PERMISSIONS = exports.DEFAULT_PERMISSIONS = 36953089;

View File

@@ -80,3 +80,10 @@ client.on('messageUpdate', (old, message) => {
if (message.author.username === 'hydrabolt')
console.log('Message updated from', old.content, 'to', message.content);
});
client.on('message', message => {
if (message.content === '?perms?') {
console.log(message.author.username, 'asked for perms in', message.channel.name, ':');
console.log(message.channel.permissionsFor(message.author).serialize());
}
});