webhukhs 0.6.0 → 0.8.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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/.standard.yml +2 -0
  3. data/.yard-lint.yml +296 -0
  4. data/AGENTS.md +56 -0
  5. data/Appraisals +6 -2
  6. data/CHANGELOG.md +20 -0
  7. data/README.md +101 -11
  8. data/Rakefile +7 -0
  9. data/config/mutant.rb +37 -0
  10. data/config/mutant.yml +25 -0
  11. data/example/Gemfile +5 -6
  12. data/example/Gemfile.lock +260 -141
  13. data/example/app/webhooks/acme_handler.rb +16 -0
  14. data/example/app/webhooks/flaky_handler.rb +8 -0
  15. data/example/app/webhooks/signed_handler.rb +10 -0
  16. data/example/config/initializers/webhukhs.rb +4 -3
  17. data/example/config/routes.rb +3 -0
  18. data/example/db/migrate/20240601000000_add_headers_to_webhukhs_webhooks.rb +7 -0
  19. data/example/db/schema.rb +2 -1
  20. data/example/db/seeds.rb +71 -7
  21. data/gemfiles/{rails_7.1.gemfile → rails_7.2.gemfile} +1 -4
  22. data/gemfiles/rails_7.2.gemfile.lock +477 -0
  23. data/gemfiles/rails_8.0.gemfile +0 -3
  24. data/gemfiles/rails_8.0.gemfile.lock +74 -4
  25. data/gemfiles/rails_8.1.gemfile +0 -3
  26. data/gemfiles/rails_8.1.gemfile.lock +74 -4
  27. data/gemfiles/rails_master.gemfile +7 -0
  28. data/lib/webhukhs/admin/application_controller.rb +32 -0
  29. data/lib/webhukhs/admin/assets/admin.css +476 -0
  30. data/lib/webhukhs/admin/assets/admin.js +111 -0
  31. data/lib/webhukhs/admin/config/routes.rb +6 -0
  32. data/lib/webhukhs/admin/engine.rb +20 -0
  33. data/lib/webhukhs/admin/received_webhook_presenter.rb +63 -0
  34. data/lib/webhukhs/admin/received_webhooks_controller.rb +60 -0
  35. data/lib/webhukhs/admin/view_helper.rb +50 -0
  36. data/lib/webhukhs/admin/views/layouts/webhukhs/admin/application.html.erb +22 -0
  37. data/lib/webhukhs/admin/views/webhukhs/admin/received_webhooks/index.html.erb +50 -0
  38. data/lib/webhukhs/admin/views/webhukhs/admin/received_webhooks/show.html.erb +55 -0
  39. data/lib/webhukhs/admin.rb +17 -0
  40. data/lib/webhukhs/base_handler.rb +9 -6
  41. data/lib/webhukhs/controllers/receive_webhooks_controller.rb +26 -7
  42. data/lib/webhukhs/engine.rb +1 -4
  43. data/lib/webhukhs/install_generator.rb +9 -2
  44. data/lib/webhukhs/jobs/processing_job.rb +13 -12
  45. data/lib/webhukhs/models/received_webhook.rb +21 -9
  46. data/lib/webhukhs/version.rb +1 -1
  47. data/lib/webhukhs.rb +9 -0
  48. data/test/admin_test.rb +334 -0
  49. data/test/base_handler_test.rb +125 -0
  50. data/test/browser/admin_click_through.rb +208 -0
  51. data/test/processing_job_test.rb +152 -12
  52. data/test/received_webhook_test.rb +260 -0
  53. data/test/test_app.rb +39 -15
  54. data/test/test_helper.rb +69 -0
  55. data/test/webhukhs_test.rb +111 -49
  56. metadata +173 -11
  57. data/example/.ruby-version +0 -1
  58. data/gemfiles/rails_7.1.gemfile.lock +0 -412
data/example/Gemfile.lock CHANGED
@@ -1,228 +1,347 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- munster (0.1.0)
5
- rails (~> 7.1)
4
+ webhukhs (0.7.0)
5
+ assiette (~> 0.6)
6
+ rails (>= 7.2)
7
+ state_machine_enum
6
8
 
7
9
  GEM
8
10
  remote: https://rubygems.org/
9
11
  specs:
10
- actioncable (7.1.3.3)
11
- actionpack (= 7.1.3.3)
12
- activesupport (= 7.1.3.3)
12
+ action_text-trix (2.1.19)
13
+ railties
14
+ actioncable (8.1.4)
15
+ actionpack (= 8.1.4)
16
+ activesupport (= 8.1.4)
13
17
  nio4r (~> 2.0)
14
18
  websocket-driver (>= 0.6.1)
15
19
  zeitwerk (~> 2.6)
