twilio-ruby 5.10.7 → 5.11.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.
@@ -28,15 +28,6 @@ module Twilio
28
28
  @v1 ||= V1.new self
29
29
  end
30
30
 
31
- ##
32
- # @param [String] sid `CJxx…xx` A system-generated 34-character string that
33
- # uniquely identifies this Composition.
34
- # @return [Twilio::REST::Video::V1::CompositionInstance] if sid was passed.
35
- # @return [Twilio::REST::Video::V1::CompositionList]
36
- def compositions(sid=:unset)
37
- self.v1.compositions(sid)
38
- end
39
-
40
31
  ##
41
32
  # @return [Twilio::REST::Video::V1::CompositionSettingsInstance]
42
33
  def composition_settings
@@ -58,6 +49,15 @@ module Twilio
58
49
  self.v1.recording_settings()
59
50
  end
60
51
 
52
+ ##
53
+ # @param [String] sid `CJxx…xx` A system-generated 34-character string that
54
+ # uniquely identifies this Composition.
55
+ # @return [Twilio::REST::Video::V1::CompositionInstance] if sid was passed.
56
+ # @return [Twilio::REST::Video::V1::CompositionList]
57
+ def compositions(sid=:unset)
58
+ self.v1.compositions(sid)
59
+ end
60
+
61
61
  ##
62
62
  # @param [String] sid A system-generated 34-character string that uniquely
63
63
  # identifies this resource.
@@ -15,28 +15,13 @@ module Twilio
15
15
  def initialize(domain)
16
16
  super
17
17
  @version = 'v1'
18
- @compositions = nil
19
18
  @composition_settings = nil
20
19
  @recordings = nil
21
20
  @recording_settings = nil
21
+ @compositions = nil
22
22
  @rooms = nil
23
23
  end
24
24
 
25
- ##
26
- # @param [String] sid The Composition Sid that uniquely identifies the Composition
27
- # to fetch.
28
- # @return [Twilio::REST::Video::V1::CompositionContext] if sid was passed.
29
- # @return [Twilio::REST::Video::V1::CompositionList]
30
- def compositions(sid=:unset)
31
- if sid.nil?
32
- raise ArgumentError, 'sid cannot be nil'
33
- elsif sid == :unset
34
- @compositions ||= CompositionList.new self
35
- else
36
- CompositionContext.new(self, sid)
37
- end
38
- end
39
-
40
25
  ##
41
26
  # @return [Twilio::REST::Video::V1::CompositionSettingsContext]
42
27
  def composition_settings
@@ -64,6 +49,21 @@ module Twilio
64
49
  @recording_settings ||= RecordingSettingsContext.new self
65
50
  end
66
51
 
52
+ ##
53
+ # @param [String] sid The Composition Sid that uniquely identifies the Composition
54
+ # to fetch.
55
+ # @return [Twilio::REST::Video::V1::CompositionContext] if sid was passed.
56
+ # @return [Twilio::REST::Video::V1::CompositionList]
57
+ def compositions(sid=:unset)
58
+ if sid.nil?
59
+ raise ArgumentError, 'sid cannot be nil'
60
+ elsif sid == :unset
61
+ @compositions ||= CompositionList.new self
62
+ else
63
+ CompositionContext.new(self, sid)
64
+ end
65
+ end
66
+
67
67
  ##
68
68
  # @param [String] sid The sid
69
69
  # @return [Twilio::REST::Video::V1::RoomContext] if sid was passed.
@@ -3,17 +3,58 @@
3
3
  module Twilio
4
4
  module Security
5
5
  class RequestValidator
6
+ ##
7
+ # Initialize a Request Validator. auth_token will either be grabbed from the global Twilio object or you can
8
+ # pass it in here.
9
+ #
10
+ # @param [String] auth_token Your account auth token, used to sign requests
6
11
  def initialize(auth_token = nil)
7
12
  @auth_token = auth_token || Twilio.auth_token
8
13
  raise ArgumentError, 'Auth token is required' if @auth_token.nil?
9
14
  end
10
15
 
