plugins-core/permissions/plugin.ts

131 lines
3.1 KiB
TypeScript

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<string, RoleReceiver> = new Map<string, RoleReceiver>();
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.config.save().then(() =>
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;