16
- actionmailbox (7.1.3.3)
17
- actionpack (= 7.1.3.3)
18
- activejob (= 7.1.3.3)
19
- activerecord (= 7.1.3.3)
20
- activestorage (= 7.1.3.3)
21
- activesupport (= 7.1.3.3)
22
- mail (>= 2.7.1)
23
- net-imap
24
- net-pop
25
- net-smtp
26
- actionmailer (7.1.3.3)
27
- actionpack (= 7.1.3.3)
28
- actionview (= 7.1.3.3)
29
- activejob (= 7.1.3.3)
30
- activesupport (= 7.1.3.3)
31
- mail (~> 2.5, >= 2.5.4)
32
- net-imap
33
- net-pop
34
- net-smtp
20
+ actionmailbox (8.1.4)
21
+ actionpack (= 8.1.4)
22
+ activejob (= 8.1.4)
23
+ activerecord (= 8.1.4)
24
+ activestorage (= 8.1.4)
25
+ activesupport (= 8.1.4)
26
+ mail (>= 2.8.0)
27
+ actionmailer (8.1.4)
28
+ actionpack (= 8.1.4)
29
+ actionview (= 8.1.4)
30
+ activejob (= 8.1.4)
31
+ activesupport (= 8.1.4)
32
+ mail (>= 2.8.0)
35
33
  rails-dom-testing (~> 2.2)
36
- actionpack (7.1.3.3)
37
- actionview (= 7.1.3.3)
38
- activesupport (= 7.1.3.3)
34
+ actionpack (8.1.4)
35
+ actionview (= 8.1.4)
36
+ activesupport (= 8.1.4)
39
37
  nokogiri (>= 1.8.5)
40
- racc
41
38
  rack (>= 2.2.4)
42
39
  rack-session (>= 1.0.1)
43
40
  rack-test (>= 0.6.3)
44
41
  rails-dom-testing (~> 2.2)
45
42
  rails-html-sanitizer (~> 1.6)
46
- actiontext (7.1.3.3)
47
- actionpack (= 7.1.3.3)
48
- activerecord (= 7.1.3.3)
49
- activestorage (= 7.1.3.3)
50
- activesupport (= 7.1.3.3)
43
+ useragent (~> 0.16)
44
+ actiontext (8.1.4)
45
+ action_text-trix (~> 2.1.15)
46
+ actionpack (= 8.1.4)
47
+ activerecord (= 8.1.4)
48
+ activestorage (= 8.1.4)
49
+ activesupport (= 8.1.4)
51
50
  globalid (>= 0.6.0)
52
51
  nokogiri (>= 1.8.5)
53
- actionview (7.1.3.3)
54
- activesupport (= 7.1.3.3)
52
+ actionview (8.1.4)
53
+ activesupport (= 8.1.4)
55
54
  builder (~> 3.1)
56
55
  erubi (~> 1.11)
57
56
  rails-dom-testing (~> 2.2)
58
57
  rails-html-sanitizer (~> 1.6)
59
- activejob (7.1.3.3)
60
- activesupport (= 7.1.3.3)
58
+ activejob (8.1.4)
59
+ activesupport (= 8.1.4)
61
60
  globalid (>= 0.3.6)
62
- activemodel (7.1.3.3)
63
- activesupport (= 7.1.3.3)
64
- activerecord (7.1.3.3)
65
- activemodel (= 7.1.3.3)
66
- activesupport (= 7.1.3.3)
61
+ activemodel (8.1.4)
62
+ activesupport (= 8.1.4)
63
+ activerecord (8.1.4)
64
+ activemodel (= 8.1.4)
65
+ activesupport (= 8.1.4)
67
66
  timeout (>= 0.4.0)
68
- activestorage (7.1.3.3)
69
- actionpack (= 7.1.3.3)
70
- activejob (= 7.1.3.3)
71
- activerecord (= 7.1.3.3)
72
- activesupport (= 7.1.3.3)
67
+ activestorage (8.1.4)
68
+ actionpack (= 8.1.4)
69
+ activejob (= 8.1.4)
70
+ activerecord (= 8.1.4)
71
+ activesupport (= 8.1.4)
73
72
  marcel (~> 1.0)
74
- activesupport (7.1.3.3)
73
+ activesupport (8.1.4)
75
74
  base64
76
75
  bigdecimal
77
- concurrent-ruby (~> 1.0, >= 1.0.2)
76
+ concurrent-ruby (~> 1.0, >= 1.3.1)
78
77
  connection_pool (>= 2.2.5)
79
78
  drb
80
79
  i18n (>= 1.6, < 2)
80
+ json
81
+ logger (>= 1.4.2)
81
82
  minitest (>= 5.1)
82
- mutex_m
83
- tzinfo (~> 2.0)
84
- base64 (0.2.0)
85
- bigdecimal (3.1.8)
86
- builder (3.2.4)
87
- concurrent-ruby (1.2.3)
88
- connection_pool (2.4.1)
89
- crass (1.0.6)
90
- date (3.3.4)
91
- debug (1.9.2)
83
+ securerandom (>= 0.3)
84
+ tzinfo (~> 2.0, >= 2.0.5)
85
+ uri (>= 0.13.1)
86
+ assiette (0.6.1)
87
+ actionpack (>= 7.2)
88
+ base64 (0.3.0)
89
+ bigdecimal (4.1.3)
90
+ builder (3.3.0)
91
+ concurrent-ruby (1.3.8)
92
+ connection_pool (3.0.2)
93
+ crass (1.0.7)
94
+ date (3.6.0)
95
+ debug (1.11.1)
92
96
  irb (~> 1.10)
