bullet_train-outgoing_webhooks 1.2.9 → 1.2.10

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 74eccc06e9bac4c34f9d57665a043f47818085eb0b0c4c53cdca3fe5cbdb49a4
4
- data.tar.gz: b6ed8bd2705b78422b4d133c97f86d3e7e3e81619d62e9893fddfe069feba977
3
+ metadata.gz: d44b251cd89a804615ec264c52649e52bbc6c79f27e292713153be356c4ba099
4
+ data.tar.gz: b045ede97a1140a494dd9e11ae3853f3ac8f106b8e73dd33392cc76636c0ed08
5
5
  SHA512:
6
- metadata.gz: d0cd98a77bc6d65bb507f3e6adad488572579ca73373fbda33d961ea540fd598d11b43259bda446de85865bedf638e4de9bd9cf529b26d8303b351903613d9f9
7
- data.tar.gz: 8318b904b4cfe110378aed89de7d98e2cebba99abf38ecb8fa60b49c7ed7c48a4577531e25efbb07a611e2c37dc213eb25cdf1b6618bee5e3291a70e8b9c71bd
6
+ metadata.gz: 6b50b117f3313cdcf7b009f1f656a9ba9593e354958c29a62c88235f497a18db35aba83587a27e8d12fb0b9ff4343fb844c5fc156dcfb0d4dd73d83474dc32ba
7
+ data.tar.gz: c857cf75207fce59abe42e84fed7c836da7d92941ee628312a31cb02f1f0dd3781714c407e2fb2ca5f8d1938bff40760ac608d44dd6e5e29708b463e822bfe53
@@ -41,6 +41,7 @@ class Api::V1::Webhooks::Outgoing::EndpointsController < Api::V1::ApplicationCon
41
41
  *permitted_fields,
42
42
  :url,
43
43
  :name,
44
+ :version,
44
45
  :scaffolding_absolutely_abstract_creative_concept_id,
45
46
  # 🚅 super scaffolding will insert new fields above this line.
46
47
  *permitted_arrays,
@@ -0,0 +1,13 @@
1
+ class Api::V1::Webhooks::Outgoing::EventsController < Api::V1::ApplicationController
2
+ account_load_and_authorize_resource :event, through: :team, through_association: :webhooks_outgoing_events
3
+
4
+ # GET /api/v1/teams/:team_id/webhooks/outgoing/events
5
+ def index
6
+ render json: @events.map(&:payload)
7
+ end
8
+
9
+ # GET /api/v1/webhooks/outgoing/events/:id
10
+ def show
11
+ render json: @event.payload
12
+ end
13
+ end
@@ -1,7 +1,8 @@
1
1
  class Webhooks::Outgoing::GenerateJob < ApplicationJob
2
2
  queue_as :default
3
3
 
4
- def perform(obj, action)
5
- obj.generate_webhook_perform(action)
4
+ # `= [1]` ensures backwards compatibility for older installations when they upgrade.
5
+ def perform(obj, action, api_versions = [1])
6
+ obj.generate_webhook_perform(action, api_versions)
6
7
  end
7
8
  end
@@ -32,6 +32,8 @@ module Webhooks::Outgoing::DeliverySupport
32
32
  end
33
33
 
34
34
  def deliver
35
+ # TODO If we ever do away with the `async: true` default for webhook generation, then I believe this needs to
36
+ # change otherwise we'd be attempting the first delivery of webhooks inline.
35
37
  if delivery_attempts.create.attempt
36
38
  touch(:delivered_at)
37
39
  else
@@ -15,10 +15,11 @@ module Webhooks::Outgoing::EndpointSupport
15
15
 
16
16
  before_validation { url&.strip! }
17
17
 
18
- validates :url, presence: true, allowed_uri: true
18
+ validates :url, presence: true, allowed_uri: BulletTrain::OutgoingWebhooks.advanced_hostname_security
19
19
 
20
20
  after_initialize do
21
21
  self.event_type_ids ||= []
22
+ self.api_version ||= I18n.t("webhooks/outgoing/endpoints.fields.api_version.options").keys.last
22
23
  end
23
24
 
24
25
  after_save :touch_parent
@@ -28,7 +28,7 @@ module Webhooks::Outgoing::EventSupport
28
28
  end
29
29
 
30
30
  def endpoints
31
- endpoints = send(BulletTrain::OutgoingWebhooks.parent_association).webhooks_outgoing_endpoints.listening_for_event_type_id(event_type_id)
31
+ endpoints = send(BulletTrain::OutgoingWebhooks.parent_association).webhooks_outgoing_endpoints.where(api_version: api_version).listening_for_event_type_id(event_type_id)
32
32
 
