event_sub_events 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 94315c973dda08607844c54e85c32e898ba09c7c678f140227b7b590aa3c7dd3
4
+ data.tar.gz: 695a9cc7782fe1dbdb13ee31c277ba76a0a44405cde47e5623f86217c992f2be
5
+ SHA512:
6
+ metadata.gz: 5d778d89c4097a472d9593b72a9dfa74588b7b8d2586a9c9f5dff45520365d5ff8c145483a07aca79911c17ddafb40d03df1a1694a36e99a23b6510e980bccce
7
+ data.tar.gz: c8e26f57f29d47e0489703798673ad790e502267e9c45bb81cb634443d2e27c75ca14bd8d7296999c2f43b6389de72639cddb0c130e422993650fd22ceb2c8d3
@@ -0,0 +1,4 @@
1
+ # These are supported funding model platforms
2
+
3
+ github: deanpcmad
4
+ ko_fi: deanpcmad
@@ -0,0 +1,27 @@
1
+ name: Ruby
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+
8
+ pull_request:
9
+
10
+ jobs:
11
+ build:
12
+ runs-on: ubuntu-latest
13
+ name: Ruby ${{ matrix.ruby }}
14
+ strategy:
15
+ matrix:
16
+ ruby:
17
+ - '3.2.2'
18
+
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+ - name: Set up Ruby
22
+ uses: ruby/setup-ruby@v1
23
+ with:
24
+ ruby-version: ${{ matrix.ruby }}
25
+ bundler-cache: true
26
+ - name: Run the default task
27
+ run: bundle exec rake
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ .bundle/
2
+ log/*.log
3
+ pkg/
4
+ spec/dummy/db/*.sqlite3
5
+ spec/dummy/log/*.log
6
+ spec/dummy/tmp/
7
+ spec/dummy/.sass-cache
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --format documentation
data/CHANGELOG.md ADDED
@@ -0,0 +1,165 @@
1
+ ### [Unreleased] - TBD
2
+
3
+ ### 2.7.0 (Nov 27, 2022)
4
+
5
+ - Add Stripe 8 support (#159)
6
+
7
+ ### 2.6.0 (Aug 8, 2022)
8
+
9
+ - Introduce StripeEvent::ProcessError and possible HTTP 422 responses (#155, #132)
10
+
11
+ ### 2.5.0 (Aug 5, 2022)
12
+
13
+ - Add Stripe 7 support (#154)
14
+
15
+ ### 2.4.0 (May 12, 2022)
16
+
17
+ - Add Stripe 6 support (#151)
18
+ - Add Rails 7 support (#151)
19
+ - Add Ruby 3.1 support (#152)
20
+ - Improved build matrix
21
+
22
+ ### 2.3.2 (February 21, 2022)
23
+
24
+ - Fix signature validation error if the first signing secret is nil (#146)
25
+ - Update README (#143)
26
+ - Setup github actions for CI (#147)
27
+
28
+ ### 2.3.1 (May 12, 2020)
29
+
30
+ - Fix deprecation warning in Ruby 2.7 (#130)
31
+ - Fixes tests for Stripe 5.19.0 (#133)
32
+
33
+ ### 2.3.0 (August 23, 2019)
34
+
35
+ - Add support for Stripe v5.x (#119)
36
+ - Add support for Rails v6.x to the build matrix (#119)
37
+
38
+ ### 2.2.0 (December 6, 2018)
39
+
40
+ - Add support for Stripe v4.x (#119)
41
+ - Documentation Updates and Fixes (#113 and #117)
42
+
43
+ ### 2.1.1 (January 31, 2018)
44
+
45
+ - Adds better support for Rails 5.2 (#105, #106, #107)
46
+ - `StripeEvent::WebhookController` now calls `skip_before_action :verify_authenticity_token` if `Rails.application.config.action_controller.default_protect_from_forgery` is set (as it is by default in Rails 5.2)
47
+
48
+ ### 2.1.0 (yanked)
49
+
50
+ ### 2.0.0 (December 14, 2017)
51
+
52
+ **Backwards incompatible release. [Signed webhooks are now required.](https://stripe.com/docs/webhooks#signatures).**
53
+
54
+ - **Requires `StripeEvent.signing_secret` configuration** (#95, #97)
55
+ - Adds support for multiple signing secrets using `StripeEvent.signing_secrets` (#98, #99)
56
+ - Removes `StripeEvent.authentication_secret` and associated basic auth support (#97)
57
+ - Adds `StripeEvent.event_filter` (replaces use-cases for the now removed `event_retriever` config) (#97)
58
+
59
+ ### 1.9.1 (December 5, 2017)
60
+
61
+ This release is in preparation for some backward incompatible changes due to
62
+ arrive in v2.0.0. It is highly recommended that everyone secure their webhook
63
+ endpoints by using `StripeEvent.signing_secret`. See the README and [Stripe's
64
+ documentation](https://stripe.com/docs/webhooks#signatures) for more
65
+ information.
66
+
67
+ * Deprecate `StripeEvent.authentication_secret` (#96)
68
+ * Deprecate unverified use of Stripe's webhooks (#96)
69
+
70
+ ### 1.9.0 (November 30, 2017)
71
+
72
+ * Support for Rails 5.1 (#94, Thanks @krasnoukhov and @simplepractice!)
73
+
74
+ ### 1.8.0 (August 29, 2017)
75
+
76
+ * Support for [Stripe's Webhook Signature Verification](https://stripe.com/docs/webhooks#signatures) (#83, #90, Thanks @mikeycgto!)
77
+ * Secure compare during basic authentication check (#91, Thanks @mikeycgto!)
78
+
79
+ ### 1.7.0 (July 5, 2017)
80
+
81
+ * Support stripe v3 gem as a dependency (#87)
82
+
83
+ ### 1.6.0 (February 27, 2017)
84
+
85
+ * Support stripe v2 gem as a dependency (#82, b3cee03)
86
+
87
+ ### 1.5.1 (September 20, 2016)
88
+
89
+ * Better Rails 5 support. Prefer `before_action` over `before_filter`. (#69, Thanks @mcolyer)
90
+
91
+ ### 1.5.0 (February 25, 2015)
92
+ * Added [replay attack protection](https://github.com/integrallis/stripe_event#securing-your-webhook-endpoint) on webhooks. See `StripeEvent.authentication_secret`. Thanks @brentdax for both the initial discussion and the implementation! #53, #55
93
+ * Dropped official support for Rails 3.1 and Rails 4.0
94
+
95
+ ### 1.4.0 (November 1, 2014)
96
+ * Add `StripeEvent.listening?` method to easily determine if an event type has any registered handlers. Thank you to [Vladimir Andrijevik](https://github.com/vandrijevik) for the [idea and implementation](https://github.com/integrallis/stripe_event/pull/42).
97
+
98
+ ### 1.3.0 (July 22, 2014)
99
+ * Allow for ignoring particular events. Thank you to [anark](https://github.com/anark) for suggesting the change, and [Ryan McGeary](https://github.com/rmm5t) and [Pete Keen](https://github.com/peterkeen) for working on the implementation.
100
+
101
+ ### 1.2.0 (June 17, 2014)
102
+ * Gracefully authenticate `account.application.deauthorized` events. Thank you to [Ryan McGeary](https://github.com/rmm5t) for the pull request and for taking the time to test the change in a live environment.
103
+
104
+ ### 1.1.0 (January 8, 2014)
105
+ * Deprecate `StripeEvent.setup` in favor of `StripeEvent.configure`. Remove `setup` at next major release.
106
+ * `StripeEvent.configure` yields the module to the block for configuration.
107
+ * `StripeEvent.configure` will raise `ArgumentError` unless a block is given.
108
+ * Track test coverage
109
+
110
+ ### 1.0.0 (December 19, 2013)
111
+ * Internally namespace dispatched events to avoid maintaining a list of all possible event types.
112
+ * Subscribe to all event types with `StripeEvent.all` instead of `StripeEvent.subscribe`.
113
+ * Remove ability to subscribe to many event types with once call to `StripeEvent.subscribe`.
114
+ * Subscribers can be an object that responds to #call.
115
+ * Allow subscriber-generated `Stripe::StripeError`'s to bubble up. Thank you to [adamonduty](https://github.com/adamonduty) for the [patch](https://github.com/integrallis/stripe_event/pull/26).
116
+ * Only depend on `stripe` and `activesupport` gems.
117
+ * Add `rails` as a development dependency.
118
+ * Only `require 'stripe_event/engine'` if `Rails` constant exists to allow StripeEvent to be used outside of a Rails application.
119
+
120
+ ### 0.6.1 (August 19, 2013)
121
+ * Update event type list
122
+ * Update test gemfiles
123
+
124
+ ### 0.6.0 (March 18, 2013)
125
+ * Rails 4 compatibility. Thank you to Ben Ubois for reporting the [issue](https://github.com/integrallis/stripe_event/issues/13) and to Matt Goldman for the [pull request](https://github.com/integrallis/stripe_event/pull/14).
126
+ * Run specs against different Rails versions
127
+ * Refactor internal usage of AS::Notifications
128
+ * Remove jruby-openssl as platform conditional dependency
129
+
130
+ ### 0.5.0 (December 16, 2012)
131
+ * Remove `Gemfile.lock` from version control
132
+ * Internal event type list is now a set
133
+ * Update event type list
134
+ * Various internal refactorings
135
+ * More readable tests
136
+
137
+ ### 0.4.0 (September 24, 2012)
138
+ * Add configuration for custom event retrieval. Thanks to Dan Hodos for the [pull request](https://github.com/integrallis/stripe_event/pull/6).
139
+ * Move module methods only used in tests into a test helper.
140
+ * Various internal refactorings and additional tests.
141
+ * Error classes will inherit from a base error class now.
142
+
143
+ ### 0.3.1 (August 14, 2012)
144
+ * Fix controller inheritance issue. Thanks to Christopher Baran for [reporting the bug](https://github.com/integrallis/stripe_event/issues/1), and to Robert Bousquet for [fixing it](https://github.com/integrallis/stripe_event/pull/3).
145
+ * Deprecate registration method. Use 'setup' instead.
146
+
147
+ ### 0.3.0 (July 16, 2012)
148
+ * Add registration method for conveniently adding many subscribers
149
+ * Depend on jruby-openssl when running on jruby
150
+ * Remove unneeded rake dependency
151
+ * Remove configure method
152
+
153
+ ### 0.2.0 (July 12, 2012)
154
+ * Register a subscriber to one/many/all events
155
+ * Remove sqlite3 development dependency
156
+ * Setup travis-ci for repo
157
+ * Hard code a placeholder api key in dummy app. Fixes failing tests when env var not defined.
158
+
159
+ ### 0.1.1 (July 4, 2012)
160
+ * Improve README
161
+ * Specify development dependency versions
162
+ * Fix controller test which was passing incorrectly
163
+
164
+ ### 0.1.0 (June 24, 2012)
165
+ * Initial release
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "https://rubygems.org"
2
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,222 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ event_sub_events (0.1.0)
5
+ activesupport (>= 3.1)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ actioncable (7.1.1)
11
+ actionpack (= 7.1.1)
12
+ activesupport (= 7.1.1)
13
+ nio4r (~> 2.0)
14
+ websocket-driver (>= 0.6.1)
15
+ zeitwerk (~> 2.6)
16
+ actionmailbox (7.1.1)
17
+ actionpack (= 7.1.1)
18
+ activejob (= 7.1.1)
19
+ activerecord (= 7.1.1)
20
+ activestorage (= 7.1.1)
21
+ activesupport (= 7.1.1)
22
+ mail (>= 2.7.1)
23
+ net-imap
24
+ net-pop
25
+ net-smtp
26
+ actionmailer (7.1.1)
27
+ actionpack (= 7.1.1)
28
+ actionview (= 7.1.1)
29
+ activejob (= 7.1.1)
30
+ activesupport (= 7.1.1)
31
+ mail (~> 2.5, >= 2.5.4)
32
+ net-imap
33
+ net-pop
34
+ net-smtp
35
+ rails-dom-testing (~> 2.2)
36
+ actionpack (7.1.1)
37
+ actionview (= 7.1.1)
38
+ activesupport (= 7.1.1)
39
+ nokogiri (>= 1.8.5)
40
+ rack (>= 2.2.4)
41
+ rack-session (>= 1.0.1)
42
+ rack-test (>= 0.6.3)
43
+ rails-dom-testing (~> 2.2)
44
+ rails-html-sanitizer (~> 1.6)
45
+ actiontext (7.1.1)
46
+ actionpack (= 7.1.1)
47
+ activerecord (= 7.1.1)
48
+ activestorage (= 7.1.1)
49
+ activesupport (= 7.1.1)
50
+ globalid (>= 0.6.0)
51
+ nokogiri (>= 1.8.5)
52
+ actionview (7.1.1)
53
+ activesupport (= 7.1.1)
54
+ builder (~> 3.1)
55
+ erubi (~> 1.11)
56
+ rails-dom-testing (~> 2.2)
57
+ rails-html-sanitizer (~> 1.6)
58
+ activejob (7.1.1)
59
+ activesupport (= 7.1.1)
60
+ globalid (>= 0.3.6)
61
+ activemodel (7.1.1)
62
+ activesupport (= 7.1.1)
63
+ activerecord (7.1.1)
64
+ activemodel (= 7.1.1)
65
+ activesupport (= 7.1.1)
66
+ timeout (>= 0.4.0)
67
+ activestorage (7.1.1)
68
+ actionpack (= 7.1.1)
69
+ activejob (= 7.1.1)
70
+ activerecord (= 7.1.1)
71
+ activesupport (= 7.1.1)
72
+ marcel (~> 1.0)
73
+ activesupport (7.1.1)
74
+ base64
75
+ bigdecimal
76
+ concurrent-ruby (~> 1.0, >= 1.0.2)
77
+ connection_pool (>= 2.2.5)
78
+ drb
79
+ i18n (>= 1.6, < 2)
80
+ minitest (>= 5.1)
81
+ mutex_m
82
+ tzinfo (~> 2.0)
83
+ addressable (2.8.5)
84
+ public_suffix (>= 2.0.2, < 6.0)
85
+ base64 (0.1.1)
86
+ bigdecimal (3.1.4)
87
+ builder (3.2.4)
88
+ concurrent-ruby (1.2.2)
89
+ connection_pool (2.4.1)
90
+ crack (0.4.5)
91
+ rexml
92
+ crass (1.0.6)
93
+ date (3.3.3)
94
+ diff-lcs (1.5.0)
95
+ drb (2.1.1)
96
+ ruby2_keywords
97
+ erubi (1.12.0)
98
+ globalid (1.2.1)
99
+ activesupport (>= 6.1)
100
+ hashdiff (1.0.1)
101
+ i18n (1.14.1)
102
+ concurrent-ruby (~> 1.0)
103
+ io-console (0.6.0)
104
+ irb (1.8.3)
105
+ rdoc
106
+ reline (>= 0.3.8)
107
+ loofah (2.21.4)
108
+ crass (~> 1.0.2)
109
+ nokogiri (>= 1.12.0)
110
+ mail (2.8.1)
111
+ mini_mime (>= 0.1.1)
112
+ net-imap
113
+ net-pop
114
+ net-smtp
115
+ marcel (1.0.2)
116
+ mini_mime (1.1.5)
117
+ minitest (5.20.0)
118
+ mutex_m (0.1.2)
119
+ net-imap (0.4.3)
120
+ date
121
+ net-protocol
122
+ net-pop (0.1.2)
123
+ net-protocol
124
+ net-protocol (0.2.1)
125
+ timeout
126
+ net-smtp (0.4.0)
127
+ net-protocol
128
+ nio4r (2.5.9)
129
+ nokogiri (1.15.4-x86_64-linux)
130
+ racc (~> 1.4)
131
+ psych (5.1.1.1)
132
+ stringio
133
+ public_suffix (5.0.3)
134
+ racc (1.7.2)
135
+ rack (3.0.8)
136
+ rack-session (2.0.0)
137
+ rack (>= 3.0.0)
138
+ rack-test (2.1.0)
139
+ rack (>= 1.3)
140
+ rackup (2.1.0)
141
+ rack (>= 3)
142
+ webrick (~> 1.8)
143
+ rails (7.1.1)
144
+ actioncable (= 7.1.1)
145
+ actionmailbox (= 7.1.1)
146
+ actionmailer (= 7.1.1)
147
+ actionpack (= 7.1.1)
148
+ actiontext (= 7.1.1)
149
+ actionview (= 7.1.1)
150
+ activejob (= 7.1.1)
151
+ activemodel (= 7.1.1)
152
+ activerecord (= 7.1.1)
153
+ activestorage (= 7.1.1)
154
+ activesupport (= 7.1.1)
155
+ bundler (>= 1.15.0)
156
+ railties (= 7.1.1)
157
+ rails-dom-testing (2.2.0)
158
+ activesupport (>= 5.0.0)
159
+ minitest
160
+ nokogiri (>= 1.6)
161
+ rails-html-sanitizer (1.6.0)
162
+ loofah (~> 2.21)
163
+ nokogiri (~> 1.14)
164
+ railties (7.1.1)
165
+ actionpack (= 7.1.1)
166
+ activesupport (= 7.1.1)
167
+ irb
168
+ rackup (>= 1.0.0)
169
+ rake (>= 12.2)
170
+ thor (~> 1.0, >= 1.2.2)
171
+ zeitwerk (~> 2.6)
172
+ rake (13.1.0)
173
+ rdoc (6.5.0)
174
+ psych (>= 4.0.0)
175
+ reline (0.3.9)
176
+ io-console (~> 0.5)
177
+ rexml (3.2.6)
178
+ rspec-core (3.9.3)
179
+ rspec-support (~> 3.9.3)
180
+ rspec-expectations (3.9.4)
181
+ diff-lcs (>= 1.2.0, < 2.0)
182
+ rspec-support (~> 3.9.0)
183
+ rspec-mocks (3.9.1)
184
+ diff-lcs (>= 1.2.0, < 2.0)
185
+ rspec-support (~> 3.9.0)
186
+ rspec-rails (3.9.1)
187
+ actionpack (>= 3.0)
188
+ activesupport (>= 3.0)
189
+ railties (>= 3.0)
190
+ rspec-core (~> 3.9.0)
191
+ rspec-expectations (~> 3.9.0)
192
+ rspec-mocks (~> 3.9.0)
193
+ rspec-support (~> 3.9.0)
194
+ rspec-support (3.9.4)
195
+ ruby2_keywords (0.0.5)
196
+ stringio (3.0.8)
197
+ thor (1.3.0)
198
+ timeout (0.4.0)
199
+ tzinfo (2.0.6)
200
+ concurrent-ruby (~> 1.0)
201
+ webmock (1.24.6)
202
+ addressable (>= 2.3.6)
203
+ crack (>= 0.3.2)
204
+ hashdiff
205
+ webrick (1.8.1)
206
+ websocket-driver (0.7.6)
207
+ websocket-extensions (>= 0.1.0)
208
+ websocket-extensions (0.1.5)
209
+ zeitwerk (2.6.12)
210
+
211
+ PLATFORMS
212
+ x86_64-linux
213
+
214
+ DEPENDENCIES
215
+ event_sub_events!
216
+ rails (>= 3.1)
217
+ rake
218
+ rspec-rails (~> 3.7)
219
+ webmock (~> 1.9)
220
+
221
+ BUNDLED WITH
222
+ 2.4.21
data/LICENSE.md ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License
2
+
3
+ Copyright 2012-2015 Integrallis Software
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,96 @@
1
+ # EventSub
2
+
3
+ EventSub is a Ruby library for Twitch EventSub webhooks. It is built on the [ActiveSupport::Notifications API](http://api.rubyonrails.org/classes/ActiveSupport/Notifications.html).
4
+
5
+ This is forked from [stripe_event](https://github.com/integrallis/stripe_event) and modified for use with Twitch EventSub.
6
+
7
+ ## Install
8
+
9
+ ```ruby
10
+ # Gemfile
11
+ gem "eventsub"
12
+ ```
13
+
14
+ ```ruby
15
+ # config/routes.rb
16
+ mount EventSub::Engine, at: "/my-chosen-path"
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ ```ruby
22
+ # config/initializers/event_sub.rb
23
+ EventSub.signing_secret = ENV['TWITCH_SIGNING_SECRET']
24
+
25
+ EventSub.configure do |events|
26
+ events.subscribe "channel.ban" do |event|
27
+ event.subscription
28
+ event.event
29
+ end
30
+
31
+ events.all do |event|
32
+ # Handle all event types - logging, etc.
33
+ end
34
+ end
35
+ ```
36
+
37
+ ### Subscriber objects that respond to #call
38
+
39
+ ```ruby
40
+ class CustomerCreated
41
+ def call(event)
42
+ # Event handling
43
+ end
44
+ end
45
+
46
+ class BillingEventLogger
47
+ def initialize(logger)
48
+ @logger = logger
49
+ end
50
+
51
+ def call(event)
52
+ @logger.info "BILLING:#{event.type}:#{event.id}"
53
+ end
54
+ end
55
+ ```
56
+
57
+ ```ruby
58
+ EventSub.configure do |events|
59
+ events.all BillingEventLogger.new(Rails.logger)
60
+ events.subscribe 'customer.created', CustomerCreated.new
61
+ end
62
+ ```
63
+
64
+ ## Securing your webhook endpoint
65
+
66
+ ### Authenticating webhooks with signatures
67
+
68
+ Twitch will cryptographically sign webhook events with a signature which is included with a header sent with the request.
69
+ Verifying this signature lets your application properly authenticate the request originated from Twitch.
70
+
71
+ Please set the `signing_secret` configuration value:
72
+
73
+ ```ruby
74
+ EventSub.signing_secret = "abc123"
75
+ ```
76
+
77
+ Please refer to [Twitch's documentation](https://dev.twitch.tv/docs/eventsub/handling-webhook-events/#verifying-the-event-message) for more details
78
+
79
+ ### Support for multiple signing secrets
80
+
81
+ You can also supply multiple secrets by sending an array to `signing_secrets` like so:
82
+
83
+ ```ruby
84
+ EventSub.signing_secrets = [
85
+ "abc123",
86
+ "123abc"
87
+ ]
88
+ ```
89
+
90
+ ## Contributing
91
+
92
+ Bug reports and pull requests are welcome on GitHub at https://github.com/deanpcmad/eventsub-gem.
93
+
94
+ ## License
95
+
96
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
9
+
@@ -0,0 +1,23 @@
1
+ module EventSubEvents
2
+ class WebhookController < ActionController::Base
3
+
4
+ if Rails.application.config.action_controller.default_protect_from_forgery
5
+ skip_before_action :verify_authenticity_token
6
+ end
7
+
8
+ def event
9
+ EventSubEvents.instrument(verified_event)
10
+ head :ok
11
+ rescue EventSubEvents::SignatureVerificationError => e
12
+ render plain: e, status: :bad_request
13
+ end
14
+
15
+ private
16
+
17
+ def verified_event
18
+ verifier = EventSubEvents::SignatureVerifier.new(request)
19
+ verifier.reconstruct_event if verifier.verify
20
+ end
21
+
22
+ end
23
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,3 @@
1
+ EventSubEvents::Engine.routes.draw do
2
+ root to: 'webhook#event', via: :post
3
+ end
@@ -0,0 +1,34 @@
1
+ $LOAD_PATH.push File.expand_path("lib", __dir__)
2
+
3
+ # Maintain your gem's version:
4
+ require "event_sub_events/version"
5
+
6
+ # Describe your gem and declare its dependencies:
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "event_sub_events"
9
+ spec.version = EventSubEvents::VERSION
10
+ spec.authors = ["Dean Perry"]
11
+ spec.email = "dean@deanpcmad.com"
12
+
13
+ spec.summary = "Twitch EventSub webhook integration for Rails apps"
14
+ spec.homepage = "https://deanpcmad.com"
15
+ spec.license = "MIT"
16
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
17
+
18
+ # spec.metadata["homepage_uri"] = spec.homepage
19
+ # spec.metadata["source_code_uri"] = "https://github.com/deanpcmad/eventsub-gem"
20
+
21
+ # Specify which files should be added to the gem when it is released.
22
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
24
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
+ end
26
+ spec.require_paths = ["lib"]
27
+
28
+ spec.add_dependency "activesupport", ">= 3.1"
29
+
30
+ spec.add_development_dependency "rails", [">= 3.1"]
31
+ spec.add_development_dependency "rake"
32
+ spec.add_development_dependency "rspec-rails", "~> 3.7"
33
+ spec.add_development_dependency "webmock", "~> 1.9"
34
+ end
@@ -0,0 +1,5 @@
1
+ module EventSubEvents
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace EventSubEvents
4
+ end
5
+ end
@@ -0,0 +1,50 @@
1
+ require "openssl"
2
+ require "ostruct"
3
+ require "json"
4
+
5
+ module EventSubEvents
6
+ class SignatureVerifier
7
+ def initialize(request)
8
+ @request = request
9
+ end
10
+
11
+ def verify
12
+ request = @request
13
+
14
+ message_id = request.headers["Twitch-Eventsub-Message-Id"]
15
+ timestamp = request.headers["Twitch-Eventsub-Message-Timestamp"]
16
+ signature = request.headers["Twitch-Eventsub-Message-Signature"].gsub("sha256=", "")
17
+ body = request.body.read
18
+
19
+ hmac_message = message_id + timestamp + body
20
+
21
+ secrets = EventSubEvents.signing_secrets if EventSubEvents.signing_secret
22
+
23
+ secrets.each_with_index do |secret, i|
24
+ begin
25
+ hex = OpenSSL::HMAC.hexdigest('sha256', secret, hmac_message)
26
+ return validate(hex, signature)
27
+ rescue EventSubEvents::SignatureVerificationError
28
+ raise if i == secrets.length - 1
29
+ next
30
+ end
31
+ end
32
+ end
33
+
34
+ def reconstruct_event
35
+ body = @request.body.read
36
+ JSON.parse(body, object_class: OpenStruct)
37
+ end
38
+
39
+ private
40
+
41
+ def validate(hex, signature)
42
+ if ActiveSupport::SecurityUtils::secure_compare(hex, signature)
43
+ true
44
+ else
45
+ raise EventSubEvents::SignatureVerificationError
46
+ end
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,3 @@
1
+ module EventSubEvents
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,76 @@
1
+ require "active_support/notifications"
2
+ require "event_sub_events/signature_verifier"
3
+ require "event_sub_events/engine" if defined?(Rails)
4
+
5
+ module EventSubEvents
6
+ class << self
7
+ attr_accessor :adapter, :backend, :namespace, :event_filter
8
+ attr_reader :signing_secrets
9
+
10
+ def configure(&block)
11
+ raise ArgumentError, "must provide a block" unless block_given?
12
+ block.arity.zero? ? instance_eval(&block) : yield(self)
13
+ end
14
+ alias :setup :configure
15
+
16
+ def instrument(event)
17
+ event = event_filter.call(event)
18
+ backend.instrument namespace.call(event.subscription.type), event if event
19
+ end
20
+
21
+ def subscribe(name, callable = nil, &block)
22
+ callable ||= block
23
+ backend.subscribe namespace.to_regexp(name), adapter.call(callable)
24
+ end
25
+
26
+ def all(callable = nil, &block)
27
+ callable ||= block
28
+ subscribe nil, callable
29
+ end
30
+
31
+ def listening?(name)
32
+ namespaced_name = namespace.call(name)
33
+ backend.notifier.listening?(namespaced_name)
34
+ end
35
+
36
+ def signing_secret=(value)
37
+ @signing_secrets = Array(value).compact
38
+ end
39
+ alias signing_secrets= signing_secret=
40
+
41
+ def signing_secret
42
+ self.signing_secrets && self.signing_secrets.first
43
+ end
44
+ end
45
+
46
+ class Namespace < Struct.new(:value, :delimiter)
47
+ def call(name = nil)
48
+ "#{value}#{delimiter}#{name}"
49
+ end
50
+
51
+ def to_regexp(name = nil)
52
+ %r{^#{Regexp.escape call(name)}}
53
+ end
54
+ end
55
+
56
+ class NotificationAdapter < Struct.new(:subscriber)
57
+ def self.call(callable)
58
+ new(callable)
59
+ end
60
+
61
+ def call(*args)
62
+ payload = args.last
63
+ subscriber.call(payload)
64
+ end
65
+ end
66
+
67
+ class Error < StandardError; end
68
+ class UnauthorizedError < Error; end
69
+ class SignatureVerificationError < Error; end
70
+ class ProcessError < Error; end
71
+
72
+ self.adapter = NotificationAdapter
73
+ self.backend = ActiveSupport::Notifications
74
+ self.namespace = Namespace.new("event_sub", ".")
75
+ self.event_filter = lambda { |event| event }
76
+ end
data/lib/eventsub.rb ADDED
@@ -0,0 +1 @@
1
+ require "event_sub_events"
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: event_sub_events
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Dean Perry
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-02-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '3.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '3.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rails
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '3.1'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '3.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec-rails
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.7'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.7'
69
+ - !ruby/object:Gem::Dependency
70
+ name: webmock
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.9'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.9'
83
+ description:
84
+ email: dean@deanpcmad.com
85
+ executables: []
86
+ extensions: []
87
+ extra_rdoc_files: []
88
+ files:
89
+ - ".github/FUNDING.yml"
90
+ - ".github/workflows/main.yml"
91
+ - ".gitignore"
92
+ - ".rspec"
93
+ - CHANGELOG.md
94
+ - Gemfile
95
+ - Gemfile.lock
96
+ - LICENSE.md
97
+ - README.md
98
+ - Rakefile
99
+ - app/controllers/event_sub_events/webhook_controller.rb
100
+ - config/routes.rb
101
+ - event_sub_events.gemspec
102
+ - lib/event_sub_events.rb
103
+ - lib/event_sub_events/engine.rb
104
+ - lib/event_sub_events/signature_verifier.rb
105
+ - lib/event_sub_events/version.rb
106
+ - lib/eventsub.rb
107
+ homepage: https://deanpcmad.com
108
+ licenses:
109
+ - MIT
110
+ metadata: {}
111
+ post_install_message:
112
+ rdoc_options: []
113
+ require_paths:
114
+ - lib
115
+ required_ruby_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: 2.3.0
120
+ required_rubygems_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ requirements: []
126
+ rubygems_version: 3.4.22
127
+ signing_key:
128
+ specification_version: 4
129
+ summary: Twitch EventSub webhook integration for Rails apps
130
+ test_files: []