active_webhook 1.0.0

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.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.env.sample +1 -0
  3. data/.gitignore +63 -0
  4. data/.rspec +4 -0
  5. data/.rubocop.yml +86 -0
  6. data/.todo +48 -0
  7. data/.travis.yml +14 -0
  8. data/CHANGELOG.md +5 -0
  9. data/DEV_README.md +199 -0
  10. data/Gemfile +8 -0
  11. data/LICENSE.txt +21 -0
  12. data/README.md +483 -0
  13. data/Rakefile +23 -0
  14. data/active_webhook.gemspec +75 -0
  15. data/config/environment.rb +33 -0
  16. data/lib/active_webhook.rb +125 -0
  17. data/lib/active_webhook/adapter.rb +117 -0
  18. data/lib/active_webhook/callbacks.rb +53 -0
  19. data/lib/active_webhook/configuration.rb +105 -0
  20. data/lib/active_webhook/delivery/base_adapter.rb +96 -0
  21. data/lib/active_webhook/delivery/configuration.rb +16 -0
  22. data/lib/active_webhook/delivery/faraday_adapter.rb +19 -0
  23. data/lib/active_webhook/delivery/net_http_adapter.rb +28 -0
  24. data/lib/active_webhook/error_log.rb +7 -0
  25. data/lib/active_webhook/formatting/base_adapter.rb +109 -0
  26. data/lib/active_webhook/formatting/configuration.rb +18 -0
  27. data/lib/active_webhook/formatting/json_adapter.rb +19 -0
  28. data/lib/active_webhook/formatting/url_encoded_adapter.rb +28 -0
  29. data/lib/active_webhook/hook.rb +9 -0
  30. data/lib/active_webhook/logger.rb +21 -0
  31. data/lib/active_webhook/models/configuration.rb +18 -0
  32. data/lib/active_webhook/models/error_log_additions.rb +15 -0
  33. data/lib/active_webhook/models/subscription_additions.rb +72 -0
  34. data/lib/active_webhook/models/topic_additions.rb +70 -0
  35. data/lib/active_webhook/queueing/active_job_adapter.rb +43 -0
  36. data/lib/active_webhook/queueing/base_adapter.rb +67 -0
  37. data/lib/active_webhook/queueing/configuration.rb +15 -0
  38. data/lib/active_webhook/queueing/delayed_job_adapter.rb +28 -0
  39. data/lib/active_webhook/queueing/sidekiq_adapter.rb +43 -0
  40. data/lib/active_webhook/queueing/syncronous_adapter.rb +14 -0
  41. data/lib/active_webhook/subscription.rb +7 -0
  42. data/lib/active_webhook/topic.rb +7 -0
  43. data/lib/active_webhook/verification/base_adapter.rb +31 -0
  44. data/lib/active_webhook/verification/configuration.rb +13 -0
  45. data/lib/active_webhook/verification/hmac_sha256_adapter.rb +20 -0
  46. data/lib/active_webhook/verification/unsigned_adapter.rb +11 -0
  47. data/lib/active_webhook/version.rb +5 -0
  48. data/lib/generators/install_generator.rb +20 -0
  49. data/lib/generators/migrations_generator.rb +24 -0
  50. data/lib/generators/templates/20210618023338_create_active_webhook_tables.rb +31 -0
  51. data/lib/generators/templates/active_webhook_config.rb +87 -0
  52. metadata +447 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: bc8acd1e3d7b0ab18220c1550c4036bd52317f4bf8e57d6ff86935703f241e45