93
97
  reline (>= 0.3.8)
94
- drb (2.2.1)
95
- erubi (1.12.0)
96
- globalid (1.2.1)
98
+ drb (2.2.3)
99
+ erb (6.0.7)
100
+ erubi (1.13.1)
101
+ globalid (1.4.0)
97
102
  activesupport (>= 6.1)
98
- i18n (1.14.5)
103
+ i18n (1.15.2)
99
104
  concurrent-ruby (~> 1.0)
100
- io-console (0.7.2)
101
- irb (1.13.1)
105
+ io-console (0.9.4)
106
+ irb (1.18.0)
107
+ pp (>= 0.6.0)
108
+ prism (>= 1.3.0)
102
109
  rdoc (>= 4.0.0)
103
110
  reline (>= 0.4.2)
104
- loofah (2.22.0)
111
+ json (3.1.0)
112
+ logger (1.7.0)
113
+ loofah (2.25.2)
105
114
  crass (~> 1.0.2)
106
115
  nokogiri (>= 1.12.0)
107
- mail (2.8.1)
116
+ mail (2.9.1)
117
+ logger
108
118
  mini_mime (>= 0.1.1)
109
119
  net-imap
110
120
  net-pop
111
121
  net-smtp
112
- marcel (1.0.4)
122
+ marcel (1.2.1)
113
123
  mini_mime (1.1.5)
114
- minitest (5.22.3)
115
- mutex_m (0.2.0)
116
- net-imap (0.4.11)
124
+ minitest (6.0.6)
125
+ drb (~> 2.0)
126
+ prism (~> 1.5)
127
+ net-imap (0.6.8)
117
128
  date
118
129
  net-protocol
119
130
  net-pop (0.1.2)
120
131
  net-protocol
121
- net-protocol (0.2.2)
132
+ net-protocol (0.4.0)
122
133
  timeout
123
- net-smtp (0.5.0)
134
+ net-smtp (0.5.2)
124
135
  net-protocol
125
- nio4r (2.7.3)
126
- nokogiri (1.16.5-aarch64-linux)
136
+ nio4r (2.7.5)
137
+ nokogiri (1.19.4-aarch64-linux-gnu)
138
+ racc (~> 1.4)
139
+ nokogiri (1.19.4-aarch64-linux-musl)
127
140
  racc (~> 1.4)
128
- nokogiri (1.16.5-arm-linux)
141
+ nokogiri (1.19.4-arm-linux-gnu)
129
142
  racc (~> 1.4)
130
- nokogiri (1.16.5-arm64-darwin)
143
+ nokogiri (1.19.4-arm-linux-musl)
131
144
  racc (~> 1.4)
132
- nokogiri (1.16.5-x86-linux)
145
+ nokogiri (1.19.4-arm64-darwin)
133
146
  racc (~> 1.4)
134
- nokogiri (1.16.5-x86_64-darwin)
147
+ nokogiri (1.19.4-x86_64-darwin)
135
148
  racc (~> 1.4)
136
- nokogiri (1.16.5-x86_64-linux)
149
+ nokogiri (1.19.4-x86_64-linux-gnu)
137
150
  racc (~> 1.4)
138
- propshaft (0.8.0)
151
+ nokogiri (1.19.4-x86_64-linux-musl)
152
+ racc (~> 1.4)
153
+ pp (0.6.4)
154
+ prettyprint
155
+ prettyprint (0.2.1)
156
+ prism (1.9.0)
157
+ propshaft (1.3.2)
139
158
  actionpack (>= 7.0.0)
140
159
  activesupport (>= 7.0.0)
141
160
  rack
142
- railties (>= 7.0.0)
143
- psych (5.1.2)
144
- stringio
145
- puma (5.6.8)
161
+ puma (8.0.2)
146
162
  nio4r (~> 2.0)
147
- racc (1.7.3)
148
- rack (2.2.9)
149
- rack-session (1.0.2)
150
- rack (< 3)
151
- rack-test (2.1.0)
163
+ racc (1.8.1)
164
+ rack (3.2.7)
165
+ rack-session (2.1.2)
166
+ base64 (>= 0.1.0)
167
+ rack (>= 3.0.0)
168
+ rack-test (2.2.0)
152
169
  rack (>= 1.3)
153
- rackup (1.0.0)
154
- rack (< 3)
155
- webrick
156
- rails (7.1.3.3)
157
- actioncable (= 7.1.3.3)
158
- actionmailbox (= 7.1.3.3)
159
- actionmailer (= 7.1.3.3)
160
- actionpack (= 7.1.3.3)
161
- actiontext (= 7.1.3.3)
162
- actionview (= 7.1.3.3)
163
- activejob (= 7.1.3.3)
164
- activemodel (= 7.1.3.3)
165
- activerecord (= 7.1.3.3)
166
- activestorage (= 7.1.3.3)
167
- activesupport (= 7.1.3.3)
170
+ rackup (2.3.1)
171
+ rack (>= 3)
172
+ rails (8.1.4)
173
+ actioncable (= 8.1.4)
174
+ actionmailbox (= 8.1.4)
175
+ actionmailer (= 8.1.4)
176
+ actionpack (= 8.1.4)
177
+ actiontext (= 8.1.4)
178
+ actionview (= 8.1.4)
179
+ activejob (= 8.1.4)
180
+ activemodel (= 8.1.4)
181
+ activerecord (= 8.1.4)
182
+ activestorage (= 8.1.4)
183
+ activesupport (= 8.1.4)
168
184
  bundler (>= 1.15.0)
