twilio-ruby 3.11.5 → 4.0.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 (114) hide show
  1. checksums.yaml +13 -5
  2. data/.gitignore +1 -1
  3. data/.travis.yml +20 -9
  4. data/AUTHORS.md +32 -25
  5. data/CHANGES.md +203 -0
  6. data/Gemfile +8 -1
  7. data/{LICENSE → LICENSE.md} +4 -2
  8. data/Makefile +1 -2
  9. data/README.md +70 -39
  10. data/Rakefile +8 -10
  11. data/docs/faq.rst +3 -3
  12. data/docs/getting-started.rst +17 -12
  13. data/docs/index.rst +15 -0
  14. data/docs/usage/accounts.rst +6 -6
  15. data/docs/usage/addresses.rst +101 -0
  16. data/docs/usage/applications.rst +10 -10
  17. data/docs/usage/basics.rst +17 -4
  18. data/docs/usage/caller-ids.rst +4 -2
  19. data/docs/usage/conferences.rst +11 -11
  20. data/docs/usage/errors.rst +7 -7
  21. data/docs/usage/messages.rst +48 -20
  22. data/docs/usage/notifications.rst +6 -4
  23. data/docs/usage/phone-calls.rst +33 -14
  24. data/docs/usage/phone-numbers.rst +45 -31
  25. data/docs/usage/queues.rst +8 -8
  26. data/docs/usage/recordings.rst +12 -10
  27. data/docs/usage/sip.rst +15 -14
  28. data/docs/usage/taskrouter-tokens.rst +98 -0
  29. data/docs/usage/taskrouter.rst +226 -0
  30. data/docs/usage/token-generation.rst +19 -4
  31. data/docs/usage/transcriptions.rst +3 -2
  32. data/docs/usage/twiml.rst +7 -7
  33. data/docs/usage/validation.rst +39 -3
  34. data/examples/examples.rb +44 -20
  35. data/examples/print-call-log.rb +1 -1
  36. data/lib/rack/twilio_webhook_authentication.rb +47 -0
  37. data/lib/twilio-ruby/rest/accounts.rb +2 -1
  38. data/lib/twilio-ruby/rest/addresses/dependent_phone_numbers.rb +6 -0
  39. data/lib/twilio-ruby/rest/addresses.rb +12 -0
  40. data/lib/twilio-ruby/rest/base_client.rb +127 -0
  41. data/lib/twilio-ruby/rest/call_feedback.rb +28 -0
  42. data/lib/twilio-ruby/rest/call_feedback_summary.rb +13 -0
  43. data/lib/twilio-ruby/rest/calls.rb +10 -5
  44. data/lib/twilio-ruby/rest/client.rb +44 -109
  45. data/lib/twilio-ruby/rest/conferences/participants.rb +2 -2
  46. data/lib/twilio-ruby/rest/incoming_phone_numbers.rb +1 -1
  47. data/lib/twilio-ruby/rest/instance_resource.rb +2 -16
  48. data/lib/twilio-ruby/rest/list_resource.rb +20 -30
  49. data/lib/twilio-ruby/rest/lookups/phone_numbers.rb +17 -0
  50. data/lib/twilio-ruby/rest/lookups_client.rb +99 -0
  51. data/lib/twilio-ruby/rest/messages.rb +5 -0
  52. data/lib/twilio-ruby/rest/next_gen_list_resource.rb +36 -0
  53. data/lib/twilio-ruby/rest/outgoing_caller_ids.rb +1 -1
  54. data/lib/twilio-ruby/rest/queues/members.rb +1 -1
  55. data/lib/twilio-ruby/rest/sip.rb +1 -3
  56. data/lib/twilio-ruby/rest/sms/messages.rb +23 -0
  57. data/lib/twilio-ruby/rest/task_router/activities.rb +8 -0
  58. data/lib/twilio-ruby/rest/task_router/events.rb +8 -0
  59. data/lib/twilio-ruby/rest/task_router/reservations.rb +8 -0
  60. data/lib/twilio-ruby/rest/task_router/statistics.rb +26 -0
  61. data/lib/twilio-ruby/rest/task_router/task_queues.rb +17 -0
  62. data/lib/twilio-ruby/rest/task_router/task_queues_statistics.rb +15 -0
  63. data/lib/twilio-ruby/rest/task_router/tasks.rb +15 -0
  64. data/lib/twilio-ruby/rest/task_router/workers.rb +13 -0
  65. data/lib/twilio-ruby/rest/task_router/workers_statistics.rb +8 -0
  66. data/lib/twilio-ruby/rest/task_router/workflow_statistics.rb +7 -0
  67. data/lib/twilio-ruby/rest/task_router/workflows.rb +11 -0
  68. data/lib/twilio-ruby/rest/task_router/workspace_statistics.rb +7 -0
  69. data/lib/twilio-ruby/rest/task_router/workspaces.rb +17 -0
  70. data/lib/twilio-ruby/rest/task_router_client.rb +176 -0
  71. data/lib/twilio-ruby/rest/tokens.rb +7 -0
  72. data/lib/twilio-ruby/rest/usage/records.rb +2 -2
  73. data/lib/twilio-ruby/rest/utils.rb +35 -11
  74. data/lib/twilio-ruby/task_router/capability.rb +87 -0
  75. data/lib/twilio-ruby/task_router.rb +0 -0
  76. data/lib/twilio-ruby/twiml/response.rb +1 -0
  77. data/lib/twilio-ruby/util/capability.rb +10 -7
  78. data/lib/twilio-ruby/util/client_config.rb +29 -0
  79. data/lib/twilio-ruby/util/configuration.rb +7 -0
  80. data/lib/twilio-ruby/util/request_validator.rb +18 -3
  81. data/lib/twilio-ruby/version.rb +1 -1
  82. data/lib/twilio-ruby.rb +48 -0
  83. data/spec/rack/twilio_webhook_authentication_spec.rb +110 -0
  84. data/spec/rest/account_spec.rb +51 -20
  85. data/spec/rest/address_spec.rb +11 -0
  86. data/spec/rest/call_feedback_spec.rb +12 -0
  87. data/spec/rest/call_feedback_summary_spec.rb +9 -0
  88. data/spec/rest/call_spec.rb +8 -4
  89. data/spec/rest/client_spec.rb +209 -51
  90. data/spec/rest/conference_spec.rb +4 -2
  91. data/spec/rest/instance_resource_spec.rb +4 -4
  92. data/spec/rest/lookups/phone_number_spec.rb +8 -0
  93. data/spec/rest/message_spec.rb +2 -2
  94. data/spec/rest/numbers_spec.rb +25 -13
  95. data/spec/rest/queue_spec.rb +4 -2
  96. data/spec/rest/recording_spec.rb +4 -2
  97. data/spec/rest/sms/message_spec.rb +37 -0
  98. data/spec/rest/sms/messages_spec.rb +31 -0
  99. data/spec/rest/task_router/reservation_spec.rb +9 -0
  100. data/spec/rest/task_router/task_queue_spec.rb +9 -0
  101. data/spec/rest/token_spec.rb +7 -0
  102. data/spec/rest/utils_spec.rb +45 -0
  103. data/spec/spec_helper.rb +12 -3
  104. data/spec/support/fakeweb.rb +2 -0
  105. data/spec/task_router_spec.rb +114 -0
  106. data/spec/twilio_spec.rb +15 -0
  107. data/spec/util/capability_spec.rb +167 -118
  108. data/spec/util/client_config_spec.rb +21 -0
  109. data/spec/util/configuration_spec.rb +15 -0
  110. data/spec/util/request_validator_spec.rb +31 -3
  111. data/spec/util/url_encode_spec.rb +2 -2
  112. data/twilio-ruby.gemspec +28 -27
  113. metadata +93 -71
  114. data/CHANGES +0 -47
