From ba106fda38d9c34faa174670ff25607f538a4edb Mon Sep 17 00:00:00 2001 From: Felipe Cecagno <fcecagno@gmail.com> Date: Tue, 26 Mar 2019 17:03:05 -0300 Subject: [PATCH] start refactoring bbb-webhooks to use a proper config library --- bbb-webhooks/application.js | 19 +-- bbb-webhooks/callback_emitter.js | 12 +- bbb-webhooks/config.js | 115 ------------------ bbb-webhooks/config/bbb-webhooks.logrotate | 8 -- .../config/custom-environment-variables.yml | 11 ++ bbb-webhooks/config/default.example.yml | 67 ++++++++++ bbb-webhooks/config/webhooks.nginx | 9 -- bbb-webhooks/config_local.js.example | 30 ----- bbb-webhooks/extra/events.js | 8 +- bbb-webhooks/hook.js | 50 ++++---- bbb-webhooks/id_mapping.js | 22 ++-- bbb-webhooks/messageMapping.js | 1 - bbb-webhooks/package-lock.json | 48 +++++++- bbb-webhooks/package.json | 6 +- bbb-webhooks/responses.js | 46 +++++++ bbb-webhooks/test/test.js | 40 +++--- bbb-webhooks/userMapping.js | 18 +-- bbb-webhooks/utils.js | 4 +- bbb-webhooks/web_hooks.js | 10 +- bbb-webhooks/web_server.js | 27 ++-- 20 files changed, 281 insertions(+), 270 deletions(-) delete mode 100644 bbb-webhooks/config.js delete mode 100644 bbb-webhooks/config/bbb-webhooks.logrotate create mode 100644 bbb-webhooks/config/custom-environment-variables.yml create mode 100644 bbb-webhooks/config/default.example.yml delete mode 100644 bbb-webhooks/config/webhooks.nginx delete mode 100644 bbb-webhooks/config_local.js.example create mode 100644 bbb-webhooks/responses.js diff --git a/bbb-webhooks/application.js b/bbb-webhooks/application.js index b6e9985b12..e2c0c5424f 100644 --- a/bbb-webhooks/application.js +++ b/bbb-webhooks/application.js @@ -1,4 +1,4 @@ -const config = require("./config.js"); +const config = require('config'); const Hook = require("./hook.js"); const IDMapping = require("./id_mapping.js"); const WebHooks = require("./web_hooks.js"); @@ -11,14 +11,8 @@ const async = require("async"); // process to perform the callback calls. // TODO: add port (-p) and log level (-l) to the command line args module.exports = class Application { - + constructor() { - const options = { - host : process.env.REDIS_HOST || config.redis.host, - port : process.env.REDIS_PORT || config.redis.port - }; - config.redis.pubSubClient = redis.createClient(options); - config.redis.client = redis.createClient(options); this.webHooks = new WebHooks(); this.webServer = new WebServer(); } @@ -28,7 +22,7 @@ module.exports = class Application { UserMapping.initialize(() => { IDMapping.initialize(()=> { async.parallel([ - (callback) => { this.webServer.start(config.server.port, callback) }, + (callback) => { this.webServer.start(config.get("server.port"), callback) }, (callback) => { this.webServer.createPermanents(callback) }, (callback) => { this.webHooks.start(callback) } ], (err,results) => { @@ -39,4 +33,11 @@ module.exports = class Application { }); }); } + + static redisClient() { + if (!Application._redisClient) { + Application._redisClient = redis.createClient( { host: config.get("redis.host"), port: config.get("redis.port") } ); + } + return Application._redisClient; + } }; diff --git a/bbb-webhooks/callback_emitter.js b/bbb-webhooks/callback_emitter.js index 6ec7d55363..d1502ab374 100644 --- a/bbb-webhooks/callback_emitter.js +++ b/bbb-webhooks/callback_emitter.js @@ -3,7 +3,7 @@ const request = require("request"); const url = require('url'); const EventEmitter = require('events').EventEmitter; -const config = require("./config.js"); +const config = require('config'); const Logger = require("./logger.js"); const Utils = require("./utils.js"); @@ -38,7 +38,7 @@ module.exports = class CallbackEmitter extends EventEmitter { this.emit("failure", error); // get the next interval we have to wait and schedule a new try - const interval = config.hooks.retryIntervals[this.nextInterval]; + const interval = config.get("hooks.retryIntervals")[this.nextInterval]; if (interval != null) { Logger.warn(`[Emitter] trying the callback again in ${interval/1000.0} secs`); this.nextInterval++; @@ -46,7 +46,7 @@ module.exports = class CallbackEmitter extends EventEmitter { // no intervals anymore, time to give up } else { - this.nextInterval = config.hooks.permanentIntervalReset; // Reset interval to permanent hooks + this.nextInterval = config.get("hooks.permanentIntervalReset"); // Reset interval to permanent hooks if(this.permanent){ this._scheduleNext(this.nextInterval); } @@ -62,9 +62,9 @@ module.exports = class CallbackEmitter extends EventEmitter { _emitMessage(callback) { let data,requestOptions; - const serverDomain = process.env.SERVER_DOMAIN || config.bbb.serverDomain; - const sharedSecret = process.env.SHARED_SECRET || config.bbb.sharedSecret; - const bearerAuth = process.env.BEARER_AUTH || config.bbb.auth2_0; + const serverDomain = config.get("bbb.serverDomain"); + const sharedSecret = config.get("bbb.sharedSecret"); + const bearerAuth = config.get("bbb.auth2_0"); // data to be sent // note: keep keys in alphabetical order diff --git a/bbb-webhooks/config.js b/bbb-webhooks/config.js deleted file mode 100644 index ca9be42b53..0000000000 --- a/bbb-webhooks/config.js +++ /dev/null @@ -1,115 +0,0 @@ -// Global configuration file - -// load the local configs -const config = require("./config_local.js"); - -// BigBlueButton configs -if (config.bbb == null) { config.bbb = {}; } -if (!config.bbb.sharedSecret) { config.bbb.sharedSecret = "sharedSecret"; } -if (!config.bbb.apiPath) { config.bbb.apiPath = "/bigbluebutton/api"; } -// Whether to use Auth2.0 or not, Auth2.0 sends the sharedSecret whithin an Authorization header as a bearer -// and data as JSON -if (config.bbb.auth2_0 == null) { config.bbb.auth2_0 = false; } - -// Web server configs -if (!config.server) { config.server = {}; } -if (config.server.port == null) { config.server.port = 3005; } - -// Web hooks configs -if (!config.hooks) { config.hooks = {}; } -if (!config.hooks.channels) { - config.hooks.channels = { - mainChannel: 'from-akka-apps-redis-channel', - rapChannel: 'from-bbb-web-redis-channel', - chatChannel: 'from-akka-apps-chat-redis-channel', - compMeetingChannel: 'bigbluebutton:from-bbb-apps:meeting', - compUserChannel: 'bigbluebutton:from-bbb-apps:users', - compChatChannel: 'bigbluebutton:from-bbb-apps:chat', - compRapChannel: 'bigbluebutton:from-rap' - } - } -// IP where permanent hook will post data (more than 1 URL means more than 1 permanent hook) -if (!config.hooks.permanentURLs) { config.hooks.permanentURLs = []; } -// How many messages will be enqueued to be processed at the same time -if (config.hooks.queueSize == null) { config.hooks.queueSize = 10000; } -// Allow permanent hooks to receive raw message, which is the message straight from BBB -if (config.hooks.getRaw == null) { config.hooks.getRaw = true; } -// If set to higher than 1, will send events on the format: -// "event=[{event1},{event2}],timestamp=000" or "[{event1},{event2}]" (based on using auth2_0 or not) -// when there are more than 1 event on the queue at the moment of processing the queue. -if (config.hooks.multiEvent == null) { config.hooks.multiEvent = 1; } - -// Retry intervals for failed attempts for perform callback calls. -// In ms. Totals to around 5min. -config.hooks.retryIntervals = [ - 100, 500, 1000, 2000, 4000, 8000, 10000, 30000, 60000, 60000, 60000, 60000 -]; - -// Reset permanent interval when exceeding maximum attemps -config.hooks.permanentIntervalReset = 8; - -// Mappings of internal to external meeting IDs -config.mappings = {}; -config.mappings.cleanupInterval = 10000; // 10 secs, in ms -config.mappings.timeout = 1000*60*60*24; // 24 hours, in ms - -// Redis -config.redis = {}; -config.redis.host = '127.0.0.1'; -config.redis.port = 6379; -config.redis.keys = {}; -config.redis.keys.hook = id => `bigbluebutton:webhooks:hook:${id}`; -config.redis.keys.hooks = "bigbluebutton:webhooks:hooks"; -config.redis.keys.mappings = "bigbluebutton:webhooks:mappings"; -config.redis.keys.mapping = id => `bigbluebutton:webhooks:mapping:${id}`; -config.redis.keys.events = id => `bigbluebutton:webhooks:events:${id}`; -config.redis.keys.userMaps = "bigbluebutton:webhooks:userMaps"; -config.redis.keys.userMap = id => `bigbluebutton:webhooks:userMap:${id}`; - -config.api = {}; -config.api.responses = {}; -config.api.responses.failure = (key, msg) => - `<response> \ -<returncode>FAILED</returncode> \ -<messageKey>${key}</messageKey> \ -<message>${msg}</message> \ -</response>` -; -config.api.responses.checksumError = - config.api.responses.failure("checksumError", "You did not pass the checksum security check."); - -config.api.responses.createSuccess = (id, permanent, getRaw) => - `<response> \ -<returncode>SUCCESS</returncode> \ -<hookID>${id}</hookID> \ -<permanentHook>${permanent}</permanentHook> \ -<rawData>${getRaw}</rawData> \ -</response>` -; -config.api.responses.createFailure = - config.api.responses.failure("createHookError", "An error happened while creating your hook. Check the logs."); -config.api.responses.createDuplicated = id => - `<response> \ -<returncode>SUCCESS</returncode> \ -<hookID>${id}</hookID> \ -<messageKey>duplicateWarning</messageKey> \ -<message>There is already a hook for this callback URL.</message> \ -</response>` -; - -config.api.responses.destroySuccess = - `<response> \ -<returncode>SUCCESS</returncode> \ -<removed>true</removed> \ -</response>`; -config.api.responses.destroyFailure = - config.api.responses.failure("destroyHookError", "An error happened while removing your hook. Check the logs."); -config.api.responses.destroyNoHook = - config.api.responses.failure("destroyMissingHook", "The hook informed was not found."); - -config.api.responses.missingParamCallbackURL = - config.api.responses.failure("missingParamCallbackURL", "You must specify a callbackURL in the parameters."); -config.api.responses.missingParamHookID = - config.api.responses.failure("missingParamHookID", "You must specify a hookID in the parameters."); - -module.exports = config; diff --git a/bbb-webhooks/config/bbb-webhooks.logrotate b/bbb-webhooks/config/bbb-webhooks.logrotate deleted file mode 100644 index c01f43723b..0000000000 --- a/bbb-webhooks/config/bbb-webhooks.logrotate +++ /dev/null @@ -1,8 +0,0 @@ -/usr/local/bigbluebutton/bbb-webhooks/log/*.log { - size 300M - copytruncate - rotate 30 - compress - missingok - notifempty -} diff --git a/bbb-webhooks/config/custom-environment-variables.yml b/bbb-webhooks/config/custom-environment-variables.yml new file mode 100644 index 0000000000..69733ad4a7 --- /dev/null +++ b/bbb-webhooks/config/custom-environment-variables.yml @@ -0,0 +1,11 @@ +bbb: + serverDomain: SERVER_DOMAIN + sharedSecret: SHARED_SECRET + auth2_0: BEARER_AUTH +hooks: + permanentURLs: + __name: PERMANENT_HOOKS + __format: json +redis: + host: REDIS_HOST + port: REDIS_PORT diff --git a/bbb-webhooks/config/default.example.yml b/bbb-webhooks/config/default.example.yml new file mode 100644 index 0000000000..037f3b9ad6 --- /dev/null +++ b/bbb-webhooks/config/default.example.yml @@ -0,0 +1,67 @@ +# Shared secret of your BigBlueButton server. +bbb: + serverDomain: myserver.com + sharedSecret: mysharedsecret + # Whether to use Auth2.0 or not, Auth2.0 sends the sharedSecret whithin an Authorization header as a bearer + auth2_0: false + apiPath: /bigbluebutton/api + +# The port in which the API server will run. +server: + port: 3005 + +# Web hooks configs +hooks: + channels: + - from-akka-apps-redis-channel + - from-bbb-web-redis-channel + - from-akka-apps-chat-redis-channel + - bigbluebutton:from-bbb-apps:meeting + - bigbluebutton:from-bbb-apps:users + - bigbluebutton:from-bbb-apps:chat + - bigbluebutton:from-rap + # IP where permanent hook will post data (more than 1 URL means more than 1 permanent hook) + permanentURLs: [] + # How many messages will be enqueued to be processed at the same time + queueSize: 10000 + # Allow permanent hooks to receive raw message, which is the message straight from BBB + getRaw: true + # If set to higher than 1, will send events on the format: + # "event=[{event1},{event2}],timestamp=000" or "[{event1},{event2}]" (based on using auth2_0 or not) + # when there are more than 1 event on the queue at the moment of processing the queue. + multiEvent: 1 + # Retry intervals for failed attempts for perform callback calls. + # In ms. Totals to around 5min. + retryIntervals: + - 100 + - 500 + - 1000 + - 2000 + - 4000 + - 8000 + - 10000 + - 30000 + - 60000 + - 60000 + - 60000 + - 60000 + # Reset permanent interval when exceeding maximum attemps + permanentIntervalReset: 8 + +# Mappings of internal to external meeting IDs +mappings: + cleanupInterval: 10000 # 10 secs, in ms + timeout: 86400000 # 24 hours, in ms + +# Redis +redis: + host: 127.0.0.1 + port: 6379 + keys: + hookPrefix: bigbluebutton:webhooks:hook + hooks: bigbluebutton:webhooks:hooks + mappings: bigbluebutton:webhooks:mappings + mappingPrefix: bigbluebutton:webhooks:mapping + eventsPrefix: bigbluebutton:webhooks:events + userMaps: bigbluebutton:webhooks:userMaps + userMapPrefix: bigbluebutton:webhooks:userMap \ No newline at end of file diff --git a/bbb-webhooks/config/webhooks.nginx b/bbb-webhooks/config/webhooks.nginx deleted file mode 100644 index 22ec6e4e97..0000000000 --- a/bbb-webhooks/config/webhooks.nginx +++ /dev/null @@ -1,9 +0,0 @@ -# Pass to the webhooks app all requests made to the webhooks API. -location /bigbluebutton/api/hooks { - proxy_pass http://127.0.0.1:3005; - proxy_redirect default; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header Host $http_host; - proxy_set_header X-NginX-Proxy true; -} diff --git a/bbb-webhooks/config_local.js.example b/bbb-webhooks/config_local.js.example deleted file mode 100644 index 0bebd13924..0000000000 --- a/bbb-webhooks/config_local.js.example +++ /dev/null @@ -1,30 +0,0 @@ -// Local configuration file - -const config = {}; - -// Shared secret of your BigBlueButton server. -config.bbb = {}; -config.bbb.serverDomain = "myserver.com"; -config.bbb.sharedSecret = "mysharedsecret"; -// Whether to use Auth2.0 or not, Auth2.0 sends the sharedSecret whithin an Authorization header as a bearer -config.bbb.auth2_0 = false; - -// The port in which the API server will run. -config.server = {}; -config.server.port = 3005; - -// Callbacks will be triggered for all the events in this list and only for these events. -//config.hooks = {}; -//config.hooks.channels = { -// mainChannel: 'from-akka-apps-redis-channel', -// rapChannel: 'bigbluebutton:from-rap', -// chatChannel: 'from-akka-apps-chat-redis-channel' -//} - -// IP where permanent hook will post data (more than 1 URL means more than 1 permanent hook) -//config.hooks.permanentURLs = [ { url: "request.catcher.url", getRaw: false }, { url: "another.request.catcher.url", getRaw: true } ] - -// Allow global hook to receive all events with raw data -//config.hooks.getRaw = false; - -module.exports = config; diff --git a/bbb-webhooks/extra/events.js b/bbb-webhooks/extra/events.js index c527879ac9..a0997b4b75 100644 --- a/bbb-webhooks/extra/events.js +++ b/bbb-webhooks/extra/events.js @@ -3,10 +3,10 @@ // events, but only the first time they happen. const redis = require("redis"); -const config = require('../config.js'); +const config = require('config'); var target_meeting = null; var events_printed = []; -var subscriber = redis.createClient(process.env.REDIS_PORT || config.redis.port, process.env.REDIS_HOST || config.redis.host); +var subscriber = redis.createClient(config.get(redis.port), config.get(redis.host)); subscriber.on("psubscribe", function(channel, count) { console.log("subscribed to " + channel); @@ -30,8 +30,8 @@ subscriber.on("pmessage", function(pattern, channel, message) { } }); -for (let k in config.hooks.channels) { - const channel = config.hooks.channels[k]; +for (i = 0; i < config.get(hooks.channels); ++i) { + const channel = config.get(hooks.channels)[i]; subscriber.psubscribe(channel); } diff --git a/bbb-webhooks/hook.js b/bbb-webhooks/hook.js index ce2a53fc19..f15537bb13 100644 --- a/bbb-webhooks/hook.js +++ b/bbb-webhooks/hook.js @@ -2,7 +2,7 @@ const _ = require("lodash"); const async = require("async"); const redis = require("redis"); -const config = require("./config.js"); +const config = require('config'); const CallbackEmitter = require("./callback_emitter.js"); const IDMapping = require("./id_mapping.js"); const Logger = require("./logger.js"); @@ -36,15 +36,15 @@ module.exports = class Hook { this.externalMeetingID = null; this.queue = []; this.emitter = null; - this.redisClient = config.redis.client; + this.redisClient = Application.redisClient; this.permanent = false; this.getRaw = false; } save(callback) { - this.redisClient.hmset(config.redis.keys.hook(this.id), this.toRedis(), (error, reply) => { + this.redisClient.hmset(config.get("redis.keys.hookPrefix") + ":" + this.id, this.toRedis(), (error, reply) => { if (error != null) { Logger.error("[Hook] error saving hook to redis:", error, reply); } - this.redisClient.sadd(config.redis.keys.hooks, this.id, (error, reply) => { + this.redisClient.sadd(config.get("redis.keys.hooks"), this.id, (error, reply) => { if (error != null) { Logger.error("[Hook] error saving hookID to the list of hooks:", error, reply); } db[this.id] = this; @@ -54,9 +54,9 @@ module.exports = class Hook { } destroy(callback) { - this.redisClient.srem(config.redis.keys.hooks, this.id, (error, reply) => { + this.redisClient.srem(config.get("redis.keys.hooks"), this.id, (error, reply) => { if (error != null) { Logger.error("[Hook] error removing hookID from the list of hooks:", error, reply); } - this.redisClient.del(config.redis.keys.hook(this.id), error => { + this.redisClient.del(config.get("redis.keys.hookPrefix") + ":" + this.id, error => { if (error != null) { Logger.error("[Hook] error removing hook from redis:", error); } if (db[this.id]) { @@ -82,12 +82,12 @@ module.exports = class Hook { // Puts a new message in the queue. Will also trigger a processing in the queue so this // message might be processed instantly. enqueue(message) { - this.redisClient.llen(config.redis.keys.events(this.id), (error, reply) => { + this.redisClient.llen(config.get("redis.keys.eventsPrefix") + ":" + this.id, (error, reply) => { const length = reply; - if (length < config.hooks.queueSize && this.queue.length < config.hooks.queueSize) { + if (length < config.get("hooks.queueSize") && this.queue.length < config.get("hooks.queueSize")) { Logger.info(`[Hook] ${this.callbackURL} enqueueing message:`, JSON.stringify(message)); // Add message to redis queue - this.redisClient.rpush(config.redis.keys.events(this.id), JSON.stringify(message), (error,reply) => { + this.redisClient.rpush(config.get("redis.keys.eventsPrefix") + ":" + this.id, JSON.stringify(message), (error,reply) => { if (error != null) { Logger.error("[Hook] error pushing event to redis queue:", JSON.stringify(message), error); } }); this.queue.push(JSON.stringify(message)); @@ -124,8 +124,8 @@ module.exports = class Hook { // Gets the first message in the queue and start an emitter to send it. Will only do it // if there is no emitter running already and if there is a message in the queue. _processQueue() { - // Will try to send up to a defined number of messages together if they're enqueued (defined on config.hooks.multiEvent) - const lengthIn = this.queue.length > config.hooks.multiEvent ? config.hooks.multiEvent : this.queue.length; + // Will try to send up to a defined number of messages together if they're enqueued (defined on config.get("hooks.multiEvent")) + const lengthIn = this.queue.length > config.get("hooks.multiEvent") ? config.get("hooks.multiEvent") : this.queue.length; let num = lengthIn + 1; // Concat messages let message = this.queue.slice(0,lengthIn); @@ -140,7 +140,7 @@ module.exports = class Hook { delete this.emitter; while ((num -= 1)) { // Remove the sent message from redis - this.redisClient.lpop(config.redis.keys.events(this.id), (error, reply) => { + this.redisClient.lpop(config.get("redis.keys.eventsPrefix") + ":" + this.id, (error, reply) => { if (error != null) { return Logger.error("[Hook] error removing event from redis queue:", error); } }); this.queue.shift(); @@ -168,21 +168,21 @@ module.exports = class Hook { hook.callbackURL = callbackURL; hook.externalMeetingID = meetingID; hook.getRaw = getRaw; - hook.permanent = config.hooks.permanentURLs.some( obj => { + hook.permanent = config.get("hooks.permanentURLs").some( obj => { return obj.url === callbackURL }); if (hook.permanent) { - hook.id = config.hooks.permanentURLs.map(obj => obj.url).indexOf(callbackURL) + 1; - nextID = config.hooks.permanentURLs.length + 1; + hook.id = config.get("hooks.permanentURLs").map(obj => obj.url).indexOf(callbackURL) + 1; + nextID = config.get("hooks.permanentURLs").length + 1; } else { hook.id = nextID++; } // Sync permanent queue if (hook.permanent) { - hook.redisClient.llen(config.redis.keys.events(hook.id), (error, len) => { + hook.redisClient.llen(config.get("redis.keys.eventsPrefix") + ":" + hook.id, (error, len) => { if (len > 0) { const length = len; - hook.redisClient.lrange(config.redis.keys.events(hook.id), 0, len, (error, elements) => { + hook.redisClient.lrange(config.get("redis.keys.eventsPrefix") + ":" + hook.id, 0, len, (error, elements) => { elements.forEach(element => { hook.queue.push(element); }); @@ -266,12 +266,12 @@ module.exports = class Hook { // Gets all hooks from redis to populate the local database. // Calls `callback()` when done. static resync(callback) { - let client = config.redis.client; + let client = Application.redisClient; // Remove previous permanent hooks - for (let hk = 1; hk <= config.hooks.permanentURLs.length; hk++) { - client.srem(config.redis.keys.hooks, hk, (error, reply) => { + for (let hk = 1; hk <= config.get("hooks.permanentURLs").length; hk++) { + client.srem(config.get("redis.keys.hooks"), hk, (error, reply) => { if (error != null) { Logger.error("[Hook] error removing previous permanent hook from list:", error); } - client.del(config.redis.keys.hook(hk), error => { + client.del(config.get("redis.keys.hookPrefix") + ":" + hk, error => { if (error != null) { Logger.error("[Hook] error removing previous permanent hook from redis:", error); } }); }); @@ -279,11 +279,11 @@ module.exports = class Hook { let tasks = []; - client.smembers(config.redis.keys.hooks, (error, hooks) => { + client.smembers(config.get("redis.keys.hooks"), (error, hooks) => { if (error != null) { Logger.error("[Hook] error getting list of hooks from redis:", error); } hooks.forEach(id => { tasks.push(done => { - client.hgetall(config.redis.keys.hook(id), function(error, hookData) { + client.hgetall(config.get("redis.keys.hookPrefix") + ":" + id, function(error, hookData) { if (error != null) { Logger.error("[Hook] error getting information for a hook from redis:", error); } if (hookData != null) { @@ -291,9 +291,9 @@ module.exports = class Hook { let hook = new Hook(); hook.fromRedis(hookData); // sync events queue - client.llen(config.redis.keys.events(hook.id), (error, len) => { + client.llen(config.get("redis.keys.eventsPrefix") + ":" + hook.id, (error, len) => { length = len; - client.lrange(config.redis.keys.events(hook.id), 0, len, (error, elements) => { + client.lrange(config.get("redis.keys.eventsPrefix") + ":" + hook.id, 0, len, (error, elements) => { elements.forEach(element => { hook.queue.push(element); }); diff --git a/bbb-webhooks/id_mapping.js b/bbb-webhooks/id_mapping.js index f16d5fc18c..f9285d3189 100644 --- a/bbb-webhooks/id_mapping.js +++ b/bbb-webhooks/id_mapping.js @@ -2,7 +2,7 @@ const _ = require("lodash"); const async = require("async"); const redis = require("redis"); -const config = require("./config.js"); +const config = require('config'); const Logger = require("./logger.js"); const UserMapping = require("./userMapping.js"); @@ -33,13 +33,13 @@ module.exports = class IDMapping { this.externalMeetingID = null; this.internalMeetingID = null; this.lastActivity = null; - this.redisClient = config.redis.client; + this.redisClient = Application.redisClient; } save(callback) { - this.redisClient.hmset(config.redis.keys.mapping(this.id), this.toRedis(), (error, reply) => { + this.redisClient.hmset(config.get("redis.keys.mappingPrefix") + ":" + this.id, this.toRedis(), (error, reply) => { if (error != null) { Logger.error("[IDMapping] error saving mapping to redis:", error, reply); } - this.redisClient.sadd(config.redis.keys.mappings, this.id, (error, reply) => { + this.redisClient.sadd(config.get("redis.keys.mappings"), this.id, (error, reply) => { if (error != null) { Logger.error("[IDMapping] error saving mapping ID to the list of mappings:", error, reply); } db[this.internalMeetingID] = this; @@ -49,9 +49,9 @@ module.exports = class IDMapping { } destroy(callback) { - this.redisClient.srem(config.redis.keys.mappings, this.id, (error, reply) => { + this.redisClient.srem(config.get("redis.keys.mappings"), this.id, (error, reply) => { if (error != null) { Logger.error("[IDMapping] error removing mapping ID from the list of mappings:", error, reply); } - this.redisClient.del(config.redis.keys.mapping(this.id), error => { + this.redisClient.del(config.get("redis.keys.mappingPrefix") + ":" + this.id, error => { if (error != null) { Logger.error("[IDMapping] error removing mapping from redis:", error); } if (db[this.internalMeetingID]) { @@ -161,7 +161,7 @@ module.exports = class IDMapping { static cleanup() { const now = new Date().getTime(); const all = IDMapping.allSync(); - const toRemove = _.filter(all, mapping => mapping.lastActivity < (now - config.mappings.timeout)); + const toRemove = _.filter(all, mapping => mapping.lastActivity < (now - config.get("mappings.timeout"))); if (!_.isEmpty(toRemove)) { Logger.info("[IDMapping] expiring the mappings:", _.map(toRemove, map => map.print())); toRemove.forEach(mapping => { @@ -174,21 +174,21 @@ module.exports = class IDMapping { // Initializes global methods for this model. static initialize(callback) { IDMapping.resync(callback); - IDMapping.cleanupInterval = setInterval(IDMapping.cleanup, config.mappings.cleanupInterval); + IDMapping.cleanupInterval = setInterval(IDMapping.cleanup, config.get("mappings.cleanupInterval")); } // Gets all mappings from redis to populate the local database. // Calls `callback()` when done. static resync(callback) { - let client = config.redis.client; + let client = Application.redisClient; let tasks = []; - return client.smembers(config.redis.keys.mappings, (error, mappings) => { + return client.smembers(config.get("redis.keys.mappings"), (error, mappings) => { if (error != null) { Logger.error("[IDMapping] error getting list of mappings from redis:", error); } mappings.forEach(id => { tasks.push(done => { - client.hgetall(config.redis.keys.mapping(id), function(error, mappingData) { + client.hgetall(config.get("redis.keys.mappingPrefix") + ":" + id, function(error, mappingData) { if (error != null) { Logger.error("[IDMapping] error getting information for a mapping from redis:", error); } if (mappingData != null) { diff --git a/bbb-webhooks/messageMapping.js b/bbb-webhooks/messageMapping.js index 2a958ed488..a2c72684b4 100644 --- a/bbb-webhooks/messageMapping.js +++ b/bbb-webhooks/messageMapping.js @@ -1,4 +1,3 @@ -const config = require("./config.js"); const Logger = require("./logger.js"); const IDMapping = require("./id_mapping.js"); const UserMapping = require("./userMapping.js"); diff --git a/bbb-webhooks/package-lock.json b/bbb-webhooks/package-lock.json index a42e64503e..c81cb86eab 100644 --- a/bbb-webhooks/package-lock.json +++ b/bbb-webhooks/package-lock.json @@ -1,6 +1,6 @@ { "name": "bbb-callbacks", - "version": "0.9.0", + "version": "2.2.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -50,6 +50,14 @@ "uri-js": "^4.2.2" } }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, "array-flatten": { "version": "1.1.1", "resolved": "http://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -377,6 +385,15 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, + "config": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/config/-/config-1.30.0.tgz", + "integrity": "sha1-HWCp81NIoTwXV5jThOgaWhbDum4=", + "requires": { + "json5": "0.4.0", + "os-homedir": "1.0.2" + } + }, "content-disposition": { "version": "0.5.2", "resolved": "http://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", @@ -520,6 +537,11 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", @@ -767,6 +789,15 @@ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, + "js-yaml": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.0.tgz", + "integrity": "sha512-pZZoSxcCYco+DIKBTimr67J6Hy+EYGZDY/HCWC+iAEA9h1ByhMXAIVUXMcMFpOCxQ/xjXmPI2MkDL5HRm5eFrQ==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", @@ -787,6 +818,11 @@ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, + "json5": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.4.0.tgz", + "integrity": "sha1-BUNS5MTIDIbAkjh31EneF2pzLI0=" + }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -1034,6 +1070,11 @@ "resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz", "integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4=" }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, "parseurl": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", @@ -1249,6 +1290,11 @@ "supports-color": "^5.5.0" } }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, "sshpk": { "version": "1.15.2", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz", diff --git a/bbb-webhooks/package.json b/bbb-webhooks/package.json index 2a33799b1c..d5364d8c13 100755 --- a/bbb-webhooks/package.json +++ b/bbb-webhooks/package.json @@ -1,6 +1,6 @@ { "name": "bbb-callbacks", - "version": "0.9.0", + "version": "2.2.0", "description": "A module for BigBlueButton for API callbacks", "keywords": [ "bigbluebutton", @@ -17,7 +17,9 @@ "request": "2.88.0", "sha1": "1.1.1", "sinon": "^7.2.2", - "winston": "3.1.0" + "winston": "3.1.0", + "config": "1.30.0", + "js-yaml": "3.13.0" }, "engines": { "node": "8.4.0" diff --git a/bbb-webhooks/responses.js b/bbb-webhooks/responses.js new file mode 100644 index 0000000000..fd814d0354 --- /dev/null +++ b/bbb-webhooks/responses.js @@ -0,0 +1,46 @@ +responses = {}; +responses.failure = (key, msg) => + `<response> \ +<returncode>FAILED</returncode> \ +<messageKey>${key}</messageKey> \ +<message>${msg}</message> \ +</response>` +; +responses.checksumError = + responses.failure("checksumError", "You did not pass the checksum security check."); + +responses.createSuccess = (id, permanent, getRaw) => + `<response> \ +<returncode>SUCCESS</returncode> \ +<hookID>${id}</hookID> \ +<permanentHook>${permanent}</permanentHook> \ +<rawData>${getRaw}</rawData> \ +</response>` +; +responses.createFailure = + responses.failure("createHookError", "An error happened while creating your hook. Check the logs."); +responses.createDuplicated = id => + `<response> \ +<returncode>SUCCESS</returncode> \ +<hookID>${id}</hookID> \ +<messageKey>duplicateWarning</messageKey> \ +<message>There is already a hook for this callback URL.</message> \ +</response>` +; + +responses.destroySuccess = + `<response> \ +<returncode>SUCCESS</returncode> \ +<removed>true</removed> \ +</response>`; +responses.destroyFailure = + responses.failure("destroyHookError", "An error happened while removing your hook. Check the logs."); +responses.destroyNoHook = + responses.failure("destroyMissingHook", "The hook informed was not found."); + +responses.missingParamCallbackURL = + responses.failure("missingParamCallbackURL", "You must specify a callbackURL in the parameters."); +responses.missingParamHookID = + responses.failure("missingParamHookID", "You must specify a hookID in the parameters."); + +module.exports = responses; diff --git a/bbb-webhooks/test/test.js b/bbb-webhooks/test/test.js index 7239b9f16f..0e4dfc2f90 100644 --- a/bbb-webhooks/test/test.js +++ b/bbb-webhooks/test/test.js @@ -3,20 +3,20 @@ const nock = require("nock"); const Application = require('../application.js'); const Logger = require('../logger.js'); const utils = require('../utils.js'); -const config = require('../config.js'); +const config = require('config'); const Hook = require('../hook.js'); const Helpers = require('./helpers.js') const sinon = require('sinon'); const winston = require('winston'); -const sharedSecret = process.env.SHARED_SECRET || sharedSecret; +const sharedSecret = sharedSecret; // Block winston from logging Logger.remove(winston.transports.Console); describe('bbb-webhooks tests', () => { before( (done) => { - config.hooks.queueSize = 10; - config.hooks.permanentURLs = [ { url: "http://wh.requestcatcher.com", getRaw: true } ]; + config.get(hooks.queueSize) = 10; + config.get(hooks.permanentURLs) = [ { url: "http://wh.requestcatcher.com", getRaw: true } ]; application = new Application(); application.start( () => { done(); @@ -24,7 +24,7 @@ describe('bbb-webhooks tests', () => { }); beforeEach( (done) => { hooks = Hook.allGlobalSync(); - Helpers.flushall(config.redis.client); + Helpers.flushall(Application.redisClient); hooks.forEach( hook => { Helpers.flushredis(hook); }) @@ -32,7 +32,7 @@ describe('bbb-webhooks tests', () => { }) after( () => { hooks = Hook.allGlobalSync(); - Helpers.flushall(config.redis.client); + Helpers.flushall(Application.redisClient); hooks.forEach( hook => { Helpers.flushredis(hook); }) @@ -112,7 +112,7 @@ describe('bbb-webhooks tests', () => { .expect('Content-Type', /text\/xml/) .expect(200, (res) => { const hooks = Hook.allGlobalSync(); - if (hooks && hooks[0].callbackURL == config.hooks.permanentURLs[0].url) { + if (hooks && hooks[0].callbackURL == config.get(hooks.permanentURLs)[0].url) { done(); } else { @@ -148,7 +148,7 @@ describe('bbb-webhooks tests', () => { describe('Hook queues', () => { before( () => { - config.redis.pubSubClient.psubscribe("test-channel"); + config.get(Application.redisClient.psubscribe)("test-channel"); Hook.addSubscription(Helpers.callback,null,false, (err,reply) => { const hooks = Hook.allGlobalSync(); const hook = hooks[0]; @@ -164,10 +164,10 @@ describe('bbb-webhooks tests', () => { hook._processQueue.restore(); hook2._processQueue.restore(); Hook.removeSubscription(hooks[hooks.length-1].id); - config.redis.pubSubClient.unsubscribe("test-channel"); + config.get(Application.redisClient.unsubscribe)("test-channel"); }); it('should have different queues for each hook', (done) => { - config.redis.client.publish("test-channel", JSON.stringify(Helpers.rawMessage)); + config.get(Application.redisClient.publish)("test-channel", JSON.stringify(Helpers.rawMessage)); const hooks = Hook.allGlobalSync(); if (hooks && hooks[0].queue != hooks[hooks.length-1].queue) { @@ -196,7 +196,7 @@ describe('bbb-webhooks tests', () => { hook = hook[0]; for(i=0;i<=9;i++) { hook.enqueue("message" + i); } - if (hook && hook.queue.length <= config.hooks.queueSize) { + if (hook && hook.queue.length <= config.get(hooks.queueSize)) { done(); } else { @@ -207,7 +207,7 @@ describe('bbb-webhooks tests', () => { describe('/POST mapped message', () => { before( () => { - config.redis.pubSubClient.psubscribe("test-channel"); + config.get(Application.redisClient.psubscribe)("test-channel"); const hooks = Hook.allGlobalSync(); const hook = hooks[0]; hook.queue = []; @@ -217,13 +217,13 @@ describe('bbb-webhooks tests', () => { const hooks = Hook.allGlobalSync(); const hook = hooks[0]; Helpers.flushredis(hook); - config.redis.pubSubClient.unsubscribe("test-channel"); + config.get(Application.redisClient.unsubscribe)("test-channel"); }) it('should post mapped message ', (done) => { const hooks = Hook.allGlobalSync(); const hook = hooks[0]; - const getpost = nock(config.hooks.permanentURLs[0].url) + const getpost = nock(config.get(hooks.permanentURLs)[0].url) .filteringRequestBody( (body) => { let parsed = JSON.parse(body) return parsed[0].data.id ? "mapped" : "not mapped"; @@ -232,13 +232,13 @@ describe('bbb-webhooks tests', () => { .reply(200, (res) => { done(); }); - config.redis.client.publish("test-channel", JSON.stringify(Helpers.rawMessage)); + config.get(Application.redisClient.publish)("test-channel", JSON.stringify(Helpers.rawMessage)); }) }); describe('/POST raw message', () => { before( () => { - config.redis.pubSubClient.psubscribe("test-channel"); + config.get(Application.redisClient.psubscribe)("test-channel"); Hook.addSubscription(Helpers.callback,null,true, (err,hook) => { Helpers.flushredis(hook); }) @@ -247,7 +247,7 @@ describe('bbb-webhooks tests', () => { const hooks = Hook.allGlobalSync(); Hook.removeSubscription(hooks[hooks.length-1].id); Helpers.flushredis(hooks[hooks.length-1]); - config.redis.pubSubClient.unsubscribe("test-channel"); + config.get(Application.redisClient.unsubscribe)("test-channel"); }); it('should post raw message ', (done) => { const hooks = Hook.allGlobalSync(); @@ -264,10 +264,10 @@ describe('bbb-webhooks tests', () => { .reply(200, () => { done(); }); - const permanent = nock(config.hooks.permanentURLs[0].url) + const permanent = nock(config.get(hooks.permanentURLs)[0].url) .post("/") .reply(200) - config.redis.client.publish("test-channel", JSON.stringify(Helpers.rawMessage)); + config.get(Application.redisClient.publish)("test-channel", JSON.stringify(Helpers.rawMessage)); }) }); @@ -282,7 +282,7 @@ describe('bbb-webhooks tests', () => { const hooks = Hook.allGlobalSync(); const hook = hooks[0]; hook.enqueue("multiMessage2") - const getpost = nock(config.hooks.permanentURLs[0].url) + const getpost = nock(config.get(hooks.permanentURLs)[0].url) .filteringPath( (path) => { return path.split('?')[0]; }) diff --git a/bbb-webhooks/userMapping.js b/bbb-webhooks/userMapping.js index bf11b4a031..3571396a52 100644 --- a/bbb-webhooks/userMapping.js +++ b/bbb-webhooks/userMapping.js @@ -2,7 +2,7 @@ const _ = require("lodash"); const async = require("async"); const redis = require("redis"); -const config = require("./config.js"); +const config = require("config"); const Logger = require("./logger.js"); // The database of mappings. Uses the internal ID as key because it is unique @@ -33,15 +33,15 @@ module.exports = class UserMapping { this.internalUserID = null; this.meetingId = null; this.user = null; - this.redisClient = config.redis.client; + this.redisClient = Application.redisClient; } save(callback) { db[this.internalUserID] = this; - this.redisClient.hmset(config.redis.keys.userMap(this.id), this.toRedis(), (error, reply) => { + this.redisClient.hmset(config.get("redis.keys.userMapPrefix") + ":" + this.id, this.toRedis(), (error, reply) => { if (error != null) { Logger.error("[UserMapping] error saving mapping to redis:", error, reply); } - this.redisClient.sadd(config.redis.keys.userMaps, this.id, (error, reply) => { + this.redisClient.sadd(config.get("redis.keys.userMaps"), this.id, (error, reply) => { if (error != null) { Logger.error("[UserMapping] error saving mapping ID to the list of mappings:", error, reply); } (typeof callback === 'function' ? callback(error, db[this.internalUserID]) : undefined); @@ -50,9 +50,9 @@ module.exports = class UserMapping { } destroy(callback) { - this.redisClient.srem(config.redis.keys.userMaps, this.id, (error, reply) => { + this.redisClient.srem(config.get("redis.keys.userMaps"), this.id, (error, reply) => { if (error != null) { Logger.error("[UserMapping] error removing mapping ID from the list of mappings:", error, reply); } - this.redisClient.del(config.redis.keys.userMap(this.id), error => { + this.redisClient.del(config.get("redis.keys.userMapPrefix") + ":" + this.id, error => { if (error != null) { Logger.error("[UserMapping] error removing mapping from redis:", error); } if (db[this.internalUserID]) { @@ -165,15 +165,15 @@ module.exports = class UserMapping { // Gets all mappings from redis to populate the local database. // Calls `callback()` when done. static resync(callback) { - let client = config.redis.client; + let client = Application.redisClient; let tasks = []; - return client.smembers(config.redis.keys.userMaps, (error, mappings) => { + return client.smembers(config.get("redis.keys.userMaps"), (error, mappings) => { if (error != null) { Logger.error("[UserMapping] error getting list of mappings from redis:", error); } mappings.forEach(id => { tasks.push(done => { - client.hgetall(config.redis.keys.userMap(id), function(error, mappingData) { + client.hgetall(config.get("redis.keys.userMapPrefix") + ":" + id, function(error, mappingData) { if (error != null) { Logger.error("[UserMapping] error getting information for a mapping from redis:", error); } if (mappingData != null) { diff --git a/bbb-webhooks/utils.js b/bbb-webhooks/utils.js index c169e9c7b9..77c844253e 100644 --- a/bbb-webhooks/utils.js +++ b/bbb-webhooks/utils.js @@ -1,7 +1,7 @@ const sha1 = require("sha1"); const url = require("url"); -const config = require("./config"); +const config = require("config"); const Utils = exports; @@ -45,7 +45,7 @@ Utils.queryFromUrl = function(fullUrl) { // * returns: `create` Utils.methodFromUrl = function(fullUrl) { const urlObj = url.parse(fullUrl, true); - return urlObj.pathname.substr((config.bbb.apiPath + "/").length); + return urlObj.pathname.substr((config.get("bbb.apiPath") + "/").length); }; // Returns the IP address of the client that made a request `req`. diff --git a/bbb-webhooks/web_hooks.js b/bbb-webhooks/web_hooks.js index 787027787a..9f2531ad1c 100644 --- a/bbb-webhooks/web_hooks.js +++ b/bbb-webhooks/web_hooks.js @@ -2,7 +2,7 @@ const _ = require("lodash"); const async = require("async"); const redis = require("redis"); const request = require("request"); -const config = require("./config.js"); +const config = require("config"); const Hook = require("./hook.js"); const IDMapping = require("./id_mapping.js"); const Logger = require("./logger.js"); @@ -14,7 +14,7 @@ const UserMapping = require("./userMapping.js"); module.exports = class WebHooks { constructor() { - this.subscriberEvents = config.redis.pubSubClient; + this.subscriberEvents = Application.redisClient; } start(callback) { @@ -73,8 +73,8 @@ module.exports = class WebHooks { } }); - for (let k in config.hooks.channels) { - const channel = config.hooks.channels[k]; + for (i = 0; i < config.get("hooks.channels"); ++i) { + const channel = config.get("hooks.channels")[i]; this.subscriberEvents.psubscribe(channel); } } @@ -142,7 +142,7 @@ module.exports = class WebHooks { }); const sendRaw = hooks.some(hook => { return hook.getRaw }); - if (sendRaw && config.hooks.getRaw) { + if (sendRaw && config.get("hooks.getRaw")) { this._processRaw(raw); } } diff --git a/bbb-webhooks/web_server.js b/bbb-webhooks/web_server.js index be5a005783..c95b43bb6f 100644 --- a/bbb-webhooks/web_server.js +++ b/bbb-webhooks/web_server.js @@ -2,10 +2,11 @@ const _ = require("lodash"); const express = require("express"); const url = require("url"); -const config = require("./config.js"); +const config = require("config"); const Hook = require("./hook.js"); const Logger = require("./logger.js"); const Utils = require("./utils.js"); +const responses = require("./responses.js") // Web server that listens for API calls and process them. module.exports = class WebServer { @@ -56,16 +57,16 @@ module.exports = class WebServer { } if (callbackURL == null) { - respondWithXML(res, config.api.responses.missingParamCallbackURL); + respondWithXML(res, responses.missingParamCallbackURL); } else { Hook.addSubscription(callbackURL, meetingID, getRaw, function(error, hook) { let msg; if (error != null) { // the only error for now is for duplicated callbackURL - msg = config.api.responses.createDuplicated(hook.id); + msg = responses.createDuplicated(hook.id); } else if (hook != null) { - msg = config.api.responses.createSuccess(hook.id, hook.permanent, hook.getRaw); + msg = responses.createSuccess(hook.id, hook.permanent, hook.getRaw); } else { - msg = config.api.responses.createFailure; + msg = responses.createFailure; } respondWithXML(res, msg); }); @@ -73,8 +74,8 @@ module.exports = class WebServer { } // Create a permanent hook. Permanent hooks can't be deleted via API and will try to emit a message until it succeed createPermanents(callback) { - for (let i = 0; i < config.hooks.permanentURLs.length; i++) { - Hook.addSubscription(config.hooks.permanentURLs[i].url, null, config.hooks.permanentURLs[i].getRaw, function(error, hook) { + for (let i = 0; i < config.get("hooks.permanentURLs").length; i++) { + Hook.addSubscription(config.get("hooks.permanentURLs")[i].url, null, config.get("hooks.permanentURLs")[i].getRaw, function(error, hook) { if (error != null) { // there probably won't be any errors here Logger.info("[WebServer] duplicated permanent hook", error); } else if (hook != null) { @@ -92,16 +93,16 @@ module.exports = class WebServer { const hookID = urlObj.query["hookID"]; if (hookID == null) { - respondWithXML(res, config.api.responses.missingParamHookID); + respondWithXML(res, responses.missingParamHookID); } else { Hook.removeSubscription(hookID, function(error, result) { let msg; if (error != null) { - msg = config.api.responses.destroyFailure; + msg = responses.destroyFailure; } else if (!result) { - msg = config.api.responses.destroyNoHook; + msg = responses.destroyNoHook; } else { - msg = config.api.responses.destroySuccess; + msg = responses.destroySuccess; } respondWithXML(res, msg); }); @@ -144,14 +145,14 @@ module.exports = class WebServer { _validateChecksum(req, res, next) { const urlObj = url.parse(req.url, true); const checksum = urlObj.query["checksum"]; - const sharedSecret = process.env.SHARED_SECRET || config.bbb.sharedSecret; + const sharedSecret = config.get("bbb.sharedSecret"); if (checksum === Utils.checksumAPI(req.url, sharedSecret)) { next(); } else { Logger.info("[WebServer] checksum check failed, sending a checksumError response"); res.setHeader("Content-Type", "text/xml"); - res.send(cleanupXML(config.api.responses.checksumError)); + res.send(cleanupXML(responses.checksumError)); } } }; -- GitLab