169
- railties (= 7.1.3.3)
170
- rails-dom-testing (2.2.0)
185
+ railties (= 8.1.4)
186
+ rails-dom-testing (2.3.0)
171
187
  activesupport (>= 5.0.0)
172
188
  minitest
173
189
  nokogiri (>= 1.6)
174
- rails-html-sanitizer (1.6.0)
175
- loofah (~> 2.21)
176
- nokogiri (~> 1.14)
177
- railties (7.1.3.3)
178
- actionpack (= 7.1.3.3)
179
- activesupport (= 7.1.3.3)
180
- irb
190
+ rails-html-sanitizer (1.7.1)
191
+ loofah (~> 2.25, >= 2.25.2)
192
+ nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
193
+ railties (8.1.4)
194
+ actionpack (= 8.1.4)
195
+ activesupport (= 8.1.4)
196
+ irb (~> 1.13)
181
197
  rackup (>= 1.0.0)
182
198
  rake (>= 12.2)
183
199
  thor (~> 1.0, >= 1.2.2)
200
+ tsort (>= 0.2)
184
201
  zeitwerk (~> 2.6)
185
- rake (13.2.1)
186
- rdoc (6.6.3.1)
187
- psych (>= 4.0.0)
188
- reline (0.5.7)
202
+ rake (13.4.2)
203
+ rbs (4.2.0)
204
+ logger
205
+ prism (>= 1.6.0)
206
+ tsort
207
+ rdoc (8.1.0)
208
+ erb
209
+ prism (>= 1.6.0)
210
+ rbs (>= 4.0.0)
211
+ tsort
212
+ reline (0.7.0)
189
213
  io-console (~> 0.5)
190
- sqlite3 (1.7.3-aarch64-linux)
191
- sqlite3 (1.7.3-arm-linux)
192
- sqlite3 (1.7.3-arm64-darwin)
193
- sqlite3 (1.7.3-x86-linux)
194
- sqlite3 (1.7.3-x86_64-darwin)
195
- sqlite3 (1.7.3-x86_64-linux)
196
- stringio (3.1.0)
197
- thor (1.3.1)
198
- timeout (0.4.1)
214
+ securerandom (0.4.1)
215
+ sqlite3 (2.10.1-aarch64-linux-gnu)
216
+ sqlite3 (2.10.1-aarch64-linux-musl)
217
+ sqlite3 (2.10.1-arm-linux-gnu)
218
+ sqlite3 (2.10.1-arm-linux-musl)
219
+ sqlite3 (2.10.1-arm64-darwin)
220
+ sqlite3 (2.10.1-x86_64-darwin)
221
+ sqlite3 (2.10.1-x86_64-linux-gnu)
222
+ sqlite3 (2.10.1-x86_64-linux-musl)
223
+ state_machine_enum (0.1.4)
224
+ activesupport (>= 7.0)
225
+ thor (1.5.0)
226
+ timeout (0.6.1)
227
+ tsort (0.2.0)
199
228
  tzinfo (2.0.6)
200
229
  concurrent-ruby (~> 1.0)
201
- webrick (1.8.1)
202
- websocket-driver (0.7.6)
230
+ uri (1.1.2)
231
+ useragent (0.16.11)
232
+ websocket-driver (0.8.2)
233
+ base64
203
234
  websocket-extensions (>= 0.1.0)
204
235
  websocket-extensions (0.1.5)
205
- zeitwerk (2.6.14)
236
+ zeitwerk (2.8.3)
206
237
 
207
238
  PLATFORMS
208
- aarch64-linux
209
- arm-linux
239
+ aarch64-linux-gnu
240
+ aarch64-linux-musl
241
+ arm-linux-gnu
242
+ arm-linux-musl
210
243
  arm64-darwin
211
- x86-linux
212
244
  x86_64-darwin
213
- x86_64-linux
245
+ x86_64-linux-gnu
246
+ x86_64-linux-musl
214
247
 
215
248
  DEPENDENCIES
216
249
  debug
217
- munster!
218
250
  propshaft
219
- puma (~> 5.0)
220
- rails (>= 7.0.8.1)
221
- sqlite3 (~> 1.4)
251
+ puma (>= 6.0)
252
+ rails (>= 7.2)
253
+ sqlite3 (>= 2.1)
222
254
  tzinfo-data
255
+ webhukhs!
223
256
 
