restcomm-ruby 1.2.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.
- data/AUTHORS.md +38 -0
- data/CHANGES.md +171 -0
- data/Gemfile +11 -0
- data/LICENSE +662 -0
- data/LICENSE.md +19 -0
- data/Makefile +12 -0
- data/README.md +155 -0
- data/Rakefile +10 -0
- data/conf/cacert.pem +3376 -0
- data/docs/Makefile +130 -0
- data/docs/_themes/LICENSE +45 -0
- data/docs/_themes/README.rst +25 -0
- data/docs/_themes/flask_theme_support.py +86 -0
- data/docs/_themes/kr/layout.html +32 -0
- data/docs/_themes/kr/relations.html +19 -0
- data/docs/_themes/kr/static/flasky.css_t +469 -0
- data/docs/_themes/kr/static/small_flask.css +70 -0
- data/docs/_themes/kr/theme.conf +7 -0
- data/docs/_themes/kr_small/layout.html +22 -0
- data/docs/_themes/kr_small/static/flasky.css_t +287 -0
- data/docs/_themes/kr_small/theme.conf +10 -0
- data/docs/changelog.rst +1 -0
- data/docs/conf.py +266 -0
- data/docs/faq.rst +42 -0
- data/docs/getting-started.rst +100 -0
- data/docs/index.rst +109 -0
- data/docs/make.bat +170 -0
- data/docs/src/pip-delete-this-directory.txt +5 -0
- data/docs/usage/accounts.rst +96 -0
- data/docs/usage/addresses.rst +102 -0
- data/docs/usage/applications.rst +111 -0
- data/docs/usage/basics.rst +120 -0
- data/docs/usage/caller-ids.rst +47 -0
- data/docs/usage/conferences.rst +112 -0
- data/docs/usage/errors.rst +31 -0
- data/docs/usage/messages.rst +142 -0
- data/docs/usage/notifications.rst +72 -0
- data/docs/usage/phone-calls.rst +193 -0
- data/docs/usage/phone-numbers.rst +192 -0
- data/docs/usage/queues.rst +117 -0
- data/docs/usage/recordings.rst +102 -0
- data/docs/usage/sip.rst +108 -0
- data/docs/usage/token-generation.rst +96 -0
- data/docs/usage/transcriptions.rst +34 -0
- data/docs/usage/twiml.rst +69 -0
- data/docs/usage/validation.rst +107 -0
- data/examples/examples.rb +200 -0
- data/examples/print-call-log.rb +25 -0
- data/lib/rack/restcomm_webhook_authentication.rb +47 -0
- data/lib/restcomm-ruby.rb +103 -0
- data/lib/restcomm-ruby/rest/accounts.rb +17 -0
- data/lib/restcomm-ruby/rest/addresses.rb +12 -0
- data/lib/restcomm-ruby/rest/addresses/dependent_phone_numbers.rb +6 -0
- data/lib/restcomm-ruby/rest/applications.rb +6 -0
- data/lib/restcomm-ruby/rest/authorized_connect_apps.rb +6 -0
- data/lib/restcomm-ruby/rest/available_phone_numbers.rb +13 -0
- data/lib/restcomm-ruby/rest/available_phone_numbers/country.rb +10 -0
- data/lib/restcomm-ruby/rest/available_phone_numbers/local.rb +11 -0
- data/lib/restcomm-ruby/rest/available_phone_numbers/mobile.rb +11 -0
- data/lib/restcomm-ruby/rest/available_phone_numbers/toll_free.rb +11 -0
- data/lib/restcomm-ruby/rest/call_feedback.rb +28 -0
- data/lib/restcomm-ruby/rest/call_feedback_summary.rb +13 -0
- data/lib/restcomm-ruby/rest/calls.rb +37 -0
- data/lib/restcomm-ruby/rest/client.rb +555 -0
- data/lib/restcomm-ruby/rest/conferences.rb +12 -0
- data/lib/restcomm-ruby/rest/conferences/participants.rb +23 -0
- data/lib/restcomm-ruby/rest/connect_apps.rb +6 -0
- data/lib/restcomm-ruby/rest/errors.rb +14 -0
- data/lib/restcomm-ruby/rest/incoming_phone_numbers.rb +17 -0
- data/lib/restcomm-ruby/rest/incoming_phone_numbers/local.rb +13 -0
- data/lib/restcomm-ruby/rest/incoming_phone_numbers/mobile.rb +13 -0
- data/lib/restcomm-ruby/rest/incoming_phone_numbers/toll_free.rb +13 -0
- data/lib/restcomm-ruby/rest/instance_resource.rb +88 -0
- data/lib/restcomm-ruby/rest/list_resource.rb +132 -0
- data/lib/restcomm-ruby/rest/media.rb +14 -0
- data/lib/restcomm-ruby/rest/messages.rb +23 -0
- data/lib/restcomm-ruby/rest/next_gen_list_resource.rb +29 -0
- data/lib/restcomm-ruby/rest/notifications.rb +6 -0
- data/lib/restcomm-ruby/rest/outgoing_caller_ids.rb +25 -0
- data/lib/restcomm-ruby/rest/queues.rb +12 -0
- data/lib/restcomm-ruby/rest/queues/members.rb +29 -0
- data/lib/restcomm-ruby/rest/recordings.rb +35 -0
- data/lib/restcomm-ruby/rest/sandbox.rb +5 -0
- data/lib/restcomm-ruby/rest/sip.rb +10 -0
- data/lib/restcomm-ruby/rest/sip/credential_lists.rb +11 -0
- data/lib/restcomm-ruby/rest/sip/credential_lists/credentials.rb +6 -0
- data/lib/restcomm-ruby/rest/sip/domains.rb +12 -0
- data/lib/restcomm-ruby/rest/sip/domains/credential_list_mappings.rb +6 -0
- data/lib/restcomm-ruby/rest/sip/domains/ip_access_control_list_mappings.rb +6 -0
- data/lib/restcomm-ruby/rest/sip/ip_access_control_lists.rb +11 -0
- data/lib/restcomm-ruby/rest/sip/ip_access_control_lists/ip_addresses.rb +6 -0
- data/lib/restcomm-ruby/rest/sms.rb +11 -0
- data/lib/restcomm-ruby/rest/sms/messages.rb +39 -0
- data/lib/restcomm-ruby/rest/sms/short_codes.rb +8 -0
- data/lib/restcomm-ruby/rest/task_router/activities.rb +8 -0
- data/lib/restcomm-ruby/rest/task_router/events.rb +8 -0
- data/lib/restcomm-ruby/rest/task_router/reservations.rb +8 -0
- data/lib/restcomm-ruby/rest/task_router/task_queues.rb +8 -0
- data/lib/restcomm-ruby/rest/task_router/task_queues_statistics.rb +15 -0
- data/lib/restcomm-ruby/rest/task_router/tasks.rb +15 -0
- data/lib/restcomm-ruby/rest/task_router/workers.rb +8 -0
- data/lib/restcomm-ruby/rest/task_router/workers_statistics.rb +8 -0
- data/lib/restcomm-ruby/rest/task_router/workflow_statistics.rb +7 -0
- data/lib/restcomm-ruby/rest/task_router/workflows.rb +8 -0
- data/lib/restcomm-ruby/rest/task_router/workspace_statistics.rb +7 -0
- data/lib/restcomm-ruby/rest/task_router/workspaces.rb +15 -0
- data/lib/restcomm-ruby/rest/tokens.rb +7 -0
- data/lib/restcomm-ruby/rest/transcriptions.rb +6 -0
- data/lib/restcomm-ruby/rest/usage.rb +10 -0
- data/lib/restcomm-ruby/rest/usage/records.rb +21 -0
- data/lib/restcomm-ruby/rest/usage/triggers.rb +12 -0
- data/lib/restcomm-ruby/rest/utils.rb +49 -0
- data/lib/restcomm-ruby/task_router.rb +0 -0
- data/lib/restcomm-ruby/task_router/capability.rb +87 -0
- data/lib/restcomm-ruby/twiml/response.rb +16 -0
- data/lib/restcomm-ruby/util.rb +15 -0
- data/lib/restcomm-ruby/util/capability.rb +64 -0
- data/lib/restcomm-ruby/util/configuration.rb +7 -0
- data/lib/restcomm-ruby/util/request_validator.rb +37 -0
- data/lib/restcomm-ruby/version.rb +3 -0
- data/restcomm-ruby.gemspec +34 -0
- data/spec/rack/twilio_webhook_authentication_spec.rb +110 -0
- data/spec/rest/account_spec.rb +89 -0
- data/spec/rest/address_spec.rb +11 -0
- data/spec/rest/call_feedback_spec.rb +12 -0
- data/spec/rest/call_feedback_summary_spec.rb +9 -0
- data/spec/rest/call_spec.rb +22 -0
- data/spec/rest/client_spec.rb +258 -0
- data/spec/rest/conference_spec.rb +11 -0
- data/spec/rest/instance_resource_spec.rb +15 -0
- data/spec/rest/message_spec.rb +12 -0
- data/spec/rest/numbers_spec.rb +58 -0
- data/spec/rest/queue_spec.rb +11 -0
- data/spec/rest/recording_spec.rb +11 -0
- data/spec/rest/sms/message_spec.rb +37 -0
- data/spec/rest/sms/messages_spec.rb +36 -0
- data/spec/rest/task_router/reservation_spec.rb +9 -0
- data/spec/rest/task_router/task_queue_spec.rb +9 -0
- data/spec/rest/token_spec.rb +7 -0
- data/spec/rest/utils_spec.rb +45 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/support/fakeweb.rb +2 -0
- data/spec/task_router_spec.rb +114 -0
- data/spec/twilio_spec.rb +15 -0
- data/spec/util/capability_spec.rb +186 -0
- data/spec/util/configuration_spec.rb +13 -0
- data/spec/util/request_validator_spec.rb +93 -0
- data/spec/util/url_encode_spec.rb +12 -0
- metadata +298 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Restcomm::REST::SMS::Message do
|
|
4
|
+
|
|
5
|
+
before do
|
|
6
|
+
client = double("Client")
|
|
7
|
+
allow(client).to receive(:post) do
|
|
8
|
+
{'sid' => 'qwerty' }
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
allow(client).to receive(:get) do
|
|
12
|
+
{'sid' => 'qwerty', 'sms_message' => [] }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
allow(client).to receive(:delete) do
|
|
16
|
+
{'sid' => 'qwerty' }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
@message = Restcomm::REST::SMS::Message.new('someUri',client)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'should warn of deprecation of SMS Message Update' do
|
|
23
|
+
expect(@message).to receive(:warn)
|
|
24
|
+
@message.update
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'should warn of deprecation of SMS Message Refresh' do
|
|
28
|
+
expect(@message).to receive(:warn)
|
|
29
|
+
@message.refresh
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it 'should warn of deprecation of SMS Message Delete' do
|
|
33
|
+
expect(@message).to receive(:warn)
|
|
34
|
+
@message.delete
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Restcomm::REST::SMS::Messages do
|
|
4
|
+
|
|
5
|
+
before do
|
|
6
|
+
client = double("Client")
|
|
7
|
+
allow(client).to receive(:post) do
|
|
8
|
+
{'sid' => 'qwerty' }
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
allow(client).to receive(:get) do
|
|
12
|
+
{'sid' => 'qwerty', 'sms_messages' => [] }
|
|
13
|
+
end
|
|
14
|
+
@messages = Restcomm::REST::SMS::Messages.new('someUri',client)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'should warn of deprecation of SMS Messages Create' do
|
|
18
|
+
expect(@messages).to receive(:warn)
|
|
19
|
+
@messages.create to: "+1", from: "+2", body: "But Jenny!"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'should warn of deprecation of SMS Messages List' do
|
|
23
|
+
expect(@messages).to receive(:warn)
|
|
24
|
+
@messages.list to: "+1"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'should warn of deprecation of SMS Messages Get' do
|
|
28
|
+
expect(@messages).to receive(:warn)
|
|
29
|
+
@messages.get sid: "qwerty"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it 'should warn of deprecation of SMS Messages total' do
|
|
33
|
+
expect(@messages).to receive(:warn)
|
|
34
|
+
@messages.total
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Restcomm::REST::TaskRouter::Reservations do
|
|
4
|
+
it 'creates a reservation object' do
|
|
5
|
+
task = Restcomm::REST::TaskRouter::Task.new('someUri', 'someClient')
|
|
6
|
+
expect(task).to respond_to(:reservations)
|
|
7
|
+
expect(task.reservations.instance_variable_get('@path')).to eq('someUri/Reservations')
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Restcomm::REST::TaskRouter::TaskQueues do
|
|
4
|
+
it 'creates a task queue object' do
|
|
5
|
+
workspace = Restcomm::REST::TaskRouter::Workspace.new('someUri', 'someClient')
|
|
6
|
+
expect(workspace).to respond_to(:task_queues)
|
|
7
|
+
expect(workspace.task_queues.instance_variable_get('@path')).to eq('someUri/TaskQueues')
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
class UtilClass
|
|
4
|
+
include Restcomm::REST::Utils
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
describe UtilClass do
|
|
8
|
+
subject(:util) { UtilClass.new }
|
|
9
|
+
|
|
10
|
+
it 'should convert a parameter name to a Restcomm-style name' do
|
|
11
|
+
expect(util.restify('sms_url')).to eq('SmsUrl')
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'should convert all parameter names to Restcomm-style names' do
|
|
15
|
+
unrestified = {
|
|
16
|
+
:sms_url => 'someUrl',
|
|
17
|
+
'voiceFallbackUrl' => 'anotherUrl',
|
|
18
|
+
'Status_callback' => 'yetAnotherUrl'
|
|
19
|
+
}
|
|
20
|
+
restified = {
|
|
21
|
+
:SmsUrl => 'someUrl',
|
|
22
|
+
:VoiceFallbackUrl => 'anotherUrl',
|
|
23
|
+
:StatusCallback => 'yetAnotherUrl'
|
|
24
|
+
}
|
|
25
|
+
expect(util.restify(unrestified)).to eq(restified)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'should convert a Restcomm-style name to a parameter name' do
|
|
29
|
+
expect(util.derestify('SmsUrl')).to eq('sms_url')
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it 'should convert all Restcomm-style names to parameter names' do
|
|
33
|
+
unrestified = {
|
|
34
|
+
:sms_url => 'someUrl',
|
|
35
|
+
:voice_fallback_url => 'anotherUrl',
|
|
36
|
+
:status_callback => 'yetAnotherUrl'
|
|
37
|
+
}
|
|
38
|
+
restified = {
|
|
39
|
+
:SmsUrl => 'someUrl',
|
|
40
|
+
:VoiceFallbackUrl => 'anotherUrl',
|
|
41
|
+
:StatusCallback => 'yetAnotherUrl'
|
|
42
|
+
}
|
|
43
|
+
expect(util.derestify(restified)).to eq(unrestified)
|
|
44
|
+
end
|
|
45
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
2
|
+
|
|
3
|
+
require 'bundler'
|
|
4
|
+
Bundler.setup
|
|
5
|
+
|
|
6
|
+
Dir.glob(File.expand_path("../support/**/*.rb", __FILE__), &method(:require))
|
|
7
|
+
|
|
8
|
+
require 'restcomm-ruby'
|
|
9
|
+
require 'rack'
|
|
10
|
+
|
|
11
|
+
RSpec.configure do |config|
|
|
12
|
+
config.expect_with :rspec do |c|
|
|
13
|
+
c.syntax = :expect
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Restcomm::TaskRouter::Capability do
|
|
4
|
+
describe 'with a capability' do
|
|
5
|
+
before :each do
|
|
6
|
+
@capability = Restcomm::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.restcomm.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.restcomm.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.restcomm.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.restcomm.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.restcomm.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.restcomm.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
|
data/spec/twilio_spec.rb
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
describe Restcomm do
|
|
2
|
+
after(:each) do
|
|
3
|
+
Restcomm.instance_variable_set('@configuration', nil)
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
it 'should set the account sid and auth token with a config block' do
|
|
7
|
+
Restcomm.configure do |config|
|
|
8
|
+
config.account_sid = 'someSid'
|
|
9
|
+
config.auth_token = 'someToken'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
expect(Restcomm.account_sid).to eq('someSid')
|
|
13
|
+
expect(Restcomm.auth_token).to eq('someToken')
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Restcomm::Util::Capability do
|
|
4
|
+
describe 'config' do
|
|
5
|
+
after(:each) do
|
|
6
|
+
Restcomm.instance_variable_set('@configuration', nil)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it 'should set the account sid and auth token from a configuration block' do
|
|
10
|
+
Restcomm.configure do |config|
|
|
11
|
+
config.account_sid = 'someSid'
|
|
12
|
+
config.auth_token = 'someToken'
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
capability = Restcomm::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
|
+
|
|
20
|
+
it 'should overwrite account sid and auth token if passed to initializer' do
|
|
21
|
+
Restcomm.configure do |config|
|
|
22
|
+
config.account_sid = 'someSid'
|
|
23
|
+
config.auth_token = 'someToken'
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
capability = Restcomm::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
|
|
30
|
+
|
|
31
|
+
it 'should overwrite the account sid if only the sid is given' do
|
|
32
|
+
Restcomm.configure do |config|
|
|
33
|
+
config.account_sid = 'someSid'
|
|
34
|
+
config.auth_token = 'someToken'
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
capability = Restcomm::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
|
|
41
|
+
|
|
42
|
+
it 'should throw an argument error if the sid and token isn\'t set' do
|
|
43
|
+
expect { Restcomm::Util::Capability.new }.to raise_error(ArgumentError)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it 'should throw an argument error if only the account_sid is set' do
|
|
47
|
+
expect { Restcomm::Util::Capability.new 'someSid' }.to raise_error(ArgumentError)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
describe 'with a capability' do
|
|
52
|
+
before :each do
|
|
53
|
+
@capability = Restcomm::Util::Capability.new 'myAccountSid', 'myAuthToken'
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def queries(q)
|
|
57
|
+
q.scan(/scope:client:(incoming|outgoing)\?(\S+)/).map{|(type, query)| [type, Rack::Utils.parse_query(query)]}
|
|
58
|
+
end
|
|
59
|
+
|
|
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
|
|
67
|
+
|
|
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
|
|
165
|
+
|
|
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
|
|
185
|
+
end
|
|
186
|
+
end
|