@@ -0,0 +1,114 @@
1
+ require 'spec_helper'
2
+
3
+ describe Twilio::TaskRouter::Capability do
4
+ describe 'with a capability' do
5
+ before :each do
6
+ @capability = Twilio::TaskRouter::Capability.new 'AC123', 'foobar', 'WS456', 'WK789'
7
+ end
8
+
9
+ it 'should return a valid jwt when #generate_token is called' do
10
+ token = @capability.generate_token
11
+ decoded, header = JWT.decode token, 'foobar'
12
+ expect(decoded['policies']).not_to be_nil
13
+ expect(decoded['iss']).not_to be_nil
14
+ expect(decoded['exp']).not_to be_nil
15
+ end
16
+
17
+ it 'should properly set the iss key in the payload' do
18
+ token = @capability.generate_token
19
+ decoded, header = JWT.decode token, 'foobar'
20
+ expect(decoded['iss']).to eq('AC123')
21
+ end
22
+
23
+ it 'should properly set exp based on the default 1-hour ttl' do
24
+ seconds = Time.now.to_i
25
+ token = @capability.generate_token
26
+ decoded, header = JWT.decode token, 'foobar'
27
+ expect(decoded['exp']).to eq(seconds + 3600)
28
+ end
29
+
30
+ it 'should properly set exp based on the ttl arg to #generate_token' do
31
+ seconds = Time.now.to_i
32
+ ttl = rand 10000
33
+ token = @capability.generate_token ttl
34
+ decoded, header = JWT.decode token, 'foobar'
35
+ expect(decoded['exp']).to eq(seconds + ttl)
36
+ end
37
+
38
+ it 'should allow websocket operations and activity list fetches by default' do
39
+ token = @capability.generate_token
40
+ decoded, header = JWT.decode token, 'foobar'
41
+ expect(decoded['policies'].size).to eq(3)
42
+ get_policy = {
43
+ "url" => 'https://event-bridge.twilio.com/v1/wschannels/AC123/WK789',
44
+ "method" => 'GET',
45
+ "query_filter" => {},
46
+ "post_filter" => {},
47
+ "allow" => true
48
+ }
49
+ expect(decoded['policies'][0]).to eq(get_policy)
50
+ post_policy = {
51
+ "url" => 'https://event-bridge.twilio.com/v1/wschannels/AC123/WK789',
52
+ "method" => 'POST',
53
+ "query_filter" => {},
54
+ "post_filter" => {},
55
+ "allow" => true
56
+ }
57
+ expect(decoded['policies'][1]).to eq(post_policy)
58
+
59
+ activities_policy = {
60
+ 'url' => 'https://taskrouter.twilio.com/v1/Workspaces/WS456/Activities',
61
+ 'method' => 'GET',
62
+ 'query_filter' => {},
63
+ 'post_filter' => {},
64
+ 'allow' => true
65
+ }
66
+ expect(decoded['policies'][2]).to eq(activities_policy)
67
+ end
68
+
69
+ it 'should add a policy when #allow_worker_activity_updates is called' do
70
+ @capability.allow_worker_activity_updates
71
+ token = @capability.generate_token
72
+ decoded, header = JWT.decode token, 'foobar'
73
+ expect(decoded['policies'].size).to eq(4)
74
+ activity_policy = {
75
+ 'url' => 'https://taskrouter.twilio.com/v1/Workspaces/WS456/Workers/WK789',
76
+ 'method' => 'POST',
77
+ 'query_filter' => {},
78
+ 'post_filter' => {'ActivitySid' => {'required' => true}},
79
+ 'allow' => true
80
+ }
81
+ expect(decoded['policies'][-1]).to eq(activity_policy)
82
+ end
83
+
84
+ it 'should add a policy when #allow_worker_fetch_attributes is called' do
85
+ @capability.allow_worker_fetch_attributes
86
+ token = @capability.generate_token
87
+ decoded, header = JWT.decode token, 'foobar'
88
+ expect(decoded['policies'].size).to eq(4)
89
+ worker_policy = {
90
+ 'url' => 'https://taskrouter.twilio.com/v1/Workspaces/WS456/Workers/WK789',
91
+ 'method' => 'GET',
92
+ 'query_filter' => {},
93
+ 'post_filter' => {},
94
+ 'allow' => true
95
+ }
96
+ expect(decoded['policies'][-1]).to eq(worker_policy)
97
+ end
98
+
99
+ it 'should add a policy when #allow_task_reservation_updates is called' do
100
+ @capability.allow_task_reservation_updates
101
+ token = @capability.generate_token
102
+ decoded, header = JWT.decode token, 'foobar'
103
+ expect(decoded['policies'].size).to eq(4)
104
+ task_policy = {
105
+ 'url' => 'https://taskrouter.twilio.com/v1/Workspaces/WS456/Tasks/**',
106
+ 'method' => 'POST',
107
+ 'query_filter' => {},
108
+ 'post_filter' => {'ReservationStatus' => {'required' => true}},
109
+ 'allow' => true
110
+ }
111
+ expect(decoded['policies'][-1]).to eq(task_policy)
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,15 @@
1
+ describe Twilio do
2
+ after(:each) do
3
+ Twilio.instance_variable_set('@configuration', nil)
4
+ end
5
+
6
+ it 'should set the account sid and auth token with a config block' do
7
+ Twilio.configure do |config|
8
+ config.account_sid = 'someSid'
9
+ config.auth_token = 'someToken'
10
+ end
11
+
12
+ expect(Twilio.account_sid).to eq('someSid')
13
+ expect(Twilio.auth_token).to eq('someToken')
14
+ end
15
+ end
@@ -1,137 +1,186 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Twilio::Util::Capability do
4
- before :each do
5
- @capability = Twilio::Util::Capability.new 'myAccountSid', 'myAuthToken'
6
- end
4
+ describe 'config' do
5
+ after(:each) do
6
+ Twilio.instance_variable_set('@configuration', nil)
7
+ end
7
8
 