224
- RUBY VERSION
225
- ruby 3.2.2p53
257
+ CHECKSUMS
258
+ action_text-trix (2.1.19) sha256=7012f59421009cf284aa651294896414d653a61a2417c9b8714c8476d2f74009
259
+ actioncable (8.1.4) sha256=cfcd72f8c861e01ccdc96d772ad8c5ad6ed0ea7c571aef81a794b6027eaa7f11
260
+ actionmailbox (8.1.4) sha256=9c4525e577ebb671ce558f3ea78b8a634f64e56a0e6e8d105b28b873793a06eb
261
+ actionmailer (8.1.4) sha256=f82d95d6762ae46ea38f221d3363639266af4f8e56d50e2bd367558674baf093
262
+ actionpack (8.1.4) sha256=245493cc51be195a7645e6fc184880fa7e5b32ff1a08e053ee31f58c76e30ea4
263
+ actiontext (8.1.4) sha256=33ee99bea7da6af911fc7d98b17013a8e1ec62aa01b20b20e9a5366f40dbf644
264
+ actionview (8.1.4) sha256=eff1efd07c4d969abad288322b423bcb67fdbab5e324c91ca37352b80f226076
265
+ activejob (8.1.4) sha256=4ed5b2ed8d4cc5c8f5f09becfef8346f202a4884eee0c8c73cae5ac378824099
266
+ activemodel (8.1.4) sha256=9a0906c127bd118aa5f06157db12b8f750da83dccee72db2f658547a0ae7a0e8
267
+ activerecord (8.1.4) sha256=3b4957ea7f246c9231bd7faa909312eac03a9101aaf87977b6c52733ff00b04f
268
+ activestorage (8.1.4) sha256=f4956f3ec9ee63e5e0b332b57c877cb627f82b56f4cc902279310d2aa285c7a8
269
+ activesupport (8.1.4) sha256=891dd3fe43c4fc8391934b237b1189bb1f661c932a84a840043db9d46a4e80df
270
+ assiette (0.6.1) sha256=e0508d01d049c9f494fb87459b6a897fbb751fd5106714ee218bb45eaeaa94d0
271
+ base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b
272
+ bigdecimal (4.1.3) sha256=61ebe1e5e559bdc3cc6f2c0ee7f427321fc838f59611c294356eb04d6e21cf66
273
+ builder (3.3.0) sha256=497918d2f9dca528fdca4b88d84e4ef4387256d984b8154e9d5d3fe5a9c8835f
274
+ bundler (4.0.18) sha256=02d9a17429de1847b4e0c9f27a9ee4b20c0a74c0a641b4e77195d6019e3618ac
275
+ concurrent-ruby (1.3.8) sha256=b2f1be836e968ccc78ccfce277ea79c72a88633f22306782c16ff23fb415d1e1
276
+ connection_pool (3.0.2) sha256=33fff5ba71a12d2aa26cb72b1db8bba2a1a01823559fb01d29eb74c286e62e0a
277
+ crass (1.0.7) sha256=94868719948664c89ddcaf0a37c65048413dfcb1c869470a5f7a7ceb5390b295
278
+ date (3.6.0) sha256=18ac945c4e24ebd93534f8eab8c2fd8c5604b3e977105b3798d62a1e8d27b580
279
+ debug (1.11.1) sha256=2e0b0ac6119f2207a6f8ac7d4a73ca8eb4e440f64da0a3136c30343146e952b6
280
+ drb (2.2.3) sha256=0b00d6fdb50995fe4a45dea13663493c841112e4068656854646f418fda13373
281
+ erb (6.0.7) sha256=c5ca6dc25b0ef974a44dc8f59fe847577122483b1968a38dec305c60bf91ee92
282
+ erubi (1.13.1) sha256=a082103b0885dbc5ecf1172fede897f9ebdb745a4b97a5e8dc63953db1ee4ad9
283
+ globalid (1.4.0) sha256=037f12fbf1d9d7a014d501c2d5c77356fd4ddd96d7a7991d6700bba96706f427
284
+ i18n (1.15.2) sha256=00f9eb62412fe593b2a65a97daa75300d37abb8f7202ec748e94b6d46a9dd1b5
285
+ io-console (0.9.4) sha256=a403304f32928ee85e56d457b4612ca43f2703b561a3258844992bd24085fbb1
286
+ irb (1.18.0) sha256=de9454a0703a54704b9811a5ef31a60c86949fbf4013fcf244fabc7c775248e3
287
+ json (3.1.0) sha256=3ce7ccf8fde58960177a3a756c31f292a4c1e1dedee884547096a5b0604e3bd8
288
+ logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203
289
+ loofah (2.25.2) sha256=2007f746959ac65552456e04b433e83deb22759ab38c838b4445c70e43425918
290
+ mail (2.9.1) sha256=06574eca475253d6c18145dd70af80d0eb970182d55053497c5f4d797ea160e8
291
+ marcel (1.2.1) sha256=1678e9360e32f9eafa917c80029e2f6d10b2715c66a4b87b6d0da9b9cd1f859f
292
+ mini_mime (1.1.5) sha256=8681b7e2e4215f2a159f9400b5816d85e9d8c6c6b491e96a12797e798f8bccef
293
+ minitest (6.0.6) sha256=153ea36d1d987a62942382b61075745042a2b3123b1cd48f4c3675af9cc7d6f1
294
+ net-imap (0.6.8) sha256=eb30bb62227b64a3af6b518b04b2375113d69f68f15de59b0193b07d98acf6d9
295
+ net-pop (0.1.2) sha256=848b4e982013c15b2f0382792268763b748cce91c9e91e36b0f27ed26420dff3
296
+ net-protocol (0.4.0) sha256=f9f90c8c6f64794a45160bf422177a336db12809de3beeeaa26b88fcd2e8c853
297
+ net-smtp (0.5.2) sha256=35103cc04d6b2d94632f9928ede07483c24b70b9c0db1f231fea43909b678f3c
298
+ nio4r (2.7.5) sha256=6c90168e48fb5f8e768419c93abb94ba2b892a1d0602cb06eef16d8b7df1dca1
299
+ nokogiri (1.19.4-aarch64-linux-gnu) sha256=1269fb644a6de405057a53dd5c762b1209b43ca7424f839454d3dbc677c31a8f
300
+ nokogiri (1.19.4-aarch64-linux-musl) sha256=35c65b9ce72b3bb03207bdbe7067915019dc18c1b9b59139684bd6690fdd01af
301
+ nokogiri (1.19.4-arm-linux-gnu) sha256=a301313e38bb065d68239e79734bcd6f56fb6efaacebde29e9abf2a4735340ca
302
+ nokogiri (1.19.4-arm-linux-musl) sha256=588923c101bcfa78869734d247d25b598674323e7f22474fc468f6e5647311eb
303
+ nokogiri (1.19.4-arm64-darwin) sha256=a46db9853286e6597b36ebc6953817d15acf3a299583eb3f89fdc6f91dd63527
304
+ nokogiri (1.19.4-x86_64-darwin) sha256=7fd17057d3e1f00e9954a74b3cd76595d3d4a5ef233b7ed9599047c204f70551
305
+ nokogiri (1.19.4-x86_64-linux-gnu) sha256=379fae440b28915e3f19d752ce2dcf8465ed2b2fbefd2a7ca0dd497bc981a06a
306
+ nokogiri (1.19.4-x86_64-linux-musl) sha256=17dfb7c1fa194ae02fbf7c51a7afc8d278045ab3fdacfd86f91d02d7b274470b
307
+ pp (0.6.4) sha256=dfcb0fce700c41456265922884f9fe195d7fbb0674a3578e6c0f69588e82b570
308
+ prettyprint (0.2.1) sha256=d555d57ea6d7cf001d4774b693546a6bd88bec1e778ddffb5c60b68ceec4b7d4
309
+ prism (1.9.0) sha256=7b530c6a9f92c24300014919c9dcbc055bf4cdf51ec30aed099b06cd6674ef85
310
+ propshaft (1.3.2) sha256=1d56a3e56a92c21bfc29caf07406b5386b00d4c47ddf357cf989a5a234b1389e
311
+ puma (8.0.2) sha256=c8ed871dfbbe66448ea9ffd46692342d9804d4071522b52b5331b7b6e7b686fb
312
+ racc (1.8.1) sha256=4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f
313
+ rack (3.2.7) sha256=93e13e1c24f93556671d85d2d79fa228c3485815c50d7e2f265b5330c6528fb7
314
+ rack-session (2.1.2) sha256=595434f8c0c3473ae7d7ac56ecda6cc6dfd9d37c0b2b5255330aa1576967ffe8
315
+ rack-test (2.2.0) sha256=005a36692c306ac0b4a9350355ee080fd09ddef1148a5f8b2ac636c720f5c463
316
+ rackup (2.3.1) sha256=6c79c26753778e90983761d677a48937ee3192b3ffef6bc963c0950f94688868
317
+ rails (8.1.4) sha256=5f3ecdf9a2a3b79b2e31b8fee3b64a00f7284d76e5631f87d0e58e665911a33b
318
+ rails-dom-testing (2.3.0) sha256=8acc7953a7b911ca44588bf08737bc16719f431a1cc3091a292bca7317925c1d
319
+ rails-html-sanitizer (1.7.1) sha256=e797a7c9b01e567307e317c576b49ab4168017e63eea4dba9ce3cb587e2f22c2
320
+ railties (8.1.4) sha256=b5e7a8e8984e33114d68af62227971960aae1e6c02bd7c9d826ffad97fff583c
321
+ rake (13.4.2) sha256=cb825b2bd5f1f8e91ca37bddb4b9aaf345551b4731da62949be002fa89283701
322
+ rbs (4.2.0) sha256=51f7b886dcc05bc09e10b901daa6a81829f6adc03101d6ca9ea4aac6103e0674
323
+ rdoc (8.1.0) sha256=befc37880a5cfd36dcb176c748b5fd5ee39dd3536a75e81824e4972ce230f60a
324
+ reline (0.7.0) sha256=5b012d8e55dbf9d450f12bde2cf7d15ff546ae80b3f8f3b30e570d431815583d
325
+ securerandom (0.4.1) sha256=cc5193d414a4341b6e225f0cb4446aceca8e50d5e1888743fac16987638ea0b1
326
+ sqlite3 (2.10.1-aarch64-linux-gnu) sha256=48390cc2b809acd1280f5c9daaf3c2013833adb8a5ece9b0634f708651080ccd
327
+ sqlite3 (2.10.1-aarch64-linux-musl) sha256=db1bcddf98e4eeea80ca896f56aa3f9468364fa1ee8e042ddc6b628b5092fabb
328
+ sqlite3 (2.10.1-arm-linux-gnu) sha256=34a67a3fe84f705a0fad6f7aa4541579300644b9acdf414797e59929a6e3528b
329
+ sqlite3 (2.10.1-arm-linux-musl) sha256=e317adb8979b57dafd999b54410b4050296aa5d00caa664e3f75d876e2ae90e8
330
+ sqlite3 (2.10.1-arm64-darwin) sha256=45f74dad0a8ee57ae5fadfac39bf160d1f09fb0484a442223310d869cd957d92
331
+ sqlite3 (2.10.1-x86_64-darwin) sha256=00d1cd2e8ecff5ad9fffa0c97de59d4f85c5fc54eada2587d53ca0bd933b7a5d
332
+ sqlite3 (2.10.1-x86_64-linux-gnu) sha256=661ecede31e23a412059cd8c684ed84e332f64f167e4a90902cf99e8ea2c8718
333
+ sqlite3 (2.10.1-x86_64-linux-musl) sha256=67c7c5443a930157b4e148f0f4cb9ab998ee7ecfa8ce56879a6b56d1d742b2be
334
+ state_machine_enum (0.1.4) sha256=959d72af8d00e31b995a447738716e76667aadfb3612c17f59f566c083b31aac
335
+ thor (1.5.0) sha256=e3a9e55fe857e44859ce104a84675ab6e8cd59c650a49106a05f55f136425e73
336
+ timeout (0.6.1) sha256=78f57368a7e7bbadec56971f78a3f5ecbcfb59b7fcbb0a3ed6ddc08a5094accb
337
+ tsort (0.2.0) sha256=9650a793f6859a43b6641671278f79cfead60ac714148aabe4e3f0060480089f
338
+ tzinfo (2.0.6) sha256=8daf828cc77bcf7d63b0e3bdb6caa47e2272dcfaf4fbfe46f8c3a9df087a829b
339
+ uri (1.1.2) sha256=89292e98eabbef6248b0a0ed5e7e398e152f83f17560023a6d94a7f492b169fb
340
+ useragent (0.16.11) sha256=700e6413ad4bb954bb63547fa098dddf7b0ebe75b40cc6f93b8d54255b173844
341
+ webhukhs (0.7.0)
342
+ websocket-driver (0.8.2) sha256=97c556b019bf3410b4961002ac501621e9322d3f8a7bc02161a09301cc4c4146
343
+ websocket-extensions (0.1.5) sha256=1c6ba63092cda343eb53fc657110c71c754c56484aad42578495227d717a8241
344
+ zeitwerk (2.8.3) sha256=2c85125a8467ce069e20123d1e709a08955c9d29c118c25b46b7b7fafdbb92e5
226
345
 
