Add keywords for outgoing integrations across all public/private/direct channels

pull/4578/head
Chris Pitman 9 years ago
parent 6d856cfd1b
commit 409843c628
  1. 3
      packages/rocketchat-i18n/i18n/en.i18n.json
  2. 2
      packages/rocketchat-integrations/client/views/integrationsOutgoing.html
  3. 1
      packages/rocketchat-integrations/package.js
  4. 90
      packages/rocketchat-integrations/server/lib/validation.coffee
  5. 78
      packages/rocketchat-integrations/server/methods/outgoing/addOutgoingIntegration.coffee
  6. 83
      packages/rocketchat-integrations/server/methods/outgoing/updateOutgoingIntegration.coffee
  7. 9
      packages/rocketchat-integrations/server/triggers.coffee

@ -590,6 +590,7 @@
"Integration_Outgoing_WebHook": "Outgoing WebHook Integration",
"Integration_updated": "Integration has been updated",
"Integrations": "Integrations",
"Integrations_for_all_channels": "Enter <strong>all_public_channels</strong> to listen on all public channels, <strong>all_private_groups</strong> to listen on all private groups, and <strong>all_direct_messages</strong> 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"
}
}

@ -25,7 +25,7 @@
<input type="text" name="channel" value="{{data.channel}}" placeholder="{{_ 'User_or_channel_name'}}" />
<div class="settings-description">{{_ "Optional channel to listen on"}}</div>
<div class="settings-description">{{{_ "Start_with_s_for_user_or_s_for_channel_Eg_s_or_s" "@" "#" "@john" "#general"}}}</div>
<div class="settings-description">{{{_ "Leave empty to listen <strong>any public channel</strong>"}}}</div>
<div class="settings-description">{{{_ "Integrations_for_all_channels"}}}</div>
</div>
</div>
<div class="input-line double-col">

@ -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');

@ -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

@ -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}}

@ -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

@ -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]

Loading…
Cancel
Save