8
- def queries(q)
9
- q.scan(/scope:client:(incoming|outgoing)\?(\S+)/).map{|(type, query)| [type, Rack::Utils.parse_query(query)]}
10
- end
9
+ it 'should set the account sid and auth token from a configuration block' do
10
+ Twilio.configure do |config|
11
+ config.account_sid = 'someSid'
12
+ config.auth_token = 'someToken'
13
+ end
11
14
 
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
15
+ capability = Twilio::Util::Capability.new
16
+ expect(capability.instance_variable_get('@account_sid')).to eq('someSid')
17
+ expect(capability.instance_variable_get('@auth_token')).to eq('someToken')
18
+ end
19
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
20
+ it 'should overwrite account sid and auth token if passed to initializer' do
21
+ Twilio.configure do |config|
22
+ config.account_sid = 'someSid'
23
+ config.auth_token = 'someToken'
24
+ end
25
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
26
+ capability = Twilio::Util::Capability.new'otherSid', 'otherToken'
27
+ expect(capability.instance_variable_get('@account_sid')).to eq('otherSid')
28
+ expect(capability.instance_variable_get('@auth_token')).to eq('otherToken')
29
+ end
32
30
 
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
31
+ it 'should overwrite the account sid if only the sid is given' do
32
+ Twilio.configure do |config|
33
+ config.account_sid = 'someSid'
34
+ config.auth_token = 'someToken'
35
+ end
40
36
 
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
37
+ capability = Twilio::Util::Capability.new 'otherSid'
38
+ expect(capability.instance_variable_get('@account_sid')).to eq('otherSid')
39
+ expect(capability.instance_variable_get('@auth_token')).to eq('someToken')
40
+ end
47
41
 
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
42
+ it 'should throw an argument error if the sid and token isn\'t set' do
43
+ expect { Twilio::Util::Capability.new }.to raise_error(ArgumentError)
44
+ end
58
45
 
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'}]]
46
+ it 'should throw an argument error if only the account_sid is set' do
47
+ expect { Twilio::Util::Capability.new 'someSid' }.to raise_error(ArgumentError)
48
+ end
64
49
  end
