Feature #29664 » 0002-adds-the-use_webhooks-permission.patch
app/controllers/webhooks_controller.rb | ||
---|---|---|
4 | 4 |
self.main_menu = false |
5 | 5 | |
6 | 6 |
before_action :require_login |
7 |
before_action :authorize |
|
8 | ||
7 | 9 |
before_action :find_webhook, only: [:edit, :update, :destroy] |
8 | 10 | |
9 | 11 |
require_sudo_mode :create, :update, :destroy |
... | ... | |
56 | 58 |
def webhooks |
57 | 59 |
User.current.webhooks |
58 | 60 |
end |
61 | ||
62 |
def authorize |
|
63 |
deny_access unless User.current.allowed_to?(:use_webhooks, nil, global: true) |
|
64 |
end |
|
59 | 65 |
end |
app/models/webhook.rb | ||
---|---|---|
39 | 39 | |
40 | 40 |
scope :active, -> { where(active: true) } |
41 | 41 | |
42 |
before_validation ->(hook){ hook.projects = hook.projects.to_a.select{|p| p.visible?(hook.user) } }
|
|
42 |
before_validation ->(hook){ hook.projects = hook.projects.to_a & hook.setable_projects }
|
|
43 | 43 | |
44 | 44 |
# Triggers the given event for the given object, scheduling qualifying hooks |
45 | 45 |
# to be called. |
... | ... | |
61 | 61 |
.eager_load(:user) |
62 | 62 |
.where(users: { status: User::STATUS_ACTIVE }, projects_webhooks: { project_id: object.project_id }) |
63 | 63 |
.to_a.select do |hook| |
64 |
hook.events.include?(event) && object.visible?(hook.user) |
|
64 |
hook.events.include?(event) && object.visible?(hook.user) && hook.user.allowed_to?(:use_webhooks, object.project)
|
|
65 | 65 |
end |
66 | 66 |
end |
67 | 67 | |
68 | 68 |
def setable_projects |
69 |
Project.visible |
|
69 |
user = self.user || User.current |
|
70 |
Project.visible(user).to_a.select{|p| user.allowed_to?(:use_webhooks, p)} |
|
70 | 71 |
end |
71 | 72 | |
72 | 73 |
def setable_events |
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' %> |
|
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) %>
|
|
5 | 5 |
<%= call_hook(:view_my_account_contextual, :user => @user)%> |
6 | 6 |
</div> |
7 | 7 |
config/locales/de.yml | ||
---|---|---|
970 | 970 |
permission_set_issues_private: Tickets als privat oder öffentlich markieren |
971 | 971 |
permission_set_notes_private: Kommentar als privat markieren |
972 | 972 |
permission_set_own_issues_private: Eigene Tickets als privat oder öffentlich markieren |
973 |
permission_use_webhooks: Webhooks verwenden |
|
973 | 974 |
permission_view_calendar: Kalender ansehen |
974 | 975 |
permission_view_changesets: Changesets ansehen |
975 | 976 |
permission_view_documents: Dokumente ansehen |
config/locales/en.yml | ||
---|---|---|
605 | 605 |
permission_manage_related_issues: Manage related issues |
606 | 606 |
permission_import_issues: Import issues |
607 | 607 |
permission_log_time_for_other_users: Log spent time for other users |
608 |
permission_use_webhooks: Use webhooks |
|
608 | 609 | |
609 | 610 |
project_module_issue_tracking: Issue tracking |
610 | 611 |
project_module_time_tracking: Time tracking |
lib/redmine/preparation.rb | ||
---|---|---|
49 | 49 |
map.permission :manage_public_queries, {:queries => [:new, :create, :edit, :update, :destroy]}, :require => :member |
50 | 50 |
map.permission :save_queries, {:queries => [:new, :create, :edit, :update, :destroy]}, :require => :loggedin |
51 | 51 | |
52 |
# Webhooks |
|
53 |
map.permission :use_webhooks, {}, :require => :member |
|
54 | ||
52 | 55 |
map.project_module :issue_tracking do |map| |
53 | 56 |
# Issues |
54 | 57 |
map.permission :view_issues, {:issues => [:index, :show, :issue_tab], |
test/functional/webhooks_controller_test.rb | ||
---|---|---|
16 | 16 |
@project = Project.find 'ecookbook' |
17 | 17 |
@dlopper = User.find_by_login 'dlopper' |
18 | 18 |
@issue = @project.issues.first |
19 |
@role = Role.find_by_name 'Developer' |
|
20 |
@role.permissions << :use_webhooks; @role.save! |
|
19 | 21 |
@hook = create_hook |
20 | 22 |
@other_hook = create_hook user: User.find_by_login('admin'), url: 'https://example.com/other/hook' |
21 | 23 |
@request.session[:user_id] = @dlopper.id |
test/unit/webhook_test.rb | ||
---|---|---|
22 | 22 | |
23 | 23 |
@project = Project.find 'ecookbook' |
24 | 24 |
@dlopper = User.find_by_login 'dlopper' |
25 |
@role = Role.find_by_name 'Developer' |
|
26 |
@role.permissions << :use_webhooks; @role.save! |
|
25 | 27 |
@issue = @project.issues.first |
26 | 28 |
WebhookEndpointValidator.class_eval do |
27 | 29 |
@blocked_hosts = nil |
... | ... | |
68 | 70 |
assert_raise(ActiveRecord::SerializationTypeMismatch){ Webhook.new(events: 'issue.created') } |
69 | 71 |
end |
70 | 72 | |
71 |
test "should clean up project list on save" do |
|
73 |
test "should clean up project list based on permissions on save" do |
|
74 |
h = create_hook |
|
75 |
assert_equal [@project], h.projects |
|
76 |
@role.permissions.delete :use_webhooks |
|
77 |
@role.save! |
|
78 | ||
79 |
h.reload |
|
80 |
h.save |
|
81 |
h.reload |
|
82 |
assert_equal [], h.projects |
|
83 |
end |
|
84 | ||
85 |
test "should clean up project list based on project visibility on save" do |
|
72 | 86 |
h = create_hook |
73 | 87 |
assert_equal [@project], h.projects |
74 | 88 |
@project.memberships.destroy_all |
... | ... | |
80 | 94 |
assert_equal [], h.projects |
81 | 95 |
end |
82 | 96 | |
97 |
test "should filter setable projects" do |
|
98 |
assert_equal [@project], Webhook.new(user: @dlopper).setable_projects |
|
99 | ||
100 |
@role.permissions.delete :use_webhooks |
|
101 |
@role.save! |
|
102 |
@dlopper.reload |
|
103 |
assert_equal [], Webhook.new(user: @dlopper).setable_projects |
|
104 |
end |
|
105 | ||
83 | 106 |
test "should check ip address at run time" do |
84 | 107 |
Redmine::Configuration.with('webhook_blocklist' => ['*.example.org', '10.0.0.0/8', '192.168.0.0/16']) do |
85 | 108 |
%w[ |
... | ... | |
109 | 132 |
assert_equal [], Webhook.hooks_for('issue.created', @issue) |
110 | 133 |
end |
111 | 134 | |
135 |
test "should check permission when looking for hooks" do |
|
136 |
hook = create_hook |
|
137 |
assert @issue.visible?(hook.user) |
|
138 |
assert_equal [hook], Webhook.hooks_for('issue.created', @issue) |
|
139 |
@role.permissions.delete :use_webhooks |
|
140 |
@role.save! |
|
141 |
assert_equal [], Webhook.hooks_for('issue.created', @issue) |
|
142 |
end |
|
143 | ||
112 | 144 |
test "should not find inactive hook" do |
113 | 145 |
hook = create_hook active: false |
114 | 146 |
assert @issue.visible?(hook.user) |