diff options
Diffstat (limited to 'app/models/integrations')
-rw-r--r-- | app/models/integrations/base_chat_notification.rb | 40 | ||||
-rw-r--r-- | app/models/integrations/chat_message/base_message.rb | 6 | ||||
-rw-r--r-- | app/models/integrations/jira.rb | 10 |
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 |