33
33
  case subject_type
34
34
  when "Scaffolding::AbsolutelyAbstract::CreativeConcept"
@@ -32,24 +32,31 @@ module Webhooks::Outgoing::IssuingModel
32
32
  # and this object has a parent where an associated outgoing webhooks endpoint could be registered.
33
33
  if event_type
34
34
  # Only generate an event record if an endpoint is actually listening for this event type.
35
- if parent.endpoints_listening_for_event_type?(event_type)
35
+ # If there are endpoints listening, make sure we know which API versions they're looking for.
36
+ if (api_versions = parent.endpoint_api_versions_listening_for_event_type(event_type)).any?
36
37
  if async
37
38
  # serialization can be heavy so run it as a job
38
- Webhooks::Outgoing::GenerateJob.perform_later(self, action)
39
+ Webhooks::Outgoing::GenerateJob.perform_later(self, action, api_versions)
39
40
  else
40
- generate_webhook_perform(action)
41
+ generate_webhook_perform(action, api_versions)
41
42
  end
42
43
  end
43
44
  end
44
45
  end
45
46
 
46
- def generate_webhook_perform(action)
47
+ def generate_webhook_perform(action, api_versions)
47
48
  event_type = Webhooks::Outgoing::EventType.find_by(id: "#{self.class.name.underscore}.#{action}")
48
- # TODO This is crazy that we generate JSON just to parse it. Can't be good for performance.
49
- # Does Jbuilder support generating a hash instead of a JSON string?
50
- data = JSON.parse(to_api_json)
51
- webhook = send(BulletTrain::OutgoingWebhooks.parent_association).webhooks_outgoing_events.create(event_type_id: event_type.id, subject: self, data: data)
52
- webhook.deliver
49
+
50
+ api_versions.each do |api_version|
51
+ webhook = send(BulletTrain::OutgoingWebhooks.parent_association).webhooks_outgoing_events.create(
52
+ event_type_id: event_type.id,
53
+ subject: self,
54
+ data: to_api_json(api_version),
55
+ api_version: api_version
56
+ )
57
+
58
+ webhook.deliver
59
+ end
53
60
  end
54
61
 
55
62
  def generate_created_webhook
@@ -12,15 +12,19 @@ module Webhooks::Outgoing::TeamSupport
12
12
  true
13
13
  end
14
14
 
15
- def endpoints_listening_for_event_type?(event_type)
15
+ def endpoint_api_versions_for_event_type(event_type)
16
+ webhooks_outgoing_endpoints.listening_for_event_type_id(event_type.id).pluck(:api_version).uniq
17
+ end
18
+
19
+ def endpoint_api_versions_listening_for_event_type(event_type)
16
20
  if should_cache_endpoints_listening_for_event_type?
17
- key = "#{cache_key_with_version}/endpoints_for_event_type/#{event_type.cache_key}"
21
+ key = "#{cache_key_with_version}/endpoints_for_event_type/#{event_type.cache_key}/api_version"
18
22
 
19
23
  Rails.cache.fetch(key, expires_in: 24.hours, race_condition_ttl: 5.seconds) do
20
- webhooks_outgoing_endpoints.listening_for_event_type_id(event_type.id).any?
24
+ endpoint_api_versions_for_event_type(event_type)
21
25
  end
22
26
  else
23
- webhooks_outgoing_endpoints.listening_for_event_type_id(event_type.id).any?
27
+ endpoint_api_versions_for_event_type(event_type)
24
28
  end
25
29
  end
26
30
 
@@ -100,6 +100,8 @@ module Webhooks::Outgoing::UriFiltering
100
100
  end
101
101
 
102
102
  def _allowed_uri?(uri)
103
+ return true unless uri.present?
104
+
103
105
  config = Rails.configuration.outgoing_webhooks
104
106
  hostname = uri.hostname.downcase
105
107
 
@@ -4,6 +4,9 @@
4
4
  <% with_field_settings form: form do %>
5
5
  <%= render 'shared/fields/text_field', method: :name, options: {autofocus: true} %>
6
6
  <%= render 'shared/fields/text_field', method: :url %>
7
+ <% unless I18n.t("webhooks/outgoing/endpoints.fields.api_version.options").keys.one? %>
8
+ <%= render 'shared/fields/super_select', method: :api_version %>
9
+ <% end %>
7
10
  <%= render 'shared/fields/super_select', method: :event_type_ids, html_options: {multiple: true},
8
11
  choices: @endpoint.valid_event_types.map { |event_type| [event_type.label_string, event_type.id] } %>