16
+ ##
17
+ # Validates that after hashing a request with Twilio's request-signing algorithm
18
+ # (https://www.twilio.com/docs/usage/security#validating-requests), the hash matches the signature parameter
19
+ #
20
+ # @param [String] url The url sent to your server, including any query parameters
21
+ # @param [String, Hash, #to_unsafe_h] params In most cases, this is the POST parameters as a hash. If you received
22
+ # a bodySHA256 parameter in the query string, this parameter can instead be the POST body as a string to
23
+ # validate JSON or other text-based payloads that aren't x-www-form-urlencoded.
24
+ # @param [String] signature The expected signature, from the X-Twilio-Signature header of the request
25
+ #
26
+ # @return [Boolean] whether or not the computed signature matches the signature parameter
11
27
  def validate(url, params, signature)
12
- params_hash = params_to_hash(params)
13
- expected = build_signature_for(url, params_hash)
14
- secure_compare(expected, signature)
28
+ params_hash = body_or_hash(params)
29
+ if params_hash.is_a? Enumerable
30
+ expected = build_signature_for(url, params_hash)
31
+ secure_compare(expected, signature)
32
+ else
33
+ expected_signature = build_signature_for(url, {})
34
+ body_hash = URI.decode_www_form(URI(url).query).to_h['bodySHA256']
35
+ expected_hash = build_hash_for(params)
36
+ secure_compare(expected_signature, signature) && secure_compare(expected_hash, body_hash)
37
+ end
15
38
  end
16
39
 
40
+ ##
41
+ # Build a SHA256 hash for a body string
42
+ #
43
+ # @param [String] body String to hash
44
+ #
45
+ # @return [String] A base64-encoded SHA256 of the body string
46
+ def build_hash_for(body)
47
+ hasher = OpenSSL::Digest.new('sha256')
48
+ Base64.encode64(hasher.digest(body)).strip
49
+ end
50
+
51
+ ##
52
+ # Build a SHA1-HMAC signature for a url and parameter hash
53
+ #
54
+ # @param [String] url The request url, including any query parameters
55
+ # @param [#join] params The POST parameters
56
+ #
57
+ # @return [String] A base64 encoded SHA1-HMAC
17
58
  def build_signature_for(url, params)
18
59
  data = url + params.sort.join
19
60
  digest = OpenSSL::Digest.new('sha1')
@@ -44,11 +85,11 @@ module Twilio
44
85
  #
45
86
  # We use `to_unsafe_h` as `to_h` returns a hash of the permitted
46
87
  # parameters only and we need all the parameters to create the signature.
47
- def params_to_hash(params)
48
- if params.respond_to?(:to_unsafe_h)
49
- params.to_unsafe_h
88
+ def body_or_hash(params_or_body)
89
+ if params_or_body.respond_to?(:to_unsafe_h)
90
+ params_or_body.to_unsafe_h
50
91
  else
51
- params
92
+ params_or_body
52
93
  end
53
94
  end
54
95
  end
@@ -175,8 +175,11 @@ module Twilio
175
175
  # loop:: Times to loop message
176
176
  # language:: Message langauge
177
177
  # keyword_args:: additional attributes
178
- def say(message, voice: nil, loop: nil, language: nil, **keyword_args)
179
- append(Say.new(message, voice: voice, loop: loop, language: language, **keyword_args))
178
+ def say(message: nil, voice: nil, loop: nil, language: nil, **keyword_args)
179
+ say = Say.new(message: message, voice: voice, loop: loop, language: language, **keyword_args)
180
+
181
+ yield(say) if block_given?
182
+ append(say)
180
183
  end
181
184
 
182
185
  ##
@@ -207,10 +210,192 @@ module Twilio
207
210
  ##
208
211
  # <Say> TwiML Verb
209
212
  class Say < TwiML
210
- def initialize(message, **keyword_args)
213
+ def initialize(message: nil, **keyword_args)
211
214
  super(**keyword_args)
212
215
  @name = 'Say'
