Subject: [PATCH] Feature: webhook --- Index: Gemfile IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/Gemfile b/Gemfile --- a/Gemfile (revision f9673061812c2f08e3775f61597c44826a430ea3) +++ b/Gemfile (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da) @@ -15,6 +15,7 @@ gem 'rbpdf', '~> 1.21.3' gem 'addressable' gem 'rubyzip', '~> 2.3.0' +gem 'rest-client', '~> 2.1' # Ruby Standard Gems gem 'csv', '~> 3.2.6' Index: app/controllers/webhooks_controller.rb IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/app/controllers/webhooks_controller.rb b/app/controllers/webhooks_controller.rb new file mode 100644 --- /dev/null (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da) +++ b/app/controllers/webhooks_controller.rb (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da) @@ -0,0 +1,78 @@ +# frozen_string_literal: true + +class WebhooksController < ApplicationController + self.main_menu = false + + before_action :require_login + before_action :check_enabled + before_action :authorize + before_action :find_webhook, :only => [:edit, :update, :destroy] + + require_sudo_mode :create, :update, :destroy + + helper :projects + + def index + @webhooks = webhooks_scope.order(:url) + end + + def new + @webhook = User.current.webhooks.build + end + + def edit + end + + def create + @webhook = User.current.webhooks.build(webhook_params) + if @webhook.save + redirect_to webhooks_path + else + render :new + end + end + + def update + if @webhook.update(webhook_params) + redirect_to webhooks_path + else + render :edit + end + end + + def destroy + @webhook.destroy + redirect_to webhooks_path + end + + private + + def webhooks_scope + if User.current.admin? + Webhook.includes(:user).references(:users) + else + User.current.webhooks + end + end + + def webhook_params + attrs = params.require(:webhook).permit(:url, :secret, :active, :events => [], :project_ids => [], :tracker_ids => []) + attrs[:events] = Array(attrs[:events]).reject(&:blank?) + attrs[:project_ids] = Array(attrs[:project_ids]).reject(&:blank?) + attrs[:tracker_ids] = Array(attrs[:tracker_ids]).reject(&:blank?) + attrs + end + + def find_webhook + @webhook = webhooks_scope.find_by(:id => params[:id]) + render_404 unless @webhook + end + + def authorize + deny_access unless User.current.allowed_to?(:use_webhooks, nil, :global => true) + end + + def check_enabled + render_403 unless Webhook.enabled? + end +end Index: app/jobs/webhook_job.rb IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/app/jobs/webhook_job.rb b/app/jobs/webhook_job.rb new file mode 100644 --- /dev/null (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da) +++ b/app/jobs/webhook_job.rb (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da) @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class WebhookJob < ApplicationJob + def perform(hook_id, payload_json) + previous_user = User.current + hook = Webhook.find_by(:id => hook_id) + return unless hook&.user&.active? + + User.current = hook.user + hook.call(payload_json) + ensure + User.current = previous_user + end +end Index: app/models/issue.rb IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/app/models/issue.rb b/app/models/issue.rb --- a/app/models/issue.rb (revision f9673061812c2f08e3775f61597c44826a430ea3) +++ b/app/models/issue.rb (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da) @@ -127,6 +127,9 @@ # https://api.rubyonrails.org/v5.2.3/classes/ActiveSupport/Callbacks/ClassMethods.html#method-i-set_callback after_create_commit :send_notification after_create_commit :add_auto_watcher + after_create_commit -> {Webhook.trigger('issue.created', self)} + after_update_commit :trigger_issue_webhooks + after_destroy_commit -> {Webhook.trigger('issue.deleted', self)} after_commit :create_parent_issue_journal # Returns a SQL conditions string used to find all issues visible by the specified user @@ -164,6 +167,20 @@ end end + def trigger_issue_webhooks + Webhook.trigger('issue.updated', self) + + return unless saved_change_to_status_id? + + previous_status = IssueStatus.find_by(:id => saved_change_to_status_id.first) + current_status = status + + return unless current_status&.is_closed? + return if previous_status&.is_closed? + + Webhook.trigger('issue.closed', self) + end + # Returns true if usr or current user is allowed to view the issue def visible?(usr=nil) (usr || User.current).allowed_to?(:view_issues, self.project) do |role, user| Index: app/models/project.rb IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/app/models/project.rb b/app/models/project.rb --- a/app/models/project.rb (revision f9673061812c2f08e3775f61597c44826a430ea3) +++ b/app/models/project.rb (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da) @@ -47,6 +47,7 @@ has_many :queries, :dependent => :destroy has_many :documents, :dependent => :destroy has_many :news, lambda {includes(:author)}, :dependent => :destroy + has_and_belongs_to_many :webhooks has_many :issue_categories, lambda {order(:name)}, :dependent => :delete_all has_many :boards, lambda {order(:position)}, :inverse_of => :project, :dependent => :destroy has_one :repository, lambda {where(:is_default => true)} Index: app/models/user.rb IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/app/models/user.rb b/app/models/user.rb --- a/app/models/user.rb (revision f9673061812c2f08e3775f61597c44826a430ea3) +++ b/app/models/user.rb (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da) @@ -91,6 +91,7 @@ has_one :api_token, lambda {where "#{table.name}.action='api'"}, :class_name => 'Token' has_one :email_address, lambda {where :is_default => true}, :autosave => true has_many :email_addresses, :dependent => :delete_all + has_many :webhooks, :dependent => :destroy belongs_to :auth_source scope :logged, lambda {where("#{User.table_name}.status <> #{STATUS_ANONYMOUS}")} Index: app/models/webhook.rb IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/app/models/webhook.rb b/app/models/webhook.rb new file mode 100644 --- /dev/null (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da) +++ b/app/models/webhook.rb (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da) @@ -0,0 +1,166 @@ +# frozen_string_literal: true + +require 'rest-client' + +class Webhook < ApplicationRecord + belongs_to :user + has_and_belongs_to_many :projects + has_and_belongs_to_many :trackers + + serialize :events, Array + + validates :url, :presence => true, + :length => {:maximum => 2000}, + :webhook_endpoint => true + validates :secret, :length => {:maximum => 255}, :allow_blank => true + validate :validate_events + validate :validate_projects + validate :validate_trackers + + scope :active, -> {where(:active => true)} + + before_validation :filter_projects + before_validation :filter_trackers + after_initialize :ensure_events_array + + def self.enabled? + Setting.webhooks_enabled? + end + + def self.trigger(event, object) + return unless enabled? + + hooks_for(event, object).each do |hook| + payload = hook.payload(event, object) + WebhookJob.perform_later(hook.id, payload.to_json) + end + end + + def self.hooks_for(event, object) + project = object.respond_to?(:project) ? object.project : nil + return [] unless project + + active + .joins(:projects, :user) + .where(:projects => {:id => project.id}) + .where(:users => {:status => User::STATUS_ACTIVE}) + .select do |hook| + hook.events.include?(event) && + (!object.respond_to?(:visible?) || object.visible?(hook.user)) && + hook.user.allowed_to?(:use_webhooks, project) && + hook.tracker_allowed?(object) + end + end + + def setable_projects + member = user || User.current + return Project.none unless member + + Project.allowed_to(member, :use_webhooks).sorted + end + + def setable_events + WebhookPayload::EVENTS + end + + def setable_event_names + setable_events.flat_map {|type, actions| actions.map {|action| "#{type}.#{action}"}} + end + + def setable_trackers + project_trackers = setable_projects.includes(:trackers).flat_map(&:trackers) + project_trackers.uniq.sort_by(&:position) + end + + def payload(event, object) + WebhookPayload.new(event, object, user).to_h + end + + def call(payload_json) + Executor.new(url, payload_json, secret).call + true + rescue => e + Rails.logger.warn do + "Webhook delivery failed: #{e.class}: #{e.message}\n#{Array(e.backtrace).join("\n")}" + end + false + end + + class Executor + def initialize(url, payload, secret) + @url = url + @payload = payload + @secret = secret + end + + def call + raise URI::BadURIError unless WebhookEndpointValidator.safe_webhook_uri?(@url) + + headers = { + :accept => '*/*', + :content_type => :json, + :user_agent => 'Redmine' + } + headers['X-Redmine-Signature-256'] = compute_signature if @secret.present? + + Rails.logger.debug {"Webhook: POST #{@url}"} + RestClient.post(@url, @payload, headers) + end + + private + + def compute_signature + 'sha256=' + OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), @secret, @payload) + end + end + + def tracker_allowed?(object) + return true unless object.respond_to?(:tracker_id) + tracker_ids.blank? || tracker_ids.include?(object.tracker_id) + end + + private + + def ensure_events_array + self.events ||= [] + end + + def filter_projects + return if project_ids.blank? + + allowed_ids = setable_projects.map(&:id) + self.project_ids = project_ids & allowed_ids + end + + def filter_trackers + return if tracker_ids.blank? + + allowed_ids = setable_trackers.map(&:id) + self.tracker_ids = tracker_ids & allowed_ids + end + + def validate_events + self.events = Array(events).reject(&:blank?) + if events.blank? || (events - setable_event_names).any? + errors.add(:events, :invalid) + end + end + + def validate_projects + if project_ids.blank? + errors.add(:projects, :blank) + end + end + + def validate_trackers + self.tracker_ids = tracker_ids & setable_trackers.map(&:id) + + if issue_events_selected? && tracker_ids.blank? + errors.add(:trackers, :blank) + end + end + + def issue_events_selected? + Array(events).any? {|event| event.to_s.start_with?('issue.')} + end +end Index: app/models/webhook_payload.rb IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/app/models/webhook_payload.rb b/app/models/webhook_payload.rb new file mode 100644 --- /dev/null (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da) +++ b/app/models/webhook_payload.rb (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da) @@ -0,0 +1,201 @@ +# frozen_string_literal: true + +class WebhookPayload + EVENTS = { + :issue => %w[created updated closed deleted], + :wiki_page => %w[created updated deleted] + }.freeze + + attr_reader :event, :object, :user + + def initialize(event, object, user) + @event = event + @object = object + @user = user + end + + def to_h + type, action = event.split('.') + type = type&.to_sym + unless EVENTS[type]&.include?(action) + raise ArgumentError, "Unsupported webhook event: #{event}" + end + + payload, timestamp = send("#{type}_payload", action) + timestamp ||= Time.current + { + :type => event, + :timestamp => timestamp.utc.iso8601, + :data => payload + } + end + + private + + def issue_payload(action) + issue = object + journal = %w[updated closed].include?(action) ? issue.current_journal : nil + + payload = { + :issue => issue_hash(issue) + } + payload[:journal] = journal_hash(journal) if journal + + timestamp = + case action + when 'created' + issue.created_on + when 'closed' + issue.closed_on || Time.current + when 'deleted' + Time.current + else + journal&.created_on || issue.updated_on + end + + [payload, timestamp] + end + + def wiki_page_payload(action) + page, content = wiki_page_and_content + payload = { + :wiki_page => wiki_page_hash(page) + } + payload[:content] = wiki_content_hash(content) if content + + timestamp = + case action + when 'created' + content&.created_on || Time.current + when 'deleted' + Time.current + else + content&.updated_on || Time.current + end + + [payload, timestamp] + end + + def issue_hash(issue) + hash = { + :id => issue.id, + :subject => issue.subject, + :description => issue.description, + :is_private => issue.is_private?, + :project => project_hash(issue.project), + :tracker => reference_hash(issue.tracker), + :status => status_hash(issue.status), + :priority => reference_hash(issue.priority), + :author => user_hash(issue.author), + :assigned_to => user_hash(issue.assigned_to), + :category => reference_hash(issue.category), + :fixed_version => reference_hash(issue.fixed_version), + :parent => issue.parent_id ? {:id => issue.parent_id} : nil, + :start_date => issue.start_date&.to_s, + :due_date => issue.due_date&.to_s, + :done_ratio => issue.done_ratio, + :estimated_hours => issue.estimated_hours, + :total_estimated_hours => issue.total_estimated_hours, + :created_on => issue.created_on&.iso8601, + :updated_on => issue.updated_on&.iso8601, + :closed_on => issue.closed_on&.iso8601 + } + + if user&.allowed_to?(:view_time_entries, issue.project) + hash[:spent_hours] = issue.spent_hours + hash[:total_spent_hours] = issue.total_spent_hours + end + + custom_fields = issue.visible_custom_field_values(user).map do |value| + { + :id => value.custom_field_id, + :name => value.custom_field.name, + :value => value.value + } + end + hash[:custom_fields] = custom_fields if custom_fields.any? + + hash.compact + end + + def journal_hash(journal) + return unless journal + + { + :id => journal.id, + :notes => journal.notes, + :created_on => journal.created_on&.iso8601, + :user => user_hash(journal.user), + :details => journal.visible_details(user).map do |detail| + { + :property => detail.property, + :prop_key => detail.prop_key, + :old_value => detail.old_value, + :value => detail.value + } + end + } + end + + def wiki_page_hash(page) + return {} unless page + + { + :id => page.id, + :title => page.title, + :project => project_hash(page.project), + :parent_id => page.parent_id, + :created_on => page.created_on&.iso8601, + :updated_on => page.updated_on&.iso8601 + }.compact + end + + def wiki_content_hash(content) + return unless content + + { + :version => content.version, + :text => content.text, + :comments => content.comments, + :author => user_hash(content.author), + :created_on => content.created_on&.iso8601, + :updated_on => content.updated_on&.iso8601 + } + end + + def wiki_page_and_content + if object.is_a?(WikiContent) + [object.page, object] + else + [object, object.respond_to?(:content) ? object.content : nil] + end + end + + def project_hash(project) + return unless project + + { + :id => project.id, + :identifier => project.identifier, + :name => project.name + } + end + + def reference_hash(record) + return unless record + + {:id => record.id, :name => record.name} + end + + def status_hash(status) + return unless status + + {:id => status.id, :name => status.name, :is_closed => status.is_closed?} + end + + def user_hash(user_record) + return unless user_record + + {:id => user_record.id, :name => user_record.name} + end +end Index: app/models/wiki_content.rb IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/app/models/wiki_content.rb b/app/models/wiki_content.rb --- a/app/models/wiki_content.rb (revision f9673061812c2f08e3775f61597c44826a430ea3) +++ b/app/models/wiki_content.rb (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da) @@ -33,6 +33,8 @@ after_save :create_version after_create_commit :send_notification_create after_update_commit :send_notification_update + after_create_commit :trigger_webhook_create + after_update_commit :trigger_webhook_update scope :without_text, lambda {select(:id, :page_id, :version, :updated_on)} @@ -101,4 +103,12 @@ Mailer.deliver_wiki_content_updated(self) end end + + def trigger_webhook_create + Webhook.trigger('wiki_page.created', self) + end + + def trigger_webhook_update + Webhook.trigger('wiki_page.updated', self) + end end Index: app/models/wiki_page.rb IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb --- a/app/models/wiki_page.rb (revision f9673061812c2f08e3775f61597c44826a430ea3) +++ b/app/models/wiki_page.rb (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da) @@ -61,6 +61,7 @@ before_destroy :delete_redirects before_save :handle_rename_or_move, :update_wiki_start_page after_save :handle_children_move, :delete_selected_attachments + after_destroy_commit -> {Webhook.trigger('wiki_page.deleted', self)} # eager load information about last updates, without loading text scope :with_updated_on, lambda {preload(:content_without_text)} Index: app/validators/webhook_endpoint_validator.rb IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/app/validators/webhook_endpoint_validator.rb b/app/validators/webhook_endpoint_validator.rb new file mode 100644 --- /dev/null (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da) +++ b/app/validators/webhook_endpoint_validator.rb (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da) @@ -0,0 +1,178 @@ +# frozen_string_literal: true + +require 'set' +require 'uri' +require 'resolv' +require 'ipaddr' + +class WebhookEndpointValidator < ActiveModel::EachValidator + BAD_PORTS = Set[25, 111, 135, 139, 445, 1433, 1521, 2049, 3306, 3389, 5985, 5986].freeze + + def validate_each(record, attribute, value) + return if value.blank? + + valid, reason = self.class.validate_uri(value) + record.errors.add(attribute, :invalid, message: reason && " (#{reason})") unless valid + end + + class << self + def safe_webhook_uri?(value) + valid, = validate_uri(value) + valid + end + + def validate_uri(value) + uri = value.is_a?(URI) ? value : URI.parse(value.to_s) + + return [false, 'must use http or https'] unless valid_scheme?(uri.scheme) + + host_reason = host_validation_error(uri.host) + return [false, host_reason] if host_reason + + return [false, 'uses a disallowed port'] unless valid_port?(uri.port) + + [true, nil] + rescue URI::Error, ArgumentError => e + Rails.logger.warn {"Webhook endpoint rejected: #{value.inspect} (#{e.message})"} + [false, e.message] + end + + def valid_scheme?(scheme) + %w[http https].include?(scheme) + end + + def host_validation_error(host) + return 'host is missing' if host.blank? + + blocked = blocked_targets + allowed = allowed_targets + + host_allowlisted = allowed[:host_pattern]&.match?(host) + + return 'host is blocklisted' if host_blocked?(host, blocked) + if !allowlist_empty?(allowed) && !host_allowlisted && !allowlist_ip_allowed_for_host?(host, allowed) + return "host is not on the allowlist" + end + + addresses = ip_literal?(host) ? [host] : resolve_addresses(host) + return nil if addresses.blank? && allowlist_empty?(allowed) + + addresses.each do |ip| + ipaddr = IPAddr.new(ip) + allowlisted_ip = host_allowlisted || allowlist_ip_allowed?(ipaddr, allowed) + + return "address #{ipaddr} is blocklisted" if blocked[:ips].any? {|entry| entry.include?(ipaddr)} + return "address #{ipaddr} is not on the allowlist" if !allowlist_empty?(allowed) && !allowlisted_ip + return "address #{ipaddr} is not reachable from the public network" if !allowlisted_ip && (ipaddr.loopback? || ipaddr.link_local? || ipaddr.private?) + rescue IPAddr::Error + return "address #{ip.inspect} is invalid" + end + + nil + end + + def valid_port?(port) + port.present? && !BAD_PORTS.include?(port) + end + + def resolve_addresses(host) + addresses = [] + Resolv.each_address(host) {|ip| addresses << ip} + addresses + rescue Resolv::ResolvError + [] + end + + def ip_literal?(host) + IPAddr.new(host) + true + rescue IPAddr::Error + false + end + + def blocked_targets + @blocked_targets ||= begin + ips = [] + host_patterns = [] + Array(Redmine::Configuration['webhook_blocklist']).each do |entry| + entry = entry.to_s.strip + next if entry.empty? + + begin + ips << IPAddr.new(entry) + rescue IPAddr::Error + host_patterns << entry + end + end + { + :ips => ips.freeze, + :host_pattern => build_host_pattern(host_patterns) + } + end + end + + def allowed_targets + @allowed_targets ||= begin + ips = [] + host_patterns = [] + Array(Redmine::Configuration['webhook_allowlist']).each do |entry| + entry = entry.to_s.strip + next if entry.empty? + + begin + ips << IPAddr.new(entry) + rescue IPAddr::Error + host_patterns << entry + end + end + { + :ips => ips.freeze, + :host_pattern => build_host_pattern(host_patterns) + } + end + end + + def build_host_pattern(patterns) + return if patterns.empty? + + sources = patterns.map do |value| + if value.start_with?('*.') + "(?:.*\\.)?#{Regexp.escape(value.delete_prefix('*.'))}" + else + Regexp.escape(value) + end + end + + Regexp.new("\\A(?:#{sources.join('|')})\\z", Regexp::IGNORECASE) + end + + def host_blocked?(host, blocked) + blocked[:host_pattern]&.match?(host) + end + + def host_allowed_by_allowlist?(host, allowed) + return true if allowlist_empty?(allowed) + + allowed[:host_pattern]&.match?(host) || allowlist_ip_allowed_for_host?(host, allowed) + end + + def allowlist_empty?(allowed) + allowed[:ips].empty? && allowed[:host_pattern].nil? + end + + def allowlist_ip_allowed_for_host?(host, allowed) + addresses = ip_literal?(host) ? [host] : resolve_addresses(host) + return false if addresses.empty? + + addresses.any? do |ip| + allowlist_ip_allowed?(IPAddr.new(ip), allowed) + rescue IPAddr::Error + false + end + end + + def allowlist_ip_allowed?(ipaddr, allowed) + allowed[:ips].any? {|entry| entry.include?(ipaddr)} + end + end +end Index: app/views/my/_sidebar.html.erb IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/app/views/my/_sidebar.html.erb b/app/views/my/_sidebar.html.erb --- a/app/views/my/_sidebar.html.erb (revision f9673061812c2f08e3775f61597c44826a430ea3) +++ b/app/views/my/_sidebar.html.erb (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da) @@ -31,6 +31,11 @@ <% else %> <%= l(:label_missing_api_access_key) %> <% end %> + +<% if Setting.webhooks_enabled? && User.current.allowed_to?(:use_webhooks, nil, :global => true) %> +
<%= link_to l(:label_webhook_plural), webhooks_path, :class => 'icon icon-link' %>
+<% end %> (<%= link_to l(:button_reset), my_api_key_path, :method => :post %>) <% end %> Index: app/views/settings/_api.html.erb IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/app/views/settings/_api.html.erb b/app/views/settings/_api.html.erb --- a/app/views/settings/_api.html.erb (revision f9673061812c2f08e3775f61597c44826a430ea3) +++ b/app/views/settings/_api.html.erb (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da) @@ -4,6 +4,8 @@<%= setting_check_box :rest_api_enabled %>
<%= setting_check_box :jsonp_enabled %>
+ +<%= setting_check_box :webhooks_enabled %>
<%= submit_tag l(:button_save) %> Index: app/views/webhooks/_form.html.erb IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/app/views/webhooks/_form.html.erb b/app/views/webhooks/_form.html.erb new file mode 100644 --- /dev/null (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da) +++ b/app/views/webhooks/_form.html.erb (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da) @@ -0,0 +1,68 @@ +<%= error_messages_for @webhook %> ++ <%= f.text_field :url, :required => true, :size => 60 %> + <%= l(:webhook_url_info) %> +
++ <%= f.text_field :secret %> + <%= raw l(:webhook_secret_info_html) %> +
++ <%= f.check_box :active %> <%= l(:field_active) %> +
+<%= submit_tag l(:button_save) %>
+<% end %> Index: app/views/webhooks/index.html.erb IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/app/views/webhooks/index.html.erb b/app/views/webhooks/index.html.erb new file mode 100644 --- /dev/null (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da) +++ b/app/views/webhooks/index.html.erb (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da) @@ -0,0 +1,43 @@ +| <%= l(:label_user) %> | + <% end %> +<%= l(:field_active) %> | +<%= l(:field_url) %> | +<%= l(:label_webhook_events) %> | +<%= l(:label_project_plural) %> | ++ |
|---|---|---|---|---|---|
| <%= h hook.user %> | + <% end %> +<%= hook.active? ? l(:general_text_Yes) : l(:general_text_No) %> | +<%= truncate(hook.url, :length => 50) %> | +<%= safe_join(hook.events.map {|e| content_tag(:code, e)}, ', ') %> | +<%= safe_join(hook.projects.visible.map {|p| link_to_project(p)}, ', ') %> | ++ <%= link_to l(:button_edit), edit_webhook_path(hook), :class => 'icon icon-edit' %> + <%= link_to l(:button_delete), webhook_path(hook), :method => :delete, :data => {:confirm => l(:text_are_you_sure)}, :class => 'icon icon-del' %> + | +
<%= l(:label_no_data) %>
+<% end %> Index: app/views/webhooks/new.html.erb IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/app/views/webhooks/new.html.erb b/app/views/webhooks/new.html.erb new file mode 100644 --- /dev/null (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da) +++ b/app/views/webhooks/new.html.erb (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da) @@ -0,0 +1,4 @@ +<%= labelled_form_for @webhook, :url => webhooks_path do |f| %> + <%= render :partial => 'form', :locals => {:f => f} %> +<%= submit_tag l(:button_create) %>
+<% end %> Index: config/locales/ar.yml IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/config/locales/ar.yml b/config/locales/ar.yml --- a/config/locales/ar.yml (revision f9673061812c2f08e3775f61597c44826a430ea3) +++ b/config/locales/ar.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da) @@ -1487,3 +1487,22 @@ text_default_active_job_queue_changed: Default queue adapter which is well suited only for dev/test changed twofa_already_setup: Two-factor authentication already set up + + label_webhook_plural: "Webhooks" + label_webhook_new: "New webhook" + label_webhook_edit: "Edit webhook" + label_webhook_events: "Events" + webhook_events_issue: "Issues" + webhook_events_issue_created: "Issue created" + webhook_events_issue_updated: "Issue updated" + webhook_events_issue_closed: "Issue closed" + webhook_events_issue_deleted: "Issue deleted" + webhook_events_wiki_page: "Wiki pages" + webhook_events_wiki_page_created: "Wiki page created" + webhook_events_wiki_page_updated: "Wiki page updated" + webhook_events_wiki_page_deleted: "Wiki page deleted" + webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs." + webhook_secret_info_html: "If set, Redmine will include an HMAC signature in theX-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/az.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/az.yml b/config/locales/az.yml
--- a/config/locales/az.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/az.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1579,3 +1579,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/bg.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/bg.yml b/config/locales/bg.yml
--- a/config/locales/bg.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/bg.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1432,3 +1432,22 @@
text_project_destroy_enter_identifier: За да потвърдите действието, въведете идентификатора на проекта (%{identifier}) по-долу.
field_name_or_email_or_login: Име, e-mail или login име
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/bs.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/bs.yml b/config/locales/bs.yml
--- a/config/locales/bs.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/bs.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1474,3 +1474,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/ca.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/ca.yml b/config/locales/ca.yml
--- a/config/locales/ca.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/ca.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1475,3 +1475,22 @@
text_select_apply_issue_status: Marca l'estat de la incidència
field_name_or_email_or_login: Nom, correu o login
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/cs.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/cs.yml b/config/locales/cs.yml
--- a/config/locales/cs.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/cs.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1469,3 +1469,22 @@
text_default_active_job_queue_changed: Výchozí adaptér fronty, vhodný pouze pro
vývoj/testování, byl změněn
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/da.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/da.yml b/config/locales/da.yml
--- a/config/locales/da.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/da.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1504,3 +1504,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/de.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/de.yml b/config/locales/de.yml
--- a/config/locales/de.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/de.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1455,3 +1455,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/el.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/el.yml b/config/locales/el.yml
--- a/config/locales/el.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/el.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1487,3 +1487,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/en-GB.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/en-GB.yml b/config/locales/en-GB.yml
--- a/config/locales/en-GB.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/en-GB.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1488,3 +1488,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/en.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/en.yml b/config/locales/en.yml
--- a/config/locales/en.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/en.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -922,6 +922,24 @@
label_year: Year
label_month: Month
label_week: Week
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
label_date_from: From
label_date_to: To
label_language_based: Based on user's language
Index: config/locales/es-PA.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/es-PA.yml b/config/locales/es-PA.yml
--- a/config/locales/es-PA.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/es-PA.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1517,3 +1517,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/es.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/es.yml b/config/locales/es.yml
--- a/config/locales/es.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/es.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1553,3 +1553,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/et.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/et.yml b/config/locales/et.yml
--- a/config/locales/et.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/et.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1492,3 +1492,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/eu.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/eu.yml b/config/locales/eu.yml
--- a/config/locales/eu.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/eu.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1488,3 +1488,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/fa.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/fa.yml b/config/locales/fa.yml
--- a/config/locales/fa.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/fa.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1421,3 +1421,22 @@
field_name_or_email_or_login: نام، رایانامه یا شناسه کاربری
text_default_active_job_queue_changed: آداپتور پیشفرض صف که به شکل مناسبی کار میکند تنها برای توسعه/آزمون تغییر کرد
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/fi.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/fi.yml b/config/locales/fi.yml
--- a/config/locales/fi.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/fi.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1508,3 +1508,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/fr.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
--- a/config/locales/fr.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/fr.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1471,3 +1471,22 @@
field_name_or_email_or_login: Nom, email ou login
text_default_active_job_queue_changed: Gestionnaire de file par défaut le plus adapté
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/gl.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/gl.yml b/config/locales/gl.yml
--- a/config/locales/gl.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/gl.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1492,3 +1492,22 @@
field_name_or_email_or_login: Nome, correo electrónico ou usuario
text_default_active_job_queue_changed: Cambiado o adaptador do sistema de colas por defecto dado que só está pensado para desenvolvemento/probas
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/he.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/he.yml b/config/locales/he.yml
--- a/config/locales/he.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/he.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1492,3 +1492,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/hr.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/hr.yml b/config/locales/hr.yml
--- a/config/locales/hr.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/hr.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1484,3 +1484,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/hu.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/hu.yml b/config/locales/hu.yml
--- a/config/locales/hu.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/hu.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1506,3 +1506,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/id.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/id.yml b/config/locales/id.yml
--- a/config/locales/id.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/id.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1489,3 +1489,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/it.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/it.yml b/config/locales/it.yml
--- a/config/locales/it.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/it.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1426,3 +1426,22 @@
text_project_destroy_enter_identifier: "Per confermare, inserisci l'identificativo del progetto (%{identifier}) qui sotto."
field_name_or_email_or_login: Nome, email o login
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/ja.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/ja.yml b/config/locales/ja.yml
--- a/config/locales/ja.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/ja.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1439,3 +1439,22 @@
field_name_or_email_or_login: 姓名・メールアドレス・ログインID
text_default_active_job_queue_changed: キューアダプターがデフォルト (開発・テスト用) 以外のものに変更済み
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/ko.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/ko.yml b/config/locales/ko.yml
--- a/config/locales/ko.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/ko.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1508,3 +1508,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/lt.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/lt.yml b/config/locales/lt.yml
--- a/config/locales/lt.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/lt.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1448,3 +1448,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/lv.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/lv.yml b/config/locales/lv.yml
--- a/config/locales/lv.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/lv.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1481,3 +1481,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/mk.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/mk.yml b/config/locales/mk.yml
--- a/config/locales/mk.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/mk.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1487,3 +1487,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/mn.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/mn.yml b/config/locales/mn.yml
--- a/config/locales/mn.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/mn.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1487,3 +1487,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/nl.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/nl.yml b/config/locales/nl.yml
--- a/config/locales/nl.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/nl.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1462,3 +1462,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/no.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/no.yml b/config/locales/no.yml
--- a/config/locales/no.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/no.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1477,3 +1477,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/pl.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/pl.yml b/config/locales/pl.yml
--- a/config/locales/pl.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/pl.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1431,3 +1431,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/pt-BR.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml
--- a/config/locales/pt-BR.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/pt-BR.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1492,3 +1492,22 @@
text_default_active_job_queue_changed: Adaptador de fila padrão que é bem adequado
apenas para dev/test foi alterado
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/pt.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/pt.yml b/config/locales/pt.yml
--- a/config/locales/pt.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/pt.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1480,3 +1480,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/ro.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/ro.yml b/config/locales/ro.yml
--- a/config/locales/ro.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/ro.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1482,3 +1482,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/ru.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/ru.yml b/config/locales/ru.yml
--- a/config/locales/ru.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/ru.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1557,3 +1557,22 @@
field_name_or_email_or_login: Имя, email или логин
text_default_active_job_queue_changed: Изменен адаптер очереди по умолчанию, который хорошо подходит только для разработки/тестирования
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/sk.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/sk.yml b/config/locales/sk.yml
--- a/config/locales/sk.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/sk.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1476,3 +1476,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/sl.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/sl.yml b/config/locales/sl.yml
--- a/config/locales/sl.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/sl.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1487,3 +1487,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/sq.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/sq.yml b/config/locales/sq.yml
--- a/config/locales/sq.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/sq.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1449,3 +1449,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/sr-YU.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/sr-YU.yml b/config/locales/sr-YU.yml
--- a/config/locales/sr-YU.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/sr-YU.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1489,3 +1489,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/sr.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/sr.yml b/config/locales/sr.yml
--- a/config/locales/sr.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/sr.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1488,3 +1488,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/sv.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/sv.yml b/config/locales/sv.yml
--- a/config/locales/sv.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/sv.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1520,3 +1520,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/ta-IN.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/ta-IN.yml b/config/locales/ta-IN.yml
--- a/config/locales/ta-IN.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/ta-IN.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1486,3 +1486,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/th.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/th.yml b/config/locales/th.yml
--- a/config/locales/th.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/th.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1483,3 +1483,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/tr.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/tr.yml b/config/locales/tr.yml
--- a/config/locales/tr.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/tr.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1486,3 +1486,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/uk.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/uk.yml b/config/locales/uk.yml
--- a/config/locales/uk.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/uk.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1475,3 +1475,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/vi.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/vi.yml b/config/locales/vi.yml
--- a/config/locales/vi.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/vi.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1492,3 +1492,22 @@
text_default_active_job_queue_changed: Default queue adapter which is well suited
only for dev/test changed
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/zh-TW.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml
--- a/config/locales/zh-TW.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/zh-TW.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1504,3 +1504,22 @@
field_name_or_email_or_login: 姓名, 電子郵件或帳戶名稱
text_default_active_job_queue_changed: 已變更僅適用於開發/測試環境的佇列適配器 (queue adapter)
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/locales/zh.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/locales/zh.yml b/config/locales/zh.yml
--- a/config/locales/zh.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/locales/zh.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -1423,3 +1423,22 @@
field_name_or_email_or_login: 姓名、电子邮件或登录名
text_default_active_job_queue_changed: 仅适用于开发/测试环境的默认队列适配器已改变
twofa_already_setup: Two-factor authentication already set up
+
+ label_webhook_plural: "Webhooks"
+ label_webhook_new: "New webhook"
+ label_webhook_edit: "Edit webhook"
+ label_webhook_events: "Events"
+ webhook_events_issue: "Issues"
+ webhook_events_issue_created: "Issue created"
+ webhook_events_issue_updated: "Issue updated"
+ webhook_events_issue_closed: "Issue closed"
+ webhook_events_issue_deleted: "Issue deleted"
+ webhook_events_wiki_page: "Wiki pages"
+ webhook_events_wiki_page_created: "Wiki page created"
+ webhook_events_wiki_page_updated: "Wiki page updated"
+ webhook_events_wiki_page_deleted: "Wiki page deleted"
+ webhook_url_info: "Redmine will send a POST request to this URL when one of the selected events in one of the selected projects occurs."
+ webhook_secret_info_html: "If set, Redmine will include an HMAC signature in the X-Redmine-Signature-256 header."
+ permission_use_webhooks: "Use webhooks"
+ setting_webhooks_enabled: "Enable webhooks"
+ label_integrations: "Integrations"
Index: config/routes.rb
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/routes.rb b/config/routes.rb
--- a/config/routes.rb (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/routes.rb (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -317,6 +317,7 @@
get 'attachments/download/:id', :to => 'attachments#download', :id => /\d+/
get 'attachments/thumbnail/:id(/:size)', :to => 'attachments#thumbnail', :id => /\d+/, :size => /\d+/, :as => 'thumbnail'
resources :attachments, :only => [:show, :update, :destroy]
+ resources :webhooks, :except => [:show]
# register plugin object types with ObjectTypeConstraint.register_object_type(PluginModel.name.underscore.pluralize')
constraints Redmine::Acts::Attachable::ObjectTypeConstraint do
Index: config/settings.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/config/settings.yml b/config/settings.yml
--- a/config/settings.yml (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/config/settings.yml (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -322,6 +322,9 @@
jsonp_enabled:
default: 0
security_notifications: 1
+webhooks_enabled:
+ default: 0
+ security_notifications: 1
default_notification_option:
default: 'only_my_events'
emails_header:
Index: db/migrate/20231120120000_create_webhooks.rb
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/db/migrate/20231120120000_create_webhooks.rb b/db/migrate/20231120120000_create_webhooks.rb
new file mode 100644
--- /dev/null (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
+++ b/db/migrate/20231120120000_create_webhooks.rb (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class CreateWebhooks < ActiveRecord::Migration[6.1]
+ def change
+ create_table :webhooks do |t|
+ t.references :user, :null => false
+ t.string :url, :limit => 2000, :null => false
+ t.string :secret, :limit => 255
+ t.boolean :active, :default => true, :null => false
+ t.text :events
+ t.timestamps
+ end
+ end
+end
Index: db/migrate/20231120120100_create_projects_webhooks.rb
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/db/migrate/20231120120100_create_projects_webhooks.rb b/db/migrate/20231120120100_create_projects_webhooks.rb
new file mode 100644
--- /dev/null (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
+++ b/db/migrate/20231120120100_create_projects_webhooks.rb (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+class CreateProjectsWebhooks < ActiveRecord::Migration[6.1]
+ def change
+ create_table :projects_webhooks, :id => false do |t|
+ t.references :project, :null => false
+ t.references :webhook, :null => false
+ end
+
+ add_index :projects_webhooks, [:project_id, :webhook_id], :unique => true, :name => 'index_projects_webhooks_on_project_and_webhook'
+ end
+end
Index: db/migrate/20231120120200_create_trackers_webhooks.rb
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/db/migrate/20231120120200_create_trackers_webhooks.rb b/db/migrate/20231120120200_create_trackers_webhooks.rb
new file mode 100644
--- /dev/null (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
+++ b/db/migrate/20231120120200_create_trackers_webhooks.rb (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class CreateTrackersWebhooks < ActiveRecord::Migration[6.1]
+ def change
+ create_table :trackers_webhooks, :id => false do |t|
+ t.references :tracker, :null => false
+ t.references :webhook, :null => false
+ end
+
+ add_index :trackers_webhooks, [:tracker_id, :webhook_id], :unique => true,
+ :name => 'index_trackers_webhooks_on_tracker_and_webhook'
+ end
+end
Index: doc/webhooks.md
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/doc/webhooks.md b/doc/webhooks.md
new file mode 100644
--- /dev/null (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
+++ b/doc/webhooks.md (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -0,0 +1,109 @@
+# Webhooks
+
+Redmine can send webhooks whenever issues or wiki pages change. A webhook delivers
+an HTTP POST request to an external service with a JSON payload that describes
+the event.
+
+## Enabling webhooks
+1. Go to **Administration → Settings → API** and enable **Enable webhooks**.
+2. Ensure background jobs are running so delivery jobs can be processed.
+ Webhook deliveries are enqueued as Active Job jobs, so they need a queue
+ runner:
+ - **Default (development/test)**: Rails uses the `:async` adapter, which
+ runs jobs in background threads inside the Redmine process. No extra
+ setup is required, but jobs stop if the process stops.
+ - **Production**: Configure a persistent queue adapter (for example
+ `:delayed_job` or `:sidekiq`) and run a worker process. With
+ `:delayed_job`, start a worker using `bundle exec rake jobs:work` and
+ supervise it via systemd, a service manager, or a cron-launched wrapper
+ so it restarts if it exits. With Sidekiq, run the Sidekiq process and
+ point it at the same Redis instance you configured for Active Job. Remember
+ to restart Sidekiq after patching the code!
+
+## Permissions
+Only users with the **Use webhooks** permission can create webhooks. The current
+implementation grants this permission to project members. Each webhook also
+respects the visibility of projects and issues for the webhook owner when
+selecting projects and when delivering events.
+
+## Creating a webhook
+1. Open **My account → Webhooks**.
+2. Click **New webhook**, then fill in the URL, optional secret, events,
+ projects, and (for issue events) **trackers**.
+3. Save the webhook. Active webhooks will enqueue a delivery job for each
+ matching event.
+
+### Tracker filters for issue events
+- Trackers determine which issues will trigger `issue.*` events. If you select
+ any issue events, you must pick at least one tracker; issues using other
+ trackers are skipped.
+- Choose only the trackers you care about to reduce traffic. When your project
+ list changes, the tracker list automatically narrows to the trackers used by
+ the projects you can select.
+
+### Secrets and signatures
+If you set a secret, Redmine includes an `X-Redmine-Signature-256` header. It is
+an HMAC SHA-256 signature of the request body using the provided secret.
+
+## Events and payload
+Supported events:
+- `issue.created`, `issue.updated`, `issue.closed`, `issue.deleted`
+- `wiki_page.created`, `wiki_page.updated`, `wiki_page.deleted`
+
+### When does a webhook fire?
+- The event is enqueued after the database transaction commits (so failed
+ saves do not send anything).
+- The webhook must be **active** and belong to a **user who is still active**.
+- The webhook’s user must have the **Use webhooks** permission on the project.
+- The issue or wiki page must be **visible to the webhook owner**; if the owner
+ cannot see the record, the event is skipped.
+- For issue events, the issue’s **tracker must be selected** on the webhook.
+- `issue.closed` fires only when an issue changes from a non-closed status to a
+ closed status.
+- Events are triggered regardless of which user performs the change. For
+ example, if Alice owns a webhook for Project A, and Bob updates or deletes an
+ issue in Project A, Alice’s webhook will still fire as long as she can see
+ the issue and has permission on that project.
+
+The request body is a JSON object with:
+- `type`: the event name, for example `issue.updated`
+- `timestamp`: ISO8601 timestamp of the event
+- `data`: object with the payload
+
+Issue payloads include the Redmine API representation of the issue, and for
+updates they also include the last journal entry with visible details for the
+webhook owner.
+
+Wiki payloads include the page and, for updates, the version number.
+
+## Safety checks
+Webhook endpoints must use HTTP(S) and cannot target loopback, link-local, or
+private addresses unless they are explicitly allowlisted. You can further
+restrict or block destinations:
+
+- **Blocklist** (`webhook_blocklist` in `config/configuration.yml`): a list of
+ hostnames (exact or `*.example.com` wildcards) or IP/CIDR entries that are
+ rejected. This is useful to prevent callbacks to internal hosts.
+- **Allowlist** (`webhook_allowlist` in `config/configuration.yml`): if set,
+ only hostnames or IPs/CIDRs that match the list are accepted. A hostname
+ entry covers all IPs it resolves to (including private ranges if you choose
+ to allow them). Both lists use the same syntax, for example:
+
+ ```yaml
+ production:
+ webhook_allowlist:
+ - hooks.example.com # exact host
+ - "*.hooks.example.org" # wildcard host
+ - 203.0.113.0/24 # CIDR range
+ - 10.254.80.0/24 # allow a private range (use with care)
+ webhook_blocklist:
+ - 10.0.0.0/8
+ - intranet.example.com
+ ```
+
+Leading and trailing whitespace around entries is ignored. If no allowlist is
+defined, any public host passes unless blocked or private.
+
+Endpoints are validated when saved and again before delivery. The validation
+error includes the reason (for example, blocked host, outside allowlist, or
+private address). A failed delivery logs the error but does not raise to users.
Index: lib/redmine/preparation.rb
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/lib/redmine/preparation.rb b/lib/redmine/preparation.rb
--- a/lib/redmine/preparation.rb (revision f9673061812c2f08e3775f61597c44826a430ea3)
+++ b/lib/redmine/preparation.rb (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -48,6 +48,7 @@
# Queries
map.permission :manage_public_queries, {:queries => [:new, :create, :edit, :update, :destroy]}, :require => :member
map.permission :save_queries, {:queries => [:new, :create, :edit, :update, :destroy]}, :require => :loggedin
+ map.permission :use_webhooks, {}, :require => :member
map.project_module :issue_tracking do |map|
# Issues
Index: test/functional/webhooks_controller_test.rb
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/test/functional/webhooks_controller_test.rb b/test/functional/webhooks_controller_test.rb
new file mode 100644
--- /dev/null (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
+++ b/test/functional/webhooks_controller_test.rb (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+require File.expand_path('../../test_helper', __FILE__)
+
+class WebhooksControllerTest < Redmine::ControllerTest
+ fixtures :projects, :users, :roles, :members, :member_roles, :trackers
+
+ def setup
+ %w[Manager Developer].each do |role_name|
+ Role.find_by_name(role_name).add_permission! :use_webhooks
+ end
+ end
+
+ def test_admin_can_view_all_webhooks
+ with_webhooks_enabled do
+ hook_one = create_webhook_for(User.find(2))
+ hook_two = create_webhook_for(User.find(3), 'https://example.net')
+
+ @request.session[:user_id] = 1
+ get :index
+
+ assert_response :success
+ assert_select 'table.list tbody tr', 2
+ assert_select 'td.username', :text => hook_one.user.name
+ assert_select 'td.username', :text => hook_two.user.name
+ end
+ end
+
+ def test_admin_can_edit_other_user_webhook
+ with_webhooks_enabled do
+ webhook = create_webhook_for(User.find(2))
+
+ @request.session[:user_id] = 1
+ get :edit, :params => {:id => webhook.id}
+
+ assert_response :success
+ assert_select 'form[action=?]', webhook_path(webhook)
+ end
+ end
+
+ private
+
+ def with_webhooks_enabled
+ with_settings :webhooks_enabled => '1' do
+ yield
+ end
+ end
+
+ def create_webhook_for(user, url = 'https://example.com')
+ project = Project.find(1)
+ role = Role.find_by_name('Manager')
+ tracker = Tracker.find(1)
+
+ unless user.member_of?(project)
+ Member.create!(:project => project, :principal => user, :roles => [role])
+ end
+
+ project.trackers << tracker unless project.trackers.include?(tracker)
+
+ Webhook.create!(
+ :user => user,
+ :url => url,
+ :projects => [project],
+ :trackers => [tracker],
+ :events => ['issue.created']
+ )
+ end
+end
Index: test/unit/webhook_endpoint_validator_test.rb
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/test/unit/webhook_endpoint_validator_test.rb b/test/unit/webhook_endpoint_validator_test.rb
new file mode 100644
--- /dev/null (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
+++ b/test/unit/webhook_endpoint_validator_test.rb (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -0,0 +1,104 @@
+# frozen_string_literal: true
+
+require File.expand_path('../../test_helper', __FILE__)
+
+class WebhookEndpointValidatorTest < ActiveSupport::TestCase
+ def teardown
+ WebhookEndpointValidator.unstub(:blocked_targets)
+ WebhookEndpointValidator.unstub(:allowed_targets)
+ WebhookEndpointValidator.unstub(:resolve_addresses)
+ rescue Mocha::NotInitializedError
+ # ignore when nothing was stubbed
+ end
+
+ def test_rejects_private_ip_addresses
+ WebhookEndpointValidator.stubs(:blocked_targets).returns(:ips => [], :host_pattern => nil)
+ WebhookEndpointValidator.stubs(:allowed_targets).returns(:ips => [], :host_pattern => nil)
+ WebhookEndpointValidator.stubs(:resolve_addresses).returns(['192.168.0.10'])
+
+ assert_not WebhookEndpointValidator.safe_webhook_uri?('http://example.test')
+ end
+
+ def test_allows_private_ip_addresses_on_allowlist
+ allowlist = {:ips => [IPAddr.new('10.254.80.0/24')], :host_pattern => nil}
+ WebhookEndpointValidator.stubs(:blocked_targets).returns(:ips => [], :host_pattern => nil)
+ WebhookEndpointValidator.stubs(:allowed_targets).returns(allowlist)
+ WebhookEndpointValidator.stubs(:resolve_addresses).returns(['10.254.80.25'])
+
+ assert WebhookEndpointValidator.safe_webhook_uri?('https://fileservermonitoring.geoxyz.be')
+ end
+
+ def test_allows_hosts_on_allowlist_pattern
+ WebhookEndpointValidator.stubs(:blocked_targets).returns(:ips => [], :host_pattern => nil)
+ WebhookEndpointValidator.stubs(:allowed_targets).returns(
+ :ips => [],
+ :host_pattern => Regexp.new('\\Aallowed\\.example\\.org\\z')
+ )
+ WebhookEndpointValidator.stubs(:resolve_addresses).returns(['203.0.113.5'])
+
+ assert WebhookEndpointValidator.safe_webhook_uri?('https://allowed.example.org')
+ assert_not WebhookEndpointValidator.safe_webhook_uri?('https://other.example.org')
+ end
+
+ def test_allowlisted_hostname_does_not_require_ip_entry
+ allowlist = {:ips => [], :host_pattern => Regexp.new('\\Afileservermonitoring\\.geoxyz\\.be\\z')}
+ WebhookEndpointValidator.stubs(:blocked_targets).returns(:ips => [], :host_pattern => nil)
+ WebhookEndpointValidator.stubs(:allowed_targets).returns(allowlist)
+ WebhookEndpointValidator.stubs(:resolve_addresses).returns(['203.0.113.7'])
+
+ assert WebhookEndpointValidator.safe_webhook_uri?('https://fileservermonitoring.geoxyz.be/redmine/webhook')
+ end
+
+ def test_allows_hosts_with_ip_allowlist_entry
+ allowlist = {:ips => [IPAddr.new('203.0.113.0/24')], :host_pattern => nil}
+ WebhookEndpointValidator.stubs(:blocked_targets).returns(:ips => [], :host_pattern => nil)
+ WebhookEndpointValidator.stubs(:allowed_targets).returns(allowlist)
+ WebhookEndpointValidator.stubs(:resolve_addresses).returns(['203.0.113.99'])
+
+ assert WebhookEndpointValidator.safe_webhook_uri?('https://example.net')
+
+ WebhookEndpointValidator.stubs(:resolve_addresses).returns(['198.51.100.10'])
+ assert_not WebhookEndpointValidator.safe_webhook_uri?('https://example.net')
+ end
+
+ def test_hostname_allowlist_accepts_resolved_ip
+ allowlist = {:ips => [], :host_pattern => Regexp.new('\\Aallowed\\.example\\.org\\z')}
+ WebhookEndpointValidator.stubs(:blocked_targets).returns(:ips => [], :host_pattern => nil)
+ WebhookEndpointValidator.stubs(:allowed_targets).returns(allowlist)
+ WebhookEndpointValidator.stubs(:resolve_addresses).returns(['203.0.113.10'])
+
+ assert WebhookEndpointValidator.safe_webhook_uri?('https://allowed.example.org/webhook')
+ end
+
+ def test_hostname_not_on_allowlist_is_rejected
+ allowlist = {:ips => [], :host_pattern => Regexp.new('\\Aallowed\\.example\\.org\\z')}
+ WebhookEndpointValidator.stubs(:blocked_targets).returns(:ips => [], :host_pattern => nil)
+ WebhookEndpointValidator.stubs(:allowed_targets).returns(allowlist)
+ WebhookEndpointValidator.stubs(:resolve_addresses).returns(['203.0.113.20'])
+
+ assert_not WebhookEndpointValidator.safe_webhook_uri?('https://other.example.org/webhook')
+ end
+
+ def test_hostname_allowlist_allows_private_ip_when_host_is_allowlisted
+ allowlist = {:ips => [], :host_pattern => Regexp.new('\\Ainternal\\.example\\.org\\z')}
+ WebhookEndpointValidator.stubs(:blocked_targets).returns(:ips => [], :host_pattern => nil)
+ WebhookEndpointValidator.stubs(:allowed_targets).returns(allowlist)
+ WebhookEndpointValidator.stubs(:resolve_addresses).returns(['192.168.50.10'])
+
+ assert WebhookEndpointValidator.safe_webhook_uri?('https://internal.example.org/webhook')
+ end
+
+ def test_allows_hostnames_with_whitespace_in_allowlist_entries
+ WebhookEndpointValidator.unstub(:allowed_targets)
+ WebhookEndpointValidator.instance_variable_set(:@allowed_targets, nil)
+
+ Redmine::Configuration.stubs(:[]).with('webhook_allowlist').returns([' fileservermonitoring.geoxyz.be '])
+ WebhookEndpointValidator.stubs(:blocked_targets).returns(:ips => [], :host_pattern => nil)
+ WebhookEndpointValidator.stubs(:resolve_addresses).returns(['203.0.113.5'])
+
+ assert WebhookEndpointValidator.safe_webhook_uri?('https://fileservermonitoring.geoxyz.be/redmine/webhook')
+ ensure
+ WebhookEndpointValidator.instance_variable_set(:@allowed_targets, nil)
+ Redmine::Configuration.unstub(:[])
+ end
+end
Index: test/unit/webhook_test.rb
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/test/unit/webhook_test.rb b/test/unit/webhook_test.rb
new file mode 100644
--- /dev/null (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
+++ b/test/unit/webhook_test.rb (revision 833d7e3d85eb74ec9bc1d45a64a445f6c577a7da)
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+require File.expand_path('../../test_helper', __FILE__)
+
+class WebhookTest < ActiveSupport::TestCase
+ fixtures :projects, :users, :members, :member_roles, :roles, :trackers, :issues, :issue_statuses
+
+ def setup
+ %w[Manager Developer].each do |role_name|
+ Role.find_by_name(role_name).add_permission! :use_webhooks
+ end
+ end
+
+ def test_issue_events_require_trackers
+ webhook = Webhook.new(
+ :user => User.find(2),
+ :url => 'https://example.com',
+ :projects => [Project.find(1)],
+ :events => ['issue.created']
+ )
+
+ assert webhook.invalid?
+ assert_includes webhook.errors.attribute_names, :trackers
+ end
+
+ def test_hooks_for_filters_by_tracker
+ webhook = Webhook.create!(
+ :user => User.find(1),
+ :url => 'https://example.com',
+ :projects => [Project.find(1)],
+ :trackers => [Tracker.find(1)],
+ :events => ['issue.created']
+ )
+
+ allowed_issue = Issue.find(1) # tracker_id 1
+ filtered_issue = Issue.find(2) # tracker_id 2
+
+ assert_equal [webhook], Webhook.hooks_for('issue.created', allowed_issue)
+ assert_equal [], Webhook.hooks_for('issue.created', filtered_issue)
+ end
+
+ def test_trigger_enqueues_jobs_when_enabled
+ webhook = Webhook.create!(
+ :user => User.find(1),
+ :url => 'https://example.com',
+ :projects => [Project.find(1)],
+ :trackers => [Tracker.find(1)],
+ :events => ['issue.created']
+ )
+
+ issue = Issue.find(1)
+
+ with_settings :webhooks_enabled => '1' do
+ WebhookJob.expects(:perform_later).with(webhook.id, includes('issue.created')).once
+
+ Webhook.trigger('issue.created', issue)
+ end
+ end
+
+ def test_issue_closed_event_is_triggered_on_status_transition
+ issue = Issue.find(1)
+
+ Webhook.expects(:trigger).with('issue.updated', issue).once
+ Webhook.expects(:trigger).with('issue.closed', issue).once
+
+ issue.update_attribute(:status_id, IssueStatus.find_by(:is_closed => true).id)
+ end
+
+ def test_issue_closed_event_not_triggered_without_status_change
+ issue = Issue.find(1)
+
+ Webhook.expects(:trigger).with('issue.updated', issue).once
+ Webhook.expects(:trigger).with('issue.closed', anything).never
+
+ issue.update_attribute(:subject, 'Changed without status update')
+ end
+end