4
+ data.tar.gz: aac9a54fced0844aa949f155c6df5fbcc6fe386b9df701e6e1ef9fa1d8b4cf2e
5
+ SHA512:
6
+ metadata.gz: d7c48dbcb856125ee8d951e1ad9998e02048a96aaa452b63a1042b98503d5ed003bdecf6efbd2e7012aeed7deb09c27e5a11d64bd72fb61683c642f6ea5f25b8
7
+ data.tar.gz: ec57e66ad519b0e2a65ed97cd4e750146466a0ffa6ba300826d10c3acf0a55ffb4e49712176d6a9e60afe94b88efc375dacec9444e7de55dec6c7a1fbfc135a8
data/.env.sample ADDED
@@ -0,0 +1 @@
1
+ SIDEKIQ_SOMETHING=1
data/.gitignore ADDED
@@ -0,0 +1,63 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+ *~
13
+ log/*
14
+ measurement/*
15
+
16
+ # Used by dotenv library to load environment variables.
17
+ .env
18
+
19
+
20
+ # Ignore Byebug command history file.
21
+ .byebug_history
22
+
23
+ ## Specific to RubyMotion:
24
+ .dat*
25
+ .repl_history
26
+ build/
27
+ *.bridgesupport
28
+ build-iPhoneOS/
29
+ build-iPhoneSimulator/
30
+
31
+ ## Specific to RubyMotion (use of CocoaPods):
32
+ #
33
+ # We recommend against adding the Pods directory to your .gitignore. However
34
+ # you should judge for yourself, the pros and cons are mentioned at:
35
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
36
+ #
37
+ # vendor/Pods/
38
+
39
+ ## Documentation cache and generated files:
40
+ /.yardoc/
41
+ /_yardoc/
42
+ /doc/
43
+ /rdoc/
44
+
45
+ ## Environment normalization:
46
+ /.bundle/
47
+ /vendor/bundle
48
+ /lib/bundler/man/
49
+
50
+ # for a library or gem, you might want to ignore these files since the code is
51
+ # intended to run in multiple environments; otherwise, check them in:
52
+ Gemfile.lock
53
+
54
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
55
+ .rvmrc
56
+ .ruby-version
57
+ .ruby-gemset
58
+
59
+ # Used by RuboCop. Remote config files pulled in from inherit_from directive.
60
+ # .rubocop-https?--*
61
+
62
+ # rspec failure tracking
63
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,4 @@
1
+ --format progress
2
+ --color
3
+ --require spec_helper
4
+ --order rand
data/.rubocop.yml ADDED
@@ -0,0 +1,86 @@
1
+ # I can't get the requires to work with sublime:
2
+ # SEE: https://github.com/pderichs/sublime_rubocop/issues/66
3
+ # -- https://gist.github.com/topher6345/4f921ca3e7938132563e
4
+ # -- https://forum.sublimetext.com/t/run-command-after-saving-file/44016
5
+ # -- https://medium.com/devnetwork/running-rubocop-only-on-modified-files-a21aed86e06d
6
+ # -- https://code.tutsplus.com/tutorials/how-to-create-a-sublime-text-2-plugin--net-22685
7
+
8
+ # -- https://github.com/SublimeLinter/SublimeLinter-rubocop/issues/19
9
+ # -- https://github.com/fnando/sublime-codefmt
10
+ # -- https://github.com/fnando/sublime-switch-case
11
+ # -- https://github.com/fnando/sublime-rubocop-completion/issues/1
12
+ # required these fixes:
13
+ # -- install PackageDev https://forum.sublimetext.com/t/pathlib-not-found-in-purchased-version/49978
14
+ # -- download all 3 packages via git clone rather than package manager
15
+ # -- renamed several files and directories to match
16
+ # -- brew update
17
+ # -- brew doctor
18
+ # -- brew install prettier yapf
19
+
20
+ require:
21
+ - rubocop-performance
22
+ - rubocop-rspec
23
+
24
+ AllCops:
25
+ TargetRubyVersion: 2.5
26
+ NewCops: enable
27
+
28
+ Style/Documentation:
29
+ Enabled: false
30
+
31
+ Naming/VariableNumber:
32
+ Enabled: false
33
+
34
+ Metrics/BlockLength:
35
+ Exclude:
36
+ - "**/*.rake"
37
+ - "config/**/*"
38
+ - "Rakefile"
39
+ - "spec/**/*.rb"
40
+ - "*.gemspec"
41
+
42
+ Layout/LineLength:
43
+ Max: 120
44
+
45
+ Style/BlockComments:
46
+ Enabled: false
47
+
48
+ Style/ClassAndModuleChildren:
49
+ Enabled: false
50
+
51
+ Style/RedundantBegin:
52
+ Enabled: false
53
+
54
+ Style/StringLiterals:
55
+ EnforcedStyle: single_quotes
56
+
57
+ Style/StringLiteralsInInterpolation:
58
+ Enabled: true
59
+
60
+ Style/WordArray:
61
+ EnforcedStyle: brackets
62
+
63
+ Metrics/MethodLength:
64
+ Max: 15
65
+
66
+ Style/HashSyntax:
67
+ Enabled: false
68
+
69
+ Style/StringHashKeys:
70
+ Enabled: false
71
+
72
+ Metrics/AbcSize:
73
+ Enabled: false
74
+
75
+ Layout/DotPosition:
76
+ Enabled: false
77
+
78
+ Lint/AmbiguousBlockAssociation:
79
+ Exclude:
80
+ - "spec/**/*"
81
+
82
+ RSpec/NamedSubject:
83
+ Enabled: false
84
+ # Rails:
85
+ # Enabled: true
86
+
data/.todo ADDED
@@ -0,0 +1,48 @@
1
+
2
+
3
+ -------------------------------------------------------------------------------------
4
+
5
+ ...meanwhile, back at planet scope...
6
+
7
+ bundle exec rspec spec/gql/v2/objects/organization_type_spec.rb spec/gql/v2/objects/user_type_spec.rb spec/gql/v2/objects/query_type_spec.rb spec/gql/v2/objects/webhook_* spec/gql/v2/mutations/webhook_subscriptions/* spec/libs/acts_as_webhook_spec.rb spec/gql/*/schema_type_spec.rb
8
+
9
+
10
+ 1. deploy (wait until friday)
11
+ 1. create new repo
12
+ 1. squash
13
+ 1. push
14
+
15
+
16
+ -------------------------------------------------------------------------------------
17
+
18
+ ...meanwhile, back at planet active_webbhook...
19
+
20
+ 1. deploy (wait until friday)
21
+ 1. create new repo
22
+ 1. squash
23
+ 1. push
24
+
25
+ -------------------------------------------------------------------------------------
26
+ # everything below this line is optional
27
+
28
+ 1. add rate limiting
29
+
30
+ 1. update the readme
31
+ - list all config options with brief descriptions (and link to config file for more information)
32
+ - list all gem dependencies for each adapter
33
+ - change customization to separate use cases
34
+
35
+ 1. solve rubygems
36
+
37
+ 1. fix generator
38
+ - didn't work for scope
39
+ - rename active_webhook_config.rb to initializers/active_webhook.rb
40
+ ? add option to install models & factories (see devise) [accept list of models to create & namespace]
41
+
42
+
43
+
44
+
45
+
46
+
47
+
48
+
data/.travis.yml ADDED
@@ -0,0 +1,14 @@
1
+ # SEE: https://docs.travis-ci.com/user/languages/ruby/
2
+
3
+ language: ruby
4
+ rvm:
5
+ - 2.5.3
6
+ before_install:
7
+ - gem install bundler:1.17.3
8
+ install:
9
+ - bundle _1.17.3_ install --jobs=3 --retry=3
10
+ - bundle exec rake db:reset
11
+ env:
12
+ # - 'TEST_RAILS_VERSION="~> 5.2.3"'
13
+ # - 'TEST_RAILS_VERSION="~> 6.0.3"'
14
+ - 'TEST_RAILS_VERSION="~> 6.1.3.2"'
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ # Changelog
2
+
3
+ ## 1.0.0 (02-Jul-2021)
4
+
5
+ * Initial public release
data/DEV_README.md ADDED
@@ -0,0 +1,199 @@
1
+ ## inspired by
2
+
3
+ `https://benediktdeicke.com/2017/09/sending-webhooks-with-rails/`
4
+
5
+ ## look at importing server from https://github.com/nsweeting/activehook
6
+
7
+ ## bootstrapped with:
8
+
9
+ `bundle gem active_webhook --test=rspec --mit`
10
+
11
+ ## bootstrapped dummy rails app with
12
+
13
+ `rails new dummy --skip-spring --skip-listen --skip-bootsnap --skip-action-text --skip-active-storage --skip-action-cable --skip-action-mailer --skip-action-mailbox --skip-test --skip-system-test --skip-active-job --skip-active-record --skip-javascript`
14
+
15
+ [then dicarded and used fully dummy]
16
+
17
+ [SEE](https://lokalise.com/blog/create-a-ruby-gem-basics/)
18
+ [SEE](https://lokalise.com/blog/how-to-create-a-ruby-gem-testing-suite/)
19
+
20
+ rails d model active_webhook/subscription
21
+
22
+ rails d model active_webhook/topic
23
+
24
+ rails g model active_webhook/subscription \
25
+ user_id:integer \
26
+ state:tinyint \
27
+ topic_key:string \
28
+ topic_version:string \
29
+ updated_at:datetime \
30
+ disabled_reason:string \
31
+ format:string \
32
+ callback_url:text \
33
+ company_id:integer \
34
+ query:text
35
+
36
+ rails g model active_webhook/topic \
37
+ key:string \
38
+ version:string \
39
+ state:tinyint \
40
+ query:string \
41
+
42
+
43
+ -------------------------------------------------------------------------------------
44
+ # everything below this line is deferred until needed
45
+
46
+ 1. consolidate formatting/*_adapter.rb into hook/builder.rb
47
+ - change content_type & encoded_data methods use ActiveWebhook.configuration.content_type
48
+ - add ActiveWebhook.configuration.builder
49
+ - delete Hook (in favor of basic hash) ?
50
+
51
+ 1. add `config.queueing.delay` trigger(in: nil) => [1.second]
52
+ - do not add to Topic or Subscription models (because they aren't loaded before check for performance reasons)
53
+ - evaluate to config.nil? ? method.option : config.value
54
+ - configure each queuing adapter to pass delay to underlying implementation
55
+
56
+ 1. add `config.buffering.adapter` => [:disabled, :enabled, Buffering::BaseAdapter]
57
+ - introduce shim into queueing/base_adapter#call that passes to active_webbhook/buffer/*adapter and back
58
+ - make sure that all queuing adapters delay after buffer is flushed
59
+ - add buffer/disabled_adapter and buffer/enabled_adapter
60
+ - implement as follows:
61
+ - if enabled, require `request_store`
62
+ - monkey_patch transaction block (or observe callbacks)
63
+ - add `buffer.t_level` and `buffer.entries`
64
+ - store t_level with buffer entry args
65
+ - on rollback, `buffer.entries.delete` where `entry.t_level` >= `buffer.t_level`; then `buffer.t_level -= 1`
66
+ - on commit, `buffer.entries.t.level -= 1` where `entry.t_level` >= `buffer.t_level`; then `buffer.t_level -= 1`
67
+ - if rails, `ActionController.include ActiveWebhook::Buferable` that wraps each action with `begin; ActiveWebhook.buffer.start; ensure; ActiveWebhook.buffer.flush; end
68
+ - note: Def controller might require different implementation from transactions; need to research transaction callbacks and commits during transaction
69
+ - https://github.com/steveklabnik/request_store
70
+ - https://www.justinweiss.com/articles/better-globals-with-a-tiny-activesupport-module/
71
+
72
+ 1. add `ActiveWebhook.cancel(...same args as trigger)`
73
+ - clears matching `buffer.entries` via `buffer.cancel(**kwargs)`
74
+ - relies on `config.buffer.eq?(a, b)`
75
+
76
+ 1. add `config.buffering.remove_duplicates` and trigger(remove_duplicates: nil, **) [true, false]
77
+ - do not add to Topic or Subscription models (because they aren't loaded before check for performance reasons)
78
+ - evaluate to config.nil? ? method.option : config.value
79
+ - raise runtime error if true and bufferring_adapter is disabled
80
+ - relies on `config.buffer.eq?(a, b)`
81
+
82
+ 1. add `config.delivery.retry_count` and trigger(retry_count: nil, **) [true, false]
83
+ - do not add to Topic or Subscription models (because they aren't loaded before check for performance reasons)
84
+ - evaluate to config.nil? ? method.option : config.value
85
+ - solve how to specify retry count with exponential backoff for each queuing adapter
86
+ - match option name to active_job
87
+
88
+ 1. add `config.delivery.time_limit` and trigger(time_limit: nil, **) [true, false]
89
+ - do not add to Topic or Subscription models (because they aren't loaded before check for performance reasons)
90
+ - evaluate to config.nil? ? method.option : config.value
91
+ - solve how to specify time limit for each queuing adapter
92
+ - match option name to active_job
93
+
94
+ 1. add jid to context in syncronous queuing adapter (if possible)
95
+ - solve how to generate an auto increment Id across servers (maybe hash or hex a server id and counter; could store server in db and load on start)
96
+ - https://www.google.com/search?q=rails+set+global+variable+per+request&client=safari&hl=en-us&ei=xF3NYKDaKYX_-wSAu5KIAw&oq=rails+set+global+variable+per+request
97
+
98
+
99
+
100
+ Scratchpad
101
+ ---
102
+ # in spec/spec_helper.rb
103
+
104
+ # Restablish connection (severed from app load)
105
+ ActiveRecord::Base.establish_connection(DB_CONFIG)
106
+
107
+ # log sql (as level debug)
108
+ ActiveRecord::Base.logger = Rails.logger
109
+
110
+
111
+ ----
112
+ # in Rakefile
113
+
114
+ # require "bundler/gem_tasks"
115
+ # require "rspec/core/rake_task"
116
+ # Bundler::GemHelper.install_tasks
117
+ # rescue LoadError
118
+ # puts "although not required, bundler is recommended for running the tests"
119
+ # end
120
+ # require "rake"
121
+
122
+ # RSpec::Core::RakeTask.new(:spec) do |spec|
123
+ # spec.pattern = 'spec/**/*_spec.rb'
124
+ # end
125
+
126
+ # namespace :db do
127
+ # desc "Create the database"
128
+ # task :create do
129
+ # initialize_rake_environment
130
+ # if ActiveRecord::Base.connection.respond_to? :create_database
131
+ # ActiveRecord::Base.connection.create_database(DB_CONFIG["database"])
132
+ # else
133
+ # ActiveRecord::Base.connection.send :connect
134
+ # end
135
+ # puts "Database created."
136
+ # end
137
+
138
+ # desc "Migrate the database"
139
+ # task :migrate do
140
+ # initialize_rake_environment
141
+ # ActiveRecord::Base.connection.migration_context.migrate
142
+ # Rake::Task["db:schema"].invoke
143
+ # puts "Database migrated."
144
+ # end
145
+
146
+ # desc "Drop the database"
147
+ # task :drop do
148
+ # initialize_rake_environment
149
+ # ActiveRecord::Base.connection.close
150
+ # if ActiveRecord::Base.connection.respond_to? :drop_database
151
+ # ActiveRecord::Base.connection.drop_database(DB_CONFIG["database"])
152
+ # else
153
+ # f = [__dir__, "db", "#{ENV['RACK_ENV']}.sqlite3"].join("/")
154
+ # File.delete(f) if File.exist?(f)
155
+ # end
156
+ # puts "Database deleted."
157
+ # end
158
+
159
+ # desc "Reset the database"
160
+ # task :reset => %i[drop create migrate]
161
+
162
+ # desc "Create a db/schema.rb file that is portable against any DB supported by AR"
163
+ # task :schema do
164
+ # initialize_rake_environment
165
+ # require "active_record/schema_dumper"
166
+ # filename = "db/schema.rb"
167
+ # File.open(filename, "w:utf-8") do |file|
168
+ # ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
169
+ # end
170
+ # end
171
+ # end
172
+
173
+ # namespace :g do
174
+ # desc "Generate migration"
175
+ # task :migration do
176
+ # initialize_rake_environment
177
+ # name = ARGV[1] || raise("Specify name: rake g:migration your_migration")
178
+ # timestamp = Time.now.strftime("%Y%m%d%H%M%S")
179
+ # path = File.expand_path("../db/migrate/#{timestamp}_#{name}.rb", __FILE__)
180
+ # migration_class = name.split("_").map(&:capitalize).join
181
+
182
+ # File.open(path, "w") do |file|
183
+ # file.write <<~FILE
184
+ # class #{migration_class} < ActiveRecord::Migration
185
+ # def self.up
186
+ # end
187
+ # def self.down
188
+ # end
189
+ # end
190
+ # FILE
191
+ # end
192
+
193
+ # puts "Migration #{path} created"
194
+ # abort # needed stop other tasks
195
+ # end
196
+ # end
197
+
198
+
199
+
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
+
7
+ # Specify your gem's dependencies in active_webhook.gemspec
8
+ gemspec