9
12
  <%= render 'shared/fields/super_select', method: :scaffolding_absolutely_abstract_creative_concept_id,
@@ -16,6 +16,7 @@ components:
16
16
  scheme: bearer
17
17
  schemas:
18
18
  <%= automatic_components_for Webhooks::Outgoing::Endpoint %>
19
+ <%= automatic_components_for Webhooks::Outgoing::Event %>
19
20
  <%# 🚅 super scaffolding will insert new components above this line. %>
20
21
  parameters:
21
22
  id:
@@ -28,4 +29,5 @@ security:
28
29
  - BearerAuth: []
29
30
  paths:
30
31
  <%= automatic_paths_for Webhooks::Outgoing::Endpoint, Team %>
32
+ <%= automatic_paths_for Webhooks::Outgoing::Event, Team, except: %i[create update delete] %>
31
33
  <%# 🚅 super scaffolding will insert new paths above this line. %>
@@ -0,0 +1,12 @@
1
+ json.data schema: {object: OpenStruct.new, object_title: I18n.t("webhooks/outgoing/events.fields.data.heading"), object_description: I18n.t("webhooks/outgoing/events.fields.data.heading")} do
2
+ json.id schema: {type: :integer, description: I18n.t("webhooks/outgoing/events.fields.data.id.heading")}
3
+ json.name schema: {type: :string, description: I18n.t("webhooks/outgoing/events.fields.data.name.heading")}
4
+ json.description schema: {type: :string, description: I18n.t("webhooks/outgoing/events.fields.data.description.heading")}
5
+ json.created_at schema: {type: :string, format: "date-time", description: I18n.t("webhooks/outgoing/events.fields.data.created_at.heading")}
6
+ json.updated_at schema: {type: :string, format: "date-time", description: I18n.t("webhooks/outgoing/events.fields.data.updated_at.heading")}
7
+ end
8
+
9
+ json.event_id schema: {type: :string, description: I18n.t("webhooks/outgoing/events.fields.event_id.heading")}
10
+ json.event_type schema: {type: :integer, description: I18n.t("webhooks/outgoing/events.fields.event_type.heading")}
11
+ json.subject_id schema: {type: :integer, description: I18n.t("webhooks/outgoing/events.fields.subject_id.heading")}
12
+ json.subject_type schema: {type: :string, description: I18n.t("webhooks/outgoing/events.fields.subject_type.heading")}
@@ -0,0 +1 @@
1
+ json.array! @events, partial: "api/v1/webhooks/outgoing/events/event", as: :event
@@ -0,0 +1 @@
1
+ json.partial! "api/v1/webhooks/outgoing/events/event", event: @event
@@ -39,6 +39,13 @@ en:
39
39
  label: *url
40
40
  heading: *url
41
41
 
42
+ api_version:
43
+ _: &api_version API Version
44
+ label: *api_version
45
+ heading: *api_version
46
+ options:
47
+ 1: V1
48
+
42
49
  event_type_ids: &event_types
43
50
  _: &event_type_ids Event Types
44
51
  label: *event_type_ids
@@ -114,8 +121,9 @@ en:
114
121
  webhooks/outgoing/endpoint:
115
122
  name: *name
116
123
  url: *url
124
+ api_version: *api_version
117
125
  event_type_ids: *event_type_ids
126
+ scaffolding_absolutely_abstract_creative_concept_id: *scaffolding_absolutely_abstract_creative_concept_id
118
127
  # 🚅 super scaffolding will insert new activerecord attributes above this line.
119
128
  created_at: *created_at
120
- updated_at: *updated_at
121
- scaffolding_absolutely_abstract_creative_concept_id: *scaffolding_absolutely_abstract_creative_concept_id
129
+ updated_at: *updated_at
@@ -1,10 +1,72 @@
1
1
  en:
2
- webhooks/outgoing/events:
3
- fields:
4
- uuid: &uuid
5
- heading: Event UUID
6
- short_uuid: *uuid
7
- event_type_name:
8
- heading: Event Type
2
+ webhooks/outgoing/events: &events
3
+ label: &label Webhooks Events
4
+ fields: &fields
5
+ data:
6
+ _: &data Event Data
7
+ label: *data
8
+ heading: *data
9
+
10
+ id:
11
+ _: &id Event ID
12
+ label: *id
13
+ heading: *id
14
+
15
+ name:
16
+ _: &name Event Name
17
+ label: *name
18
+ heading: *name
19
+
20
+ description:
21
+ _: &description Event Description
22
+ label: *description
23
+ heading: *description
24
+
25
+ created_at:
26
+ _: &created_at DateTime Event was added
27
+ label: *created_at
28
+ heading: *created_at
29
+ updated_at:
30
+ _: &updated_at DateTime Event was updated
31
+ label: *updated_at
32
+ heading: *updated_at
33
+
34
+ event_id:
35
+ _: &event_id Event UUID
36
+ label: *event_id
37
+ heading: *event_id
38
+
39
+ event_type:
40
+ _: &event_type Event Type
41
+ label: *event_type
42
+ heading: *event_type
43
+
44
+ subject_id:
45
+ _: &subject_id Subject ID
46
+ label: *subject_id
47
+ heading: *subject_id
48
+
49
+ subject_type:
50
+ _: &subject_type Subject Type
51
+ label: *subject_type
52
+ heading: *subject_type
53
+
9
54
  payload:
10
- heading: JSON Payload
55
+ _: &payload Payload
56
+ label: *payload
57
+ heading: *payload
58
+
59
+ uuid:
60
+ _: &uuid UUID
61
+ label: *uuid
62
+ heading: *uuid
63
+
64
+ short_uuid:
65
+ _: &short_uuid Short UUID
66
+ label: *short_uuid
67
+ heading: *short_uuid
68
+
69
+ event_type_name:
70
+ _: &event_type_name Event Type Name
71
+ label: *event_type_name
72
+ heading: *event_type_name
data/config/routes.rb CHANGED
@@ -6,10 +6,9 @@ Rails.application.routes.draw do
6
6
  resources BulletTrain::OutgoingWebhooks.parent_resource do
7
7
  namespace :webhooks do
8
8
  namespace :outgoing do
9
- resources :events
10
9
  resources :endpoints do
11
- resources :deliveries, only: [:index, :show] do
12
- resources :delivery_attempts, only: [:index, :show]
10
+ resources :deliveries, only: %i[index show] do
11
+ resources :delivery_attempts, only: %i[index show]
13
12
  end
14
13
  end
15
14
  end
@@ -25,6 +24,7 @@ Rails.application.routes.draw do
25
24
  namespace :webhooks do
26
25
  namespace :outgoing do
27
26
  resources :endpoints, defaults: {format: :json}
27
+ resources :events, only: %i[index show], defaults: {format: :json}
28
28
  end
29
29
  end
30
30
  end
@@ -1,5 +1,5 @@
1
1
  module BulletTrain
2
2
  module OutgoingWebhooks
3
- VERSION = "1.2.9"
3
+ VERSION = "1.2.10"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bullet_train-outgoing_webhooks
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.9
4
+ version: 1.2.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Culver
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-28 00:00:00.000000000 Z
11
+ date: 2022-12-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: standard
@@ -71,6 +71,7 @@ files:
71
71
  - app/controllers/api/v1/webhooks.rb
72
72
  - app/controllers/api/v1/webhooks/outgoing.rb
73
73
  - app/controllers/api/v1/webhooks/outgoing/endpoints_controller.rb
74
+ - app/controllers/api/v1/webhooks/outgoing/events_controller.rb
74
75
  - app/jobs/webhooks/outgoing/delivery_job.rb
75
76
  - app/jobs/webhooks/outgoing/generate_job.rb
76
77
  - app/models/concerns/webhooks/outgoing/delivery_attempt_support.rb
@@ -126,6 +127,9 @@ files:
126
127
  - app/views/api/v1/webhooks/outgoing/endpoints/_endpoint.json.jbuilder
127
128
  - app/views/api/v1/webhooks/outgoing/endpoints/index.json.jbuilder
128
129
  - app/views/api/v1/webhooks/outgoing/endpoints/show.json.jbuilder
130
+ - app/views/api/v1/webhooks/outgoing/events/_event.json.jbuilder
131
+ - app/views/api/v1/webhooks/outgoing/events/index.json.jbuilder
132
+ - app/views/api/v1/webhooks/outgoing/events/show.json.jbuilder
129
133
  - config/locales/en/webhooks/outgoing/deliveries.en.yml
130
134
  - config/locales/en/webhooks/outgoing/delivery_attempts.en.yml
131
135
  - config/locales/en/webhooks/outgoing/endpoints.en.yml
@@ -178,7 +182,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
178
182
  - !ruby/object:Gem::Version
179
183
  version: '0'
180
184
  requirements: []
181
- rubygems_version: 3.3.7
185
+ rubygems_version: 3.4.1
182
186
  signing_key:
183
187
  specification_version: 4
184
188
  summary: Allow users of your Rails application to subscribe and receive webhooks when