65
50
 
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
- @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
51
+ describe 'with a capability' do
52
+ before :each do
53
+ @capability = Twilio::Util::Capability.new 'myAccountSid', 'myAuthToken'
54
+ end
76
55
 
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
56
+ def queries(q)
57
+ q.scan(/scope:client:(incoming|outgoing)\?(\S+)/).map{|(type, query)| [type, Rack::Utils.parse_query(query)]}
58
+ end
88
59
 
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
60
+ it 'should return a valid jwt when #generate is called' do
61
+ token = @capability.generate
62
+ decoded, header = JWT.decode token, 'myAuthToken'
63
+ expect(decoded['scope']).not_to be_nil
64
+ expect(decoded['iss']).not_to be_nil
65
+ expect(decoded['exp']).not_to be_nil
66
+ end
97
67
 
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
- @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
68
+ it 'should properly set the iss key in the payload' do
69
+ token = @capability.generate
70
+ decoded, header = JWT.decode token, 'myAuthToken'
71
+ expect(decoded['iss']).to eq('myAccountSid')
72
+ end
73
+
74
+ it 'should properly set the exp key based on the default hour ttl' do
75
+ seconds = Time.now.to_i
76
+ token = @capability.generate
77
+ decoded, header = JWT.decode token, 'myAuthToken'
78
+ expect(decoded['exp']).to eq(seconds + 3600)
79
+ end
80
+
81
+ it 'should properly set the exp key based on the ttl passed to #generate' do
82
+ ttl = rand 10000
83
+ seconds = Time.now.to_i
84
+ token = @capability.generate ttl
85
+ decoded, header = JWT.decode token, 'myAuthToken'
86
+ expect(decoded['exp']).to eq(seconds + ttl)
87
+ end
88
+
89
+ it 'should generate a proper incoming client scope string' do
90
+ @capability.allow_client_incoming 'andrew'
91
+ token = @capability.generate
92
+ decoded, header = JWT.decode token, 'myAuthToken'
93
+ expect(queries(decoded['scope'])).to eq([['incoming', {'clientName' => 'andrew'}]])
94
+ end
95
+
96
+ it 'should generate multiple proper incoming client scope strings' do
97
+ @capability.allow_client_incoming 'andrew'
98
+ @capability.allow_client_incoming 'bridget'
99
+ token = @capability.generate
100
+ decoded, header = JWT.decode token, 'myAuthToken'
101
+ expect(queries(decoded['scope'])).to eq([
102
+ ['incoming', {'clientName' => 'andrew'}],
103
+ ['incoming', {'clientName' => 'bridget'}]
104
+ ])
105
+ end
106
+
107
+ it 'should generate a proper outgoing client scope string' do
108
+ @capability.allow_client_outgoing 'myAppSid'
109
+ token = @capability.generate
110
+ decoded, header = JWT.decode token, 'myAuthToken'
111
+ expect(queries(decoded['scope'])).to eq([['outgoing', {'appSid' => 'myAppSid'}]])
112
+ end
113
+
114
+ it 'should generate a proper outgoing client scope string with parameters' do
115
+ app_params_hash = {'key' => 'a value', :foo => 'bar/baz'}
116
+ @capability.allow_client_outgoing 'myAppSid', app_params_hash
117
+ app_params = @capability.instance_eval {url_encode(app_params_hash)}
118
+ params_hash = {'appSid' => 'myAppSid', 'appParams' => app_params}
119
+ @capability.instance_eval {url_encode(params_hash)}
120
+ token = @capability.generate
121
+ decoded, header= JWT.decode token, 'myAuthToken'
122
+ expect(queries(decoded['scope'])).to eq([['outgoing', params_hash]])
123
+ end
124
+
125
+ it 'should generate a proper outgoing client scope string based on the ' +
126
+ 'client name when calling #allow_client_incoming first' do
127
+ @capability.allow_client_incoming 'andrew'
128
+ @capability.allow_client_outgoing 'myAppSid'
129
+ token = @capability.generate
130
+ decoded, header = JWT.decode token, 'myAuthToken'
131
+ expect(queries(decoded['scope'])).to eq([
132
+ ['incoming', {'clientName' => 'andrew'}],
133
+ ['outgoing', {'clientName' => 'andrew', 'appSid' => 'myAppSid'}]
134
+ ])
135
+ end
136
+
137
+ it 'should generate a proper outgoing client scope string based on the ' +
138
+ 'client name when calling #allow_client_incoming second' do
139
+ @capability.allow_client_outgoing 'myAppSid'
140
+ @capability.allow_client_incoming 'andrew'
141
+ token = @capability.generate
142
+ decoded, header = JWT.decode token, 'myAuthToken'
143
+ expect(queries(decoded['scope'])).to eq([["incoming", {"clientName"=>"andrew"}], ["outgoing", {"clientName"=>"andrew", "appSid"=>"myAppSid"}]])
144
+ end
145
+
146
+ it 'should generate a proper outgoing client scope string with parameters ' +
147
+ 'and a client name when calling #allow_client_incoming first' do
148
+ @capability.allow_client_incoming 'andrew'
149
+ app_params_hash = {'key' => 'a value', :foo => 'bar/baz'}
150
+ @capability.allow_client_outgoing 'myAppSid', app_params_hash
151
+ app_params = @capability.instance_eval {url_encode(app_params_hash)}
152
+ params_hash = {'appSid' => 'myAppSid', 'appParams' => app_params, 'clientName' => 'andrew'}
153
+ @capability.instance_eval {url_encode(params_hash)}
154
+ token = @capability.generate
155
+ decoded, header = JWT.decode token, 'myAuthToken'
156
+ scopes = queries(decoded['scope'])
157
+ expect(scopes.shift).to eq(["incoming", {"clientName"=>"andrew"}])
158
+ scope = scopes.shift
159
+ expect(scope.first).to eq('outgoing')
160
+ expect(Rack::Utils.parse_query(scope.last['appParams'])).to eq({'key' => 'a value', 'foo' => 'bar/baz'})
161
+ expect(scope.last["clientName"]).to eq("andrew")
162
+ expect(scope.last["appSid"]).to eq("myAppSid")
163
+ expect(scopes).to be_empty
164
+ end
117
165
 
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
- @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
166
+ it 'should generate a proper outgoing client scope string with parameters ' +
167
+ 'and a client name when calling #allow_client_incoming second' do
168
+ app_params_hash = {'key' => 'a value', :foo => 'bar/baz'}
169
+ @capability.allow_client_outgoing 'myAppSid', app_params_hash
170
+ @capability.allow_client_incoming 'andrew'
171
+ app_params = @capability.instance_eval {url_encode(app_params_hash)}
172
+ params_hash = {'appSid' => 'myAppSid', 'appParams' => app_params, 'clientName' => 'andrew'}
173
+ @capability.instance_eval {url_encode(params_hash)}
174
+ token = @capability.generate
175
+ decoded, header = JWT.decode token, 'myAuthToken'
176
+ scopes = queries(decoded['scope'])
177
+ expect(scopes.shift).to eq(["incoming", {"clientName"=>"andrew"}])
178
+ scope = scopes.shift
179
+ expect(scope.first).to eq('outgoing')
180
+ expect(Rack::Utils.parse_query(scope.last['appParams'])).to eq({'key' => 'a value', 'foo' => 'bar/baz'})
181
+ expect(scope.last["clientName"]).to eq("andrew")
182
+ expect(scope.last["appSid"]).to eq("myAppSid")
183
+ expect(scopes).to be_empty
184
+ end
136
185
  end
