diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json
index 178c455ea1e..ee6840338c4 100644
--- a/packages/rocketchat-i18n/i18n/en.i18n.json
+++ b/packages/rocketchat-i18n/i18n/en.i18n.json
@@ -590,6 +590,7 @@
"Integration_Outgoing_WebHook": "Outgoing WebHook Integration",
"Integration_updated": "Integration has been updated",
"Integrations": "Integrations",
+ "Integrations_for_all_channels": "Enter all_public_channels to listen on all public channels, all_private_groups to listen on all private groups, and all_direct_messages to listen to all direct messages.",
"InternalHubot": "Internal Hubot",
"InternalHubot_ScriptsToLoad": "Scripts to load",
"InternalHubot_ScriptsToLoad_Description": "Please enter a comma separated list of scripts to load from https://github.com/github/hubot-scripts/tree/master/src/scripts",
@@ -1424,4 +1425,4 @@
"your_message_optional": "your message (optional)",
"Your_password_is_wrong": "Your password is wrong!",
"Your_push_was_sent_to_s_devices": "Your push was sent to %s devices"
-}
\ No newline at end of file
+}
diff --git a/packages/rocketchat-integrations/client/views/integrationsOutgoing.html b/packages/rocketchat-integrations/client/views/integrationsOutgoing.html
index 4d7bca6929e..49e8dc1f56a 100644
--- a/packages/rocketchat-integrations/client/views/integrationsOutgoing.html
+++ b/packages/rocketchat-integrations/client/views/integrationsOutgoing.html
@@ -25,7 +25,7 @@
{{_ "Optional channel to listen on"}}
{{{_ "Start_with_s_for_user_or_s_for_channel_Eg_s_or_s" "@" "#" "@john" "#general"}}}
- {{{_ "Leave empty to listen any public channel "}}}
+ {{{_ "Integrations_for_all_channels"}}}
diff --git a/packages/rocketchat-integrations/package.js b/packages/rocketchat-integrations/package.js
index 39251305cbe..eee59622436 100644
--- a/packages/rocketchat-integrations/package.js
+++ b/packages/rocketchat-integrations/package.js
@@ -41,6 +41,7 @@ Package.onUse(function(api) {
api.addFiles('client/stylesheets/load.coffee', 'server');
api.addFiles('server/logger.js', 'server');
+ api.addFiles('server/lib/validation.coffee', 'server');
api.addFiles('server/models/Integrations.coffee', 'server');
diff --git a/packages/rocketchat-integrations/server/lib/validation.coffee b/packages/rocketchat-integrations/server/lib/validation.coffee
new file mode 100644
index 00000000000..a9ac119e268
--- /dev/null
+++ b/packages/rocketchat-integrations/server/lib/validation.coffee
@@ -0,0 +1,90 @@
+RocketChat.integrations.validateOutgoing = (integration, userId) ->
+ if integration.channel?.trim? and integration.channel.trim() is ''
+ delete integration.channel
+
+ if integration.username.trim() is ''
+ throw new Meteor.Error 'error-invalid-username', 'Invalid username', { method: 'addOutgoingIntegration' }
+
+ if not Match.test integration.urls, [String]
+ throw new Meteor.Error 'error-invalid-urls', 'Invalid URLs', { method: 'addOutgoingIntegration' }
+
+ for url, index in integration.urls
+ delete integration.urls[index] if url.trim() is ''
+
+ integration.urls = _.without integration.urls, [undefined]
+
+ if integration.urls.length is 0
+ throw new Meteor.Error 'error-invalid-urls', 'Invalid URLs', { method: 'addOutgoingIntegration' }
+
+ channels = if integration.channel then _.map(integration.channel.split(','), (channel) -> s.trim(channel)) else []
+
+ scopedChannels = ['all_public_channels', 'all_private_groups', 'all_direct_messages']
+ for channel in channels
+ if channel[0] not in ['@', '#'] and channel not in scopedChannels
+ throw new Meteor.Error 'error-invalid-channel-start-with-chars', 'Invalid channel. Start with @ or #', { method: 'updateIncomingIntegration' }
+
+ if integration.triggerWords?
+ if not Match.test integration.triggerWords, [String]
+ throw new Meteor.Error 'error-invalid-triggerWords', 'Invalid triggerWords', { method: 'addOutgoingIntegration' }
+
+ for triggerWord, index in integration.triggerWords
+ delete integration.triggerWords[index] if triggerWord.trim() is ''
+
+ integration.triggerWords = _.without integration.triggerWords, [undefined]
+
+ if integration.scriptEnabled is true and integration.script? and integration.script.trim() isnt ''
+ try
+ babelOptions = Babel.getDefaultOptions({ runtime: false })
+ babelOptions = _.extend(babelOptions, { compact: true, minified: true, comments: false })
+
+ integration.scriptCompiled = Babel.compile(integration.script, babelOptions).code
+ integration.scriptError = undefined
+ catch e
+ integration.scriptCompiled = undefined
+ integration.scriptError = _.pick e, 'name', 'message', 'stack'
+
+
+ for channel in channels
+ if channel in scopedChannels
+ if channel is 'all_public_channels'
+ #No special permissions needed to add integration to public channels
+ else if not RocketChat.authz.hasPermission userId, 'manage-integrations'
+ throw new Meteor.Error 'error-invalid-channel', 'Invalid Channel', { method: 'addOutgoingIntegration' }
+ else
+ record = undefined
+ channelType = channel[0]
+ channel = channel.substr(1)
+
+ switch channelType
+ when '#'
+ record = RocketChat.models.Rooms.findOne
+ $or: [
+ {_id: channel}
+ {name: channel}
+ ]
+ when '@'
+ record = RocketChat.models.Users.findOne
+ $or: [
+ {_id: channel}
+ {username: channel}
+ ]
+
+ if record is undefined
+ throw new Meteor.Error 'error-invalid-room', 'Invalid room', { method: 'addOutgoingIntegration' }
+
+ if record.usernames? and
+ (not RocketChat.authz.hasPermission userId, 'manage-integrations') and
+ (RocketChat.authz.hasPermission userId, 'manage-own-integrations') and
+ Meteor.user()?.username not in record.usernames
+ throw new Meteor.Error 'error-invalid-channel', 'Invalid Channel', { method: 'addOutgoingIntegration' }
+
+ user = RocketChat.models.Users.findOne({username: integration.username})
+
+ if not user?
+ throw new Meteor.Error 'error-invalid-user', 'Invalid user', { method: 'addOutgoingIntegration' }
+
+ integration.type = 'webhook-outgoing'
+ integration.userId = user._id
+ integration.channel = channels
+
+ return integration
diff --git a/packages/rocketchat-integrations/server/methods/outgoing/addOutgoingIntegration.coffee b/packages/rocketchat-integrations/server/methods/outgoing/addOutgoingIntegration.coffee
index 90e9860285c..af42d9bb291 100644
--- a/packages/rocketchat-integrations/server/methods/outgoing/addOutgoingIntegration.coffee
+++ b/packages/rocketchat-integrations/server/methods/outgoing/addOutgoingIntegration.coffee
@@ -1,7 +1,5 @@
Meteor.methods
addOutgoingIntegration: (integration) ->
- if integration.channel?.trim? and integration.channel.trim() is ''
- delete integration.channel
if (not RocketChat.authz.hasPermission @userId, 'manage-integrations') and
not (RocketChat.authz.hasPermission @userId, 'manage-own-integrations') and
@@ -9,82 +7,8 @@ Meteor.methods
not (RocketChat.authz.hasPermission @userId, 'manage-own-integrations', 'bot')
throw new Meteor.Error 'not_authorized'
- if integration.username.trim() is ''
- throw new Meteor.Error 'error-invalid-username', 'Invalid username', { method: 'addOutgoingIntegration' }
+ integration = RocketChat.integrations.validateOutgoing(integration, @userId)
- if not Match.test integration.urls, [String]
- throw new Meteor.Error 'error-invalid-urls', 'Invalid URLs', { method: 'addOutgoingIntegration' }
-
- for url, index in integration.urls
- delete integration.urls[index] if url.trim() is ''
-
- integration.urls = _.without integration.urls, [undefined]
-
- if integration.urls.length is 0
- throw new Meteor.Error 'error-invalid-urls', 'Invalid URLs', { method: 'addOutgoingIntegration' }
-
- channels = if integration.channel then _.map(integration.channel.split(','), (channel) -> s.trim(channel)) else []
-
- for channel in channels
- if channel[0] not in ['@', '#']
- throw new Meteor.Error 'error-invalid-channel-start-with-chars', 'Invalid channel. Start with @ or #', { method: 'updateIncomingIntegration' }
-
- if integration.triggerWords?
- if not Match.test integration.triggerWords, [String]
- throw new Meteor.Error 'error-invalid-triggerWords', 'Invalid triggerWords', { method: 'addOutgoingIntegration' }
-
- for triggerWord, index in integration.triggerWords
- delete integration.triggerWords[index] if triggerWord.trim() is ''
-
- integration.triggerWords = _.without integration.triggerWords, [undefined]
-
- if integration.scriptEnabled is true and integration.script? and integration.script.trim() isnt ''
- try
- babelOptions = Babel.getDefaultOptions({ runtime: false })
- babelOptions = _.extend(babelOptions, { compact: true, minified: true, comments: false })
-
- integration.scriptCompiled = Babel.compile(integration.script, babelOptions).code
- integration.scriptError = undefined
- catch e
- integration.scriptCompiled = undefined
- integration.scriptError = _.pick e, 'name', 'message', 'stack'
-
-
- for channel in channels
- record = undefined
- channelType = channel[0]
- channel = channel.substr(1)
-
- switch channelType
- when '#'
- record = RocketChat.models.Rooms.findOne
- $or: [
- {_id: channel}
- {name: channel}
- ]
- when '@'
- record = RocketChat.models.Users.findOne
- $or: [
- {_id: channel}
- {username: channel}
- ]
-
- if record is undefined
- throw new Meteor.Error 'error-invalid-room', 'Invalid room', { method: 'addOutgoingIntegration' }
-
- if record.usernames? and
- (not RocketChat.authz.hasPermission @userId, 'manage-integrations') and
- (RocketChat.authz.hasPermission @userId, 'manage-own-integrations') and
- Meteor.user()?.username not in record.usernames
- throw new Meteor.Error 'error-invalid-channel', 'Invalid Channel', { method: 'addOutgoingIntegration' }
-
- user = RocketChat.models.Users.findOne({username: integration.username})
-
- if not user?
- throw new Meteor.Error 'error-invalid-user', 'Invalid user', { method: 'addOutgoingIntegration' }
-
- integration.type = 'webhook-outgoing'
- integration.userId = user._id
integration._createdAt = new Date
integration._createdBy = RocketChat.models.Users.findOne @userId, {fields: {username: 1}}
diff --git a/packages/rocketchat-integrations/server/methods/outgoing/updateOutgoingIntegration.coffee b/packages/rocketchat-integrations/server/methods/outgoing/updateOutgoingIntegration.coffee
index c1bc0c2aca8..d9db71a1484 100644
--- a/packages/rocketchat-integrations/server/methods/outgoing/updateOutgoingIntegration.coffee
+++ b/packages/rocketchat-integrations/server/methods/outgoing/updateOutgoingIntegration.coffee
@@ -1,43 +1,10 @@
Meteor.methods
updateOutgoingIntegration: (integrationId, integration) ->
-
- if integration.username.trim() is ''
- throw new Meteor.Error 'error-invalid-username', 'Invalid username', { method: 'updateOutgoingIntegration' }
-
- if not Match.test integration.urls, [String]
- throw new Meteor.Error 'error-invalid-urls', 'Invalid URLs', { method: 'updateOutgoingIntegration' }
-
- for url, index in integration.urls
- delete integration.urls[index] if url.trim() is ''
-
- integration.urls = _.without integration.urls, [undefined]
-
- if integration.urls.length is 0
- throw new Meteor.Error 'error-invalid-urls', 'Invalid URLs', { method: 'updateOutgoingIntegration' }
-
- if _.isString(integration.channel)
- integration.channel = integration.channel.trim()
- else
- integration.channel = undefined
-
- channels = if integration.channel then _.map(integration.channel.split(','), (channel) -> s.trim(channel)) else []
-
- for channel in channels
- if channel[0] not in ['@', '#']
- throw new Meteor.Error 'error-invalid-channel-start-with-chars', 'Invalid channel. Start with @ or #', { method: 'updateIncomingIntegration' }
+ integration = RocketChat.integrations.validateOutgoing(integration, @userId)
if not integration.token? or integration.token?.trim() is ''
throw new Meteor.Error 'error-invalid-token', 'Invalid token', { method: 'updateOutgoingIntegration' }
- if integration.triggerWords?
- if not Match.test integration.triggerWords, [String]
- throw new Meteor.Error 'error-invalid-triggerWords', 'Invalid triggerWords', { method: 'updateOutgoingIntegration' }
-
- for triggerWord, index in integration.triggerWords
- delete integration.triggerWords[index] if triggerWord.trim() is ''
-
- integration.triggerWords = _.without integration.triggerWords, [undefined]
-
currentIntegration = null
if RocketChat.authz.hasPermission @userId, 'manage-integrations'
@@ -50,50 +17,6 @@ Meteor.methods
if not currentIntegration?
throw new Meteor.Error 'invalid_integration', '[methods] updateOutgoingIntegration -> integration not found'
- if integration.scriptEnabled is true and integration.script? and integration.script.trim() isnt ''
- try
- babelOptions = Babel.getDefaultOptions({ runtime: false })
- babelOptions = _.extend(babelOptions, { compact: true, minified: true, comments: false })
-
- integration.scriptCompiled = Babel.compile(integration.script, babelOptions).code
- integration.scriptError = undefined
- catch e
- integration.scriptCompiled = undefined
- integration.scriptError = _.pick e, 'name', 'message', 'stack',
-
-
- for channel in channels
- record = undefined
- channelType = channel[0]
- channel = channel.substr(1)
-
- switch channelType
- when '#'
- record = RocketChat.models.Rooms.findOne
- $or: [
- {_id: channel}
- {name: channel}
- ]
- when '@'
- record = RocketChat.models.Users.findOne
- $or: [
- {_id: channel}
- {username: channel}
- ]
-
- if record is undefined
- throw new Meteor.Error 'error-invalid-room', 'Invalid room', { method: 'updateOutgoingIntegration' }
-
- if record.usernames? and
- (not RocketChat.authz.hasPermission @userId, 'manage-integrations') and
- (RocketChat.authz.hasPermission @userId, 'manage-own-integrations') and
- Meteor.user()?.username not in record.usernames
- throw new Meteor.Error 'error-invalid-channel', 'Invalid Channel', { method: 'updateOutgoingIntegration' }
-
- user = RocketChat.models.Users.findOne({username: integration.username})
-
- if not user?
- throw new Meteor.Error 'error-invalid-user', 'Invalid user', { method: 'updateOutgoingIntegration' }
RocketChat.models.Integrations.update integrationId,
$set:
@@ -102,9 +25,9 @@ Meteor.methods
avatar: integration.avatar
emoji: integration.emoji
alias: integration.alias
- channel: channels
+ channel: integration.channel
username: integration.username
- userId: user._id
+ userId: integration.userId
urls: integration.urls
token: integration.token
script: integration.script
diff --git a/packages/rocketchat-integrations/server/triggers.coffee b/packages/rocketchat-integrations/server/triggers.coffee
index 625bbad822b..5ea52c66696 100644
--- a/packages/rocketchat-integrations/server/triggers.coffee
+++ b/packages/rocketchat-integrations/server/triggers.coffee
@@ -278,6 +278,9 @@ ExecuteTriggers = (message, room) ->
if triggers['@'+id]?
triggersToExecute.push trigger for key, trigger of triggers['@'+id]
+ if triggers.all_direct_messages?
+ triggersToExecute.push trigger for key, trigger of triggers.all_direct_messages
+
if id isnt username and triggers['@'+username]?
triggersToExecute.push trigger for key, trigger of triggers['@'+username]
@@ -285,6 +288,9 @@ ExecuteTriggers = (message, room) ->
if triggers.__any?
triggersToExecute.push trigger for key, trigger of triggers.__any
+ if triggers.all_public_channels?
+ triggersToExecute.push trigger for key, trigger of triggers.all_public_channels
+
if triggers['#'+room._id]?
triggersToExecute.push trigger for key, trigger of triggers['#'+room._id]
@@ -292,6 +298,9 @@ ExecuteTriggers = (message, room) ->
triggersToExecute.push trigger for key, trigger of triggers['#'+room.name]
else
+ if triggers.all_private_groups?
+ triggersToExecute.push trigger for key, trigger of triggers.all_private_groups
+
if triggers['#'+room._id]?
triggersToExecute.push trigger for key, trigger of triggers['#'+room._id]