foreman_webhooks 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +619 -0
- data/README.md +30 -0
- data/Rakefile +49 -0
- data/app/controllers/api/v2/webhook_templates_controller.rb +110 -0
- data/app/controllers/api/v2/webhooks_controller.rb +61 -0
- data/app/controllers/concerns/foreman_webhooks/controller/parameters/webhook.rb +34 -0
- data/app/controllers/concerns/foreman_webhooks/controller/parameters/webhook_template.rb +34 -0
- data/app/controllers/webhook_templates_controller.rb +5 -0
- data/app/controllers/webhooks_controller.rb +39 -0
- data/app/jobs/foreman_webhooks/deliver_webhook_job.rb +27 -0
- data/app/lib/foreman_webhooks/renderer/scope/webhook_template.rb +36 -0
- data/app/models/webhook.rb +141 -0
- data/app/models/webhook_template.rb +59 -0
- data/app/services/foreman_webhooks/webhook_service.rb +111 -0
- data/app/subscribers/foreman_webhooks/event_subscriber.rb +9 -0
- data/app/views/api/v2/webhook_templates/base.json.rabl +5 -0
- data/app/views/api/v2/webhook_templates/create.json.rabl +5 -0
- data/app/views/api/v2/webhook_templates/index.json.rabl +5 -0
- data/app/views/api/v2/webhook_templates/main.json.rabl +7 -0
- data/app/views/api/v2/webhook_templates/show.json.rabl +11 -0
- data/app/views/api/v2/webhook_templates/update.json.rabl +5 -0
- data/app/views/api/v2/webhooks/base.json.rabl +5 -0
- data/app/views/api/v2/webhooks/create.json.rabl +5 -0
- data/app/views/api/v2/webhooks/index.json.rabl +5 -0
- data/app/views/api/v2/webhooks/main.json.rabl +8 -0
- data/app/views/api/v2/webhooks/show.json.rabl +17 -0
- data/app/views/api/v2/webhooks/update.json.rabl +5 -0
- data/app/views/foreman_webhooks/webhook_templates/ansible_tower_-_host_in_inventory.erb +20 -0
- data/app/views/foreman_webhooks/webhook_templates/empty_payload.erb +6 -0
- data/app/views/foreman_webhooks/webhook_templates/webhook_template_-_payload_default.erb +11 -0
- data/app/views/webhook_templates/_alerts.html.erb +3 -0
- data/app/views/webhook_templates/_custom_tab_headers.html.erb +1 -0
- data/app/views/webhook_templates/_custom_tabs.html.erb +5 -0
- data/app/views/webhook_templates/edit.html.erb +3 -0
- data/app/views/webhook_templates/index.html.erb +29 -0
- data/app/views/webhook_templates/new.html.erb +3 -0
- data/app/views/webhooks/_form.html.erb +37 -0
- data/app/views/webhooks/_templates.html.erb +5 -0
- data/app/views/webhooks/edit.html.erb +3 -0
- data/app/views/webhooks/new.html.erb +3 -0
- data/config/routes.rb +45 -0
- data/db/migrate/20191016100128_create_webhook_targets.rb +13 -0
- data/db/migrate/20200831194208_rename_webhook_targets_to_webhooks.rb +7 -0
- data/db/migrate/20200831194514_add_template_to_webhooks.rb +7 -0
- data/db/migrate/20200907232758_rename_webhook_permissions.rb +22 -0
- data/db/migrate/20200908004234_add_columns_to_webhooks.rb +13 -0
- data/db/migrate/20201014115147_rename_ca_file_column.rb +7 -0
- data/db/migrate/20201109135301_add_http_headers.rb +8 -0
- data/db/seeds.d/95_webhook_templates.rb +7 -0
- data/lib/foreman_webhooks.rb +6 -0
- data/lib/foreman_webhooks/engine.rb +80 -0
- data/lib/foreman_webhooks/version.rb +5 -0
- data/lib/tasks/foreman_webhooks_tasks.rake +47 -0
- data/package.json +45 -0
- data/test/controllers/api/v2/webhook_templates_controller_test.rb +200 -0
- data/test/controllers/api/v2/webhooks_controller_test.rb +108 -0
- data/test/factories/webhook.rb +20 -0
- data/test/factories/webhook_target.rb +9 -0
- data/test/factories/webhook_template.rb +16 -0
- data/test/jobs/foreman_webhooks/deliver_webhook_job_test.rb +17 -0
- data/test/models/webhook_test.rb +38 -0
- data/test/test_plugin_helper.rb +8 -0
- data/test/unit/foreman_webhooks/webhook_service_test.rb +53 -0
- data/webpack/ForemanWebhooks/Routes/ForemanWebhooksRoutes.js +12 -0
- data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/EmptyWebhooksTable/index.js +29 -0
- data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhookDeleteModal.js +43 -0
- data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhooksTable/Components/EnabledCell.js +16 -0
- data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhooksTable/Components/Formatters/__tests__/__snapshots__/enabledCellFormatter.test.js.snap +7 -0
- data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhooksTable/Components/Formatters/__tests__/enabledCellFormatter.test.js +7 -0
- data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhooksTable/Components/Formatters/enabledCellFormatter.js +6 -0
- data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhooksTable/Components/Formatters/index.js +1 -0
- data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhooksTable/Components/__tests__/EnabledCell.test.js +14 -0
- data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhooksTable/Components/__tests__/__snapshots__/EnabledCell.test.js.snap +17 -0
- data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhooksTable/WebhooksTable.js +75 -0
- data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhooksTable/WebhooksTableSchema.js +41 -0
- data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhooksTable/__tests__/WebhooksTable.test.js +57 -0
- data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhooksTable/__tests__/__snapshots__/WebhooksTable.test.js.snap +115 -0
- data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhooksTable/index.js +25 -0
- data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/WebhooksIndexPage.js +87 -0
- data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/__tests__/WebhooksIndexPage.fixtures.js +74 -0
- data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/__tests__/WebhooksIndexPage.test.js +21 -0
- data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/__tests__/__snapshots__/WebhooksIndexPage.test.js.snap +68 -0
- data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/index.js +51 -0
- data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksPageActions.js +51 -0
- data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksPageHelpers.js +29 -0
- data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksPageSelectors.js +85 -0
- data/webpack/ForemanWebhooks/Routes/Webhooks/__tests__/WebhooksPageHelpers.test.js +20 -0
- data/webpack/ForemanWebhooks/Routes/Webhooks/__tests__/WebhooksPageSelectors.test.js +45 -0
- data/webpack/ForemanWebhooks/Routes/Webhooks/__tests__/__snapshots__/WebhooksPageSelectors.test.js.snap +50 -0
- data/webpack/ForemanWebhooks/Routes/Webhooks/constants.js +13 -0
- data/webpack/__mocks__/foremanReact/common/HOC.js +2 -0
- data/webpack/__mocks__/foremanReact/common/I18n.js +7 -0
- data/webpack/__mocks__/foremanReact/common/helpers.js +7 -0
- data/webpack/__mocks__/foremanReact/common/urlHelpers.js +1 -0
- data/webpack/__mocks__/foremanReact/components/ForemanModal/ForemanModalActions.js +2 -0
- data/webpack/__mocks__/foremanReact/components/ForemanModal/ForemanModalHooks.js +10 -0
- data/webpack/__mocks__/foremanReact/components/ForemanModal/index.js +18 -0
- data/webpack/__mocks__/foremanReact/components/Layout/LayoutActions.js +2 -0
- data/webpack/__mocks__/foremanReact/components/Pagination/PaginationWrapper.js +2 -0
- data/webpack/__mocks__/foremanReact/components/common/EmptyState.js +5 -0
- data/webpack/__mocks__/foremanReact/components/common/table.js +5 -0
- data/webpack/__mocks__/foremanReact/constants.js +24 -0
- data/webpack/__mocks__/foremanReact/redux/API/APISelectors.js +6 -0
- data/webpack/__mocks__/foremanReact/redux/API/index.js +10 -0
- data/webpack/__mocks__/foremanReact/redux/actions/toasts.js +8 -0
- data/webpack/__mocks__/foremanReact/routes/common/PageLayout/PageLayout.js +10 -0
- data/webpack/index.js +0 -0
- data/webpack/routes_index.js +4 -0
- metadata +195 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class WebhookTemplate < Template
|
|
4
|
+
audited
|
|
5
|
+
|
|
6
|
+
include Authorizable
|
|
7
|
+
extend FriendlyId
|
|
8
|
+
friendly_id :name
|
|
9
|
+
include Parameterizable::ByIdName
|
|
10
|
+
|
|
11
|
+
class << self
|
|
12
|
+
# we have to override the base_class because polymorphic associations does not detect it correctly, more details at
|
|
13
|
+
# http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/has_many#1010-Polymorphic-has-many-within-inherited-class-gotcha
|
|
14
|
+
def base_class
|
|
15
|
+
self
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
self.table_name = 'templates'
|
|
19
|
+
|
|
20
|
+
before_destroy EnsureNotUsedBy.new(:webhooks)
|
|
21
|
+
has_many :webhooks, foreign_key: :webhook_template_id
|
|
22
|
+
|
|
23
|
+
validates :name, uniqueness: true
|
|
24
|
+
|
|
25
|
+
include Taxonomix
|
|
26
|
+
scoped_search on: :name, complete_value: true, default_order: true
|
|
27
|
+
scoped_search on: :locked, complete_value: { true: true, false: false }
|
|
28
|
+
scoped_search on: :snippet, complete_value: { true: true, false: false }
|
|
29
|
+
scoped_search on: :template
|
|
30
|
+
scoped_search on: :default, only_explicit: true, complete_value: { true: true, false: false }
|
|
31
|
+
|
|
32
|
+
# with proc support, default_scope can no longer be chained
|
|
33
|
+
# include all default scoping here
|
|
34
|
+
default_scope lambda {
|
|
35
|
+
with_taxonomy_scope do
|
|
36
|
+
order("#{Template.table_name}.name")
|
|
37
|
+
end
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
def self.default_render_scope_class
|
|
41
|
+
ForemanWebhooks::Renderer::Scope::WebhookTemplate
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def taxonomy_foreign_conditions
|
|
45
|
+
{ webhook_template_id: id }
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def self.acceptable_template_input_types
|
|
49
|
+
[:user]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def self.log_render_results?
|
|
53
|
+
true
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def support_single_host_render?
|
|
57
|
+
false
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ForemanWebhooks
|
|
4
|
+
class WebhookService
|
|
5
|
+
attr_accessor :webhook, :event_name, :payload, :rendered_headers, :rendered_url
|
|
6
|
+
|
|
7
|
+
delegate :logger, to: Rails
|
|
8
|
+
|
|
9
|
+
def initialize(webhook:, event_name:, payload:, headers:, url:)
|
|
10
|
+
@webhook = webhook
|
|
11
|
+
@event_name = event_name
|
|
12
|
+
@payload = payload
|
|
13
|
+
@rendered_headers = headers
|
|
14
|
+
@rendered_url = url
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def execute
|
|
18
|
+
logger.info("Performing '#{webhook.name}' webhook request for event '#{event_name}'")
|
|
19
|
+
Foreman::Logging.blob("Payload for '#{event_name}'", payload)
|
|
20
|
+
headers = {}
|
|
21
|
+
begin
|
|
22
|
+
headers = JSON.parse(rendered_headers)
|
|
23
|
+
rescue StandardError => e
|
|
24
|
+
logger.warn("Could not parse HTTP headers JSON, ignoring: #{e}")
|
|
25
|
+
logger.debug("Headers: #{rendered_headers}")
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
response = self.class.request(url: webhook.target_url,
|
|
29
|
+
payload: payload,
|
|
30
|
+
http_method: webhook.http_method,
|
|
31
|
+
user: webhook.user,
|
|
32
|
+
password: webhook.password,
|
|
33
|
+
content_type: webhook.http_content_type,
|
|
34
|
+
headers: headers,
|
|
35
|
+
ca_verify: webhook.verify_ssl?,
|
|
36
|
+
ca_string: webhook.ca_certs_store,
|
|
37
|
+
follow_redirects: true)
|
|
38
|
+
|
|
39
|
+
status = case response.code.to_i
|
|
40
|
+
when 400..599
|
|
41
|
+
logger.error("#{webhook.http_method.to_s.upcase} response was #{response.code}")
|
|
42
|
+
:error
|
|
43
|
+
else
|
|
44
|
+
logger.info("#{webhook.http_method.to_s.upcase} response was #{response.code}")
|
|
45
|
+
:success
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
{
|
|
49
|
+
status: status,
|
|
50
|
+
message: response.message,
|
|
51
|
+
http_status: response.code.to_i
|
|
52
|
+
}
|
|
53
|
+
rescue SocketError, OpenSSL::SSL::SSLError, Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::EHOSTUNREACH, Net::OpenTimeout, Net::ReadTimeout => e
|
|
54
|
+
Foreman::Logging.exception("Failed to execute the webhook #{webhook.name} -> #{event_name}", e)
|
|
55
|
+
{
|
|
56
|
+
status: :error,
|
|
57
|
+
message: e.to_s
|
|
58
|
+
}
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def self.request(url:, payload: '', http_method: :GET, user: nil, password: nil, content_type: 'application/json', headers: {}, ca_string: nil, ca_verify: false, follow_redirects: true, redirect_limit: 3)
|
|
62
|
+
uri = URI.parse(url)
|
|
63
|
+
|
|
64
|
+
request = Object.const_get("Net::HTTP::#{http_method.to_s.capitalize}").new(uri.request_uri)
|
|
65
|
+
request.basic_auth(user, password) if user && password
|
|
66
|
+
request['Content-Type'] = content_type
|
|
67
|
+
request['X-Request-Id'] = ::Logging.mdc['request'] || SecureRandom.uuid
|
|
68
|
+
request['X-Session-Id'] = ::Logging.mdc['session'] || SecureRandom.uuid
|
|
69
|
+
headers.each_pair do |key, value|
|
|
70
|
+
request[key.to_s] = value.to_s
|
|
71
|
+
end
|
|
72
|
+
request.body = payload
|
|
73
|
+
|
|
74
|
+
Rails.logger.debug("Webhook #{http_method.to_s.upcase} request: #{uri}")
|
|
75
|
+
Rails.logger.debug("Headers: #{request.to_hash.inspect}")
|
|
76
|
+
Rails.logger.debug("Body: #{request.body.inspect}")
|
|
77
|
+
|
|
78
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
79
|
+
http.open_timeout = Setting[:proxy_request_timeout]
|
|
80
|
+
http.read_timeout = Setting[:proxy_request_timeout]
|
|
81
|
+
http.ssl_timeout = Setting[:proxy_request_timeout]
|
|
82
|
+
if uri.scheme == 'https'
|
|
83
|
+
http.use_ssl = true
|
|
84
|
+
http.verify_mode = ca_verify ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
|
|
85
|
+
http.cert_store = ca_string if ca_string
|
|
86
|
+
end
|
|
87
|
+
http.request(request) do |response|
|
|
88
|
+
case response
|
|
89
|
+
when Net::HTTPRedirection then
|
|
90
|
+
new_location = response['location']
|
|
91
|
+
Rails.logger.debug "Redirected to #{new_location} (redirects left: #{redirect_limit})"
|
|
92
|
+
raise(::Foreman::Exception, N_(format('Too many HTTP redirects when calling %{uri}', uri: uri, code: response.code))) if redirect_limit <= 0
|
|
93
|
+
|
|
94
|
+
self.request(url: new_location,
|
|
95
|
+
payload: payload,
|
|
96
|
+
http_method: http_method,
|
|
97
|
+
user: user,
|
|
98
|
+
password: password,
|
|
99
|
+
content_type: content_type,
|
|
100
|
+
ca_string: ca_string,
|
|
101
|
+
ca_verify: ca_verify,
|
|
102
|
+
headers: headers,
|
|
103
|
+
follow_redirects: follow_redirects,
|
|
104
|
+
redirect_limit: redirect_limit - 1)
|
|
105
|
+
else
|
|
106
|
+
response
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
object @webhook_template
|
|
4
|
+
|
|
5
|
+
extends 'api/v2/webhook_templates/main'
|
|
6
|
+
|
|
7
|
+
attributes :template, :default, :snippet, :locked
|
|
8
|
+
|
|
9
|
+
node do |webhook_template|
|
|
10
|
+
partial('api/v2/taxonomies/children_nodes', object: webhook_template)
|
|
11
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
object @webhook
|
|
4
|
+
|
|
5
|
+
extends 'api/v2/webhooks/main'
|
|
6
|
+
|
|
7
|
+
attributes :target_url,
|
|
8
|
+
:event,
|
|
9
|
+
:http_method,
|
|
10
|
+
:http_content_type,
|
|
11
|
+
:enabled,
|
|
12
|
+
:verify_ssl,
|
|
13
|
+
:http_headers
|
|
14
|
+
|
|
15
|
+
child :webhook_template do
|
|
16
|
+
extends 'api/v2/webhook_templates/base'
|
|
17
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<%#
|
|
2
|
+
name: Ansible Tower - Host in Inventory
|
|
3
|
+
description: Create/update a host with associated inventory in Ansible Tower.
|
|
4
|
+
snippet: false
|
|
5
|
+
model: WebhookTemplate
|
|
6
|
+
-%>
|
|
7
|
+
<%#
|
|
8
|
+
Create URL: https://tower/api/v2/hosts
|
|
9
|
+
Update/Delete URL: https://tower/api/v2/hosts/$HOST_ID
|
|
10
|
+
-%>
|
|
11
|
+
<%=
|
|
12
|
+
payload({
|
|
13
|
+
"name": @object.name,
|
|
14
|
+
"description": "Created via Foreman Webhook",
|
|
15
|
+
"inventory": @object.host_param('ansible_tower_inventory_id') || 1,
|
|
16
|
+
"enabled": true,
|
|
17
|
+
"instance_id": "",
|
|
18
|
+
"variables": ""
|
|
19
|
+
}, with_defaults: false)
|
|
20
|
+
-%>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<li><a href='#template_type' data-toggle='tab'><%= _('Type') %></a></li>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<% title _('Webhook Templates') %>
|
|
2
|
+
|
|
3
|
+
<% title_actions new_link(_('Create Template')) %>
|
|
4
|
+
|
|
5
|
+
<table class="<%= table_css_classes 'table-fixed' %>">
|
|
6
|
+
<thead>
|
|
7
|
+
<tr>
|
|
8
|
+
<th class="col-md-3"><%= sort :name, as: s_('WebhookTemplate|Name') %></th>
|
|
9
|
+
<th class="col-md-1"><%= sort :snippet, as: s_('WebhookTemplate|Snippet') %></th>
|
|
10
|
+
<th class="col-md-1"><%= sort :locked, as: s_('WebhookTemplate|Locked'), default: 'DESC' %></th>
|
|
11
|
+
<th class="col-md-1"><%= _('Actions') %></th>
|
|
12
|
+
</tr>
|
|
13
|
+
</thead>
|
|
14
|
+
<tbody>
|
|
15
|
+
<% for webhook_template in @templates %>
|
|
16
|
+
<tr>
|
|
17
|
+
<td class="ellipsis"><%= link_to_if_authorized webhook_template,
|
|
18
|
+
hash_for_edit_webhook_template_path(id: webhook_template.to_param).
|
|
19
|
+
merge(auth_object: webhook_template, authorizer: authorizer, permission: 'edit_webhook_templates') %>
|
|
20
|
+
</td>
|
|
21
|
+
<td align='center'><%= checked_icon webhook_template.snippet %></td>
|
|
22
|
+
<td align='center'><%= locked_icon webhook_template.locked?, _('This template is locked for editing.') %>
|
|
23
|
+
</td>
|
|
24
|
+
<td><%= action_buttons(*permitted_actions(webhook_template)) %></td>
|
|
25
|
+
</tr>
|
|
26
|
+
<% end %>
|
|
27
|
+
</tbody>
|
|
28
|
+
</table>
|
|
29
|
+
<%= will_paginate_with_info @templates %>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<%= form_for @webhook, url: (@webhook.new_record? ? webhooks_path : webhook_path(id: @webhook)) do |f| %>
|
|
2
|
+
<%= base_errors_for @webhook %>
|
|
3
|
+
<%= text_f f, :name %>
|
|
4
|
+
<%= text_f f, :target_url, help_inline: _('Target URL that should be called by Foreman') %>
|
|
5
|
+
|
|
6
|
+
<%= text_f f, :user, help_block: _('Authentication credentials') %>
|
|
7
|
+
<%= password_f f, :password, keep_value: true %>
|
|
8
|
+
|
|
9
|
+
<%= selectable_f f, :http_method, Webhook::ALLOWED_HTTP_METHODS,
|
|
10
|
+
{ include_blank: false,
|
|
11
|
+
selected: @webhook.http_method },
|
|
12
|
+
{ label: _('HTTP Method'),
|
|
13
|
+
label_help: _(f.object.try(:description)),
|
|
14
|
+
required: true } %>
|
|
15
|
+
<%= text_f f, :http_content_type %>
|
|
16
|
+
|
|
17
|
+
<%= render('templates', f: f) %>
|
|
18
|
+
|
|
19
|
+
<%= selectable_f f, :event, Webhook.available_events.sort.map { |e| e.delete_suffix(Webhook::EVENT_POSTFIX) },
|
|
20
|
+
{ include_blank: false,
|
|
21
|
+
selected: @webhook.event&.delete_suffix(Webhook::EVENT_POSTFIX) },
|
|
22
|
+
{ label: _('Subscribe to'),
|
|
23
|
+
label_help: _(f.object.try(:description)),
|
|
24
|
+
required: true } %>
|
|
25
|
+
|
|
26
|
+
<%= checkbox_f f, :enabled, help_inline: _('If unchecked, the webhook will be inactive') %>
|
|
27
|
+
<%= checkbox_f f, :verify_ssl, help_inline: _("Uncheck this option to disable validation of the receiver's SSL certificate") %>
|
|
28
|
+
<%= textarea_f f, :ssl_ca_certs, label: _('X509 Certification Authorities'),
|
|
29
|
+
size: 'col-md-8', rows: 10,
|
|
30
|
+
placeholder: _("Optional CAs in PEM format concatenated to verify the receiver's SSL certificate.") %>
|
|
31
|
+
|
|
32
|
+
<%= textarea_f f, :http_headers, label: _('Optional HTTP headers as JSON (ERB allowed)'),
|
|
33
|
+
size: 'col-md-8', rows: 6,
|
|
34
|
+
placeholder: "{\n\"X-Shellhook-Arg-1\": \"value\"\n}" %>
|
|
35
|
+
|
|
36
|
+
<%= submit_or_cancel(f, false, { react_cancel_button: true, cancel_path: '/webhooks' }) %>
|
|
37
|
+
<% end %>
|
data/config/routes.rb
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Rails.application.routes.draw do
|
|
4
|
+
resources :webhooks, except: %i[index show] do
|
|
5
|
+
collection do
|
|
6
|
+
get 'auto_complete_search'
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
match '/webhooks' => 'react#index', via: :get
|
|
10
|
+
|
|
11
|
+
namespace :api, defaults: { format: 'json' } do
|
|
12
|
+
scope '(:apiv)',
|
|
13
|
+
module: :v2,
|
|
14
|
+
defaults: { apiv: 'v2' },
|
|
15
|
+
apiv: /v1|v2/,
|
|
16
|
+
constraints: ApiConstraints.new(version: 2, default: true) do
|
|
17
|
+
resources :webhooks, only: %i[index show create update destroy]
|
|
18
|
+
resources :webhook_templates, except: %i[new edit] do
|
|
19
|
+
member do
|
|
20
|
+
post :clone
|
|
21
|
+
get :export
|
|
22
|
+
end
|
|
23
|
+
collection do
|
|
24
|
+
post :import
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
scope 'templates' do
|
|
31
|
+
resources :webhook_templates, except: :show do
|
|
32
|
+
member do
|
|
33
|
+
get 'clone_template'
|
|
34
|
+
get 'lock'
|
|
35
|
+
get 'unlock'
|
|
36
|
+
get 'export'
|
|
37
|
+
post 'preview'
|
|
38
|
+
end
|
|
39
|
+
collection do
|
|
40
|
+
post 'preview'
|
|
41
|
+
get 'auto_complete_search'
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|