137
186
  end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe Twilio::Util::ClientConfig do
4
+ Twilio::Util::ClientConfig::DEFAULTS.each do |attribute, value|
5
+ it "sets an attribute with a default value" do
6
+ config = Twilio::Util::ClientConfig.new
7
+ expect(config.send(attribute)).to eq(value)
8
+ end
9
+
10
+ it "can update the value for the attribute" do
11
+ config = Twilio::Util::ClientConfig.new
12
+ config.send("#{attribute}=", "blah")
13
+ expect(config.send(attribute)).to eq("blah")
14
+ end
15
+
16
+ it "can set the value from a hash in the initializer" do
17
+ config = Twilio::Util::ClientConfig.new(attribute => 'blah')
18
+ expect(config.send(attribute)).to eq("blah")
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Twilio::Util::Configuration do
4
+ it 'should have an account sid attribute' do
5
+ config = Twilio::Util::Configuration.new
6
+ config.account_sid = 'someSid'
7
+ expect(config.account_sid).to eq('someSid')
8
+ end
9
+
10
+ it 'should have an auth token attribute' do
11
+ config = Twilio::Util::Configuration.new
12
+ config.auth_token = 'someToken'
13
+ expect(config.auth_token).to eq('someToken')
14
+ end
15
+ end
@@ -1,6 +1,34 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Twilio::Util::RequestValidator do
4
+ describe 'configuration' do
5
+ after(:each) do
6
+ Twilio.instance_variable_set('@configuration', nil)
7
+ end
8
+
9
+ it 'should set the auth token from a configuration block' do
10
+ Twilio.configure do |config|
11
+ config.auth_token = 'someToken'
12
+ end
13
+
14
+ validator = Twilio::Util::RequestValidator.new
15
+ expect(validator.instance_variable_get('@auth_token')).to eq('someToken')
16
+ end
17
+
18
+ it 'should overwrite the auth token if passed to initializer' do
19
+ Twilio.configure do |config|
20
+ config.auth_token = 'someToken'
21
+ end
22
+
23
+ validator = Twilio::Util::RequestValidator.new 'otherToken'
24
+ expect(validator.instance_variable_get('@auth_token')).to eq('otherToken')
25
+ end
26
+
27
+ it 'should throw an argument error if the auth token isn\'t set' do
28
+ expect { Twilio::Util::RequestValidator.new }.to raise_error(ArgumentError)
29
+ end
30
+ end
31
+
4
32
  it 'should properly validate a Twilio Voice request' do
