From 509f1798492fd7e7fc4094604ab5cdbc0d9d741c Mon Sep 17 00:00:00 2001 From: Bradley Hilton Date: Thu, 1 Feb 2018 16:24:21 -0600 Subject: [PATCH] Fix incoming integrations being able to trigger a new message with a GET if there is no script enabled --- .../rocketchat-integrations/server/api/api.js | 114 +++++++++++------- 1 file changed, 68 insertions(+), 46 deletions(-) diff --git a/packages/rocketchat-integrations/server/api/api.js b/packages/rocketchat-integrations/server/api/api.js index f2b563272c172..a64e0124c6322 100644 --- a/packages/rocketchat-integrations/server/api/api.js +++ b/packages/rocketchat-integrations/server/api/api.js @@ -1,4 +1,4 @@ -/* globals Api Meteor Restivus logger processWebhookMessage*/ +/* globals Meteor Restivus logger processWebhookMessage*/ // TODO: remove globals import _ from 'underscore'; @@ -6,6 +6,57 @@ import s from 'underscore.string'; import vm from 'vm'; import moment from 'moment'; +const Api = new Restivus({ + enableCors: true, + apiPath: 'hooks/', + auth: { + user() { + const payloadKeys = Object.keys(this.bodyParams); + const payloadIsWrapped = (this.bodyParams && this.bodyParams.payload) && payloadKeys.length === 1; + if (payloadIsWrapped && this.request.headers['content-type'] === 'application/x-www-form-urlencoded') { + try { + this.bodyParams = JSON.parse(this.bodyParams.payload); + } catch ({message}) { + return { + error: { + statusCode: 400, + body: { + success: false, + error: message + } + } + }; + } + } + + this.integration = RocketChat.models.Integrations.findOne({ + _id: this.request.params.integrationId, + token: decodeURIComponent(this.request.params.token) + }); + + if (!this.integration) { + logger.incoming.info('Invalid integration id', this.request.params.integrationId, 'or token', this.request.params.token); + + return { + error: { + statusCode: 404, + body: { + success: false, + error: 'Invalid integration id or token provided.' + } + } + }; + } + + const user = RocketChat.models.Users.findOne({ + _id: this.integration.userId + }); + + return { user }; + } + } +}); + const compiledScripts = {}; function buildSandbox(store = {}) { const sandbox = { @@ -41,78 +92,45 @@ function buildSandbox(store = {}) { function getIntegrationScript(integration) { const compiledScript = compiledScripts[integration._id]; - if ((compiledScript != null) && +compiledScript._updatedAt === +integration._updatedAt) { + if (compiledScript && +compiledScript._updatedAt === +integration._updatedAt) { return compiledScript.script; } + const script = integration.scriptCompiled; - const {sandbox, store} = buildSandbox(); + const { sandbox, store } = buildSandbox(); try { logger.incoming.info('Will evaluate script of Trigger', integration.name); logger.incoming.debug(script); + const vmScript = vm.createScript(script, 'script.js'); vmScript.runInNewContext(sandbox); - if (sandbox.Script != null) { + if (sandbox.Script) { compiledScripts[integration._id] = { script: new sandbox.Script(), store, _updatedAt: integration._updatedAt }; + return compiledScripts[integration._id].script; } - } catch ({stack}) { + } catch ({ stack }) { logger.incoming.error('[Error evaluating Script in Trigger', integration.name, ':]'); logger.incoming.error(script.replace(/^/gm, ' ')); logger.incoming.error('[Stack:]'); logger.incoming.error(stack.replace(/^/gm, ' ')); throw RocketChat.API.v1.failure('error-evaluating-script'); } - if (sandbox.Script == null) { + + if (!sandbox.Script) { logger.incoming.error('[Class "Script" not in Trigger', integration.name, ']'); throw RocketChat.API.v1.failure('class-script-not-found'); } } -Api = new Restivus({ - enableCors: true, - apiPath: 'hooks/', - auth: { - user() { - const payloadKeys = Object.keys(this.bodyParams); - const payloadIsWrapped = (this.bodyParams && this.bodyParams.payload) && payloadKeys.length === 1; - if (payloadIsWrapped && this.request.headers['content-type'] === 'application/x-www-form-urlencoded') { - try { - this.bodyParams = JSON.parse(this.bodyParams.payload); - } catch ({message}) { - return { - error: { - statusCode: 400, - body: { - success: false, - error: message - } - } - }; - } - } - this.integration = RocketChat.models.Integrations.findOne({ - _id: this.request.params.integrationId, - token: decodeURIComponent(this.request.params.token) - }); - if (this.integration == null) { - logger.incoming.info('Invalid integration id', this.request.params.integrationId, 'or token', this.request.params.token); - return; - } - const user = RocketChat.models.Users.findOne({ - _id: this.integration.userId - }); - return {user}; - } - } -}); - function createIntegration(options, user) { logger.incoming.info('Add integration', options.name); logger.incoming.debug(options); + Meteor.runAsUser(user._id, function() { switch (options['event']) { case 'newMessageOnChannel': @@ -142,18 +160,22 @@ function createIntegration(options, user) { }); } }); + return RocketChat.API.v1.success(); } function removeIntegration(options, user) { logger.incoming.info('Remove integration'); logger.incoming.debug(options); + const integrationToRemove = RocketChat.models.Integrations.findOne({ urls: options.target_url }); + Meteor.runAsUser(user._id, () => { return Meteor.call('deleteOutgoingIntegration', integrationToRemove._id); }); + return RocketChat.API.v1.success(); } @@ -176,7 +198,7 @@ function executeIntegrationRest() { emoji: this.integration.emoji }; - if (this.integration.scriptEnabled === true && this.integration.scriptCompiled && this.integration.scriptCompiled.trim() !== '') { + if (this.integration.scriptEnabled && this.integration.scriptCompiled && this.integration.scriptCompiled.trim() !== '') { let script; try { script = getIntegrationScript(this.integration); @@ -240,7 +262,7 @@ function executeIntegrationRest() { // TODO: Turn this into an option on the integrations - no body means a success // TODO: Temporary fix for https://github.com/RocketChat/Rocket.Chat/issues/7770 until the above is implemented - if (!this.bodyParams) { + if (!this.bodyParams || (_.isEmpty(this.bodyParams) && !this.integration.scriptEnabled)) { // return RocketChat.API.v1.failure('body-empty'); return RocketChat.API.v1.success(); }