summaryrefslogtreecommitdiff
path: root/app/models/integrations
diff options
context:
space:
mode:
Diffstat (limited to 'app/models/integrations')
-rw-r--r--app/models/integrations/base_chat_notification.rb40
-rw-r--r--app/models/integrations/chat_message/base_message.rb6
-rw-r--r--app/models/integrations/jira.rb10
3 files changed, 40 insertions, 16 deletions
diff --git a/app/models/integrations/base_chat_notification.rb b/app/models/integrations/base_chat_notification.rb
index 8700b673370..963ba918089 100644
--- a/app/models/integrations/base_chat_notification.rb
+++ b/app/models/integrations/base_chat_notification.rb
@@ -23,6 +23,7 @@ module Integrations
].freeze
SECRET_MASK = '************'
+ CHANNEL_LIMIT_PER_EVENT = 10
attribute :category, default: 'chat'
@@ -37,7 +38,8 @@ module Integrations
presence: true,
public_url: true,
if: -> (integration) { integration.activated? && integration.requires_webhook? }
- validates :labels_to_be_notified_behavior, inclusion: { in: LABEL_NOTIFICATION_BEHAVIOURS }, allow_blank: true
+ validates :labels_to_be_notified_behavior, inclusion: { in: LABEL_NOTIFICATION_BEHAVIOURS }, allow_blank: true, if: :activated?
+ validate :validate_channel_limit, if: :activated?
def initialize_properties
super
@@ -132,17 +134,15 @@ module Integrations
return false unless message
- event_type = data[:event_type] || object_kind
-
- channel_names = event_channel_value(event_type).presence || channel.presence
- channels = channel_names&.split(',')&.map(&:strip)
+ event = data[:event_type] || object_kind
+ channels = channels_for_event(event)
opts = {}
opts[:channel] = channels if channels.present?
opts[:username] = username if username
if notify(message, opts)
- log_usage(event_type, user_id_from_hook_data(data))
+ log_usage(event, user_id_from_hook_data(data))
return true
end
@@ -297,6 +297,34 @@ module Integrations
false
end
end
+
+ def channels_for_event(event)
+ channel_names = event_channel_value(event).presence || channel.presence
+ return [] unless channel_names
+
+ channel_names.split(',').map(&:strip).uniq
+ end
+
+ def unique_channels
+ @unique_channels ||= supported_events.flat_map do |event|
+ channels_for_event(event)
+ end.uniq
+ end
+
+ def validate_channel_limit
+ supported_events.each do |event|
+ count = channels_for_event(event).count
+ next unless count > CHANNEL_LIMIT_PER_EVENT
+
+ errors.add(
+ event_channel_name(event).to_sym,
+ format(
+ s_('SlackIntegration|cannot have more than %{limit} channels'),
+ limit: CHANNEL_LIMIT_PER_EVENT
+ )
+ )
+ end
+ end
end
end
diff --git a/app/models/integrations/chat_message/base_message.rb b/app/models/integrations/chat_message/base_message.rb
index 554b422c0fa..501b214a769 100644
--- a/app/models/integrations/chat_message/base_message.rb
+++ b/app/models/integrations/chat_message/base_message.rb
@@ -5,10 +5,6 @@ module Integrations
class BaseMessage
RELATIVE_LINK_REGEX = %r{!\[[^\]]*\]\((/uploads/[^\)]*)\)}.freeze
- # Markup characters which are used for links in HTML, Markdown,
- # and Slack "mrkdwn" syntax (`<http://example.com|Label>`).
- UNSAFE_MARKUP_CHARACTERS = '<>[]|'
-
attr_reader :markdown
attr_reader :user_full_name
attr_reader :user_name
@@ -85,7 +81,7 @@ module Integrations
# - https://api.slack.com/reference/surfaces/formatting#escaping
# - https://gitlab.com/gitlab-org/slack-notifier#escaping
def strip_markup(string)
- string&.delete(UNSAFE_MARKUP_CHARACTERS)
+ SlackMarkdownSanitizer.sanitize(string)
end
def attachment_color
diff --git a/app/models/integrations/jira.rb b/app/models/integrations/jira.rb
index 45302a0bd09..d96a848c72e 100644
--- a/app/models/integrations/jira.rb
+++ b/app/models/integrations/jira.rb
@@ -48,21 +48,21 @@ module Integrations
section: SECTION_TYPE_CONNECTION,
required: true,
title: -> { s_('JiraService|Web URL') },
- help: -> { s_('JiraService|Base URL of the Jira instance.') },
+ help: -> { s_('JiraService|Base URL of the Jira instance') },
placeholder: 'https://jira.example.com',
exposes_secrets: true
field :api_url,
section: SECTION_TYPE_CONNECTION,
title: -> { s_('JiraService|Jira API URL') },
- help: -> { s_('JiraService|If different from Web URL.') },
+ help: -> { s_('JiraService|If different from the Web URL') },
exposes_secrets: true
field :username,
section: SECTION_TYPE_CONNECTION,
required: true,
- title: -> { s_('JiraService|Username or Email') },
- help: -> { s_('JiraService|Use a username for server version and an email for cloud version.') }
+ title: -> { s_('JiraService|Username or email') },
+ help: -> { s_('JiraService|Username for the server version or an email for the cloud version') }
field :password,
section: SECTION_TYPE_CONNECTION,
@@ -70,7 +70,7 @@ module Integrations
title: -> { s_('JiraService|Password or API token') },
non_empty_password_title: -> { s_('JiraService|Enter new password or API token') },
non_empty_password_help: -> { s_('JiraService|Leave blank to use your current password or API token.') },
- help: -> { s_('JiraService|Use a password for server version and an API token for cloud version.') }
+ help: -> { s_('JiraService|Password for the server version or an API token for the cloud version') }
field :jira_issue_transition_id, api_only: true