5
33
  token = '2bd9e9638872de601313dc77410d3b23'
6
34
  validator = Twilio::Util::RequestValidator.new token
@@ -34,7 +62,7 @@ describe Twilio::Util::RequestValidator do
34
62
  'ApplicationSid' => 'AP44efecad51364e80b133bb7c07eb8204'
35
63
  }
36
64
  signature = 'oVb2kXoVy8GEfwBDjR8bk/ZZ6eA='
37
- validator.validate(url, params, signature).should == true
65
+ expect(validator.validate(url, params, signature)).to eq(true)
38
66
  end
39
67
 
40
68
  it 'should properly validate a Twilio SMS request' do
@@ -60,6 +88,6 @@ describe Twilio::Util::RequestValidator do
60
88
  'SmsSid' => 'SM2003cbd5e6a3701999aa3e5f20ff2787'
61
89
  }
62
90
  signature = 'mxeiv65lEe0b8L6LdVw2jgJi8yw='
63
- validator.validate(url, params, signature).should == true
91
+ expect(validator.validate(url, params, signature)).to eq(true)
64
92
  end
65
- end
93
+ end
@@ -5,8 +5,8 @@ describe Twilio::Util do
5
5
 
6
6
  it 'should parse a Date object' do
7
7
  today = Time.now