213
- @value = message
216
+ @value = message unless message.nil?
217
+ yield(self) if block_given?
218
+ end
219
+
220
+ ##
221
+ # Create a new <Break> element
222
+ # strength:: Set a pause based on strength
223
+ # time:: Set a pause to a specific length of time in seconds or milliseconds, available values: [number]s, [number]ms
224
+ # keyword_args:: additional attributes
225
+ def break(strength: nil, time: nil, **keyword_args)
226
+ append(SsmlBreak.new(strength: strength, time: time, **keyword_args))
227
+ end
228
+
229
+ ##
230
+ # Create a new <Emphasis> element
231
+ # words:: Words to emphasize
232
+ # level:: Specify the degree of emphasis
233
+ # keyword_args:: additional attributes
234
+ def emphasis(words, level: nil, **keyword_args)
235
+ append(SsmlEmphasis.new(words, level: level, **keyword_args))
236
+ end
237
+
238
+ ##
239
+ # Create a new <P> element
240
+ # words:: Words to speak
241
+ # keyword_args:: additional attributes
242
+ def p(words, **keyword_args)
243
+ append(SsmlP.new(words, **keyword_args))
244
+ end
245
+
246
+ ##
247
+ # Create a new <Phoneme> element
248
+ # words:: Words to speak
249
+ # alphabet:: Specify the phonetic alphabet
250
+ # ph:: Specifiy the phonetic symbols for pronunciation
251
+ # keyword_args:: additional attributes
252
+ def phoneme(words, alphabet: nil, ph: nil, **keyword_args)
253
+ append(SsmlPhoneme.new(words, alphabet: alphabet, ph: ph, **keyword_args))
254
+ end
255
+
256
+ ##
257
+ # Create a new <Prosody> element
258
+ # words:: Words to speak
259
+ # volume:: Specify the volume, available values: default, silent, x-soft, soft, medium, loud, x-loud, +ndB, -ndB
260
+ # rate:: Specify the rate, available values: x-slow, slow, medium, fast, x-fast, n%
261
+ # pitch:: Specify the pitch, available values: default, x-low, low, medium, high, x-high, +n%, -n%
262
+ # keyword_args:: additional attributes
263
+ def prosody(words, volume: nil, rate: nil, pitch: nil, **keyword_args)
264
+ append(SsmlProsody.new(words, volume: volume, rate: rate, pitch: pitch, **keyword_args))
265
+ end
266
+
267
+ ##
268
+ # Create a new <S> element
269
+ # words:: Words to speak
270
+ # keyword_args:: additional attributes
271
+ def s(words, **keyword_args)
272
+ append(SsmlS.new(words, **keyword_args))
273
+ end
274
+
275
+ ##
276
+ # Create a new <Say-As> element
277
+ # words:: Words to be interpreted
278
+ # interpret-as:: Specify the type of words are spoken
279
+ # role:: Specify the format of the date when interpret-as is set to date
280
+ # keyword_args:: additional attributes
281
+ def say_as(words, interpretAs: nil, role: nil, **keyword_args)
282
+ append(SsmlSayAs.new(words, interpretAs: interpretAs, role: role, **keyword_args))
283
+ end
284
+
285
+ ##
286
+ # Create a new <Sub> element
287
+ # words:: Words to be substituted
288
+ # alias:: Substitute a different word (or pronunciation) for selected text such as an acronym or abbreviation
289
+ # keyword_args:: additional attributes
290
+ def sub(words, aliasAttribute: nil, **keyword_args)
291
+ append(SsmlSub.new(words, aliasAttribute: aliasAttribute, **keyword_args))
292
+ end
293
+
294
+ ##
295
+ # Create a new <W> element
296
+ # words:: Words to speak
297
+ # role:: Customize the pronunciation of words by specifying the word’s part of speech or alternate meaning
298
+ # keyword_args:: additional attributes
299
+ def w(words, role: nil, **keyword_args)
300
+ append(SsmlW.new(words, role: role, **keyword_args))
301
+ end
302
+ end
303
+
304
+ ##
305
+ # Improving Pronunciation by Specifying Parts of Speech in <Say>
306
+ class SsmlW < TwiML
307
+ def initialize(words, **keyword_args)
308
+ super(**keyword_args)
309
+ @name = 'W'
310
+ @value = words
311
+ yield(self) if block_given?
312
+ end
313
+ end
314
+
315
+ ##
316
+ # Pronouncing Acronyms and Abbreviations in <Say>
317
+ class SsmlSub < TwiML
318
+ def initialize(words, **keyword_args)
319
+ super(**keyword_args)
320
+ @name = 'Sub'
321
+ @value = words
322
+ yield(self) if block_given?
323
+ end
324
+ end
325
+
326
+ ##
327
+ # Controlling How Special Types of Words Are Spoken in <Say>
328
+ class SsmlSayAs < TwiML
329
+ def initialize(words, **keyword_args)
330
+ super(**keyword_args)
331
+ @name = 'Say-As'
332
+ @value = words
333
+ yield(self) if block_given?
334
+ end
335
+ end
336
+
337
+ ##
338
+ # Adding A Pause Between Sentences in <Say>
339
+ class SsmlS < TwiML
340
+ def initialize(words, **keyword_args)
341
+ super(**keyword_args)
342
+ @name = 'S'
343
+ @value = words
344
+ yield(self) if block_given?
345
+ end
346
+ end
347
+
348
+ ##
349
+ # Controling Volume, Speaking Rate, and Pitch in <Say>
350
+ class SsmlProsody < TwiML
351
+ def initialize(words, **keyword_args)
352
+ super(**keyword_args)
353
+ @name = 'Prosody'
354
+ @value = words
355
+ yield(self) if block_given?
356
+ end
357
+ end
358
+
359
+ ##
360
+ # Using Phonetic Pronunciation in <Say>
361
+ class SsmlPhoneme < TwiML
362
+ def initialize(words, **keyword_args)
363
+ super(**keyword_args)
364
+ @name = 'Phoneme'
365
+ @value = words
366
+ yield(self) if block_given?
367
+ end
368
+ end
369
+
370
+ ##
371
+ # Adding a Pause Between Paragraphs in <Say>
372
+ class SsmlP < TwiML
373
+ def initialize(words, **keyword_args)
374
+ super(**keyword_args)
375
+ @name = 'P'
376
+ @value = words
377
+ yield(self) if block_given?
378
+ end
379
+ end
380
+
381
+ ##
382
+ # Emphasizing Words in <Say>
383
+ class SsmlEmphasis < TwiML
384
+ def initialize(words, **keyword_args)
385
+ super(**keyword_args)
386
+ @name = 'Emphasis'
387
+ @value = words
388
+ yield(self) if block_given?
389
+ end
390
+ end
391
+
392
+ ##
393
+ # Adding a Pause in <Say>
394
+ class SsmlBreak < TwiML
395
+ def initialize(**keyword_args)
396
+ super(**keyword_args)
397
+ @name = 'Break'
398
+
214
399
  yield(self) if block_given?
