twilio-ruby 3.7.0 → 3.7.1
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.
- data/Rakefile +1 -5
- data/lib/twilio-ruby/rest/client.rb +7 -5
- data/lib/twilio-ruby/version.rb +1 -1
- data/spec/rest/account_spec.rb +57 -0
- data/spec/rest/call_spec.rb +15 -0
- data/spec/rest/client_spec.rb +100 -0
- data/spec/rest/conference_spec.rb +9 -0
- data/spec/rest/instance_resource_spec.rb +15 -0
- data/spec/rest/recording_spec.rb +9 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/util/capability_spec.rb +137 -0
- data/spec/util/request_validator_spec.rb +65 -0
- data/twilio-ruby.gemspec +2 -1
- metadata +24 -8
- data/test/twilio_spec.rb +0 -393
data/Rakefile
CHANGED
|
@@ -45,6 +45,8 @@ module Twilio
|
|
|
45
45
|
include Twilio::Util
|
|
46
46
|
include Twilio::REST::Utils
|
|
47
47
|
|
|
48
|
+
API_VERSION = '2010-04-01'
|
|
49
|
+
|
|
48
50
|
HTTP_HEADERS = {
|
|
49
51
|
'Accept' => 'application/json',
|
|
50
52
|
'Accept-Charset' => 'utf-8',
|
|
@@ -194,10 +196,8 @@ module Twilio
|
|
|
194
196
|
##
|
|
195
197
|
# Set up +account+ and +accounts+ attributes.
|
|
196
198
|
def set_up_subresources # :doc:
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
@account = Twilio::REST::Account.new account_uri, self
|
|
200
|
-
@accounts = Twilio::REST::Accounts.new accounts_uri, self
|
|
199
|
+
@accounts = Twilio::REST::Accounts.new "/#{API_VERSION}/Accounts", self
|
|
200
|
+
@account = @accounts.get @account_sid
|
|
201
201
|
end
|
|
202
202
|
|
|
203
203
|
##
|
|
@@ -218,7 +218,9 @@ module Twilio
|
|
|
218
218
|
rescue Exception
|
|
219
219
|
if retries_left > 0 then retries_left -= 1; retry else raise end
|
|
220
220
|
end
|
|
221
|
-
|
|
221
|
+
if response.body and !response.body.empty?
|
|
222
|
+
object = MultiJson.load response.body
|
|
223
|
+
end
|
|
222
224
|
if response.kind_of? Net::HTTPClientError
|
|
223
225
|
raise Twilio::REST::RequestError.new object['message'], object['code']
|
|
224
226
|
end
|
data/lib/twilio-ruby/version.rb
CHANGED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Twilio::REST::Account do
|
|
4
|
+
it 'should set up an incoming phone numbers resources object' do
|
|
5
|
+
account = Twilio::REST::Account.new('someUri', 'someClient')
|
|
6
|
+
account.respond_to?(:incoming_phone_numbers).should == true
|
|
7
|
+
account.incoming_phone_numbers.instance_variable_get('@uri').should == 'someUri/IncomingPhoneNumbers'
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it 'should set up an available phone numbers resources object' do
|
|
11
|
+
account = Twilio::REST::Account.new('someUri', 'someClient')
|
|
12
|
+
account.respond_to?(:available_phone_numbers).should == true
|
|
13
|
+
account.available_phone_numbers.instance_variable_get('@uri').should == 'someUri/AvailablePhoneNumbers'
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'should set up an outgoing caller ids resources object' do
|
|
17
|
+
account = Twilio::REST::Account.new('someUri', 'someClient')
|
|
18
|
+
account.respond_to?(:outgoing_caller_ids).should == true
|
|
19
|
+
account.outgoing_caller_ids.instance_variable_get('@uri').should == 'someUri/OutgoingCallerIds'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'should set up a calls resources object' do
|
|
23
|
+
account = Twilio::REST::Account.new('someUri', 'someClient')
|
|
24
|
+
account.respond_to?(:calls).should == true
|
|
25
|
+
account.calls.instance_variable_get('@uri').should == 'someUri/Calls'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'should set up a conferences resources object' do
|
|
29
|
+
account = Twilio::REST::Account.new('someUri', 'someClient')
|
|
30
|
+
account.respond_to?(:conferences).should == true
|
|
31
|
+
account.conferences.instance_variable_get('@uri').should == 'someUri/Conferences'
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'should set up a sms resource object' do
|
|
35
|
+
account = Twilio::REST::Account.new('someUri', 'someClient')
|
|
36
|
+
account.respond_to?(:sms).should == true
|
|
37
|
+
account.sms.instance_variable_get('@uri').should == 'someUri/SMS'
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'should set up a recordings resources object' do
|
|
41
|
+
account = Twilio::REST::Account.new('someUri', 'someClient')
|
|
42
|
+
account.respond_to?(:recordings).should == true
|
|
43
|
+
account.recordings.instance_variable_get('@uri').should == 'someUri/Recordings'
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it 'should set up a transcriptions resources object' do
|
|
47
|
+
account = Twilio::REST::Account.new('someUri', 'someClient')
|
|
48
|
+
account.respond_to?(:transcriptions).should == true
|
|
49
|
+
account.transcriptions.instance_variable_get('@uri').should == 'someUri/Transcriptions'
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'should set up a notifications resources object' do
|
|
53
|
+
account = Twilio::REST::Account.new('someUri', 'someClient')
|
|
54
|
+
account.respond_to?(:notifications).should == true
|
|
55
|
+
account.notifications.instance_variable_get('@uri').should == 'someUri/Notifications'
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Twilio::REST::Call do
|
|
4
|
+
it 'should set up a recordings resources object' do
|
|
5
|
+
call = Twilio::REST::Call.new('someUri', 'someClient')
|
|
6
|
+
call.respond_to?(:recordings).should == true
|
|
7
|
+
call.recordings.instance_variable_get('@uri').should == 'someUri/Recordings'
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it 'should set up a notifications resources object' do
|
|
11
|
+
call = Twilio::REST::Call.new('someUri', 'someClient')
|
|
12
|
+
call.respond_to?(:notifications).should == true
|
|
13
|
+
call.notifications.instance_variable_get('@uri').should == 'someUri/Notifications'
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Twilio::REST::Client do
|
|
4
|
+
it 'should not raise an error if the response body is empty' do
|
|
5
|
+
FakeWeb.register_uri(:any, %r/api\.twilio\.com/, :body => '')
|
|
6
|
+
twilio = Twilio::REST::Client.new('someSid', 'someToken')
|
|
7
|
+
Twilio::REST::IncomingPhoneNumber.new('/phone_number', twilio).delete
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it 'should not raise an error if the response body is nil' do
|
|
11
|
+
response = double(:response, :body => nil)
|
|
12
|
+
connection = double(:connection, :request => response)
|
|
13
|
+
twilio = Twilio::REST::Client.new('someSid', 'someToken')
|
|
14
|
+
twilio.instance_variable_set(:@connection, connection)
|
|
15
|
+
Twilio::REST::IncomingPhoneNumber.new('/phone_number', twilio).delete
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it 'should set up a new client instance with the given sid and token' do
|
|
19
|
+
twilio = Twilio::REST::Client.new('someSid', 'someToken')
|
|
20
|
+
twilio.account_sid.should == 'someSid'
|
|
21
|
+
twilio.instance_variable_get('@auth_token').should == 'someToken'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it 'should set up the proper default http ssl connection' do
|
|
25
|
+
twilio = Twilio::REST::Client.new('someSid', 'someToken')
|
|
26
|
+
connection = twilio.instance_variable_get('@connection')
|
|
27
|
+
connection.address.should == 'api.twilio.com'
|
|
28
|
+
connection.port.should == 443
|
|
29
|
+
connection.use_ssl?.should == true
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it 'should set up the requested ssl verification ca_file if provided' do
|
|
33
|
+
twilio = Twilio::REST::Client.new('someSid', 'someToken', :ssl_ca_file => '/path/to/ca/file')
|
|
34
|
+
connection = twilio.instance_variable_get('@connection')
|
|
35
|
+
connection.ca_file.should == '/path/to/ca/file'
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it 'should set up the proper http ssl connection when a different domain is given' do
|
|
39
|
+
twilio = Twilio::REST::Client.new('someSid', 'someToken', :host => 'api.faketwilio.com')
|
|
40
|
+
connection = twilio.instance_variable_get('@connection')
|
|
41
|
+
connection.address.should == 'api.faketwilio.com'
|
|
42
|
+
connection.port.should == 443
|
|
43
|
+
connection.use_ssl?.should == true
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it 'should adjust the open and read timeouts on the underlying Net::HTTP object when asked' do
|
|
47
|
+
timeout = rand(30)
|
|
48
|
+
twilio = Twilio::REST::Client.new('someSid', 'someToken', :timeout => timeout)
|
|
49
|
+
connection = twilio.instance_variable_get('@connection')
|
|
50
|
+
connection.port.should == 443
|
|
51
|
+
connection.use_ssl?.should == true
|
|
52
|
+
connection.open_timeout.should == timeout
|
|
53
|
+
connection.read_timeout.should == timeout
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'should set up the proper http ssl connection when a proxy_host is given' do
|
|
57
|
+
twilio = Twilio::REST::Client.new('someSid', 'someToken', :host => 'api.faketwilio.com', :proxy_addr => 'localhost')
|
|
58
|
+
connection = twilio.instance_variable_get('@connection')
|
|
59
|
+
connection.proxy?.should == true
|
|
60
|
+
connection.proxy_address.should == 'localhost'
|
|
61
|
+
connection.proxy_port.should == 80
|
|
62
|
+
connection.address.should == 'api.faketwilio.com'
|
|
63
|
+
connection.port.should == 443
|
|
64
|
+
connection.use_ssl?.should == true
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it 'should set up the proper http ssl connection when a proxy_host and proxy_port are given' do
|
|
68
|
+
twilio = Twilio::REST::Client.new('someSid', 'someToken', :host => 'api.faketwilio.com', :proxy_addr => 'localhost', :proxy_port => 13128)
|
|
69
|
+
connection = twilio.instance_variable_get('@connection')
|
|
70
|
+
connection.proxy?.should == true
|
|
71
|
+
connection.proxy_address.should == 'localhost'
|
|
72
|
+
connection.proxy_port.should == 13128
|
|
73
|
+
connection.address.should == 'api.faketwilio.com'
|
|
74
|
+
connection.port.should == 443
|
|
75
|
+
connection.use_ssl?.should == true
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it 'should set up an accounts resources object' do
|
|
79
|
+
twilio = Twilio::REST::Client.new('someSid', 'someToken')
|
|
80
|
+
twilio.respond_to?(:accounts).should == true
|
|
81
|
+
twilio.accounts.instance_variable_get('@uri').should == '/2010-04-01/Accounts'
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it 'should set up an account object with the given sid' do
|
|
85
|
+
twilio = Twilio::REST::Client.new('someSid', 'someToken')
|
|
86
|
+
twilio.respond_to?(:account).should == true
|
|
87
|
+
twilio.account.instance_variable_get('@uri').should == '/2010-04-01/Accounts/someSid'
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it 'should convert all parameter names to Twilio-style names' do
|
|
91
|
+
twilio = Twilio::REST::Client.new('someSid', 'someToken')
|
|
92
|
+
untwilified = {:sms_url => 'someUrl', 'voiceFallbackUrl' => 'anotherUrl',
|
|
93
|
+
'Status_callback' => 'yetAnotherUrl'}
|
|
94
|
+
twilified = {:SmsUrl => 'someUrl', :VoiceFallbackUrl => 'anotherUrl',
|
|
95
|
+
:StatusCallback => 'yetAnotherUrl'}
|
|
96
|
+
twilio.instance_eval do
|
|
97
|
+
twilify(untwilified).should == twilified
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Twilio::REST::Conference do
|
|
4
|
+
it 'should set up a participants resources object' do
|
|
5
|
+
call = Twilio::REST::Conference.new('someUri', 'someClient')
|
|
6
|
+
call.respond_to?(:participants).should == true
|
|
7
|
+
call.participants.instance_variable_get('@uri').should == 'someUri/Participants'
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Twilio::REST::InstanceResource do
|
|
4
|
+
it 'should set up an internal reference to the uri and client' do
|
|
5
|
+
resource = Twilio::REST::InstanceResource.new('some/uri', 'someClient')
|
|
6
|
+
resource.instance_variable_get('@uri').should == 'some/uri'
|
|
7
|
+
resource.instance_variable_get('@client').should == 'someClient'
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it 'should set up object properties if passed' do
|
|
11
|
+
params = {'SomeKey' => 'someValue'}
|
|
12
|
+
resource = Twilio::REST::InstanceResource.new('uri', 'client', params)
|
|
13
|
+
resource.some_key.should == 'someValue'
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Twilio::REST::Recording do
|
|
4
|
+
it 'should set up a transcriptions resources object' do
|
|
5
|
+
call = Twilio::REST::Recording.new('someUri', 'someClient')
|
|
6
|
+
call.respond_to?(:transcriptions).should == true
|
|
7
|
+
call.transcriptions.instance_variable_get('@uri').should == 'someUri/Transcriptions'
|
|
8
|
+
end
|
|
9
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Twilio::Util::Capability do
|
|
4
|
+
before :each do
|
|
5
|
+
@capability = Twilio::Util::Capability.new 'myAccountSid', 'myAuthToken'
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def queries(q)
|
|
9
|
+
q.scan(/scope:client:(incoming|outgoing)\?(\S+)/).map{|(type, query)| [type, Rack::Utils.parse_query(query)]}
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it 'should return a valid jwt when #generate is called' do
|
|
13
|
+
token = @capability.generate
|
|
14
|
+
decoded = JWT.decode token, 'myAuthToken'
|
|
15
|
+
decoded['scope'].should_not be_nil
|
|
16
|
+
decoded['iss'].should_not be_nil
|
|
17
|
+
decoded['exp'].should_not be_nil
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'should properly set the iss key in the payload' do
|
|
21
|
+
token = @capability.generate
|
|
22
|
+
decoded = JWT.decode token, 'myAuthToken'
|
|
23
|
+
decoded['iss'].should == 'myAccountSid'
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'should properly set the exp key based on the default hour ttl' do
|
|
27
|
+
seconds = Time.now.to_i
|
|
28
|
+
token = @capability.generate
|
|
29
|
+
decoded = JWT.decode token, 'myAuthToken'
|
|
30
|
+
decoded['exp'].should == seconds + 3600
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'should properly set the exp key based on the ttl passed to #generate' do
|
|
34
|
+
ttl = rand 10000
|
|
35
|
+
seconds = Time.now.to_i
|
|
36
|
+
token = @capability.generate ttl
|
|
37
|
+
decoded = JWT.decode token, 'myAuthToken'
|
|
38
|
+
decoded['exp'].should == seconds + ttl
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'should generate a proper incoming client scope string' do
|
|
42
|
+
@capability.allow_client_incoming 'andrew'
|
|
43
|
+
token = @capability.generate
|
|
44
|
+
decoded = JWT.decode token, 'myAuthToken'
|
|
45
|
+
queries(decoded['scope']).should == [['incoming', {'clientName' => 'andrew'}]]
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'should generate multiple proper incoming client scope strings' do
|
|
49
|
+
@capability.allow_client_incoming 'andrew'
|
|
50
|
+
@capability.allow_client_incoming 'bridget'
|
|
51
|
+
token = @capability.generate
|
|
52
|
+
decoded = JWT.decode token, 'myAuthToken'
|
|
53
|
+
queries(decoded['scope']).should == [
|
|
54
|
+
['incoming', {'clientName' => 'andrew'}],
|
|
55
|
+
['incoming', {'clientName' => 'bridget'}]
|
|
56
|
+
]
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it 'should generate a proper outgoing client scope string' do
|
|
60
|
+
@capability.allow_client_outgoing 'myAppSid'
|
|
61
|
+
token = @capability.generate
|
|
62
|
+
decoded = JWT.decode token, 'myAuthToken'
|
|
63
|
+
queries(decoded['scope']).should == [['outgoing', {'appSid' => 'myAppSid'}]]
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it 'should generate a proper outgoing client scope string with parameters' do
|
|
67
|
+
app_params_hash = {'key' => 'a value', :foo => 'bar/baz'}
|
|
68
|
+
@capability.allow_client_outgoing 'myAppSid', app_params_hash
|
|
69
|
+
app_params = @capability.instance_eval {url_encode(app_params_hash)}
|
|
70
|
+
params_hash = {'appSid' => 'myAppSid', 'appParams' => app_params}
|
|
71
|
+
params = @capability.instance_eval {url_encode(params_hash)}
|
|
72
|
+
token = @capability.generate
|
|
73
|
+
decoded = JWT.decode token, 'myAuthToken'
|
|
74
|
+
queries(decoded['scope']).should == [['outgoing', params_hash]]
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it 'should generate a proper outgoing client scope string based on the ' +
|
|
78
|
+
'client name when calling #allow_client_incoming first' do
|
|
79
|
+
@capability.allow_client_incoming 'andrew'
|
|
80
|
+
@capability.allow_client_outgoing 'myAppSid'
|
|
81
|
+
token = @capability.generate
|
|
82
|
+
decoded = JWT.decode token, 'myAuthToken'
|
|
83
|
+
queries(decoded['scope']).should == [
|
|
84
|
+
['incoming', {'clientName' => 'andrew'}],
|
|
85
|
+
['outgoing', {'clientName' => 'andrew', 'appSid' => 'myAppSid'}]
|
|
86
|
+
]
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it 'should generate a proper outgoing client scope string based on the ' +
|
|
90
|
+
'client name when calling #allow_client_incoming second' do
|
|
91
|
+
@capability.allow_client_outgoing 'myAppSid'
|
|
92
|
+
@capability.allow_client_incoming 'andrew'
|
|
93
|
+
token = @capability.generate
|
|
94
|
+
decoded = JWT.decode token, 'myAuthToken'
|
|
95
|
+
queries(decoded['scope']).should == [["incoming", {"clientName"=>"andrew"}], ["outgoing", {"clientName"=>"andrew", "appSid"=>"myAppSid"}]]
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it 'should generate a proper outgoing client scope string with parameters ' +
|
|
99
|
+
'and a client name when calling #allow_client_incoming first' do
|
|
100
|
+
@capability.allow_client_incoming 'andrew'
|
|
101
|
+
app_params_hash = {'key' => 'a value', :foo => 'bar/baz'}
|
|
102
|
+
@capability.allow_client_outgoing 'myAppSid', app_params_hash
|
|
103
|
+
app_params = @capability.instance_eval {url_encode(app_params_hash)}
|
|
104
|
+
params_hash = {'appSid' => 'myAppSid', 'appParams' => app_params, 'clientName' => 'andrew'}
|
|
105
|
+
params = @capability.instance_eval {url_encode(params_hash)}
|
|
106
|
+
token = @capability.generate
|
|
107
|
+
decoded = JWT.decode token, 'myAuthToken'
|
|
108
|
+
scopes = queries(decoded['scope'])
|
|
109
|
+
scopes.shift.should == ["incoming", {"clientName"=>"andrew"}]
|
|
110
|
+
scope = scopes.shift
|
|
111
|
+
scope.first.should == 'outgoing'
|
|
112
|
+
Rack::Utils.parse_query(scope.last['appParams']).should == {'key' => 'a value', 'foo' => 'bar/baz'}
|
|
113
|
+
scope.last["clientName"].should == "andrew"
|
|
114
|
+
scope.last["appSid"].should == "myAppSid"
|
|
115
|
+
scopes.should be_empty
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it 'should generate a proper outgoing client scope string with parameters ' +
|
|
119
|
+
'and a client name when calling #allow_client_incoming second' do
|
|
120
|
+
app_params_hash = {'key' => 'a value', :foo => 'bar/baz'}
|
|
121
|
+
@capability.allow_client_outgoing 'myAppSid', app_params_hash
|
|
122
|
+
@capability.allow_client_incoming 'andrew'
|
|
123
|
+
app_params = @capability.instance_eval {url_encode(app_params_hash)}
|
|
124
|
+
params_hash = {'appSid' => 'myAppSid', 'appParams' => app_params, 'clientName' => 'andrew'}
|
|
125
|
+
params = @capability.instance_eval {url_encode(params_hash)}
|
|
126
|
+
token = @capability.generate
|
|
127
|
+
decoded = JWT.decode token, 'myAuthToken'
|
|
128
|
+
scopes = queries(decoded['scope'])
|
|
129
|
+
scopes.shift.should == ["incoming", {"clientName"=>"andrew"}]
|
|
130
|
+
scope = scopes.shift
|
|
131
|
+
scope.first.should == 'outgoing'
|
|
132
|
+
Rack::Utils.parse_query(scope.last['appParams']).should == {'key' => 'a value', 'foo' => 'bar/baz'}
|
|
133
|
+
scope.last["clientName"].should == "andrew"
|
|
134
|
+
scope.last["appSid"].should == "myAppSid"
|
|
135
|
+
scopes.should be_empty
|
|
136
|
+
end
|
|
137
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Twilio::Util::RequestValidator do
|
|
4
|
+
it 'should properly validate a Twilio Voice request' do
|
|
5
|
+
token = '2bd9e9638872de601313dc77410d3b23'
|
|
6
|
+
validator = Twilio::Util::RequestValidator.new token
|
|
7
|
+
url = 'http://twiliotests.heroku.com/validate/voice'
|
|
8
|
+
params = {
|
|
9
|
+
'ToState' => 'California',
|
|
10
|
+
'CalledState' => 'California',
|
|
11
|
+
'Direction' => 'inbound',
|
|
12
|
+
'FromState' => 'CA',
|
|
13
|
+
'AccountSid' => 'ACba8bc05eacf94afdae398e642c9cc32d',
|
|
14
|
+
'Caller' => '+14153595711',
|
|
15
|
+
'CallerZip' => '94108',
|
|
16
|
+
'CallerCountry' => 'US',
|
|
17
|
+
'From' => '+14153595711',
|
|
18
|
+
'FromCity' => 'SAN FRANCISCO',
|
|
19
|
+
'CallerCity' => 'SAN FRANCISCO',
|
|
20
|
+
'To' => '+14157669926',
|
|
21
|
+
'FromZip' => '94108',
|
|
22
|
+
'FromCountry' => 'US',
|
|
23
|
+
'ToCity' => '',
|
|
24
|
+
'CallStatus' => 'ringing',
|
|
25
|
+
'CalledCity' => '',
|
|
26
|
+
'CallerState' => 'CA',
|
|
27
|
+
'CalledZip' => '',
|
|
28
|
+
'ToZip' => '',
|
|
29
|
+
'ToCountry' => 'US',
|
|
30
|
+
'CallSid' => 'CA136d09cd59a3c0ec8dbff44da5c03f31',
|
|
31
|
+
'CalledCountry' => 'US',
|
|
32
|
+
'Called' => '+14157669926',
|
|
33
|
+
'ApiVersion' => '2010-04-01',
|
|
34
|
+
'ApplicationSid' => 'AP44efecad51364e80b133bb7c07eb8204'
|
|
35
|
+
}
|
|
36
|
+
signature = 'oVb2kXoVy8GEfwBDjR8bk/ZZ6eA='
|
|
37
|
+
validator.validate(url, params, signature).should == true
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'should properly validate a Twilio SMS request' do
|
|
41
|
+
token = '2bd9e9638872de601313dc77410d3b23'
|
|
42
|
+
validator = Twilio::Util::RequestValidator.new token
|
|
43
|
+
url = 'http://twiliotests.heroku.com/validate/sms'
|
|
44
|
+
params = {
|
|
45
|
+
'ToState' => 'CA',
|
|
46
|
+
'FromState' => 'CA',
|
|
47
|
+
'AccountSid' => 'ACba8bc05eacf94afdae398e642c9cc32d',
|
|
48
|
+
'SmsMessageSid' => 'SM2003cbd5e6a3701999aa3e5f20ff2787',
|
|
49
|
+
'Body' => 'Orly',
|
|
50
|
+
'From' => '+14159354345',
|
|
51
|
+
'FromCity' => 'SAN FRANCISCO',
|
|
52
|
+
'SmsStatus' => 'received',
|
|
53
|
+
'FromZip' => '94107',
|
|
54
|
+
'FromCountry' => 'US',
|
|
55
|
+
'To' => '+14158141819',
|
|
56
|
+
'ToCity' => 'SAN FRANCISCO',
|
|
57
|
+
'ToZip' => '94105',
|
|
58
|
+
'ToCountry' => 'US',
|
|
59
|
+
'ApiVersion' => '2010-04-01',
|
|
60
|
+
'SmsSid' => 'SM2003cbd5e6a3701999aa3e5f20ff2787'
|
|
61
|
+
}
|
|
62
|
+
signature = 'mxeiv65lEe0b8L6LdVw2jgJi8yw='
|
|
63
|
+
validator.validate(url, params, signature).should == true
|
|
64
|
+
end
|
|
65
|
+
end
|
data/twilio-ruby.gemspec
CHANGED
|
@@ -9,11 +9,12 @@ Gem::Specification.new do |s|
|
|
|
9
9
|
s.description = 'A simple library for communicating with the Twilio REST API, building TwiML, and generating Twilio Client Capability Tokens'
|
|
10
10
|
s.summary = 'A simple library for communicating with the Twilio REST API, building TwiML, and generating Twilio Client Capability Tokens'
|
|
11
11
|
s.homepage = 'http://github.com/twilio/twilio-ruby'
|
|
12
|
+
s.license = 'MIT'
|
|
12
13
|
|
|
13
14
|
s.platform = Gem::Platform::RUBY
|
|
14
15
|
s.require_paths = %w[lib]
|
|
15
16
|
s.files = `git ls-files`.split("\n")
|
|
16
|
-
s.test_files = Dir['
|
|
17
|
+
s.test_files = Dir['spec/**/*.rb']
|
|
17
18
|
|
|
18
19
|
s.add_dependency('multi_json', '>= 1.3.0')
|
|
19
20
|
s.add_dependency('builder', '>= 2.1.2')
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: twilio-ruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
hash:
|
|
4
|
+
hash: 25
|
|
5
5
|
prerelease:
|
|
6
6
|
segments:
|
|
7
7
|
- 3
|
|
8
8
|
- 7
|
|
9
|
-
-
|
|
10
|
-
version: 3.7.
|
|
9
|
+
- 1
|
|
10
|
+
version: 3.7.1
|
|
11
11
|
platform: ruby
|
|
12
12
|
authors:
|
|
13
13
|
- Andrew Benton
|
|
@@ -15,7 +15,7 @@ autorequire:
|
|
|
15
15
|
bindir: bin
|
|
16
16
|
cert_chain: []
|
|
17
17
|
|
|
18
|
-
date: 2012-
|
|
18
|
+
date: 2012-08-01 00:00:00 -07:00
|
|
19
19
|
default_executable:
|
|
20
20
|
dependencies:
|
|
21
21
|
- !ruby/object:Gem::Dependency
|
|
@@ -180,12 +180,20 @@ files:
|
|
|
180
180
|
- lib/twilio-ruby/util/capability.rb
|
|
181
181
|
- lib/twilio-ruby/util/request_validator.rb
|
|
182
182
|
- lib/twilio-ruby/version.rb
|
|
183
|
-
-
|
|
183
|
+
- spec/rest/account_spec.rb
|
|
184
|
+
- spec/rest/call_spec.rb
|
|
185
|
+
- spec/rest/client_spec.rb
|
|
186
|
+
- spec/rest/conference_spec.rb
|
|
187
|
+
- spec/rest/instance_resource_spec.rb
|
|
188
|
+
- spec/rest/recording_spec.rb
|
|
189
|
+
- spec/spec_helper.rb
|
|
190
|
+
- spec/util/capability_spec.rb
|
|
191
|
+
- spec/util/request_validator_spec.rb
|
|
184
192
|
- twilio-ruby.gemspec
|
|
185
193
|
has_rdoc: true
|
|
186
194
|
homepage: http://github.com/twilio/twilio-ruby
|
|
187
|
-
licenses:
|
|
188
|
-
|
|
195
|
+
licenses:
|
|
196
|
+
- MIT
|
|
189
197
|
post_install_message:
|
|
190
198
|
rdoc_options:
|
|
191
199
|
- --line-numbers
|
|
@@ -222,4 +230,12 @@ signing_key:
|
|
|
222
230
|
specification_version: 3
|
|
223
231
|
summary: A simple library for communicating with the Twilio REST API, building TwiML, and generating Twilio Client Capability Tokens
|
|
224
232
|
test_files:
|
|
225
|
-
-
|
|
233
|
+
- spec/spec_helper.rb
|
|
234
|
+
- spec/rest/call_spec.rb
|
|
235
|
+
- spec/rest/conference_spec.rb
|
|
236
|
+
- spec/rest/account_spec.rb
|
|
237
|
+
- spec/rest/instance_resource_spec.rb
|
|
238
|
+
- spec/rest/client_spec.rb
|
|
239
|
+
- spec/rest/recording_spec.rb
|
|
240
|
+
- spec/util/capability_spec.rb
|
|
241
|
+
- spec/util/request_validator_spec.rb
|
data/test/twilio_spec.rb
DELETED
|
@@ -1,393 +0,0 @@
|
|
|
1
|
-
$LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
|
|
2
|
-
require 'twilio-ruby'
|
|
3
|
-
require 'fakeweb'
|
|
4
|
-
require 'rack'
|
|
5
|
-
|
|
6
|
-
describe Twilio::REST::Client do
|
|
7
|
-
before :all do
|
|
8
|
-
FakeWeb.register_uri(:any, %r/http:\/\/api.twilio.com\//, :body => '{"message": "You tried to reach Twilio"}')
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
it 'should set up a new client instance with the given sid and token' do
|
|
12
|
-
twilio = Twilio::REST::Client.new('someSid', 'someToken')
|
|
13
|
-
twilio.account_sid.should == 'someSid'
|
|
14
|
-
twilio.instance_variable_get('@auth_token').should == 'someToken'
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
it 'should set up the proper default http ssl connection' do
|
|
18
|
-
twilio = Twilio::REST::Client.new('someSid', 'someToken')
|
|
19
|
-
connection = twilio.instance_variable_get('@connection')
|
|
20
|
-
connection.address.should == 'api.twilio.com'
|
|
21
|
-
connection.port.should == 443
|
|
22
|
-
connection.use_ssl?.should == true
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
it 'should set up the requested ssl verification ca_file if provided' do
|
|
26
|
-
twilio = Twilio::REST::Client.new('someSid', 'someToken', :ssl_ca_file => '/path/to/ca/file')
|
|
27
|
-
connection = twilio.instance_variable_get('@connection')
|
|
28
|
-
connection.ca_file.should == '/path/to/ca/file'
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
it 'should set up the proper http ssl connection when a different domain is given' do
|
|
32
|
-
twilio = Twilio::REST::Client.new('someSid', 'someToken', :host => 'api.faketwilio.com')
|
|
33
|
-
connection = twilio.instance_variable_get('@connection')
|
|
34
|
-
connection.address.should == 'api.faketwilio.com'
|
|
35
|
-
connection.port.should == 443
|
|
36
|
-
connection.use_ssl?.should == true
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
it 'should adjust the open and read timeouts on the underlying Net::HTTP object when asked' do
|
|
40
|
-
timeout = rand(30)
|
|
41
|
-
twilio = Twilio::REST::Client.new('someSid', 'someToken', :timeout => timeout)
|
|
42
|
-
connection = twilio.instance_variable_get('@connection')
|
|
43
|
-
connection.port.should == 443
|
|
44
|
-
connection.use_ssl?.should == true
|
|
45
|
-
connection.open_timeout.should == timeout
|
|
46
|
-
connection.read_timeout.should == timeout
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
it 'should set up the proper http ssl connection when a proxy_host is given' do
|
|
50
|
-
twilio = Twilio::REST::Client.new('someSid', 'someToken', :host => 'api.faketwilio.com', :proxy_addr => 'localhost')
|
|
51
|
-
connection = twilio.instance_variable_get('@connection')
|
|
52
|
-
connection.proxy?.should == true
|
|
53
|
-
connection.proxy_address.should == 'localhost'
|
|
54
|
-
connection.proxy_port.should == 80
|
|
55
|
-
connection.address.should == 'api.faketwilio.com'
|
|
56
|
-
connection.port.should == 443
|
|
57
|
-
connection.use_ssl?.should == true
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
it 'should set up the proper http ssl connection when a proxy_host and proxy_port are given' do
|
|
61
|
-
twilio = Twilio::REST::Client.new('someSid', 'someToken', :host => 'api.faketwilio.com', :proxy_addr => 'localhost', :proxy_port => 13128)
|
|
62
|
-
connection = twilio.instance_variable_get('@connection')
|
|
63
|
-
connection.proxy?.should == true
|
|
64
|
-
connection.proxy_address.should == 'localhost'
|
|
65
|
-
connection.proxy_port.should == 13128
|
|
66
|
-
connection.address.should == 'api.faketwilio.com'
|
|
67
|
-
connection.port.should == 443
|
|
68
|
-
connection.use_ssl?.should == true
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
it 'should set up an accounts resources object' do
|
|
72
|
-
twilio = Twilio::REST::Client.new('someSid', 'someToken')
|
|
73
|
-
twilio.respond_to?(:accounts).should == true
|
|
74
|
-
twilio.accounts.instance_variable_get('@uri').should == '/2010-04-01/Accounts'
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
it 'should set up an account object with the given sid' do
|
|
78
|
-
twilio = Twilio::REST::Client.new('someSid', 'someToken')
|
|
79
|
-
twilio.respond_to?(:account).should == true
|
|
80
|
-
twilio.account.instance_variable_get('@uri').should == '/2010-04-01/Accounts/someSid'
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
it 'should convert all parameter names to Twilio-style names' do
|
|
84
|
-
twilio = Twilio::REST::Client.new('someSid', 'someToken')
|
|
85
|
-
untwilified = {:sms_url => 'someUrl', 'voiceFallbackUrl' => 'anotherUrl',
|
|
86
|
-
'Status_callback' => 'yetAnotherUrl'}
|
|
87
|
-
twilified = {:SmsUrl => 'someUrl', :VoiceFallbackUrl => 'anotherUrl',
|
|
88
|
-
:StatusCallback => 'yetAnotherUrl'}
|
|
89
|
-
twilio.instance_eval do
|
|
90
|
-
twilify(untwilified).should == twilified
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
describe Twilio::REST::InstanceResource do
|
|
96
|
-
it 'should set up an internal reference to the uri and client' do
|
|
97
|
-
resource = Twilio::REST::InstanceResource.new('some/uri', 'someClient')
|
|
98
|
-
resource.instance_variable_get('@uri').should == 'some/uri'
|
|
99
|
-
resource.instance_variable_get('@client').should == 'someClient'
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
it 'should set up object properties if passed' do
|
|
103
|
-
params = {'SomeKey' => 'someValue'}
|
|
104
|
-
resource = Twilio::REST::InstanceResource.new('uri', 'client', params)
|
|
105
|
-
resource.some_key.should == 'someValue'
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
describe Twilio::REST::Account do
|
|
110
|
-
it 'should set up an incoming phone numbers resources object' do
|
|
111
|
-
account = Twilio::REST::Account.new('someUri', 'someClient')
|
|
112
|
-
account.respond_to?(:incoming_phone_numbers).should == true
|
|
113
|
-
account.incoming_phone_numbers.instance_variable_get('@uri').should == 'someUri/IncomingPhoneNumbers'
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
it 'should set up an available phone numbers resources object' do
|
|
117
|
-
account = Twilio::REST::Account.new('someUri', 'someClient')
|
|
118
|
-
account.respond_to?(:available_phone_numbers).should == true
|
|
119
|
-
account.available_phone_numbers.instance_variable_get('@uri').should == 'someUri/AvailablePhoneNumbers'
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
it 'should set up an outgoing caller ids resources object' do
|
|
123
|
-
account = Twilio::REST::Account.new('someUri', 'someClient')
|
|
124
|
-
account.respond_to?(:outgoing_caller_ids).should == true
|
|
125
|
-
account.outgoing_caller_ids.instance_variable_get('@uri').should == 'someUri/OutgoingCallerIds'
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
it 'should set up a calls resources object' do
|
|
129
|
-
account = Twilio::REST::Account.new('someUri', 'someClient')
|
|
130
|
-
account.respond_to?(:calls).should == true
|
|
131
|
-
account.calls.instance_variable_get('@uri').should == 'someUri/Calls'
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
it 'should set up a conferences resources object' do
|
|
135
|
-
account = Twilio::REST::Account.new('someUri', 'someClient')
|
|
136
|
-
account.respond_to?(:conferences).should == true
|
|
137
|
-
account.conferences.instance_variable_get('@uri').should == 'someUri/Conferences'
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
it 'should set up a sms resource object' do
|
|
141
|
-
account = Twilio::REST::Account.new('someUri', 'someClient')
|
|
142
|
-
account.respond_to?(:sms).should == true
|
|
143
|
-
account.sms.instance_variable_get('@uri').should == 'someUri/SMS'
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
it 'should set up a recordings resources object' do
|
|
147
|
-
account = Twilio::REST::Account.new('someUri', 'someClient')
|
|
148
|
-
account.respond_to?(:recordings).should == true
|
|
149
|
-
account.recordings.instance_variable_get('@uri').should == 'someUri/Recordings'
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
it 'should set up a transcriptions resources object' do
|
|
153
|
-
account = Twilio::REST::Account.new('someUri', 'someClient')
|
|
154
|
-
account.respond_to?(:transcriptions).should == true
|
|
155
|
-
account.transcriptions.instance_variable_get('@uri').should == 'someUri/Transcriptions'
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
it 'should set up a notifications resources object' do
|
|
159
|
-
account = Twilio::REST::Account.new('someUri', 'someClient')
|
|
160
|
-
account.respond_to?(:notifications).should == true
|
|
161
|
-
account.notifications.instance_variable_get('@uri').should == 'someUri/Notifications'
|
|
162
|
-
end
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
describe Twilio::REST::Call do
|
|
166
|
-
it 'should set up a recordings resources object' do
|
|
167
|
-
call = Twilio::REST::Call.new('someUri', 'someClient')
|
|
168
|
-
call.respond_to?(:recordings).should == true
|
|
169
|
-
call.recordings.instance_variable_get('@uri').should == 'someUri/Recordings'
|
|
170
|
-
end
|
|
171
|
-
|
|
172
|
-
it 'should set up a notifications resources object' do
|
|
173
|
-
call = Twilio::REST::Call.new('someUri', 'someClient')
|
|
174
|
-
call.respond_to?(:notifications).should == true
|
|
175
|
-
call.notifications.instance_variable_get('@uri').should == 'someUri/Notifications'
|
|
176
|
-
end
|
|
177
|
-
end
|
|
178
|
-
|
|
179
|
-
describe Twilio::REST::Conference do
|
|
180
|
-
it 'should set up a participants resources object' do
|
|
181
|
-
call = Twilio::REST::Conference.new('someUri', 'someClient')
|
|
182
|
-
call.respond_to?(:participants).should == true
|
|
183
|
-
call.participants.instance_variable_get('@uri').should == 'someUri/Participants'
|
|
184
|
-
end
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
describe Twilio::REST::Recording do
|
|
188
|
-
it 'should set up a transcriptions resources object' do
|
|
189
|
-
call = Twilio::REST::Recording.new('someUri', 'someClient')
|
|
190
|
-
call.respond_to?(:transcriptions).should == true
|
|
191
|
-
call.transcriptions.instance_variable_get('@uri').should == 'someUri/Transcriptions'
|
|
192
|
-
end
|
|
193
|
-
end
|
|
194
|
-
|
|
195
|
-
describe Twilio::Util::RequestValidator do
|
|
196
|
-
it 'should properly validate a Twilio Voice request' do
|
|
197
|
-
token = '2bd9e9638872de601313dc77410d3b23'
|
|
198
|
-
validator = Twilio::Util::RequestValidator.new token
|
|
199
|
-
url = 'http://twiliotests.heroku.com/validate/voice'
|
|
200
|
-
params = {
|
|
201
|
-
'ToState' => 'California',
|
|
202
|
-
'CalledState' => 'California',
|
|
203
|
-
'Direction' => 'inbound',
|
|
204
|
-
'FromState' => 'CA',
|
|
205
|
-
'AccountSid' => 'ACba8bc05eacf94afdae398e642c9cc32d',
|
|
206
|
-
'Caller' => '+14153595711',
|
|
207
|
-
'CallerZip' => '94108',
|
|
208
|
-
'CallerCountry' => 'US',
|
|
209
|
-
'From' => '+14153595711',
|
|
210
|
-
'FromCity' => 'SAN FRANCISCO',
|
|
211
|
-
'CallerCity' => 'SAN FRANCISCO',
|
|
212
|
-
'To' => '+14157669926',
|
|
213
|
-
'FromZip' => '94108',
|
|
214
|
-
'FromCountry' => 'US',
|
|
215
|
-
'ToCity' => '',
|
|
216
|
-
'CallStatus' => 'ringing',
|
|
217
|
-
'CalledCity' => '',
|
|
218
|
-
'CallerState' => 'CA',
|
|
219
|
-
'CalledZip' => '',
|
|
220
|
-
'ToZip' => '',
|
|
221
|
-
'ToCountry' => 'US',
|
|
222
|
-
'CallSid' => 'CA136d09cd59a3c0ec8dbff44da5c03f31',
|
|
223
|
-
'CalledCountry' => 'US',
|
|
224
|
-
'Called' => '+14157669926',
|
|
225
|
-
'ApiVersion' => '2010-04-01',
|
|
226
|
-
'ApplicationSid' => 'AP44efecad51364e80b133bb7c07eb8204'
|
|
227
|
-
}
|
|
228
|
-
signature = 'oVb2kXoVy8GEfwBDjR8bk/ZZ6eA='
|
|
229
|
-
validator.validate(url, params, signature).should == true
|
|
230
|
-
end
|
|
231
|
-
|
|
232
|
-
it 'should properly validate a Twilio SMS request' do
|
|
233
|
-
token = '2bd9e9638872de601313dc77410d3b23'
|
|
234
|
-
validator = Twilio::Util::RequestValidator.new token
|
|
235
|
-
url = 'http://twiliotests.heroku.com/validate/sms'
|
|
236
|
-
params = {
|
|
237
|
-
'ToState' => 'CA',
|
|
238
|
-
'FromState' => 'CA',
|
|
239
|
-
'AccountSid' => 'ACba8bc05eacf94afdae398e642c9cc32d',
|
|
240
|
-
'SmsMessageSid' => 'SM2003cbd5e6a3701999aa3e5f20ff2787',
|
|
241
|
-
'Body' => 'Orly',
|
|
242
|
-
'From' => '+14159354345',
|
|
243
|
-
'FromCity' => 'SAN FRANCISCO',
|
|
244
|
-
'SmsStatus' => 'received',
|
|
245
|
-
'FromZip' => '94107',
|
|
246
|
-
'FromCountry' => 'US',
|
|
247
|
-
'To' => '+14158141819',
|
|
248
|
-
'ToCity' => 'SAN FRANCISCO',
|
|
249
|
-
'ToZip' => '94105',
|
|
250
|
-
'ToCountry' => 'US',
|
|
251
|
-
'ApiVersion' => '2010-04-01',
|
|
252
|
-
'SmsSid' => 'SM2003cbd5e6a3701999aa3e5f20ff2787'
|
|
253
|
-
}
|
|
254
|
-
signature = 'mxeiv65lEe0b8L6LdVw2jgJi8yw='
|
|
255
|
-
validator.validate(url, params, signature).should == true
|
|
256
|
-
end
|
|
257
|
-
end
|
|
258
|
-
|
|
259
|
-
describe Twilio::Util::Capability do
|
|
260
|
-
before :each do
|
|
261
|
-
@capability = Twilio::Util::Capability.new 'myAccountSid', 'myAuthToken'
|
|
262
|
-
end
|
|
263
|
-
|
|
264
|
-
def queries(q)
|
|
265
|
-
q.scan(/scope:client:(incoming|outgoing)\?(\S+)/).map{|(type, query)| [type, Rack::Utils.parse_query(query)]}
|
|
266
|
-
end
|
|
267
|
-
|
|
268
|
-
it 'should return a valid jwt when #generate is called' do
|
|
269
|
-
token = @capability.generate
|
|
270
|
-
decoded = JWT.decode token, 'myAuthToken'
|
|
271
|
-
decoded['scope'].should_not be_nil
|
|
272
|
-
decoded['iss'].should_not be_nil
|
|
273
|
-
decoded['exp'].should_not be_nil
|
|
274
|
-
end
|
|
275
|
-
|
|
276
|
-
it 'should properly set the iss key in the payload' do
|
|
277
|
-
token = @capability.generate
|
|
278
|
-
decoded = JWT.decode token, 'myAuthToken'
|
|
279
|
-
decoded['iss'].should == 'myAccountSid'
|
|
280
|
-
end
|
|
281
|
-
|
|
282
|
-
it 'should properly set the exp key based on the default hour ttl' do
|
|
283
|
-
seconds = Time.now.to_i
|
|
284
|
-
token = @capability.generate
|
|
285
|
-
decoded = JWT.decode token, 'myAuthToken'
|
|
286
|
-
decoded['exp'].should == seconds + 3600
|
|
287
|
-
end
|
|
288
|
-
|
|
289
|
-
it 'should properly set the exp key based on the ttl passed to #generate' do
|
|
290
|
-
ttl = rand 10000
|
|
291
|
-
seconds = Time.now.to_i
|
|
292
|
-
token = @capability.generate ttl
|
|
293
|
-
decoded = JWT.decode token, 'myAuthToken'
|
|
294
|
-
decoded['exp'].should == seconds + ttl
|
|
295
|
-
end
|
|
296
|
-
|
|
297
|
-
it 'should generate a proper incoming client scope string' do
|
|
298
|
-
@capability.allow_client_incoming 'andrew'
|
|
299
|
-
token = @capability.generate
|
|
300
|
-
decoded = JWT.decode token, 'myAuthToken'
|
|
301
|
-
queries(decoded['scope']).should == [['incoming', {'clientName' => 'andrew'}]]
|
|
302
|
-
end
|
|
303
|
-
|
|
304
|
-
it 'should generate multiple proper incoming client scope strings' do
|
|
305
|
-
@capability.allow_client_incoming 'andrew'
|
|
306
|
-
@capability.allow_client_incoming 'bridget'
|
|
307
|
-
token = @capability.generate
|
|
308
|
-
decoded = JWT.decode token, 'myAuthToken'
|
|
309
|
-
queries(decoded['scope']).should == [
|
|
310
|
-
['incoming', {'clientName' => 'andrew'}],
|
|
311
|
-
['incoming', {'clientName' => 'bridget'}]
|
|
312
|
-
]
|
|
313
|
-
end
|
|
314
|
-
|
|
315
|
-
it 'should generate a proper outgoing client scope string' do
|
|
316
|
-
@capability.allow_client_outgoing 'myAppSid'
|
|
317
|
-
token = @capability.generate
|
|
318
|
-
decoded = JWT.decode token, 'myAuthToken'
|
|
319
|
-
queries(decoded['scope']).should == [['outgoing', {'appSid' => 'myAppSid'}]]
|
|
320
|
-
end
|
|
321
|
-
|
|
322
|
-
it 'should generate a proper outgoing client scope string with parameters' do
|
|
323
|
-
app_params_hash = {'key' => 'a value', :foo => 'bar/baz'}
|
|
324
|
-
@capability.allow_client_outgoing 'myAppSid', app_params_hash
|
|
325
|
-
app_params = @capability.instance_eval {url_encode(app_params_hash)}
|
|
326
|
-
params_hash = {'appSid' => 'myAppSid', 'appParams' => app_params}
|
|
327
|
-
params = @capability.instance_eval {url_encode(params_hash)}
|
|
328
|
-
token = @capability.generate
|
|
329
|
-
decoded = JWT.decode token, 'myAuthToken'
|
|
330
|
-
queries(decoded['scope']).should == [['outgoing', params_hash]]
|
|
331
|
-
end
|
|
332
|
-
|
|
333
|
-
it 'should generate a proper outgoing client scope string based on the ' +
|
|
334
|
-
'client name when calling #allow_client_incoming first' do
|
|
335
|
-
@capability.allow_client_incoming 'andrew'
|
|
336
|
-
@capability.allow_client_outgoing 'myAppSid'
|
|
337
|
-
token = @capability.generate
|
|
338
|
-
decoded = JWT.decode token, 'myAuthToken'
|
|
339
|
-
queries(decoded['scope']).should == [
|
|
340
|
-
['incoming', {'clientName' => 'andrew'}],
|
|
341
|
-
['outgoing', {'clientName' => 'andrew', 'appSid' => 'myAppSid'}]
|
|
342
|
-
]
|
|
343
|
-
end
|
|
344
|
-
|
|
345
|
-
it 'should generate a proper outgoing client scope string based on the ' +
|
|
346
|
-
'client name when calling #allow_client_incoming second' do
|
|
347
|
-
@capability.allow_client_outgoing 'myAppSid'
|
|
348
|
-
@capability.allow_client_incoming 'andrew'
|
|
349
|
-
token = @capability.generate
|
|
350
|
-
decoded = JWT.decode token, 'myAuthToken'
|
|
351
|
-
queries(decoded['scope']).should == [["incoming", {"clientName"=>"andrew"}], ["outgoing", {"clientName"=>"andrew", "appSid"=>"myAppSid"}]]
|
|
352
|
-
end
|
|
353
|
-
|
|
354
|
-
it 'should generate a proper outgoing client scope string with parameters ' +
|
|
355
|
-
'and a client name when calling #allow_client_incoming first' do
|
|
356
|
-
@capability.allow_client_incoming 'andrew'
|
|
357
|
-
app_params_hash = {'key' => 'a value', :foo => 'bar/baz'}
|
|
358
|
-
@capability.allow_client_outgoing 'myAppSid', app_params_hash
|
|
359
|
-
app_params = @capability.instance_eval {url_encode(app_params_hash)}
|
|
360
|
-
params_hash = {'appSid' => 'myAppSid', 'appParams' => app_params, 'clientName' => 'andrew'}
|
|
361
|
-
params = @capability.instance_eval {url_encode(params_hash)}
|
|
362
|
-
token = @capability.generate
|
|
363
|
-
decoded = JWT.decode token, 'myAuthToken'
|
|
364
|
-
scopes = queries(decoded['scope'])
|
|
365
|
-
scopes.shift.should == ["incoming", {"clientName"=>"andrew"}]
|
|
366
|
-
scope = scopes.shift
|
|
367
|
-
scope.first.should == 'outgoing'
|
|
368
|
-
Rack::Utils.parse_query(scope.last['appParams']).should == {'key' => 'a value', 'foo' => 'bar/baz'}
|
|
369
|
-
scope.last["clientName"].should == "andrew"
|
|
370
|
-
scope.last["appSid"].should == "myAppSid"
|
|
371
|
-
scopes.should be_empty
|
|
372
|
-
end
|
|
373
|
-
|
|
374
|
-
it 'should generate a proper outgoing client scope string with parameters ' +
|
|
375
|
-
'and a client name when calling #allow_client_incoming second' do
|
|
376
|
-
app_params_hash = {'key' => 'a value', :foo => 'bar/baz'}
|
|
377
|
-
@capability.allow_client_outgoing 'myAppSid', app_params_hash
|
|
378
|
-
@capability.allow_client_incoming 'andrew'
|
|
379
|
-
app_params = @capability.instance_eval {url_encode(app_params_hash)}
|
|
380
|
-
params_hash = {'appSid' => 'myAppSid', 'appParams' => app_params, 'clientName' => 'andrew'}
|
|
381
|
-
params = @capability.instance_eval {url_encode(params_hash)}
|
|
382
|
-
token = @capability.generate
|
|
383
|
-
decoded = JWT.decode token, 'myAuthToken'
|
|
384
|
-
scopes = queries(decoded['scope'])
|
|
385
|
-
scopes.shift.should == ["incoming", {"clientName"=>"andrew"}]
|
|
386
|
-
scope = scopes.shift
|
|
387
|
-
scope.first.should == 'outgoing'
|
|
388
|
-
Rack::Utils.parse_query(scope.last['appParams']).should == {'key' => 'a value', 'foo' => 'bar/baz'}
|
|
389
|
-
scope.last["clientName"].should == "andrew"
|
|
390
|
-
scope.last["appSid"].should == "myAppSid"
|
|
391
|
-
scopes.should be_empty
|
|
392
|
-
end
|
|
393
|
-
end
|