8
- url = url_encode({'DateSent>' => today})
8
+ url = url_encode('DateSent>' => today)
9
9
 
10
- url.should == "DateSent%3E=#{today.strftime('%Y-%m-%d')}"
10
+ expect(url).to eq("DateSent%3E=#{today.strftime('%Y-%m-%d')}")
11
11
  end
12
12
  end
data/twilio-ruby.gemspec CHANGED
@@ -1,33 +1,34 @@
1
- require './lib/twilio-ruby/version'
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'twilio-ruby/version'
2
5
 
3
- Gem::Specification.new do |s|
4
- s.name = 'twilio-ruby'
5
- s.version = Twilio::VERSION
6
- s.author = 'Andrew Benton'
7
- s.email = 'andrew@twilio.com'
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'twilio-ruby'
8
+ spec.version = Twilio::VERSION
9
+ spec.authors = ['Andrew Benton']
10
+ spec.email = ['andrew@twilio.com']
11
+ spec.summary = 'A simple library for communicating with the Twilio REST API, building TwiML, and generating Twilio Client Capability Tokens'
12
+ spec.description = 'A simple library for communicating with the Twilio REST API, building TwiML, and generating Twilio Client Capability Tokens'
13
+ spec.homepage = 'http://github.com/twilio/twilio-ruby'
14
+ spec.license = 'MIT'
8
15
 