215
400
  end
216
401
  end
@@ -320,8 +505,11 @@ module Twilio
320
505
  # loop:: Times to loop message
321
506
  # language:: Message langauge
322
507
  # keyword_args:: additional attributes
323
- def say(message, voice: nil, loop: nil, language: nil, **keyword_args)
324
- append(Say.new(message, voice: voice, loop: loop, language: language, **keyword_args))
508
+ def say(message: nil, voice: nil, loop: nil, language: nil, **keyword_args)
509
+ say = Say.new(message: message, voice: voice, loop: loop, language: language, **keyword_args)
510
+
511
+ yield(say) if block_given?
512
+ append(say)
325
513
  end
326
514
 
327
515
  ##
@@ -1,3 +1,3 @@
1
1
  module Twilio
2
- VERSION = '5.10.7'
2
+ VERSION = '5.11.0'
3
3
  end
@@ -41,7 +41,7 @@ describe 'IpAddress' do
41
41
  "date_updated": "Mon, 20 Jul 2015 17:27:10 +0000",
42
42
  "friendly_name": "friendly_name",
43
43
  "ip_access_control_list_sid": "ALaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
44
- "ip_address": "ip_address",
44
+ "ip_address": "192.168.1.1",
45
45
  "cidr_prefix_length": 32,