227
346
  BUNDLED WITH
228
- 2.5.6
347
+ 4.0.18
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Accepts anything and takes the event id from the payload, when there is one
4
+ class AcmeHandler < Webhukhs::BaseHandler
5
+ def process(received_webhook)
6
+ Rails.logger.info { "AcmeHandler processed #{received_webhook.body.bytesize} bytes" }
7
+ end
8
+
9
+ def extract_event_id_from_request(action_dispatch_request)
10
+ JSON.parse(action_dispatch_request.body.read).fetch("id")
11
+ rescue JSON::ParserError, KeyError, TypeError
12
+ super
13
+ ensure
14
+ action_dispatch_request.body.rewind
15
+ end
16
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Fails to process every webhook, and ends up in `error`
4
+ class FlakyHandler < Webhukhs::BaseHandler
5
+ def process(received_webhook)
6
+ raise "Upstream said no to #{received_webhook.handler_event_id}"
7
+ end
8
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Refuses anything without the right signature header, and ends up in `failed_validation`
4
+ class SignedHandler < Webhukhs::BaseHandler
5
+ SECRET = "example-secret"
6
+
7
+ def valid?(action_dispatch_request)
8
+ action_dispatch_request.headers["X-Signature"] == SECRET
9
+ end
10
+ end
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../../app/webhooks/webhook_test_handler"
4
-
5
3
  Webhukhs.configure do |config|