9
- s.description = 'A simple library for communicating with the Twilio REST API, building TwiML, and generating Twilio Client Capability Tokens'
10
- s.summary = 'A simple library for communicating with the Twilio REST API, building TwiML, and generating Twilio Client Capability Tokens'
11
- s.homepage = 'http://github.com/twilio/twilio-ruby'
12
- s.license = 'MIT'
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+ spec.required_ruby_version = '>= 1.9.3'
21
+ spec.extra_rdoc_files = ['README.md', 'LICENSE.md']
22
+ spec.rdoc_options = ['--line-numbers', '--inline-source', '--title', 'twilio-ruby', '--main', 'README.md']
13
23
 
14
- s.platform = Gem::Platform::RUBY
15
- s.require_paths = %w[lib]
16
- s.files = `git ls-files`.split("\n")
17
- s.test_files = Dir['spec/**/*.rb']
18
-
19
- s.add_dependency('multi_json', '>= 1.3.0')
20
- s.add_dependency('builder', '>= 2.1.2')
21
- s.add_dependency('jwt', '>= 0.1.2')
22
- s.add_dependency('jruby-openssl') if RUBY_PLATFORM == 'java'
24
+ spec.add_dependency('multi_json', '>= 1.3.0')
25
+ spec.add_dependency('builder', '>= 2.1.2')
26
+ spec.add_dependency('jwt', '~> 1.0')
27
+ spec.add_dependency('jruby-openssl') if RUBY_PLATFORM == 'java'
23
28
  # Workaround for RBX <= 2.2.1, should be fixed in next version
24
- s.add_dependency('rubysl') if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
25
-
26
- s.add_development_dependency 'rake', '~> 0.9.0'
27
- s.add_development_dependency 'rspec', '~> 2.6.0'
28
- s.add_development_dependency 'fakeweb', '~> 1.3.0'
29
- s.add_development_dependency 'rack', '~> 1.3.0'
29
+ spec.add_dependency('rubysl') if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
30
30
 
31
- s.extra_rdoc_files = ['README.md', 'LICENSE']
32
- s.rdoc_options = ['--line-numbers', '--inline-source', '--title', 'twilio-ruby', '--main', 'README.md']
31
+ spec.add_development_dependency 'bundler', '~> 1.5'
32
+ spec.extra_rdoc_files = ['README.md', 'LICENSE.md']
33
+ spec.rdoc_options = ['--line-numbers', '--inline-source', '--title', 'twilio-ruby', '--main', 'README.md']
33
34
  end