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.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +11 -26
  4. data/Rakefile +5 -11
  5. data/app/assets/config/bullet_train_outgoing_webhooks_web_manifest.js +0 -0
  6. data/app/controllers/account/webhooks/outgoing/deliveries_controller.rb +79 -0
  7. data/app/controllers/account/webhooks/outgoing/delivery_attempts_controller.rb +80 -0
  8. data/app/controllers/account/webhooks/outgoing/endpoints_controller.rb +79 -0
  9. data/app/views/account/webhooks/outgoing/deliveries/_breadcrumbs.html.erb +8 -0
  10. data/app/views/account/webhooks/outgoing/deliveries/_delivery.json.jbuilder +10 -0
  11. data/app/views/account/webhooks/outgoing/deliveries/_form.html.erb +21 -0
  12. data/app/views/account/webhooks/outgoing/deliveries/_index.html.erb +73 -0
  13. data/app/views/account/webhooks/outgoing/deliveries/_menu_item.html.erb +10 -0
  14. data/app/views/account/webhooks/outgoing/deliveries/_success_indicator.html.erb +7 -0
  15. data/app/views/account/webhooks/outgoing/deliveries/edit.html.erb +12 -0
  16. data/app/views/account/webhooks/outgoing/deliveries/index.html.erb +6 -0
  17. data/app/views/account/webhooks/outgoing/deliveries/index.json.jbuilder +1 -0
  18. data/app/views/account/webhooks/outgoing/deliveries/new.html.erb +12 -0
  19. data/app/views/account/webhooks/outgoing/deliveries/show.html.erb +37 -0
  20. data/app/views/account/webhooks/outgoing/deliveries/show.json.jbuilder +1 -0
  21. data/app/views/account/webhooks/outgoing/delivery_attempts/_breadcrumbs.html.erb +8 -0
  22. data/app/views/account/webhooks/outgoing/delivery_attempts/_delivery_attempt.json.jbuilder +12 -0
  23. data/app/views/account/webhooks/outgoing/delivery_attempts/_form.html.erb +22 -0
  24. data/app/views/account/webhooks/outgoing/delivery_attempts/_index.html.erb +69 -0
  25. data/app/views/account/webhooks/outgoing/delivery_attempts/_menu_item.html.erb +10 -0
  26. data/app/views/account/webhooks/outgoing/delivery_attempts/_success_indicator.html.erb +7 -0
  27. data/app/views/account/webhooks/outgoing/delivery_attempts/edit.html.erb +12 -0
  28. data/app/views/account/webhooks/outgoing/delivery_attempts/index.html.erb +6 -0
  29. data/app/views/account/webhooks/outgoing/delivery_attempts/index.json.jbuilder +1 -0
  30. data/app/views/account/webhooks/outgoing/delivery_attempts/new.html.erb +12 -0
  31. data/app/views/account/webhooks/outgoing/delivery_attempts/show.html.erb +32 -0
  32. data/app/views/account/webhooks/outgoing/delivery_attempts/show.json.jbuilder +1 -0
  33. data/app/views/account/webhooks/outgoing/endpoints/_breadcrumbs.html.erb +8 -0
  34. data/app/views/account/webhooks/outgoing/endpoints/_endpoint.json.jbuilder +10 -0
  35. data/app/views/account/webhooks/outgoing/endpoints/_form.html.erb +21 -0
  36. data/app/views/account/webhooks/outgoing/endpoints/_index.html.erb +62 -0
  37. data/app/views/account/webhooks/outgoing/endpoints/_menu_item.html.erb +10 -0
  38. data/app/views/account/webhooks/outgoing/endpoints/edit.html.erb +12 -0
  39. data/app/views/account/webhooks/outgoing/endpoints/index.html.erb +6 -0
  40. data/app/views/account/webhooks/outgoing/endpoints/index.json.jbuilder +1 -0
  41. data/app/views/account/webhooks/outgoing/endpoints/new.html.erb +12 -0
  42. data/app/views/account/webhooks/outgoing/endpoints/show.html.erb +42 -0
  43. data/app/views/account/webhooks/outgoing/endpoints/show.json.jbuilder +1 -0
  44. data/config/locales/en/webhooks/outgoing/deliveries.en.yml +112 -0
  45. data/config/locales/en/webhooks/outgoing/delivery_attempts.en.yml +122 -0
  46. data/config/locales/en/webhooks/outgoing/endpoints.en.yml +108 -0
  47. data/config/locales/en/webhooks/outgoing/events.en.yml +10 -0
  48. data/config/routes.rb +18 -0
  49. data/lib/bullet_train/outgoing_webhooks/engine.rb +6 -0
  50. data/lib/bullet_train/outgoing_webhooks/version.rb +1 -3
  51. data/lib/bullet_train/outgoing_webhooks.rb +2 -19
  52. data/lib/tasks/bullet_train/outgoing_webhooks_tasks.rake +4 -0
  53. metadata +58 -75
  54. data/.standard.yml +0 -2
  55. data/CHANGELOG.md +0 -5
  56. data/CODE_OF_CONDUCT.md +0 -84
  57. data/Gemfile +0 -12
  58. data/Gemfile.lock +0 -194
  59. data/LICENSE.txt +0 -21
  60. data/bin/console +0 -15
  61. data/bin/setup +0 -8
  62. data/lib/jobs/webhooks/outgoing/delivery_job.rb +0 -9
  63. data/lib/models/concerns/webhooks/outgoing/has_uuid.rb +0 -21
  64. data/lib/models/concerns/webhooks/outgoing/issuing_model.rb +0 -57
  65. data/lib/models/concerns/webhooks/outgoing/team_support.rb +0 -15
  66. data/lib/models/webhooks/outgoing/delivery.rb +0 -62
  67. data/lib/models/webhooks/outgoing/delivery_attempt.rb +0 -49
  68. data/lib/models/webhooks/outgoing/endpoint.rb +0 -22
  69. data/lib/models/webhooks/outgoing/event.rb +0 -41
  70. data/lib/models/webhooks/outgoing/event_type.rb +0 -15
  71. data/lib/models/webhooks/outgoing.rb +0 -11
  72. data/lib/models/webhooks.rb +0 -2
  73. 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,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here
@@ -1,9 +0,0 @@
1
- # TODO Make this work off of `ApplicationJob`.
2
- class Webhooks::Outgoing::DeliveryJob < ActiveJob::Base
3
- # TODO Make this configurable.
4
- queue_as Webhooks::Outgoing.job_queue
5
-
6
- def perform(delivery)
7
- delivery.deliver
8
- end
9
- end
@@ -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
@@ -1,11 +0,0 @@
1
- module Webhooks::Outgoing
2
- def self.table_name_prefix
3
- "webhooks_outgoing_"
4
- end
5
-
6
- mattr_accessor :team_model
7
- @@team_model = "Team"
8
-
9
- mattr_accessor :job_queue
10
- @@job_queue = :default
11
- end
@@ -1,2 +0,0 @@
1
- module Webhooks
2
- end
@@ -1,6 +0,0 @@
1
- module BulletTrain
2
- module OutgoingWebhooks
3
- VERSION: String
4
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
5
- end
6
- end