6
4
  config.active_handlers = {
7
- "test-handler" => "WebhookTestHandler"
5
+ "test-handler" => "WebhookTestHandler",
6
+ "acme" => "AcmeHandler",
7
+ "signed" => "SignedHandler",
8
+ "flaky" => "FlakyHandler"
8
9
  }
9
10
  end
@@ -2,4 +2,7 @@
2
2
 
3
3
  Rails.application.routes.draw do
4
4
  mount Webhukhs::Engine, at: "/webhooks", as: "webhooks"
5
+ # In a real app this goes behind authentication - see the README
6
+ mount Webhukhs::Admin::Engine, at: "/admin/webhukhs"
7
+ root to: redirect("/admin/webhukhs")
5
8
  end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddHeadersToWebhukhsWebhooks < ActiveRecord::Migration[7.0]
4
+ def change
5
+ add_column :received_webhooks, :request_headers, :json, null: true
6
+ end
7
+ end
data/example/db/schema.rb CHANGED
@@ -10,7 +10,7 @@
10
10
  #
11
11
  # It's strongly recommended that you check this file into your version control system.
12
12
 
13
- ActiveRecord::Schema[7.0].define(version: 2024_05_23_125859) do
13
+ ActiveRecord::Schema[8.1].define(version: 2024_06_01_000000) do
14
14
  create_table "received_webhooks", force: :cascade do |t|
