signalwire 2.3.4 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +10 -0
- data/.github/workflows/ci.yml +25 -0
- data/CHANGELOG.md +8 -0
- data/README.md +4 -3
- data/lib/rack/signalwire_webhook_authentication.rb +51 -0
- data/lib/signalwire/sdk.rb +1 -0
- data/lib/signalwire/version.rb +1 -1
- data/lib/signalwire/webhook/validate_request.rb +56 -0
- data/signalwire.gemspec +4 -3
- metadata +31 -14
- data/.drone.yml +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: df430132083360896fd829e7137d80fa718d4f8fb7870c24c7b334d802f8de61
|
4
|
+
data.tar.gz: ec2b8b710595d900db60988bc5c28873b932bc965bbe5c82172a38b198478c52
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 11b434f415f50072036be156b1c2ba5926851d6a7e408aa0c1c05f7755143fd34b7b5eeb309fe43f53a5764961d45d335531f2dd40a79b94a76a35e7582579af
|
7
|
+
data.tar.gz: 847521247be584ebcfa30ae4131b58f475468e412280ca8f17bd01fffa278e78712f7a706fd67756f4311e045eece5da72f2954e51b3b2ffa290fd90e3c24974
|
@@ -0,0 +1,25 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ "main" ]
|
6
|
+
pull_request:
|
7
|
+
branches: [ "main" ]
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
test:
|
11
|
+
name: Test
|
12
|
+
runs-on: ubuntu-latest
|
13
|
+
strategy:
|
14
|
+
fail-fast: false
|
15
|
+
matrix:
|
16
|
+
ruby-version: ['2.6', '2.7', '3.0', '3.1', '3.2']
|
17
|
+
steps:
|
18
|
+
- uses: actions/checkout@v4
|
19
|
+
- name: Set up Ruby
|
20
|
+
uses: ruby/setup-ruby@v1
|
21
|
+
with:
|
22
|
+
ruby-version: ${{ matrix.ruby-version }}
|
23
|
+
bundler-cache: true
|
24
|
+
- name: Run tests
|
25
|
+
run: bundle exec rspec
|
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,14 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
|
5
5
|
|
6
6
|
## [Unreleased]
|
7
7
|
|
8
|
+
## [2.5.0] - 2023-10-26
|
9
|
+
### Added
|
10
|
+
- Add Middleware `SignalwireWebhookAuthentication`
|
11
|
+
|
12
|
+
## [2.4.0] - 2023-10-13
|
13
|
+
### Added
|
14
|
+
- Add Webhook `ValidateRequest`
|
15
|
+
|
8
16
|
## [2.3.4] - 2020-09-09
|
9
17
|
### Fixed
|
10
18
|
- Correctly ignore non-call events and clear handlers on call end
|
data/README.md
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
# SignalWire Ruby
|
2
2
|
|
3
3
|
|
4
|
-
[![
|
4
|
+
[![CI](https://github.com/signalwire/signalwire-ruby/actions/workflows/ci.yml/badge.svg)](https://github.com/signalwire/signalwire-ruby/actions/workflows/ci.yml)
|
5
|
+
[![Gem Version](https://badge.fury.io/rb/signalwire.svg)](https://badge.fury.io/rb/signalwire)
|
5
6
|
|
6
7
|
The Relay SDK for Ruby enables Ruby developers to connect and use SignalWire's Relay APIs within their own Ruby code. Our Relay SDK allows developers to build or add robust and innovative communication services to their applications.
|
7
8
|
|
@@ -34,5 +35,5 @@ Relay SDK forRuby follows Semantic Versioning 2.0 as defined at <http://semver.o
|
|
34
35
|
|
35
36
|
## License
|
36
37
|
|
37
|
-
Relay SDK for Ruby is copyright © 2018-
|
38
|
-
[SignalWire](http://signalwire.com). It is free software, and may be redistributed under the terms specified in the [MIT-LICENSE](https://github.com//signalwire/signalwire-ruby/blob/master/LICENSE) file.
|
38
|
+
Relay SDK for Ruby is copyright © 2018-2023
|
39
|
+
[SignalWire](http://signalwire.com). It is free software, and may be redistributed under the terms specified in the [MIT-LICENSE](https://github.com//signalwire/signalwire-ruby/blob/master/LICENSE) file.
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rack/media_type'
|
4
|
+
|
5
|
+
module Rack
|
6
|
+
class SignalwireWebhookAuthentication
|
7
|
+
FORM_URLENCODED_MEDIA_TYPE = Rack::MediaType.type('application/x-www-form-urlencoded')
|
8
|
+
|
9
|
+
def initialize(app, private_key, *paths, &private_key_lookup)
|
10
|
+
@app = app
|
11
|
+
@private_key = private_key
|
12
|
+
define_singleton_method(:get_private_key, private_key_lookup) if block_given?
|
13
|
+
@path_regex = Regexp.union(paths)
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(env)
|
17
|
+
return @app.call(env) unless env['PATH_INFO'].match(@path_regex)
|
18
|
+
request = Rack::Request.new(env)
|
19
|
+
original_url = request.url
|
20
|
+
params = extract_params!(request)
|
21
|
+
private_key = @private_key || get_private_key(params['AccountSid'])
|
22
|
+
validator = Signalwire::Webhook::ValidateRequest.new(private_key)
|
23
|
+
signature = env['HTTP_X_SIGNALWIRE_SIGNATURE'] || env['HTTP_X_TWILIO_SIGNATURE'] || ''
|
24
|
+
if validator.validate(original_url, params, signature)
|
25
|
+
@app.call(env)
|
26
|
+
else
|
27
|
+
[
|
28
|
+
403,
|
29
|
+
{ 'Content-Type' => 'text/plain' },
|
30
|
+
['Signalwire Request Validation Failed.']
|
31
|
+
]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def extract_params!(request)
|
36
|
+
return {} unless request.post?
|
37
|
+
|
38
|
+
if request.media_type == FORM_URLENCODED_MEDIA_TYPE
|
39
|
+
request.POST
|
40
|
+
else
|
41
|
+
request.body.rewind
|
42
|
+
body = request.body.read
|
43
|
+
request.body.rewind
|
44
|
+
body
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private :extract_params!
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
data/lib/signalwire/sdk.rb
CHANGED
data/lib/signalwire/version.rb
CHANGED
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'openssl'
|
4
|
+
|
5
|
+
module Signalwire::Webhook
|
6
|
+
class ValidateRequest
|
7
|
+
attr_reader :private_key
|
8
|
+
|
9
|
+
def initialize(private_key)
|
10
|
+
@private_key = private_key
|
11
|
+
raise ArgumentError, 'Private key is required' if @private_key.nil?
|
12
|
+
end
|
13
|
+
|
14
|
+
def validate(url, raw_body, header)
|
15
|
+
return false if header.nil? || url.nil?
|
16
|
+
|
17
|
+
# compatibility validation for POST parameters of x-www-form-urlencoded requests
|
18
|
+
if raw_body.is_a?(Hash)
|
19
|
+
return validate_with_compatibility_api(url, raw_body, header)
|
20
|
+
end
|
21
|
+
|
22
|
+
# relay json validation
|
23
|
+
payload = url + raw_body
|
24
|
+
expected_signature = compute_signature(payload)
|
25
|
+
valid = secure_compare(expected_signature, header)
|
26
|
+
|
27
|
+
return true if valid
|
28
|
+
|
29
|
+
# fallback compatibilty json validation
|
30
|
+
validate_with_compatibility_api(url, raw_body, header)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def validate_with_compatibility_api(url, params, signature)
|
36
|
+
validator = Twilio::Security::RequestValidator.new(private_key)
|
37
|
+
validator.validate(url, params, signature)
|
38
|
+
end
|
39
|
+
|
40
|
+
def compute_signature(payload)
|
41
|
+
OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha1'), private_key, payload)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Constant time string comparison, from ActiveSupport
|
45
|
+
def secure_compare(a, b)
|
46
|
+
return false if a.nil? || b.nil?
|
47
|
+
return false unless a.bytesize == b.bytesize
|
48
|
+
|
49
|
+
l = a.unpack "C#{a.bytesize}"
|
50
|
+
|
51
|
+
res = 0
|
52
|
+
b.each_byte { |byte| res |= byte ^ l.shift }
|
53
|
+
res == 0
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/signalwire.gemspec
CHANGED
@@ -27,17 +27,18 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.add_development_dependency 'bundler', '~> 2.1'
|
28
28
|
spec.add_development_dependency 'bundler-audit', '~> 0.6'
|
29
29
|
spec.add_development_dependency 'guard-rspec', '~> 4.7'
|
30
|
-
spec.add_development_dependency '
|
30
|
+
spec.add_development_dependency 'rack', '~> 2.0'
|
31
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
31
32
|
spec.add_development_dependency 'rdoc', '~> 6.1'
|
32
33
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
33
34
|
spec.add_development_dependency 'rubocop', '~> 0.67'
|
34
35
|
spec.add_development_dependency 'ruby-prof', '~> 0.17'
|
35
36
|
spec.add_development_dependency 'simplecov', '~> 0.16'
|
36
|
-
spec.add_development_dependency 'vcr', '~>
|
37
|
+
spec.add_development_dependency 'vcr', '~> 5.0'
|
37
38
|
spec.add_development_dependency 'webmock', '~> 3.5'
|
38
39
|
|
39
40
|
spec.add_dependency 'twilio-ruby', '~> 5.0'
|
40
|
-
spec.add_dependency 'faye-websocket', '~> 0.
|
41
|
+
spec.add_dependency 'faye-websocket', '~> 0.11'
|
41
42
|
spec.add_dependency 'concurrent-ruby', '~> 1.1'
|
42
43
|
spec.add_dependency 'has-guarded-handlers', '~> 1.6.3'
|
43
44
|
spec.add_dependency 'logger', '~> 1.3'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: signalwire
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- SignalWire Team
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-11-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,20 +52,34 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '4.7'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rack
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '2.0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: rake
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
58
72
|
requirements:
|
59
73
|
- - "~>"
|
60
74
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
75
|
+
version: '13.0'
|
62
76
|
type: :development
|
63
77
|
prerelease: false
|
64
78
|
version_requirements: !ruby/object:Gem::Requirement
|
65
79
|
requirements:
|
66
80
|
- - "~>"
|
67
81
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
82
|
+
version: '13.0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: rdoc
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -142,14 +156,14 @@ dependencies:
|
|
142
156
|
requirements:
|
143
157
|
- - "~>"
|
144
158
|
- !ruby/object:Gem::Version
|
145
|
-
version: '
|
159
|
+
version: '5.0'
|
146
160
|
type: :development
|
147
161
|
prerelease: false
|
148
162
|
version_requirements: !ruby/object:Gem::Requirement
|
149
163
|
requirements:
|
150
164
|
- - "~>"
|
151
165
|
- !ruby/object:Gem::Version
|
152
|
-
version: '
|
166
|
+
version: '5.0'
|
153
167
|
- !ruby/object:Gem::Dependency
|
154
168
|
name: webmock
|
155
169
|
requirement: !ruby/object:Gem::Requirement
|
@@ -184,14 +198,14 @@ dependencies:
|
|
184
198
|
requirements:
|
185
199
|
- - "~>"
|
186
200
|
- !ruby/object:Gem::Version
|
187
|
-
version: '0.
|
201
|
+
version: '0.11'
|
188
202
|
type: :runtime
|
189
203
|
prerelease: false
|
190
204
|
version_requirements: !ruby/object:Gem::Requirement
|
191
205
|
requirements:
|
192
206
|
- - "~>"
|
193
207
|
- !ruby/object:Gem::Version
|
194
|
-
version: '0.
|
208
|
+
version: '0.11'
|
195
209
|
- !ruby/object:Gem::Dependency
|
196
210
|
name: concurrent-ruby
|
197
211
|
requirement: !ruby/object:Gem::Requirement
|
@@ -234,7 +248,7 @@ dependencies:
|
|
234
248
|
- - "~>"
|
235
249
|
- !ruby/object:Gem::Version
|
236
250
|
version: '1.3'
|
237
|
-
description:
|
251
|
+
description:
|
238
252
|
email:
|
239
253
|
- open.source@signalwire.com
|
240
254
|
executables: []
|
@@ -242,7 +256,8 @@ extensions: []
|
|
242
256
|
extra_rdoc_files: []
|
243
257
|
files:
|
244
258
|
- ".document"
|
245
|
-
- ".
|
259
|
+
- ".github/dependabot.yml"
|
260
|
+
- ".github/workflows/ci.yml"
|
246
261
|
- ".gitignore"
|
247
262
|
- ".rspec"
|
248
263
|
- ".rubocop.yml"
|
@@ -272,6 +287,7 @@ files:
|
|
272
287
|
- examples/relay/tasking/tasking_receive.rb
|
273
288
|
- examples/relay/tasking/tasking_send.rb
|
274
289
|
- examples/relay/wait_for_ending.rb
|
290
|
+
- lib/rack/signalwire_webhook_authentication.rb
|
275
291
|
- lib/signalwire.rb
|
276
292
|
- lib/signalwire/blade.rb
|
277
293
|
- lib/signalwire/blade/connection.rb
|
@@ -350,12 +366,13 @@ files:
|
|
350
366
|
- lib/signalwire/sdk/twilio_set_host.rb
|
351
367
|
- lib/signalwire/sdk/voice_response.rb
|
352
368
|
- lib/signalwire/version.rb
|
369
|
+
- lib/signalwire/webhook/validate_request.rb
|
353
370
|
- signalwire.gemspec
|
354
371
|
homepage: https://github.com/signalwire/signalwire-ruby
|
355
372
|
licenses:
|
356
373
|
- MIT
|
357
374
|
metadata: {}
|
358
|
-
post_install_message:
|
375
|
+
post_install_message:
|
359
376
|
rdoc_options: []
|
360
377
|
require_paths:
|
361
378
|
- lib
|
@@ -370,8 +387,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
370
387
|
- !ruby/object:Gem::Version
|
371
388
|
version: '0'
|
372
389
|
requirements: []
|
373
|
-
rubygems_version: 3.
|
374
|
-
signing_key:
|
390
|
+
rubygems_version: 3.4.21
|
391
|
+
signing_key:
|
375
392
|
specification_version: 4
|
376
393
|
summary: Ruby client for Signalwire
|
377
394
|
test_files: []
|