diff --git a/.rubocop.yml b/.rubocop.yml index 6ed2290..287f769 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,47 +1,44 @@ +require: + - rubocop-performance + - rubocop-rails + Rails: Enabled: true AllCops: - TargetRubyVersion: 2.2 + TargetRubyVersion: 2.3 TargetRailsVersion: 5.2 -Metrics/AbcSize: - Max: 65 +Metrics: + Enabled: false -Metrics/BlockLength: - Max: 60 - -Metrics/ClassLength: - Max: 500 - -Metrics/CyclomaticComplexity: - Max: 20 - -Metrics/LineLength: +Layout/LineLength: Max: 140 -Metrics/MethodLength: - Max: 60 +Rails/ApplicationJob: + Enabled: false -Metrics/ModuleLength: - Max: 500 - -Metrics/PerceivedComplexity: - Max: 25 - -Rails/SkipsModelValidations: +Rails/ApplicationRecord: Enabled: false Rails/CreateTableWithTimestamps: Enabled: false -# we drop this, if we drop Rails 4.2 support -Rails/ApplicationRecord: - Enabled: false +Rails/HelperInstanceVariable: + Enabled: false + +Rails/SkipsModelValidations: + Enabled: false + +Performance/ChainArrayAllocation: + Enabled: true Style/AutoResourceCleanup: Enabled: true +Style/FrozenStringLiteralComment: + Enabled: false + Style/Documentation: Enabled: false diff --git a/.travis.yml b/.travis.yml index 82c33fc..2b2c7da 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,19 +1,22 @@ language: ruby +dist: xenial rvm: - - 2.4.5 - - 2.3.8 - - 2.2.10 + - 2.6.5 + - 2.5.7 + - 2.4.9 + +services: + - mysql + - postgresql env: - REDMINE_VER=4.0-stable DB=postgresql - - REDMINE_VER=3.4-stable DB=postgresql + - REDMINE_VER=master DB=postgresql + - REDMINE_VER=4.0-stable DB=mysql + - REDMINE_VER=master DB=mysql sudo: true -cache: bundler - -addons: - postgresql: "9.6" notifications: webhooks: @@ -27,24 +30,20 @@ before_install: - export REDMINE_GIT_REPO=git://github.com/redmine/redmine.git - export REDMINE_PATH=$HOME/redmine - export BUNDLE_GEMFILE=$REDMINE_PATH/Gemfile + - export RAILS_ENV=test - git clone $REDMINE_GIT_REPO $REDMINE_PATH - cd $REDMINE_PATH - if [[ "$REDMINE_VER" != "master" ]]; then git checkout -b $REDMINE_VER origin/$REDMINE_VER; fi + - if [[ "$REDMINE_VER" != "master" ]]; then cp $TRAVIS_BUILD_DIR/test/support/Gemfile.local $REDMINE_PATH; fi - ln -s $TRAVIS_BUILD_DIR $REDMINE_PATH/plugins/$PLUGIN_NAME - cp $TRAVIS_BUILD_DIR/test/support/additional_environment.rb $REDMINE_PATH/config/ - cp $TRAVIS_BUILD_DIR/test/support/database-$DB-travis.yml $REDMINE_PATH/config/database.yml before_script: - # - bundle exec rake redmine:load_default_data REDMINE_LANG=en - # - bundle exec rake db:structure:dump - - psql -c 'create database travis_ci_test;' -U postgres - # - bundle exec rake db:create - - bundle exec rake db:migrate - - bundle exec rake redmine:plugins:migrate + - bundle exec rake db:create db:migrate redmine:plugins:migrate script: - export SKIP_COVERAGE=1 - - if [[ "$REDMINE_VER" == "master" ]]; then bundle exec rake redmine:plugins:test:units NAME=$PLUGIN_NAME; fi - - if [[ "$REDMINE_VER" == "master" ]]; then bundle exec rake redmine:plugins:test:functionals NAME=$PLUGIN_NAME; fi - - if [[ "$REDMINE_VER" == "master" ]]; then bundle exec rake redmine:plugins:test:integration NAME=$PLUGIN_NAME; fi - - if [[ "$REDMINE_VER" != "master" ]]; then bundle exec rake redmine:plugins:test NAME=$PLUGIN_NAME RUBYOPT="-W0"; fi + - if [[ "$REDMINE_VER" != "master" ]] && [[ "$DB" == "postgresql" ]]; then rubocop plugins/$PLUGIN_NAME; fi + - bundle exec rake redmine:plugins:test NAME=$PLUGIN_NAME RUBYOPT="-W0" + - bundle exec rake redmine:plugins:migrate NAME=$PLUGIN_NAME VERSION=0 diff --git a/CHANGELOG.md b/CHANGELOG.md index 481746e..789ed22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,25 @@ Changelog ========= +1.0.6 +----- + +- Redmine 4 is required. Use git tag 1.0.5, if you use an older version. +- Redmine 4.1 support +- Fix problems with changed fields, description and notes +- fix problems with quotes #38 + +1.0.5 +----- + +- ruby 2.4.x or newer is required + + +1.0.4 +----- + +- Frensh translation added - thanks to @ZerooCool + 1.0.3 ----- diff --git a/Gemfile b/Gemfile index e7117a8..474e102 100644 --- a/Gemfile +++ b/Gemfile @@ -1,2 +1,6 @@ gem 'slim-rails' gem 'validate_url' + +group :development, :test do + gem 'brakeman', require: false +end diff --git a/README.md b/README.md index d556d79..1ba4ca0 100644 --- a/README.md +++ b/README.md @@ -56,9 +56,10 @@ Go to Rocket.Chat documentation [Incoming WebHook Scripting](https://rocket.chat Requirements ------------ -* Redmine version >= 3.0.0 -* Ruby version >= 2.1.5 +* Redmine version >= 4.0.0 +* Ruby version >= 2.4.0 +If you want to use it with Redmine 3.x, use git tag 1.0.5 Installation ------------ @@ -66,10 +67,11 @@ Installation Install ``redmine_messenger`` plugin for `Redmine` cd $REDMINE_ROOT - git clone git://github.com/alphanodes/redmine_messenger.git plugins/redmine_messenger - bundle install --without development test + git clone https://github.com/AlphaNodes/redmine_messenger.git plugins/redmine_messenger + bundle update bundle exec rake redmine:plugins:migrate RAILS_ENV=production +Make sure that the directory is named `redmine_messenger` (you cannot use another name for it)! Restart Redmine (application server) and you should see the plugin show up in the Plugins page. Under the configuration options, set the Messenger API URL to the URL for an Incoming WebHook integration in your Messenger account and also set the Messenger diff --git a/app/models/messenger.rb b/app/models/messenger.rb index 429c5de..638df89 100644 --- a/app/models/messenger.rb +++ b/app/models/messenger.rb @@ -1,253 +1,270 @@ require 'net/http' +require 'uri' class Messenger include Redmine::I18n - def self.markup_format(text) - # TODO: output format should be markdown, but at the moment there is no - # solution without using pandoc (http://pandoc.org/), which requires - # packages on os level - # - # Redmine::WikiFormatting.html_parser.to_text(text) - ERB::Util.html_escape(text) - end + class << self + def markup_format(text) + # TODO: output format should be markdown, but at the moment there is no + # solution without using pandoc (http://pandoc.org/), which requires + # packages on os level + # + # Redmine::WikiFormatting.html_parser.to_text(text) - def self.default_url_options - { only_path: true, script_name: Redmine::Utils.relative_url_root } - end + text = +text.to_s + text.gsub!('&', '&') + text.gsub!('<', '<') + text.gsub!('>', '>') - def self.speak(msg, channels, url, options) - url ||= RedmineMessenger.settings[:messenger_url] - - return if url.blank? - return if channels.blank? - - params = { - text: msg, - link_names: 1 - } - - username = Messenger.textfield_for_project(options[:project], :messenger_username) - params[:username] = username if username.present? - params[:attachments] = [options[:attachment]] if options[:attachment] && options[:attachment].any? - - icon = Messenger.textfield_for_project(options[:project], :messenger_icon) - if icon.present? - if icon.start_with? ':' - params[:icon_emoji] = icon - else - params[:icon_url] = icon - end + text end - channels.each do |channel| - uri = URI(url) - params[:channel] = channel - http_options = { use_ssl: uri.scheme == 'https' } - http_options[:verify_mode] = OpenSSL::SSL::VERIFY_NONE unless RedmineMessenger.setting?(:messenger_verify_ssl) + def default_url_options + { only_path: true, script_name: Redmine::Utils.relative_url_root } + end - begin - req = Net::HTTP::Post.new(uri) - req.set_form_data(payload: params.to_json) - Net::HTTP.start(uri.hostname, uri.port, http_options) do |http| - response = http.request(req) - Rails.logger.warn(response) unless [Net::HTTPSuccess, Net::HTTPRedirection, Net::HTTPOK].include? response + def speak(msg, channels, url, options) + url ||= RedmineMessenger.settings[:messenger_url] + + return if url.blank? + return if channels.blank? + + params = { + text: msg, + link_names: 1 + } + + username = Messenger.textfield_for_project(options[:project], :messenger_username) + params[:username] = username if username.present? + params[:attachments] = [options[:attachment]] if options[:attachment]&.any? + icon = Messenger.textfield_for_project(options[:project], :messenger_icon) + if icon.present? + if icon.start_with? ':' + params[:icon_emoji] = icon + else + params[:icon_url] = icon + end + end + + channels.each do |channel| + uri = URI(url) + params[:channel] = channel + http_options = { use_ssl: uri.scheme == 'https' } + http_options[:verify_mode] = OpenSSL::SSL::VERIFY_NONE unless RedmineMessenger.setting?(:messenger_verify_ssl) + begin + req = Net::HTTP::Post.new(uri) + req.set_form_data(payload: params.to_json) + Net::HTTP.start(uri.hostname, uri.port, http_options) do |http| + response = http.request(req) + Rails.logger.warn(response.inspect) unless [Net::HTTPSuccess, Net::HTTPRedirection, Net::HTTPOK].include? response + end + rescue StandardError => e + Rails.logger.warn("cannot connect to #{url}") + Rails.logger.warn(e) end - rescue StandardError => e - Rails.logger.warn("cannot connect to #{url}") - Rails.logger.warn(e) end end - end - def self.object_url(obj) - if Setting.host_name.to_s =~ %r{\A(https?\://)?(.+?)(\:(\d+))?(/.+)?\z}i - host = Regexp.last_match(2) - port = Regexp.last_match(4) - prefix = Regexp.last_match(5) - Rails.application.routes.url_for(obj.event_url(host: host, protocol: Setting.protocol, port: port, script_name: prefix)) - else - Rails.application.routes.url_for(obj.event_url(host: Setting.host_name, protocol: Setting.protocol, script_name: '')) - end - end - - def self.url_for_project(proj) - return if proj.blank? - - # project based - pm = MessengerSetting.find_by(project_id: proj.id) - return pm.messenger_url if !pm.nil? && pm.messenger_url.present? - - # parent project based - parent_url = url_for_project(proj.parent) - return parent_url if parent_url.present? - # system based - return RedmineMessenger.settings[:messenger_url] if RedmineMessenger.settings[:messenger_url].present? - - nil - end - - def self.textfield_for_project(proj, config) - return if proj.blank? - - # project based - pm = MessengerSetting.find_by(project_id: proj.id) - return pm.send(config) if !pm.nil? && pm.send(config).present? - - default_textfield(proj, config) - end - - def self.default_textfield(proj, config) - # parent project based - parent_field = textfield_for_project(proj.parent, config) - return parent_field if parent_field.present? - return RedmineMessenger.settings[config] if RedmineMessenger.settings[config].present? - - '' - end - - def self.channels_for_project(proj) - return [] if proj.blank? - - # project based - pm = MessengerSetting.find_by(project_id: proj.id) - if !pm.nil? && pm.messenger_channel.present? - return [] if pm.messenger_channel == '-' - - return pm.messenger_channel.split(',').map(&:strip).uniq - end - default_project_channels(proj) - end - - def self.default_project_channels(proj) - # parent project based - parent_channel = channels_for_project(proj.parent) - return parent_channel if parent_channel.present? - # system based - if RedmineMessenger.settings[:messenger_channel].present? && - RedmineMessenger.settings[:messenger_channel] != '-' - return RedmineMessenger.settings[:messenger_channel].split(',').map(&:strip).uniq + def object_url(obj) + if Setting.host_name.to_s =~ %r{\A(https?\://)?(.+?)(\:(\d+))?(/.+)?\z}i + host = Regexp.last_match(2) + port = Regexp.last_match(4) + prefix = Regexp.last_match(5) + Rails.application.routes.url_for(obj.event_url(host: host, protocol: Setting.protocol, port: port, script_name: prefix)) + else + Rails.application.routes.url_for(obj.event_url(host: Setting.host_name, protocol: Setting.protocol, script_name: '')) + end end - [] - end + def url_for_project(proj) + return if proj.blank? - def self.setting_for_project(proj, config) - return false if proj.blank? + # project based + pm = MessengerSetting.find_by(project_id: proj.id) + return pm.messenger_url if !pm.nil? && pm.messenger_url.present? - @setting_found = 0 - # project based - pm = MessengerSetting.find_by(project_id: proj.id) - unless pm.nil? || pm.send(config).zero? - @setting_found = 1 - return false if pm.send(config) == 1 - return true if pm.send(config) == 2 - # 0 = use system based settings + # parent project based + parent_url = url_for_project(proj.parent) + return parent_url if parent_url.present? + # system based + return RedmineMessenger.settings[:messenger_url] if RedmineMessenger.settings[:messenger_url].present? + + nil end - default_project_setting(proj, config) - end - def self.default_project_setting(proj, config) - if proj.present? && proj.parent.present? - parent_setting = setting_for_project(proj.parent, config) - return parent_setting if @setting_found == 1 + def textfield_for_project(proj, config) + return if proj.blank? + + # project based + pm = MessengerSetting.find_by(project_id: proj.id) + return pm.send(config) if !pm.nil? && pm.send(config).present? + + default_textfield(proj, config) end - # system based - return true if RedmineMessenger.settings[config].present? && RedmineMessenger.setting?(config) - false - end + def default_textfield(proj, config) + # parent project based + parent_field = textfield_for_project(proj.parent, config) + return parent_field if parent_field.present? + return RedmineMessenger.settings[config] if RedmineMessenger.settings[config].present? - def self.detail_to_field(detail) - field_format = nil - key = nil - escape = true + '' + end - if detail.property == 'cf' - key = CustomField.find(detail.prop_key).name rescue nil - title = key - field_format = CustomField.find(detail.prop_key).field_format rescue nil - elsif detail.property == 'attachment' - key = 'attachment' - title = I18n.t :label_attachment - else - key = detail.prop_key.to_s.sub('_id', '') - title = if key == 'parent' - I18n.t "field_#{key}_issue" + def channels_for_project(proj) + return [] if proj.blank? + + # project based + pm = MessengerSetting.find_by(project_id: proj.id) + if !pm.nil? && pm.messenger_channel.present? + return [] if pm.messenger_channel == '-' + + return pm.messenger_channel.split(',').map!(&:strip).uniq + end + default_project_channels(proj) + end + + def setting_for_project(proj, config) + return false if proj.blank? + + @setting_found = 0 + # project based + pm = MessengerSetting.find_by(project_id: proj.id) + unless pm.nil? || pm.send(config).zero? + @setting_found = 1 + return false if pm.send(config) == 1 + return true if pm.send(config) == 2 + # 0 = use system based settings + end + default_project_setting(proj, config) + end + + def default_project_setting(proj, config) + if proj.present? && proj.parent.present? + parent_setting = setting_for_project(proj.parent, config) + return parent_setting if @setting_found == 1 + end + # system based + return true if RedmineMessenger.settings[config].present? && RedmineMessenger.setting?(config) + + false + end + + def detail_to_field(detail) + field_format = nil + key = nil + escape = true + value = detail.value.to_s + + if detail.property == 'cf' + key = CustomField.find(detail.prop_key)&.name + unless key.nil? + title = key + field_format = CustomField.find(detail.prop_key)&.field_format + value = IssuesController.helpers.format_value(detail.value, detail.custom_field) if detail.value.present? + end + elsif detail.property == 'attachment' + key = 'attachment' + title = I18n.t :label_attachment + value = detail.value.to_s + else + key = detail.prop_key.to_s.sub('_id', '') + title = if key == 'parent' + I18n.t "field_#{key}_issue" + else + I18n.t "field_#{key}" + end + value = detail.value.to_s + end + + short = true + + case key + when 'title', 'subject', 'description' + short = false + when 'tracker' + value = object_field_value(Tracker, detail.value) + when 'project' + value = object_field_value(Project, detail.value) + when 'status' + value = object_field_value(IssueStatus, detail.value) + when 'priority' + value = object_field_value(IssuePriority, detail.value) + when 'category' + value = object_field_value(IssueCategory, detail.value) + when 'assigned_to' + value = object_field_value(User, detail.value) + when 'fixed_version' + value = object_field_value(Version, detail.value) + when 'attachment' + attachment = Attachment.find(detail.prop_key) + value = if attachment.present? + escape = false + "<#{Messenger.object_url attachment}|#{markup_format(attachment.filename)}>" + else + detail.prop_key.to_s + end + + when 'parent' + issue = Issue.find(detail.value) + value = if issue.present? + escape = false + "<#{Messenger.object_url issue}|#{markup_format(issue)}>" + else + detail.value.to_s + end + end + + value = object_field_value(Version, detail.value) if detail.property == 'cf' && field_format == 'version' + value = if value.present? + if escape + markup_format(value) + else + value + end else - I18n.t "field_#{key}" + '-' end + + result = { title: title, value: value } + result[:short] = true if short + result end - short = true - value = detail.value.to_s - - case key - when 'title', 'subject', 'description' - short = false - when 'tracker' - tracker = Tracker.find(detail.value) - value = tracker.to_s if tracker.present? - when 'project' - project = Project.find(detail.value) - value = project.to_s if project.present? - when 'status' - status = IssueStatus.find(detail.value) - value = status.to_s if status.present? - when 'priority' - priority = IssuePriority.find(detail.value) - value = priority.to_s if priority.present? - when 'category' - category = IssueCategory.find(detail.value) - value = category.to_s if category.present? - when 'assigned_to' - user = User.find(detail.value) - value = user.to_s if user.present? - when 'fixed_version' - fixed_version = Version.find(detail.value) - value = fixed_version.to_s if fixed_version.present? - when 'attachment' - attachment = Attachment.find(detail.prop_key) - value = "<#{Messenger.object_url attachment}|#{ERB::Util.html_escape(attachment.filename)}>" if attachment.present? - escape = false - when 'parent' - issue = Issue.find(detail.value) - value = "<#{Messenger.object_url issue}|#{ERB::Util.html_escape(issue)}>" if issue.present? - escape = false + def mentions(project, text) + names = [] + Messenger.textfield_for_project(project, :default_mentions) + .split(',').each { |m| names.push m.strip } + names += extract_usernames(text) unless text.nil? + names.present? ? ' To: ' + names.uniq.join(', ') : nil end - if detail.property == 'cf' && field_format == 'version' - version = Version.find(detail.value) - value = version.to_s if version.present? + private + + def object_field_value(klass, id) + obj = klass.find_by(id: id) + obj.nil? ? id.to_s : obj.to_s end - value = if value.present? - if escape - ERB::Util.html_escape(value) - else - value - end - else - '-' - end + def extract_usernames(text) + text = '' if text.nil? + # messenger usernames may only contain lowercase letters, numbers, + # dashes, dots and underscores and must start with a letter or number. + text.scan(/@[a-z0-9][a-z0-9_\-.]*/).uniq + end - result = { title: title, value: value } - result[:short] = true if short - result - end + def default_project_channels(proj) + # parent project based + parent_channel = channels_for_project(proj.parent) + return parent_channel if parent_channel.present? + # system based + if RedmineMessenger.settings[:messenger_channel].present? && + RedmineMessenger.settings[:messenger_channel] != '-' + return RedmineMessenger.settings[:messenger_channel].split(',').map!(&:strip).uniq + end - def self.mentions(project, text) - names = [] - Messenger.textfield_for_project(project, :default_mentions) - .split(',').each { |m| names.push m.strip } - names += extract_usernames(text) unless text.nil? - names.present? ? ' To: ' + names.uniq.join(', ') : nil - end - - def self.extract_usernames(text) - text = '' if text.nil? - # messenger usernames may only contain lowercase letters, numbers, - # dashes, dots and underscores and must start with a letter or number. - text.scan(/@[a-z0-9][a-z0-9_\-.]*/).uniq + [] + end end end diff --git a/app/views/messenger_settings/_show.html.slim b/app/views/messenger_settings/_show.html.slim index c8ba65d..ba63e2d 100644 --- a/app/views/messenger_settings/_show.html.slim +++ b/app/views/messenger_settings/_show.html.slim @@ -1,12 +1,17 @@ -.box.tabular.messenger_settings - - @messenger_setting = MessengerSetting.find_or_create(@project.id) - = labelled_form_for :setting, - @messenger_setting, - url: project_messenger_setting_path(project_id: @project), - method: :put, - class: 'tabular' do |f| - = error_messages_for 'messenger_setting' - .box += error_messages_for 'messenger_setting' + +- @messenger_setting = MessengerSetting.find_or_create(@project.id) += labelled_form_for :setting, + @messenger_setting, + url: project_messenger_setting_path(project_id: @project), + method: :put, + class: 'tabular' do |f| + + fieldset#messenger_settings.box.tabular + - if User.current.admin? + .contextual + = link_to l(:label_administration), plugin_settings_path(id: 'redmine_messenger'), class: 'icon icon-settings' + .info = t(:messenger_settings_project_intro) br p @@ -21,50 +26,50 @@ = render partial: 'messenger_settings/messenger_text', locals: { f: f, mf: :messenger_username, size: 30 } = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :messenger_verify_ssl } + fieldset#messenger_settings.box.tabular + legend = l(:label_issue_plural) + .info = t(:messenger_issue_intro) + br + = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :auto_mentions } + = render partial: 'messenger_settings/messenger_text', locals: { f: f, mf: :default_mentions, size: 30 } + = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :display_watchers } + = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_updates } + = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :new_include_description } + = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :updated_include_description } + = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_private_issues } + = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_private_notes } + + fieldset#messenger_settings.box.tabular + legend = l(:label_wiki) + .info = t(:messenger_wiki_intro) + br + = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_wiki } + = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_wiki_updates } + + - if RedmineMessenger::REDMINE_DB_SUPPORT && User.current.allowed_to?(:view_db_entries, @project) + fieldset#messenger_settings.box.tabular + legend = l(:label_db_entry_plural) + .info = t(:messenger_db_intro) br - h3 = l(:label_issue_plural) - .info = t(:messenger_issue_intro) + = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_db } + = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_db_updates } + = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_private_db } + + - if RedmineMessenger::REDMINE_CONTACTS_SUPPORT && User.current.allowed_to?(:view_contacts, @project) + fieldset#messenger_settings.box.tabular + legend = l(:label_contact_plural) + .info = t(:messenger_contacts_intro) br - = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :auto_mentions } - = render partial: 'messenger_settings/messenger_text', locals: { f: f, mf: :default_mentions, size: 30 } - = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :display_watchers } - = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_updates } - = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :new_include_description } - = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :updated_include_description } - = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_private_issues } - = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_private_notes } + = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_contact } + = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_contact_updates } + = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_private_contacts } + - if Redmine::Plugin.installed?('redmine_passwords') && User.current.allowed_to?(:view_passwords, @project) + fieldset#messenger_settings.box.tabular + legend = l(:label_password_plural) + .info = t(:messenger_passwords_intro) br - h3 = l(:label_wiki) - .info = t(:messenger_wiki_intro) - br - = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_wiki } - = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_wiki_updates } + = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_password } + = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_password_updates } - - if RedmineMessenger::REDMINE_DB_SUPPORT && User.current.allowed_to?(:view_db_entries, @project) - br - h3 = l(:label_db_entry_plural) - .info = t(:messenger_db_intro) - br - = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_db } - = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_db_updates } - = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_private_db } - - - if RedmineMessenger::REDMINE_CONTACTS_SUPPORT && User.current.allowed_to?(:view_contacts, @project) - br - h3 = l(:label_contact_plural) - .info = t(:messenger_contacts_intro) - br - = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_contact } - = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_contact_updates } - = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_private_contacts } - - - if Redmine::Plugin.installed?('redmine_passwords') && User.current.allowed_to?(:view_passwords, @project) - br - h3 = l(:label_settings_post_password) - .info = t(:messenger_passwords_intro) - br - = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_password } - = render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_password_updates } - - = submit_tag l(:button_save) + = submit_tag l(:button_save) diff --git a/app/views/settings/_messenger_settings.html.slim b/app/views/settings/_messenger_settings.html.slim index 0e1a31a..6742cab 100644 --- a/app/views/settings/_messenger_settings.html.slim +++ b/app/views/settings/_messenger_settings.html.slim @@ -1,105 +1,105 @@ -- @settings = ActionController::Parameters.new(@settings) unless Rails.version >= '5.2' - .info = t(:messenger_settings_intro) br -p - = content_tag(:label, l(:label_settings_messenger_url)) - = text_field_tag('settings[messenger_url]', @settings[:messenger_url], size: 60, placeholder: 'https://webhook.url') - em.info = t(:messenger_url_info_html) -p - = content_tag(:label, l(:label_settings_messenger_icon)) - = text_field_tag('settings[messenger_icon]', @settings[:messenger_icon], size: 60) -p - = content_tag(:label, l(:label_settings_messenger_channel)) - = text_field_tag('settings[messenger_channel]', @settings[:messenger_channel], size: 30, placeholder: 'redmine') - em.info = t(:messenger_channel_info_html) -p - = content_tag(:label, l(:label_settings_messenger_username)) - = text_field_tag('settings[messenger_username]', @settings[:messenger_username], size: 30) -p - = content_tag(:label, l(:label_settings_messenger_verify_ssl)) - = check_box_tag 'settings[messenger_verify_ssl]', 1, @settings[:messenger_verify_ssl].to_i == 1 - em.info = t(:messenger_verify_ssl_info_html) -br -h3 = l(:label_issue_plural) -.info = t(:messenger_issue_intro) -br -p - = content_tag(:label, l(:label_settings_auto_mentions)) - = check_box_tag 'settings[auto_mentions]', 1, @settings[:auto_mentions].to_i == 1 -p - = content_tag(:label, l(:label_settings_default_mentions)) - = text_field_tag('settings[default_mentions]', @settings[:default_mentions], size: 30) - em.info = t(:default_mentionsl_info) -p - = content_tag(:label, l(:label_settings_display_watchers)) - = check_box_tag 'settings[display_watchers]', 1, @settings[:display_watchers].to_i == 1 -p - = content_tag(:label, l(:label_settings_post_updates)) - = check_box_tag 'settings[post_updates]', 1, @settings[:post_updates].to_i == 1 -p - = content_tag(:label, l(:label_settings_new_include_description)) - = check_box_tag 'settings[new_include_description]', 1, @settings[:new_include_description].to_i == 1 -p - = content_tag(:label, l(:label_settings_updated_include_description)) - = check_box_tag 'settings[updated_include_description]', 1, @settings[:updated_include_description].to_i == 1 -p - = content_tag(:label, l(:label_settings_post_private_issues)) - = check_box_tag 'settings[post_private_issues]', 1, @settings[:post_private_issues].to_i == 1 -p - = content_tag(:label, l(:label_settings_post_private_notes)) - = check_box_tag 'settings[post_private_notes]', 1, @settings[:post_private_notes].to_i == 1 +fieldset#messenger_settings.box.tabular + p + = content_tag(:label, l(:label_settings_messenger_url)) + = text_field_tag('settings[messenger_url]', @settings[:messenger_url], size: 60, placeholder: 'https://webhook.url') + em.info = t(:messenger_url_info_html) + p + = content_tag(:label, l(:label_settings_messenger_icon)) + = text_field_tag('settings[messenger_icon]', @settings[:messenger_icon], size: 60) + p + = content_tag(:label, l(:label_settings_messenger_channel)) + = text_field_tag('settings[messenger_channel]', @settings[:messenger_channel], size: 30, placeholder: 'redmine') + em.info = t(:messenger_channel_info_html) + p + = content_tag(:label, l(:label_settings_messenger_username)) + = text_field_tag('settings[messenger_username]', @settings[:messenger_username], size: 30) + p + = content_tag(:label, l(:label_settings_messenger_verify_ssl)) + = check_box_tag 'settings[messenger_verify_ssl]', 1, @settings[:messenger_verify_ssl].to_i == 1 + em.info = t(:messenger_verify_ssl_info_html) -br -h3 = l(:label_wiki) -.info = t(:messenger_wiki_intro) -br -p - = content_tag(:label, l(:label_settings_post_wiki)) - = check_box_tag 'settings[post_wiki]', 1, @settings[:post_wiki].to_i == 1 -p - = content_tag(:label, l(:label_settings_post_wiki_updates)) - = check_box_tag 'settings[post_wiki_updates]', 1, @settings[:post_wiki_updates].to_i == 1 +fieldset#messenger_settings.box.tabular + legend = l(:label_issue_plural) + .info = t(:messenger_issue_intro) + br + p + = content_tag(:label, l(:label_settings_auto_mentions)) + = check_box_tag 'settings[auto_mentions]', 1, @settings[:auto_mentions].to_i == 1 + p + = content_tag(:label, l(:label_settings_default_mentions)) + = text_field_tag('settings[default_mentions]', @settings[:default_mentions], size: 30) + em.info = t(:default_mentionsl_info) + p + = content_tag(:label, l(:label_settings_display_watchers)) + = check_box_tag 'settings[display_watchers]', 1, @settings[:display_watchers].to_i == 1 + p + = content_tag(:label, l(:label_settings_post_updates)) + = check_box_tag 'settings[post_updates]', 1, @settings[:post_updates].to_i == 1 + p + = content_tag(:label, l(:label_settings_new_include_description)) + = check_box_tag 'settings[new_include_description]', 1, @settings[:new_include_description].to_i == 1 + p + = content_tag(:label, l(:label_settings_updated_include_description)) + = check_box_tag 'settings[updated_include_description]', 1, @settings[:updated_include_description].to_i == 1 + p + = content_tag(:label, l(:label_settings_post_private_issues)) + = check_box_tag 'settings[post_private_issues]', 1, @settings[:post_private_issues].to_i == 1 + p + = content_tag(:label, l(:label_settings_post_private_notes)) + = check_box_tag 'settings[post_private_notes]', 1, @settings[:post_private_notes].to_i == 1 + +fieldset#messenger_settings.box.tabular + legend = l(:label_wiki) + .info = t(:messenger_wiki_intro) + br + p + = content_tag(:label, l(:label_settings_post_wiki)) + = check_box_tag 'settings[post_wiki]', 1, @settings[:post_wiki].to_i == 1 + p + = content_tag(:label, l(:label_settings_post_wiki_updates)) + = check_box_tag 'settings[post_wiki_updates]', 1, @settings[:post_wiki_updates].to_i == 1 - if RedmineMessenger::REDMINE_DB_SUPPORT - br - h3 = l(:label_db_entry_plural) - .info = t(:messenger_db_intro) - br - p - = content_tag(:label, l(:label_settings_post_db)) - = check_box_tag 'settings[post_db]', 1, @settings[:post_db].to_i == 1 - p - = content_tag(:label, l(:label_settings_post_db_updates)) - = check_box_tag 'settings[post_db_updates]', 1, @settings[:post_db_updates].to_i == 1 - p - = content_tag(:label, l(:label_settings_post_private_db)) - = check_box_tag 'settings[post_private_db]', 1, @settings[:post_private_db].to_i == 1 + fieldset#messenger_settings.box.tabular + legend = l(:label_db_entry_plural) + .info = t(:messenger_db_intro) + br + p + = content_tag(:label, l(:label_settings_post_db)) + = check_box_tag 'settings[post_db]', 1, @settings[:post_db].to_i == 1 + p + = content_tag(:label, l(:label_settings_post_db_updates)) + = check_box_tag 'settings[post_db_updates]', 1, @settings[:post_db_updates].to_i == 1 + p + = content_tag(:label, l(:label_settings_post_private_db)) + = check_box_tag 'settings[post_private_db]', 1, @settings[:post_private_db].to_i == 1 - if RedmineMessenger::REDMINE_CONTACTS_SUPPORT - br - h3 = l(:label_contact_plural) - .info = t(:messenger_contacts_intro) - br - p - = content_tag(:label, l(:label_settings_post_contact)) - = check_box_tag 'settings[post_contact]', 1, @settings[:post_contact].to_i == 1 - p - = content_tag(:label, l(:label_settings_post_contact_updates)) - = check_box_tag 'settings[post_contact_updates]', 1, @settings[:post_contact_updates].to_i == 1 - p - = content_tag(:label, l(:label_settings_post_private_contacts)) - = check_box_tag 'settings[post_private_contacts]', 1, @settings[:post_private_contacts].to_i == 1 + fieldset#messenger_settings.box.tabular + legend = l(:label_contact_plural) + .info = t(:messenger_contacts_intro) + br + p + = content_tag(:label, l(:label_settings_post_contact)) + = check_box_tag 'settings[post_contact]', 1, @settings[:post_contact].to_i == 1 + p + = content_tag(:label, l(:label_settings_post_contact_updates)) + = check_box_tag 'settings[post_contact_updates]', 1, @settings[:post_contact_updates].to_i == 1 + p + = content_tag(:label, l(:label_settings_post_private_contacts)) + = check_box_tag 'settings[post_private_contacts]', 1, @settings[:post_private_contacts].to_i == 1 - if Redmine::Plugin.installed?('redmine_passwords') - br - h3 = l(:label_password_plural) - .info = t(:messenger_passwords_intro) - br - p - = content_tag(:label, l(:label_settings_post_password)) - = check_box_tag 'settings[post_password]', 1, @settings[:post_password].to_i == 1 - p - = content_tag(:label, l(:label_settings_post_password_updates)) - = check_box_tag 'settings[post_password_updates]', 1, @settings[:post_password_updates].to_i == 1 + fieldset#messenger_settings.box.tabular + legend = l(:label_password_plural) + .info = t(:messenger_passwords_intro) + br + p + = content_tag(:label, l(:label_settings_post_password)) + = check_box_tag 'settings[post_password]', 1, @settings[:post_password].to_i == 1 + p + = content_tag(:label, l(:label_settings_post_password_updates)) + = check_box_tag 'settings[post_password_updates]', 1, @settings[:post_password_updates].to_i == 1 diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 26aae11..5bb0068 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -5,27 +5,27 @@ fr: label_messenger_contact_created: "[%{project_url}] Le contact %{url} créé par *%{user}*" label_messenger_contact_updated: "[%{project_url}] Le contact %{url} mis à jour par *%{user}*" label_messenger_db_entry_created: "[%{project_url}] Entrée de base de données %{url} créée par *%{user}*" - label_messenger_db_entry_updated: "[%{project_url}] Entrée de base de données %{url} créée par *%{user}*" + label_messenger_db_entry_updated: "[%{project_url}] Entrée de base de données %{url} mis à jour par *%{user}*" label_messenger_default_not_visible: Le paramètre par défaut n'est pas visible pour des raisons de sécurité label_messenger_issue_created: "[%{project_url}] Ticket %{url} créé par *%{user}*" - label_messenger_issue_updated: "[%{project_url}] Ticket %{url} créé par *%{user}*" + label_messenger_issue_updated: "[%{project_url}] Ticket %{url} mis à jour par *%{user}*" label_messenger_password_created: "[%{project_url}] Mot de passe %{url} créé par *%{user}*" - label_messenger_password_updated: "[%{project_url}] Mot de passe %{url} créé par *%{user}*" + label_messenger_password_updated: "[%{project_url}] Mot de passe %{url} mis à jour par *%{user}*" label_messenger_project_text_field_info: Laissez ce champ vide pour le système par défaut. label_messenger_setting: Paramètres de messagerie - label_messenger_settings_default: Défaillance du système + label_messenger_settings_default: Choix de l'option label_messenger_settings_disabled: Désactivé label_messenger_settings_enabled: Activé label_messenger_wiki_created: "[%{project_url}] Wiki %{url} créé par *%{user}*" - label_messenger_wiki_updated: "[%{project_url}] Wiki %{url} créé par *%{user}*" + label_messenger_wiki_updated: "[%{project_url}] Wiki %{url} mis à jour par *%{user}*" label_messenger: Messenger - label_settings_auto_mentions: Convertir les noms en mentions ? - label_settings_default_mentions: Personnes par défaut pour les mentions - label_settings_display_watchers: Afficher les observateurs ? - label_settings_messenger_channel: Messenger Salon - label_settings_messenger_icon: Messenger Icône - label_settings_messenger_url: Messenger URL - label_settings_messenger_username: Messenger Nom d'utilisateur + label_settings_auto_mentions: Convert names to mentions ? + label_settings_default_mentions: Default people for mentions + label_settings_display_watchers: Afficher l'utilisateur assigné au ticket ? + label_settings_messenger_channel: Messenger - Nom du salon + label_settings_messenger_icon: Messenger - Icône affiché + label_settings_messenger_url: Messenger - URL WebHook entrant + label_settings_messenger_username: Messenger - Nom du robot label_settings_messenger_verify_ssl: Vérifier SSL label_settings_new_include_description: Description du nouveau ticket ? label_settings_post_contact_updates: Mises à jour de contact ? @@ -38,10 +38,10 @@ fr: label_settings_post_private_db: Entrées de base de données privées ? label_settings_post_private_issues: Mises à jour des tickets privés? label_settings_post_private_notes: Mises à jour des notes privées ? - label_settings_post_updates: Émettre des mises à jour ? + label_settings_post_updates: Publier pour chaque mises à jour ? label_settings_post_wiki_updates: Mises à jour du wiki ? label_settings_post_wiki: Post Wiki ajouté ? - label_settings_updated_include_description: Description dans le numéro de mise à jour ? + label_settings_updated_include_description: Description suite à une mise à jour ? messenger_channel_info_html: 'Vous devez spécifier le canal à utiliser. Vous pouvez définir plusieurs canaux, séparés par une virgule.' messenger_contacts_intro: Activer les modifications pour les contacts à envoyer au canal Messenger prédéfini. messenger_db_intro: Activer les modifications pour la base de données à envoyer au canal Messenger prédéfini. @@ -52,4 +52,4 @@ fr: messenger_url_info_html: 'Générer une Incoming WebHook URL du service de messagerie. Laissez-le vide si vous souhaitez uniquement activer des projets spécifiques avec des paramètres de projet.' messenger_verify_ssl_info_html: 'Si votre service Messenger utilise un certificat SSL non valide ou auto-signé, désactivez-le.' messenger_wiki_intro: Activez les modifications pour les wikis à envoyer au canal Messenger prédéfini. -permission_manage_messenger: Gérer messenger + permission_manage_messenger: Gérer messenger diff --git a/db/migrate/001_create_messenger_settings.rb b/db/migrate/001_create_messenger_settings.rb index 0fe489a..392db49 100644 --- a/db/migrate/001_create_messenger_settings.rb +++ b/db/migrate/001_create_messenger_settings.rb @@ -1,4 +1,4 @@ -class CreateMessengerSettings < Rails.version < '5.2' ? ActiveRecord::Migration : ActiveRecord::Migration[4.2] +class CreateMessengerSettings < ActiveRecord::Migration[4.2] def change create_table :messenger_settings do |t| t.references :project, null: false, index: true diff --git a/db/migrate/002_add_default_mentions.rb b/db/migrate/002_add_default_mentions.rb index 1412e78..3f5221f 100644 --- a/db/migrate/002_add_default_mentions.rb +++ b/db/migrate/002_add_default_mentions.rb @@ -1,4 +1,4 @@ -class AddDefaultMentions < Rails.version < '5.2' ? ActiveRecord::Migration : ActiveRecord::Migration[4.2] +class AddDefaultMentions < ActiveRecord::Migration[4.2] def change add_column :messenger_settings, :default_mentions, :string end diff --git a/db/migrate/003_add_private_settings.rb b/db/migrate/003_add_private_settings.rb index bd89d42..f9194c3 100644 --- a/db/migrate/003_add_private_settings.rb +++ b/db/migrate/003_add_private_settings.rb @@ -1,4 +1,4 @@ -class AddPrivateSettings < Rails.version < '5.2' ? ActiveRecord::Migration : ActiveRecord::Migration[4.2] +class AddPrivateSettings < ActiveRecord::Migration[4.2] def change add_column :messenger_settings, :post_private_contacts, :integer, default: 0, null: false add_column :messenger_settings, :post_private_db, :integer, default: 0, null: false diff --git a/init.rb b/init.rb index 08b93ac..29e0ea9 100644 --- a/init.rb +++ b/init.rb @@ -1,5 +1,6 @@ -require 'redmine' -require 'redmine_messenger' +raise "\n\033[31mredmine_messenger requires ruby 2.3 or newer. Please update your ruby version.\033[0m" if RUBY_VERSION < '2.3' + +require_dependency 'redmine_messenger' Redmine::Plugin.register :redmine_messenger do name 'Redmine Messenger' @@ -7,9 +8,9 @@ Redmine::Plugin.register :redmine_messenger do url 'https://github.com/alphanodes/redmine_messenger' author_url 'https://alphanodes.com/' description 'Messenger integration for Slack, Discord, Rocketchat and Mattermost support' - version '1.0.3' + version '1.0.6' - requires_redmine version_or_higher: '3.0.0' + requires_redmine version_or_higher: '4.0.0' permission :manage_messenger, projects: :settings, messenger_settings: :update @@ -39,3 +40,13 @@ Redmine::Plugin.register :redmine_messenger do post_password_updates: '0' }, partial: 'settings/messenger_settings' end + +begin + if ActiveRecord::Base.connection.table_exists?(Setting.table_name) + Rails.configuration.to_prepare do + RedmineMessenger.setup + end + end +rescue ActiveRecord::NoDatabaseError + Rails.logger.error 'database not created yet' +end diff --git a/lib/redmine_messenger.rb b/lib/redmine_messenger.rb index 32e1869..8de5dc5 100644 --- a/lib/redmine_messenger.rb +++ b/lib/redmine_messenger.rb @@ -1,44 +1,41 @@ -Rails.configuration.to_prepare do - module RedmineMessenger - REDMINE_CONTACTS_SUPPORT = Redmine::Plugin.installed?('redmine_contacts') ? true : false - REDMINE_DB_SUPPORT = Redmine::Plugin.installed?('redmine_db') ? true : false - # this does not work at the moment, because redmine loads passwords after messener plugin - REDMINE_PASSWORDS_SUPPORT = Redmine::Plugin.installed?('redmine_passwords') ? true : false +module RedmineMessenger + REDMINE_CONTACTS_SUPPORT = Redmine::Plugin.installed?('redmine_contacts') ? true : false + REDMINE_DB_SUPPORT = Redmine::Plugin.installed?('redmine_db') ? true : false + # this does not work at the moment, because redmine loads passwords after messener plugin + REDMINE_PASSWORDS_SUPPORT = Redmine::Plugin.installed?('redmine_passwords') ? true : false - def self.settings + class << self + def setup + # Patches + Issue.include RedmineMessenger::Patches::IssuePatch + WikiPage.include RedmineMessenger::Patches::WikiPagePatch + ProjectsController.send :helper, MessengerProjectsHelper + Contact.include(RedmineMessenger::Patches::ContactPatch) if RedmineMessenger::REDMINE_CONTACTS_SUPPORT + DbEntry.include(RedmineMessenger::Patches::DbEntryPatch) if RedmineMessenger::REDMINE_DB_SUPPORT + Password.include(RedmineMessenger::Patches::PasswordPatch) if Redmine::Plugin.installed?('redmine_passwords') + + # Global helpers + ActionView::Base.include RedmineMessenger::Helpers + + # Hooks + require_dependency 'redmine_messenger/hooks' + end + + def settings if Setting[:plugin_redmine_messenger].class == Hash - if Rails.version >= '5.2' - # convert Rails 4 data - new_settings = ActiveSupport::HashWithIndifferentAccess.new(Setting[:plugin_redmine_messenger]) - Setting.plugin_redmine_messenger = new_settings - new_settings - else - ActionController::Parameters.new(Setting[:plugin_redmine_messenger]) - end + new_settings = ActiveSupport::HashWithIndifferentAccess.new(Setting[:plugin_redmine_messenger]) + Setting.plugin_redmine_messenger = new_settings + new_settings else # Rails 5 uses ActiveSupport::HashWithIndifferentAccess Setting[:plugin_redmine_messenger] end end - def self.setting?(value) + def setting?(value) return true if settings[value].to_i == 1 false end end - - # Patches - Issue.send(:include, RedmineMessenger::Patches::IssuePatch) - WikiPage.send(:include, RedmineMessenger::Patches::WikiPagePatch) - ProjectsController.send :helper, MessengerProjectsHelper - Contact.send(:include, RedmineMessenger::Patches::ContactPatch) if RedmineMessenger::REDMINE_CONTACTS_SUPPORT - DbEntry.send(:include, RedmineMessenger::Patches::DbEntryPatch) if RedmineMessenger::REDMINE_DB_SUPPORT - Password.send(:include, RedmineMessenger::Patches::PasswordPatch) if Redmine::Plugin.installed?('redmine_passwords') - - # Global helpers - ActionView::Base.send :include, RedmineMessenger::Helpers - - # Hooks - require_dependency 'redmine_messenger/hooks' end diff --git a/lib/redmine_messenger/hooks.rb b/lib/redmine_messenger/hooks.rb index c651366..1b0a62d 100644 --- a/lib/redmine_messenger/hooks.rb +++ b/lib/redmine_messenger/hooks.rb @@ -11,7 +11,8 @@ module RedmineMessenger return unless channels.present? && url && issue.changes.any? && Messenger.setting_for_project(issue.project, :post_updates) return if issue.is_private? && !Messenger.setting_for_project(issue.project, :post_private_issues) - msg = "[#{ERB::Util.html_escape(issue.project)}] #{ERB::Util.html_escape(journal.user.to_s)} updated <#{Messenger.object_url issue}|#{ERB::Util.html_escape(issue)}>" + msg = "[#{Messenger.markup_format(issue.project)}]" \ + " #{Messenger.markup_format(journal.user.to_s)} updated <#{Messenger.object_url issue}|#{Messenger.markup_format(issue)}>" repository = changeset.repository @@ -43,7 +44,9 @@ module RedmineMessenger end attachment = {} - attachment[:text] = ll(Setting.default_language, :text_status_changed_by_changeset, "<#{revision_url}|#{ERB::Util.html_escape(changeset.comments)}>") + attachment[:text] = ll(Setting.default_language, + :text_status_changed_by_changeset, + "<#{revision_url}|#{Messenger.markup_format(changeset.comments)}>") attachment[:fields] = journal.details.map { |d| Messenger.detail_to_field d } Messenger.speak(msg, channels, url, attachment: attachment, project: repository.project) diff --git a/lib/redmine_messenger/patches/contact_patch.rb b/lib/redmine_messenger/patches/contact_patch.rb index eb874d3..532f50e 100644 --- a/lib/redmine_messenger/patches/contact_patch.rb +++ b/lib/redmine_messenger/patches/contact_patch.rb @@ -4,8 +4,8 @@ module RedmineMessenger def self.included(base) base.send(:include, InstanceMethods) base.class_eval do - after_create :send_messenger_create - after_update :send_messenger_update + after_create_commit :send_messenger_create + after_update_commit :send_messenger_update end end @@ -22,7 +22,7 @@ module RedmineMessenger return unless channels.present? && url Messenger.speak(l(:label_messenger_contact_created, - project_url: "<#{Messenger.object_url project}|#{ERB::Util.html_escape(project)}>", + project_url: "<#{Messenger.object_url project}|#{Messenger.markup_format(project)}>", url: "<#{Messenger.object_url self}|#{name}>", user: User.current), channels, url, project: project) @@ -40,7 +40,7 @@ module RedmineMessenger return unless channels.present? && url Messenger.speak(l(:label_messenger_contact_updated, - project_url: "<#{Messenger.object_url project}|#{ERB::Util.html_escape(project)}>", + project_url: "<#{Messenger.object_url project}|#{Messenger.markup_format(project)}>", url: "<#{Messenger.object_url self}|#{name}>", user: User.current), channels, url, project: project) diff --git a/lib/redmine_messenger/patches/db_entry_patch.rb b/lib/redmine_messenger/patches/db_entry_patch.rb index 6f55fae..1ec5211 100644 --- a/lib/redmine_messenger/patches/db_entry_patch.rb +++ b/lib/redmine_messenger/patches/db_entry_patch.rb @@ -4,8 +4,8 @@ module RedmineMessenger def self.included(base) base.send(:include, InstanceMethods) base.class_eval do - after_create :send_messenger_create - after_update :send_messenger_update + after_create_commit :send_messenger_create + after_update_commit :send_messenger_update end end @@ -22,7 +22,7 @@ module RedmineMessenger return unless channels.present? && url Messenger.speak(l(:label_messenger_db_entry_created, - project_url: "<#{Messenger.object_url project}|#{ERB::Util.html_escape(project)}>", + project_url: "<#{Messenger.object_url project}|#{Messenger.markup_format(project)}>", url: "<#{Messenger.object_url self}|#{name}>", user: User.current), channels, url, project: project) @@ -40,7 +40,7 @@ module RedmineMessenger return unless channels.present? && url Messenger.speak(l(:label_messenger_db_entry_updated, - project_url: "<#{Messenger.object_url project}|#{ERB::Util.html_escape(project)}>", + project_url: "<#{Messenger.object_url project}|#{Messenger.markup_format(project)}>", url: "<#{Messenger.object_url self}|#{name}>", user: User.current), channels, url, project: project) diff --git a/lib/redmine_messenger/patches/issue_patch.rb b/lib/redmine_messenger/patches/issue_patch.rb index 25164bb..dcada8d 100644 --- a/lib/redmine_messenger/patches/issue_patch.rb +++ b/lib/redmine_messenger/patches/issue_patch.rb @@ -4,8 +4,8 @@ module RedmineMessenger def self.included(base) base.send(:include, InstanceMethods) base.class_eval do - after_create :send_messenger_create - after_update :send_messenger_update + after_create_commit :send_messenger_create + after_update_commit :send_messenger_update end end @@ -24,27 +24,27 @@ module RedmineMessenger attachment[:text] = Messenger.markup_format(description) end attachment[:fields] = [{ title: I18n.t(:field_status), - value: ERB::Util.html_escape(status.to_s), + value: Messenger.markup_format(status.to_s), short: true }, { title: I18n.t(:field_priority), - value: ERB::Util.html_escape(priority.to_s), + value: Messenger.markup_format(priority.to_s), short: true }] if assigned_to.present? attachment[:fields] << { title: I18n.t(:field_assigned_to), - value: ERB::Util.html_escape(assigned_to.to_s), + value: Messenger.markup_format(assigned_to.to_s), short: true } end - if RedmineMessenger.setting?(:display_watchers) && watcher_users.count > 0 + if RedmineMessenger.setting?(:display_watchers) && watcher_users.count.positive? attachment[:fields] << { title: I18n.t(:field_watcher), - value: ERB::Util.html_escape(watcher_users.join(', ')), + value: Messenger.markup_format(watcher_users.join(', ')), short: true } end Messenger.speak(l(:label_messenger_issue_created, - project_url: "<#{Messenger.object_url project}|#{ERB::Util.html_escape(project)}>", + project_url: "<#{Messenger.object_url project}|#{Messenger.markup_format(project)}>", url: send_messenger_mention_url(project, description), user: author), channels, url, attachment: attachment, project: project) @@ -63,31 +63,37 @@ module RedmineMessenger set_language_if_valid Setting.default_language attachment = {} - if current_journal.notes.present? && Messenger.setting_for_project(project, :updated_include_description) - attachment[:text] = Messenger.markup_format(current_journal.notes) + if Messenger.setting_for_project(project, :updated_include_description) + attachment[:text] = Messenger.markup_format(description) if saved_change_to_description? + + if current_journal.notes.present? + if attachment[:text].present? + attachment[:text] << content_tag('p', l(:label_comment)) + attachment[:text] << Messenger.markup_format(current_journal.notes) + else + attachment[:text] = Messenger.markup_format(current_journal.notes) + end + end end fields = current_journal.details.map { |d| Messenger.detail_to_field d } - if status_id != status_id_was + if saved_change_to_status_id? fields << { title: I18n.t(:field_status), - value: ERB::Util.html_escape(status.to_s), + value: Messenger.markup_format(status.to_s), short: true } end - if priority_id != priority_id_was + + if saved_change_to_priority_id? fields << { title: I18n.t(:field_priority), - value: ERB::Util.html_escape(priority.to_s), - short: true } - end - if assigned_to.present? - fields << { title: I18n.t(:field_assigned_to), - value: ERB::Util.html_escape(assigned_to.to_s), + value: Messenger.markup_format(priority.to_s), short: true } end + attachment[:fields] = fields if fields.any? Messenger.speak(l(:label_messenger_issue_updated, - project_url: "<#{Messenger.object_url project}|#{ERB::Util.html_escape(project)}>", - url: send_messenger_mention_url(project, current_journal.notes), + project_url: "<#{Messenger.object_url project}|#{Messenger.markup_format(project)}>", + url: send_messenger_mention_url(project, description), user: current_journal.user), channels, url, attachment: attachment, project: project) end @@ -100,7 +106,7 @@ module RedmineMessenger Messenger.textfield_for_project(project, :default_mentions).present? mention_to = Messenger.mentions(project, text) end - "<#{Messenger.object_url(self)}|#{ERB::Util.html_escape(self)}>#{mention_to}" + "<#{Messenger.object_url(self)}|#{Messenger.markup_format(self)}>#{mention_to}" end end end diff --git a/lib/redmine_messenger/patches/password_patch.rb b/lib/redmine_messenger/patches/password_patch.rb index 31c855e..b71139b 100644 --- a/lib/redmine_messenger/patches/password_patch.rb +++ b/lib/redmine_messenger/patches/password_patch.rb @@ -4,8 +4,8 @@ module RedmineMessenger def self.included(base) base.send(:include, InstanceMethods) base.class_eval do - after_create :send_messenger_create - after_update :send_messenger_update + after_create_commit :send_messenger_create + after_update_commit :send_messenger_update end end @@ -22,7 +22,7 @@ module RedmineMessenger return unless channels.present? && url Messenger.speak(l(:label_messenger_password_created, - project_url: "<#{Messenger.object_url project}|#{ERB::Util.html_escape(project)}>", + project_url: "<#{Messenger.object_url project}|#{Messenger.markup_format(project)}>", url: "<#{Messenger.object_url self}|#{name}>", user: User.current), channels, url, project: project) @@ -40,7 +40,7 @@ module RedmineMessenger return unless channels.present? && url Messenger.speak(l(:label_messenger_password_updated, - project_url: "<#{Messenger.object_url project}|#{ERB::Util.html_escape(project)}>", + project_url: "<#{Messenger.object_url project}|#{Messenger.markup_format(project)}>", url: "<#{Messenger.object_url self}|#{name}>", user: User.current), channels, url, project: project) diff --git a/lib/redmine_messenger/patches/wiki_page_patch.rb b/lib/redmine_messenger/patches/wiki_page_patch.rb index 5288bac..1486d8e 100644 --- a/lib/redmine_messenger/patches/wiki_page_patch.rb +++ b/lib/redmine_messenger/patches/wiki_page_patch.rb @@ -4,8 +4,8 @@ module RedmineMessenger def self.included(base) base.send(:include, InstanceMethods) base.class_eval do - after_create :send_messenger_create - after_update :send_messenger_update + after_create_commit :send_messenger_create + after_update_commit :send_messenger_update end end @@ -21,7 +21,7 @@ module RedmineMessenger return unless channels.present? && url Messenger.speak(l(:label_messenger_wiki_created, - project_url: "<#{Messenger.object_url project}|#{ERB::Util.html_escape(project)}>", + project_url: "<#{Messenger.object_url project}|#{Messenger.markup_format(project)}>", url: "<#{Messenger.object_url self}|#{title}>", user: User.current), channels, url, project: project) @@ -44,7 +44,7 @@ module RedmineMessenger end Messenger.speak(l(:label_messenger_wiki_updated, - project_url: "<#{Messenger.object_url project}|#{ERB::Util.html_escape(project)}>", + project_url: "<#{Messenger.object_url project}|#{Messenger.markup_format(project)}>", url: "<#{Messenger.object_url self}|#{title}>", user: content.author), channels, url, project: project, attachment: attachment) diff --git a/test/support/Gemfile.local b/test/support/Gemfile.local new file mode 100644 index 0000000..aad214b --- /dev/null +++ b/test/support/Gemfile.local @@ -0,0 +1,3 @@ +gem 'rubocop', require: false +gem 'rubocop-performance', require: false +gem 'rubocop-rails', require: false diff --git a/test/support/database-mysql-travis.yml b/test/support/database-mysql-travis.yml new file mode 100644 index 0000000..2acc077 --- /dev/null +++ b/test/support/database-mysql-travis.yml @@ -0,0 +1,8 @@ +test: + adapter: mysql2 + database: travis_ci_test + host: localhost + username: root + password: + pool: 5 + encoding: utf8mb4 diff --git a/test/unit/i18n_test.rb b/test/unit/i18n_test.rb index 1c9baae..8e2dbda 100644 --- a/test/unit/i18n_test.rb +++ b/test/unit/i18n_test.rb @@ -17,12 +17,8 @@ class I18nTest < ActiveSupport::TestCase end def test_locales_validness - lang_files_count = Dir[Rails.root.join('plugins', - 'redmine_messenger', - 'config', - 'locales', - '*.yml')].size - assert_equal lang_files_count, 3 + lang_files_count = Dir[Rails.root.join('plugins/redmine_messenger/config/locales/*.yml')].size + assert_equal lang_files_count, 4 valid_languages.each do |lang| assert set_language_if_valid(lang) end