import { Plugin, EventListener, Configurable, } from '@squeebot/core/lib/plugin'; import { logger } from '@squeebot/core/lib/core'; import { IMessage } from '@squeebot/core/lib/types'; import { fullIDMatcher } from '@squeebot/core/lib/common'; /* users: { 'service/instance/name': [ 'one', 'two', '*' ] }, rooms: { 'service/instance/room': { 'service/instance/name': [ 'three', 'four', ] } } */ declare type RoleReceiver = (msg: IMessage) => string[]; @Configurable({users: {}, rooms: {}}) class PermissionsPlugin extends Plugin { public roleReceivers: Map = new Map(); registerRoleReceiver(plugin: string, fn: RoleReceiver): void { if (this.roleReceivers.has(plugin)) { return; } this.roleReceivers.set(plugin, fn); } userPermitted(msg: IMessage, required: string[]): boolean { // Boot all guests instantly if (msg.guest === true) { return false; } // Receive permissions from a role fetching function registered by // a service or service adapter const rr = this.roleReceivers.get(msg.source.plugin.manifest.name); const userRoles = []; if (rr) { userRoles.push(...rr(msg)); } const userFull = msg.fullSenderID; const roomFull = msg.fullRoomID; if (!userFull || !roomFull) { return false; } // Check for room access for (const ch in this.config.config.rooms) { if (fullIDMatcher(roomFull, ch)) { const users = this.config.config.rooms[ch]; for (const user in users) { if (fullIDMatcher(userFull, user)) { const perms = [...users[user], ...userRoles]; let has = false; for (const perm of required) { if (perms.indexOf(perm) !== -1) { has = true; break; } } if (has) { return true; } } } } } // Check for per-user-basis permissions for (const user in this.config.config.users) { if (fullIDMatcher(userFull, user)) { const perms = this.config.config.users[user]; if (perms.indexOf('*') !== -1) { return true; } let has = false; for (const perm of required) { if (perms.indexOf(perm) !== -1) { has = true; break; } } if (has) { return true; } } } return false; } @EventListener('pluginUnload') unloadEventHandler(plugin: string | Plugin): void { if (plugin === this.name || plugin === this) { logger.debug('[%s]', this.name, 'shutting down..'); this.emit('pluginUnloaded', this); } } @EventListener('pluginUnloaded') unloadedEventHandler(plugin: string | Plugin): void { const str = (typeof plugin === 'string' ? plugin : plugin.manifest.name); if (this.roleReceivers.has(str)) { this.roleReceivers.delete(str); } } } module.exports = PermissionsPlugin;