15
15
  t.string "handler_event_id", null: false
16
16
  t.string "handler_module_name", null: false
@@ -18,6 +18,7 @@ ActiveRecord::Schema[7.0].define(version: 2024_05_23_125859) do
18
18
  t.binary "body", null: false
19
19
  t.datetime "created_at", null: false
20
20
  t.datetime "updated_at", null: false
21
+ t.json "request_headers"
21
22
  t.index ["handler_module_name", "handler_event_id"], name: "webhook_dedup_idx", unique: true
22
23
  t.index ["status"], name: "index_received_webhooks_on_status"
23
24
  end
data/example/db/seeds.rb CHANGED
@@ -1,9 +1,73 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # This file should contain all the record creation needed to seed the database with its default values.
4
- # The data can then be loaded with the bin/rails db:seed command (or created alongside the database with db:setup).
5
- #
6
- # Examples:
7
- #
8
- # movies = Movie.create([{ name: "Star Wars" }, { name: "Lord of the Rings" }])
9
- # Character.create(name: "Luke", movie: movies.first)
3
+ # A spread of webhooks to look at: every status, JSON and not, and enough rows to paginate.
4
+ # insert_all, so that the status callbacks do not enqueue (and process) anything
5
+
6
+ def headers_for(service_id, content_type)
7
+ {
8
+ "CONTENT_TYPE" => content_type,
9
+ "HTTP_HOST" => "localhost:3000",
10
+ "HTTP_USER_AGENT" => "#{service_id.capitalize}-Webhooks/2.1",
11
+ "HTTP_X_REQUEST_ID" => SecureRandom.uuid,
12
+ "REMOTE_ADDR" => "203.0.113.7",
13
+ "REQUEST_METHOD" => "POST",
14
+ "action_dispatch.request.path_parameters" => {"service_id" => service_id}
15
+ }
16
+ end
17
+
18
+ handlers = {"acme" => "AcmeHandler", "signed" => "SignedHandler", "flaky" => "FlakyHandler"}
19
+ statuses = %w[processed processed processed processed received processing skipped error failed_validation]
20
+ events = %w[invoice.paid invoice.created customer.updated payout.failed charge.refunded]
21
+
22
+ rows = 130.times.map do |i|
23
+ service_id = handlers.keys[i % handlers.length]
24
+ event_id = "evt_#{SecureRandom.alphanumeric(24)}"
25
+ received_at = (i * 37).minutes.ago
26
+ body = {
27
+ id: event_id,
28
+ type: events[i % events.length],
29
+ created: received_at.to_i,
30
+ livemode: false,
31
+ data: {
32
+ object: {
33
+ id: "in_#{SecureRandom.alphanumeric(14)}",
34
+ amount_due: rand(100..90_000),
35
+ currency: "eur",
36
+ customer: {id: "cus_#{SecureRandom.alphanumeric(14)}", email: "customer#{i}@example.com"},
37
+ lines: Array.new(i % 3 + 1) { |line| {description: "Seat #{line + 1}", quantity: 1, unit_amount: 1_200} }
38
+ }
39
+ }
40
+ }.to_json
41
+
42
+ {
43
+ handler_module_name: handlers.fetch(service_id),
44
+ handler_event_id: event_id,
45
+ status: statuses[i % statuses.length],
46
+ body: body,
47
+ request_headers: headers_for(service_id, "application/json"),
48
+ created_at: received_at,
49
+ updated_at: received_at + rand(1..90).seconds
50
+ }
51
+ end
52
+
53
+ # The bodies that are not JSON at all
54
+ odd_bodies = {
55
+ "form-encoded" => ["application/x-www-form-urlencoded", "event=invoice.paid&id=42&amount=12.50&currency=EUR"],
56
+ "xml" => ["application/xml", %(<?xml version="1.0"?>\n<notification><event>payment</event><id>42</id></notification>)],
57
+ "not-utf8" => ["application/octet-stream", "caf\xE9 au lait - latin-1, not UTF-8".b],
58
+ "truncated-json" => ["application/json", '{"id": "evt_cut_short", "type": "invoice.paid", "data": {"obj']
59
+ }
60
+ odd_bodies.each_with_index do |(name, (content_type, body)), i|
61
+ rows << {
62
+ handler_module_name: "AcmeHandler",
63
+ handler_event_id: "odd-#{name}",
64
+ status: "failed_validation",
65
+ body: body,
66
+ request_headers: headers_for("acme", content_type),
67
+ created_at: (i + 1).minutes.ago,
68
+ updated_at: (i + 1).minutes.ago
69
+ }
70
+ end
71
+
72
+ Webhukhs::ReceivedWebhook.insert_all(rows)
73
+ puts "Seeded #{rows.length} webhooks"