bullet_train-outgoing_webhooks 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/MIT-LICENSE +20 -0
- data/README.md +11 -26
- data/Rakefile +5 -11
- data/app/assets/config/bullet_train_outgoing_webhooks_web_manifest.js +0 -0
- data/app/controllers/account/webhooks/outgoing/deliveries_controller.rb +79 -0
- data/app/controllers/account/webhooks/outgoing/delivery_attempts_controller.rb +80 -0
- data/app/controllers/account/webhooks/outgoing/endpoints_controller.rb +79 -0
- data/app/views/account/webhooks/outgoing/deliveries/_breadcrumbs.html.erb +8 -0
- data/app/views/account/webhooks/outgoing/deliveries/_delivery.json.jbuilder +10 -0
- data/app/views/account/webhooks/outgoing/deliveries/_form.html.erb +21 -0
- data/app/views/account/webhooks/outgoing/deliveries/_index.html.erb +73 -0
- data/app/views/account/webhooks/outgoing/deliveries/_menu_item.html.erb +10 -0
- data/app/views/account/webhooks/outgoing/deliveries/_success_indicator.html.erb +7 -0
- data/app/views/account/webhooks/outgoing/deliveries/edit.html.erb +12 -0
- data/app/views/account/webhooks/outgoing/deliveries/index.html.erb +6 -0
- data/app/views/account/webhooks/outgoing/deliveries/index.json.jbuilder +1 -0
- data/app/views/account/webhooks/outgoing/deliveries/new.html.erb +12 -0
- data/app/views/account/webhooks/outgoing/deliveries/show.html.erb +37 -0
- data/app/views/account/webhooks/outgoing/deliveries/show.json.jbuilder +1 -0
- data/app/views/account/webhooks/outgoing/delivery_attempts/_breadcrumbs.html.erb +8 -0
- data/app/views/account/webhooks/outgoing/delivery_attempts/_delivery_attempt.json.jbuilder +12 -0
- data/app/views/account/webhooks/outgoing/delivery_attempts/_form.html.erb +22 -0
- data/app/views/account/webhooks/outgoing/delivery_attempts/_index.html.erb +69 -0
- data/app/views/account/webhooks/outgoing/delivery_attempts/_menu_item.html.erb +10 -0
- data/app/views/account/webhooks/outgoing/delivery_attempts/_success_indicator.html.erb +7 -0
- data/app/views/account/webhooks/outgoing/delivery_attempts/edit.html.erb +12 -0
- data/app/views/account/webhooks/outgoing/delivery_attempts/index.html.erb +6 -0
- data/app/views/account/webhooks/outgoing/delivery_attempts/index.json.jbuilder +1 -0
- data/app/views/account/webhooks/outgoing/delivery_attempts/new.html.erb +12 -0
- data/app/views/account/webhooks/outgoing/delivery_attempts/show.html.erb +32 -0
- data/app/views/account/webhooks/outgoing/delivery_attempts/show.json.jbuilder +1 -0
- data/app/views/account/webhooks/outgoing/endpoints/_breadcrumbs.html.erb +8 -0
- data/app/views/account/webhooks/outgoing/endpoints/_endpoint.json.jbuilder +10 -0
- data/app/views/account/webhooks/outgoing/endpoints/_form.html.erb +21 -0
- data/app/views/account/webhooks/outgoing/endpoints/_index.html.erb +62 -0
- data/app/views/account/webhooks/outgoing/endpoints/_menu_item.html.erb +10 -0
- data/app/views/account/webhooks/outgoing/endpoints/edit.html.erb +12 -0
- data/app/views/account/webhooks/outgoing/endpoints/index.html.erb +6 -0
- data/app/views/account/webhooks/outgoing/endpoints/index.json.jbuilder +1 -0
- data/app/views/account/webhooks/outgoing/endpoints/new.html.erb +12 -0
- data/app/views/account/webhooks/outgoing/endpoints/show.html.erb +42 -0
- data/app/views/account/webhooks/outgoing/endpoints/show.json.jbuilder +1 -0
- data/config/locales/en/webhooks/outgoing/deliveries.en.yml +112 -0
- data/config/locales/en/webhooks/outgoing/delivery_attempts.en.yml +122 -0
- data/config/locales/en/webhooks/outgoing/endpoints.en.yml +108 -0
- data/config/locales/en/webhooks/outgoing/events.en.yml +10 -0
- data/config/routes.rb +18 -0
- data/lib/bullet_train/outgoing_webhooks/engine.rb +6 -0
- data/lib/bullet_train/outgoing_webhooks/version.rb +1 -3
- data/lib/bullet_train/outgoing_webhooks.rb +2 -19
- data/lib/tasks/bullet_train/outgoing_webhooks_tasks.rake +4 -0
- metadata +58 -75
- data/.standard.yml +0 -2
- data/CHANGELOG.md +0 -5
- data/CODE_OF_CONDUCT.md +0 -84
- data/Gemfile +0 -12
- data/Gemfile.lock +0 -194
- data/LICENSE.txt +0 -21
- data/bin/console +0 -15
- data/bin/setup +0 -8
- data/lib/jobs/webhooks/outgoing/delivery_job.rb +0 -9
- data/lib/models/concerns/webhooks/outgoing/has_uuid.rb +0 -21
- data/lib/models/concerns/webhooks/outgoing/issuing_model.rb +0 -57
- data/lib/models/concerns/webhooks/outgoing/team_support.rb +0 -15
- data/lib/models/webhooks/outgoing/delivery.rb +0 -62
- data/lib/models/webhooks/outgoing/delivery_attempt.rb +0 -49
- data/lib/models/webhooks/outgoing/endpoint.rb +0 -22
- data/lib/models/webhooks/outgoing/event.rb +0 -41
- data/lib/models/webhooks/outgoing/event_type.rb +0 -15
- data/lib/models/webhooks/outgoing.rb +0 -11
- data/lib/models/webhooks.rb +0 -2
- data/sig/bullet_train/outgoing_webhooks.rbs +0 -6
data/LICENSE.txt
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
The MIT License (MIT)
|
2
|
-
|
3
|
-
Copyright (c) 2022 Andrew Culver
|
4
|
-
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
7
|
-
in the Software without restriction, including without limitation the rights
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
10
|
-
furnished to do so, subject to the following conditions:
|
11
|
-
|
12
|
-
The above copyright notice and this permission notice shall be included in
|
13
|
-
all copies or substantial portions of the Software.
|
14
|
-
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
-
THE SOFTWARE.
|
data/bin/console
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require "bundler/setup"
|
5
|
-
require "bullet_train/outgoing_webhooks"
|
6
|
-
|
7
|
-
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
-
# with your gem easier. You can also use a different console, if you like.
|
9
|
-
|
10
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
-
# require "pry"
|
12
|
-
# Pry.start
|
13
|
-
|
14
|
-
require "irb"
|
15
|
-
IRB.start(__FILE__)
|
data/bin/setup
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
module Webhooks::Outgoing::HasUuid
|
2
|
-
extend ActiveSupport::Concern
|
3
|
-
|
4
|
-
# define relationships.
|
5
|
-
included do
|
6
|
-
after_initialize do
|
7
|
-
self.uuid ||= SecureRandom.hex
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
# define class methods.
|
12
|
-
module ClassMethods
|
13
|
-
end
|
14
|
-
|
15
|
-
# define object methods.
|
16
|
-
def short_uuid
|
17
|
-
self.uuid.first(7)
|
18
|
-
rescue
|
19
|
-
"nil"
|
20
|
-
end
|
21
|
-
end
|
@@ -1,57 +0,0 @@
|
|
1
|
-
module Webhooks::Outgoing::IssuingModel
|
2
|
-
extend ActiveSupport::Concern
|
3
|
-
|
4
|
-
# define relationships.
|
5
|
-
included do
|
6
|
-
after_commit :generate_created_webhook, on: [:create]
|
7
|
-
after_commit :generate_updated_webhook, on: [:update]
|
8
|
-
after_commit :generate_deleted_webhook, on: [:destroy]
|
9
|
-
has_many :webhooks_outgoing_events, as: :subject, class_name: "Webhooks::Outgoing::Event", dependent: :nullify
|
10
|
-
end
|
11
|
-
|
12
|
-
# define class methods.
|
13
|
-
module ClassMethods
|
14
|
-
end
|
15
|
-
|
16
|
-
def webhooks_team
|
17
|
-
send(team_association)
|
18
|
-
end
|
19
|
-
|
20
|
-
def team_association
|
21
|
-
Webhooks::Outgoing.team_model.underscore.to_sym
|
22
|
-
end
|
23
|
-
|
24
|
-
def generate_webhook(action)
|
25
|
-
# we can only generate webhooks for objects that return their team.
|
26
|
-
return unless respond_to? team_association
|
27
|
-
|
28
|
-
# Try to find an event type definition for this action.
|
29
|
-
event_type = Webhooks::Outgoing::EventType.find_by(id: "#{self.class.name.underscore}.#{action}")
|
30
|
-
|
31
|
-
# If the event type is defined as one that people can be subscribed to,
|
32
|
-
# and this object has a team where an associated outgoing webhooks endpoint could be registered.
|
33
|
-
if event_type && webhooks_team
|
34
|
-
|
35
|
-
# Only generate an event record if an endpoint is actually listening for this event type.
|
36
|
-
if webhooks_team.webhooks_outgoing_endpoints.listening_for_event_type_id(event_type.id).any?
|
37
|
-
data = "Api::V1::#{self.class.name}Serializer".constantize.new(self).serializable_hash[:data]
|
38
|
-
webhook = webhooks_team.webhooks_outgoing_events.create(event_type_id: event_type.id, subject: self, data: data)
|
39
|
-
webhook.deliver
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def generate_created_webhook
|
45
|
-
generate_webhook("created")
|
46
|
-
end
|
47
|
-
|
48
|
-
def generate_updated_webhook
|
49
|
-
generate_webhook("updated")
|
50
|
-
end
|
51
|
-
|
52
|
-
def generate_deleted_webhook
|
53
|
-
return false unless respond_to?(team_association)
|
54
|
-
return false if webhooks_team&.being_destroyed?
|
55
|
-
generate_webhook("deleted")
|
56
|
-
end
|
57
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
module Webhooks::Outgoing::TeamSupport
|
2
|
-
extend ActiveSupport::Concern
|
3
|
-
|
4
|
-
included do
|
5
|
-
has_many :webhooks_outgoing_endpoints, class_name: "Webhooks::Outgoing::Endpoint", dependent: :destroy
|
6
|
-
has_many :webhooks_outgoing_events, class_name: "Webhooks::Outgoing::Event", dependent: :destroy
|
7
|
-
|
8
|
-
before_destroy :mark_for_destruction, prepend: true
|
9
|
-
end
|
10
|
-
|
11
|
-
def mark_for_destruction
|
12
|
-
# This allows downstream logic to check whether a team is being destroyed in order to bypass webhook issuance.
|
13
|
-
update_column(:being_destroyed, true)
|
14
|
-
end
|
15
|
-
end
|
@@ -1,62 +0,0 @@
|
|
1
|
-
class Webhooks::Outgoing::Delivery < ActiveRecord::Base
|
2
|
-
belongs_to :endpoint, class_name: "Webhooks::Outgoing::Endpoint"
|
3
|
-
belongs_to :event, class_name: "Webhooks::Outgoing::Event"
|
4
|
-
has_one :team, through: :endpoint
|
5
|
-
|
6
|
-
ATTEMPT_SCHEDULE = {
|
7
|
-
1 => 15.seconds,
|
8
|
-
2 => 1.minute,
|
9
|
-
3 => 5.minutes,
|
10
|
-
4 => 15.minutes,
|
11
|
-
5 => 1.hour,
|
12
|
-
}
|
13
|
-
|
14
|
-
has_many :delivery_attempts, class_name: "Webhooks::Outgoing::DeliveryAttempt", dependent: :destroy, foreign_key: :delivery_id
|
15
|
-
|
16
|
-
def label_string
|
17
|
-
event.short_uuid
|
18
|
-
end
|
19
|
-
|
20
|
-
def next_reattempt_delay
|
21
|
-
ATTEMPT_SCHEDULE[attempt_count]
|
22
|
-
end
|
23
|
-
|
24
|
-
def deliver_async
|
25
|
-
if still_attempting?
|
26
|
-
Webhooks::Outgoing::DeliveryJob.set(wait: next_reattempt_delay).perform_later(self)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def deliver
|
31
|
-
if delivery_attempts.create.attempt
|
32
|
-
touch(:delivered_at)
|
33
|
-
else
|
34
|
-
deliver_async
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def attempt_count
|
39
|
-
delivery_attempts.count
|
40
|
-
end
|
41
|
-
|
42
|
-
def delivered?
|
43
|
-
delivered_at.present?
|
44
|
-
end
|
45
|
-
|
46
|
-
def still_attempting?
|
47
|
-
return false if delivered?
|
48
|
-
attempt_count < max_attempts
|
49
|
-
end
|
50
|
-
|
51
|
-
def failed?
|
52
|
-
!(delivered? || still_attempting?)
|
53
|
-
end
|
54
|
-
|
55
|
-
def name
|
56
|
-
event.short_uuid
|
57
|
-
end
|
58
|
-
|
59
|
-
def max_attempts
|
60
|
-
ATTEMPT_SCHEDULE.keys.max
|
61
|
-
end
|
62
|
-
end
|
@@ -1,49 +0,0 @@
|
|
1
|
-
class Webhooks::Outgoing::DeliveryAttempt < ActiveRecord::Base
|
2
|
-
belongs_to :delivery
|
3
|
-
has_one :team, through: :delivery
|
4
|
-
scope :successful, -> { where(response_code: 200) }
|
5
|
-
|
6
|
-
before_create do
|
7
|
-
self.attempt_number = delivery.attempt_count + 1
|
8
|
-
end
|
9
|
-
|
10
|
-
def still_attempting?
|
11
|
-
error_message.nil? && response_code.nil?
|
12
|
-
end
|
13
|
-
|
14
|
-
def successful?
|
15
|
-
[200, 201, 202, 203, 204, 205, 206, 207, 226].include?(response_code)
|
16
|
-
end
|
17
|
-
|
18
|
-
def failed?
|
19
|
-
!(successful? || still_attempting?)
|
20
|
-
end
|
21
|
-
|
22
|
-
def attempt
|
23
|
-
uri = URI.parse(delivery.endpoint_url)
|
24
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
25
|
-
http.use_ssl = true if uri.scheme == "https"
|
26
|
-
request = Net::HTTP::Post.new(uri.path)
|
27
|
-
request.add_field("Content-Type", "application/json")
|
28
|
-
request.body = delivery.event.payload.to_json
|
29
|
-
|
30
|
-
begin
|
31
|
-
response = http.request(request)
|
32
|
-
self.response_message = response.message
|
33
|
-
self.response_code = response.code
|
34
|
-
self.response_body = response.body
|
35
|
-
rescue Exception => exception
|
36
|
-
self.response_code = 0
|
37
|
-
self.error_message = exception.message
|
38
|
-
end
|
39
|
-
|
40
|
-
save
|
41
|
-
successful?
|
42
|
-
end
|
43
|
-
|
44
|
-
def label_string
|
45
|
-
"#{attempt_number.ordinalize} Attempt"
|
46
|
-
end
|
47
|
-
|
48
|
-
validates :response_code, presence: true
|
49
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
class Webhooks::Outgoing::Endpoint < ActiveRecord::Base
|
2
|
-
belongs_to :team, class_name: Webhooks::Outgoing.team_model
|
3
|
-
|
4
|
-
has_many :deliveries, class_name: "Webhooks::Outgoing::Delivery", dependent: :destroy, foreign_key: :endpoint_id
|
5
|
-
has_many :events, -> { distinct }, through: :deliveries
|
6
|
-
|
7
|
-
scope :listening_for_event_type_id, ->(event_type_id) { where("event_type_ids @> ? OR event_type_ids = '[]'::jsonb", "\"#{event_type_id}\"") }
|
8
|
-
|
9
|
-
validates :name, presence: true
|
10
|
-
|
11
|
-
def valid_event_types
|
12
|
-
Webhooks::Outgoing::EventType.all
|
13
|
-
end
|
14
|
-
|
15
|
-
def event_types
|
16
|
-
event_type_ids.map { |id| Webhooks::Outgoing::EventType.find(id) }
|
17
|
-
end
|
18
|
-
|
19
|
-
def label_string
|
20
|
-
name
|
21
|
-
end
|
22
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
class Webhooks::Outgoing::Event < ActiveRecord::Base
|
2
|
-
include Webhooks::Outgoing::HasUuid
|
3
|
-
belongs_to :team, class_name: Webhooks::Outgoing.team_model
|
4
|
-
belongs_to :event_type, class_name: "Webhooks::Outgoing::EventType"
|
5
|
-
belongs_to :subject, polymorphic: true
|
6
|
-
has_many :deliveries, dependent: :destroy
|
7
|
-
|
8
|
-
before_create do
|
9
|
-
self.payload = generate_payload
|
10
|
-
end
|
11
|
-
|
12
|
-
def generate_payload
|
13
|
-
{
|
14
|
-
event_id: uuid,
|
15
|
-
event_type: event_type_id,
|
16
|
-
subject_id: subject_id,
|
17
|
-
subject_type: subject_type,
|
18
|
-
data: data
|
19
|
-
}
|
20
|
-
end
|
21
|
-
|
22
|
-
def event_type_name
|
23
|
-
payload.dig("event_type")
|
24
|
-
end
|
25
|
-
|
26
|
-
def endpoints
|
27
|
-
team.webhooks_outgoing_endpoints.listening_for_event_type_id(event_type_id)
|
28
|
-
end
|
29
|
-
|
30
|
-
def deliver
|
31
|
-
endpoints.each do |endpoint|
|
32
|
-
unless endpoint.deliveries.where(event: self).any?
|
33
|
-
endpoint.deliveries.create(event: self, endpoint_url: endpoint.url).deliver_async
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def label_string
|
39
|
-
short_uuid
|
40
|
-
end
|
41
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
class Webhooks::Outgoing::EventType < ActiveHash::Base
|
2
|
-
include ActiveHash::Associations
|
3
|
-
|
4
|
-
self.data = YAML.load_file("config/models/webhooks/outgoing/event_types.yml").map do |topic, events|
|
5
|
-
events.map { |event| event == "crud" ? ["created", "updated", "deleted"] : event }.flatten.map { |event| {id: "#{topic}.#{event}"} }
|
6
|
-
end.flatten
|
7
|
-
|
8
|
-
def name
|
9
|
-
id
|
10
|
-
end
|
11
|
-
|
12
|
-
def label_string
|
13
|
-
id
|
14
|
-
end
|
15
|
-
end
|
data/lib/models/webhooks.rb
DELETED