46
46
  "sid": "IPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
47
47
  "uri": "/2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/SIP/IpAccessControlLists/ALaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/IpAddresses/IPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.json"
@@ -120,7 +120,7 @@ describe 'IpAddress' do
120
120
  "date_updated": "Mon, 20 Jul 2015 17:27:10 +0000",
121
121
  "friendly_name": "friendly_name",
122
122
  "ip_access_control_list_sid": "ALaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
123
- "ip_address": "ip_address",
123
+ "ip_address": "192.168.1.1",
124
124
  "cidr_prefix_length": 32,
125
125
  "sid": "IPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
126
126
  "uri": "/2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/SIP/IpAccessControlLists/ALaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/IpAddresses/IPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.json"
@@ -164,7 +164,7 @@ describe 'IpAddress' do
164
164
  "date_updated": "Mon, 20 Jul 2015 17:27:10 +0000",
165
165
  "friendly_name": "friendly_name",
166
166
  "ip_access_control_list_sid": "ALaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
167
- "ip_address": "ip_address",
167
+ "ip_address": "192.168.1.1",
168
168
  "cidr_prefix_length": 32,
169
169
  "sid": "IPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
170
170
  "uri": "/2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/SIP/IpAccessControlLists/ALaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/IpAddresses/IPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.json"
@@ -208,7 +208,7 @@ describe 'IpAddress' do
208
208
  "date_updated": "Mon, 20 Jul 2015 17:27:10 +0000",
209
209
  "friendly_name": "friendly_name",
210
210
  "ip_access_control_list_sid": "ALaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
211
- "ip_address": "ip_address",
211
+ "ip_address": "192.168.1.1",
212
212
  "cidr_prefix_length": 32,
213
213
  "sid": "IPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
214
214
  "uri": "/2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/SIP/IpAccessControlLists/ALaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/IpAddresses/IPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.json"
@@ -30,84 +30,57 @@ describe Twilio::Security::RequestValidator do
30
30
  end
31
31
 
32
32
  describe 'validations' do
33
- let(:token) { '2bd9e9638872de601313dc77410d3b23' }
33
+ let(:token) { '12345' }
34
34
 
35
35
  let(:validator) { Twilio::Security::RequestValidator.new token }
36
36
 
37
- let(:voice_url) { 'http://twiliotests.heroku.com/validate/voice' }
37
+ let(:url) { 'https://mycompany.com/myapp.php?foo=1&bar=2' }
38
38
 
39
- let(:sms_url) { 'http://twiliotests.heroku.com/validate/sms' }
39
+ let(:default_signature) { 'RSOYDt4T1cUTdK1PDd93/VVr8B8=' }
40
40
 
41
- let(:voice_params) do
41
+ let(:body) { '{"property": "value", "boolean": true}' }
42
+
43
+ let(:body_hash) { 'Ch/3Y02as7ldtcmi3+lBbkFQKyg6gMfPGWMmMvluZiA=' }
44
+
45
+ let(:body_hash_encoded) { body_hash.gsub('+', '%2B').gsub('=', '%3D') }
46
+
47
+ let(:params) do
42
48
  {
43
- 'ToState' => 'California',
44
- 'CalledState' => 'California',
45
- 'Direction' => 'inbound',
46
- 'FromState' => 'CA',
47
- 'AccountSid' => 'ACba8bc05eacf94afdae398e642c9cc32d',
48
- 'Caller' => '+14153595711',
49
- 'CallerZip' => '94108',
50
- 'CallerCountry' => 'US',
51
- 'From' => '+14153595711',
52
- 'FromCity' => 'SAN FRANCISCO',
53
- 'CallerCity' => 'SAN FRANCISCO',
54
- 'To' => '+14157669926',
55
- 'FromZip' => '94108',
56
- 'FromCountry' => 'US',
57
- 'ToCity' => '',
58
- 'CallStatus' => 'ringing',
59
- 'CalledCity' => '',
60
- 'CallerState' => 'CA',
61
- 'CalledZip' => '',
62
- 'ToZip' => '',
63
- 'ToCountry' => 'US',
64
- 'CallSid' => 'CA136d09cd59a3c0ec8dbff44da5c03f31',
65
- 'CalledCountry' => 'US',
66
- 'Called' => '+14157669926',
67
- 'ApiVersion' => '2010-04-01',
68
- 'ApplicationSid' => 'AP44efecad51364e80b133bb7c07eb8204'
49
+ 'From' => '+14158675309',
50
+ 'To' => '+18005551212',
51
+ 'CallSid' => 'CA1234567890ABCDE',
52
+ 'Caller' => '+14158675309',
53
+ 'Digits' => '1234'
69
54
  }
