Project

General

Profile

Feature #29664 » Add-configuration-option-to-enable-or-disable-webhooks.patch

Katsuya HIDAKA, 2025-10-10 08:06

View differences:

app/controllers/webhooks_controller.rb
4 4
  self.main_menu = false
5 5

  
6 6
  before_action :require_login
7
  before_action :check_enabled
7 8
  before_action :authorize
8 9

  
9 10
  before_action :find_webhook, only: [:edit, :update, :destroy]
......
62 63
  def authorize
63 64
    deny_access unless User.current.allowed_to?(:use_webhooks, nil, global: true)
64 65
  end
66

  
67
  def check_enabled
68
    render_404 unless Webhook.enabled?
69
  end
65 70
end
app/models/webhook.rb
42 42

  
43 43
  before_validation ->(hook){ hook.projects = hook.projects.to_a & hook.setable_projects }
44 44

  
45
  def self.enabled?
46
    Redmine::Configuration['webhooks']
47
  end
48

  
45 49
  # Triggers the given event for the given object, scheduling qualifying hooks
46 50
  # to be called.
47 51
  def self.trigger(event, object)
52
    return unless enabled?
53

  
48 54
    hooks_for(event, object).each do |hook|
49 55
      payload = hook.payload(event, object)
50 56
      WebhookJob.perform_later(hook.id, payload.to_json)
app/views/my/account.html.erb
1 1
<div class="contextual">
2 2
<%= additional_emails_link(@user) %>
3 3
<%= link_to(sprite_icon('key', l(:button_change_password)), { :action => 'password'}, :class => 'icon icon-passwd') if @user.change_password_allowed? %>
4
<%= link_to sprite_icon('webhook', l(:label_webhook_plural)), webhooks_path, class: 'icon icon-webhook' if @user.allowed_to?(:use_webhooks, nil, global: true) %>
4
<%= link_to sprite_icon('webhook', l(:label_webhook_plural)), webhooks_path, class: 'icon icon-webhook' if Webhook.enabled? && @user.allowed_to?(:use_webhooks, nil, global: true) %>
5 5
<%= link_to(sprite_icon('apps', l('label_oauth_authorized_application_plural')), oauth_authorized_applications_path, :class => 'icon icon-applications') if Setting.rest_api_enabled? %>
6 6
<%= call_hook(:view_my_account_contextual, :user => @user)%>
7 7
</div>
config/configuration.yml.example
226 226

  
227 227
  # Webhooks
228 228
  #
229
  # Enables or disables the Webhooks feature (enabled by default).
230
  # When disabled, all related UI will be hidden, and no webhooks will be triggered,
231
  # but existing webhook data will be retained.
232
  # webhooks: true
233
  #
229 234
  # An optional list of hosts and/or IP addresses and/or IP networks which
230 235
  # should NOT be valid as webhook targets. You can add your internal IPs and
231 236
  # hostnames here to avoid possible SSRF attacks.
lib/redmine/configuration.rb
27 27
      'email_delivery' => nil,
28 28
      'max_concurrent_ajax_uploads' => 2,
29 29
      'common_mark_enable_hardbreaks' => true,
30
      'thumbnails_generation_timeout' => 10
30
      'thumbnails_generation_timeout' => 10,
31
      'webhooks' => true
31 32
    }
32 33

  
33 34
    @config = nil
lib/redmine/preparation.rb
50 50
        map.permission :save_queries, {:queries => [:new, :create, :edit, :update, :destroy]}, :require => :loggedin
51 51

  
52 52
        # Webhooks
53
        map.permission :use_webhooks, {}, :require => :member
53
        map.permission :use_webhooks, {}, :require => :member if Redmine::Configuration['webhooks']
54 54

  
55 55
        map.project_module :issue_tracking do |map|
56 56
          # Issues
test/functional/my_controller_test.rb
398 398
    assert_select 'select[name=?]', 'user[language]'
399 399
  end
400 400

  
401
  def test_my_account_should_toggle_webhook_link_with_configuration
402
    User.find(2).roles.first.add_permission!(:use_webhooks)
403

  
404
    get :account
405
    assert_response :success
406
    assert_select 'a.icon-webhook', 1
407

  
408
    Redmine::Configuration.with 'webhooks' => false do
409
      get :account
410
      assert_response :success
411
      assert_select 'a.icon-webhook', 0
412
    end
413
  end
414

  
401 415
  def test_my_account_with_avatar_enabled_should_link_to_edit_avatar
402 416
    with_settings :gravatar_enabled => '1' do
403 417
      Redmine::Configuration.with 'avatar_server_url' => 'https://gravatar.com' do
test/functional/webhooks_controller_test.rb
27 27
    assert_select 'td', text: @other_hook.url, count: 0
28 28
  end
29 29

  
30
  test "should return not found when disabled" do
31
    Redmine::Configuration.with 'webhooks' => false do
32
      get :index
33
      assert_response :not_found
34

  
35
      get :new
36
      assert_response :not_found
37
    end
38
  end
39

  
30 40
  test "should get new" do
31 41
    get :new
32 42
    assert_response :success
test/unit/webhook_test.rb
168 168
    end
169 169
  end
170 170

  
171
  test "enabled? should follow configuration flag" do
172
    assert Webhook.enabled?
173

  
174
    Redmine::Configuration.with 'webhooks' => false do
175
      assert_not Webhook.enabled?
176
    end
177

  
178
    Redmine::Configuration.with 'webhooks' => true do
179
      assert Webhook.enabled?
180
    end
181
  end
182

  
183
  test "trigger should not enqueue jobs when disabled" do
184
    create_hook
185

  
186
    Redmine::Configuration.with 'webhooks' => false do
187
      assert_no_enqueued_jobs do
188
        Webhook.trigger('issue.created', @issue)
189
      end
190
    end
191
  end
192

  
171 193
  test "should compute payload" do
172 194
    hook = create_hook
173 195
    payload = hook.payload('issue.created', @issue)
(9-9/11)