70
55
  end
71
56
 
72
- let(:sms_params) do
73
- {
74
- 'ToState' => 'CA',
75
- 'FromState' => 'CA',
76
- 'AccountSid' => 'ACba8bc05eacf94afdae398e642c9cc32d',
77
- 'SmsMessageSid' => 'SM2003cbd5e6a3701999aa3e5f20ff2787',
78
- 'Body' => 'Orly',
79
- 'From' => '+14159354345',
80
- 'FromCity' => 'SAN FRANCISCO',
81
- 'SmsStatus' => 'received',
82
- 'FromZip' => '94107',
83
- 'FromCountry' => 'US',
84
- 'To' => '+14158141819',
85
- 'ToCity' => 'SAN FRANCISCO',
86
- 'ToZip' => '94105',
87
- 'ToCountry' => 'US',
88
- 'ApiVersion' => '2010-04-01',
89
- 'SmsSid' => 'SM2003cbd5e6a3701999aa3e5f20ff2787'
90
- }
57
+ it 'should build a correct signature' do
58
+ expect(validator.build_signature_for(url, params)).to eq(default_signature)
59
+ end
60
+ it 'should validate an authentic Twilio request' do
61
+ expect(validator.validate(url, params, default_signature)).to eq(true)
62
+ end
63
+
64
+ it 'should not validate a request with wrong signature' do
65
+ expect(validator.validate(url, params, 'fake_signature')).to eq(false)
91
66
  end
92
67
 
93
- it 'should validate an authentic Twilio Voice request' do
94
- signature = 'oVb2kXoVy8GEfwBDjR8bk/ZZ6eA='
95
- expect(validator.validate(voice_url, voice_params, signature)).to eq(true)
68
+ it 'should hash body correctly' do
69
+ expect(validator.build_hash_for(body)).to eq(body_hash)
96
70
  end
97
71
 
98
- it 'should validate an authentic Twilio SMS request' do
99
- signature = 'mxeiv65lEe0b8L6LdVw2jgJi8yw='
100
- expect(validator.validate(sms_url, sms_params, signature)).to eq(true)
72
+ it 'should validate requests with body correctly' do
73
+ url_with_hash = "#{url}&bodySHA256=#{body_hash_encoded}"
74
+ expect(validator.validate(url_with_hash, body, 'afcFvPLPYT8mg/JyIVkdnqQKa2s=')).to eq(true)
101
75
  end
102
76
 
103
- it 'should not validate a Twilio Voice request with wrong signature' do
104
- signature = 'foo'
105
- expect(validator.validate(voice_url, voice_params, signature)).to eq(false)
77
+ it 'should validate with no other GET parameters' do
78
+ url_with_hash = "https://mycompany.com/myapp.php?bodySHA256=#{body_hash_encoded}"
79
+ expect(validator.validate(url_with_hash, body, 'DXnNFCj8DJ/hZmiSg4UzaDHw5Og=')).to eq(true)
106
80
  end
107
81
 
108
- it 'should not validate a Twilio SMS request with wrong signature' do
109
- signature = 'bar'
110
- expect(validator.validate(sms_url, sms_params, signature)).to eq(false)
82
+ it 'should fail validation with body but no signature' do
83
+ expect(validator.validate(url, body, default_signature)).to eq(false)
111
84
  end
112
85
  end
113
86
  end