restcomm-ruby 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) hide show
  1. data/AUTHORS.md +38 -0
  2. data/CHANGES.md +171 -0
  3. data/Gemfile +11 -0
  4. data/LICENSE +662 -0
  5. data/LICENSE.md +19 -0
  6. data/Makefile +12 -0
  7. data/README.md +155 -0
  8. data/Rakefile +10 -0
  9. data/conf/cacert.pem +3376 -0
  10. data/docs/Makefile +130 -0
  11. data/docs/_themes/LICENSE +45 -0
  12. data/docs/_themes/README.rst +25 -0
  13. data/docs/_themes/flask_theme_support.py +86 -0
  14. data/docs/_themes/kr/layout.html +32 -0
  15. data/docs/_themes/kr/relations.html +19 -0
  16. data/docs/_themes/kr/static/flasky.css_t +469 -0
  17. data/docs/_themes/kr/static/small_flask.css +70 -0
  18. data/docs/_themes/kr/theme.conf +7 -0
  19. data/docs/_themes/kr_small/layout.html +22 -0
  20. data/docs/_themes/kr_small/static/flasky.css_t +287 -0
  21. data/docs/_themes/kr_small/theme.conf +10 -0
  22. data/docs/changelog.rst +1 -0
  23. data/docs/conf.py +266 -0
  24. data/docs/faq.rst +42 -0
  25. data/docs/getting-started.rst +100 -0
  26. data/docs/index.rst +109 -0
  27. data/docs/make.bat +170 -0
  28. data/docs/src/pip-delete-this-directory.txt +5 -0
  29. data/docs/usage/accounts.rst +96 -0
  30. data/docs/usage/addresses.rst +102 -0
  31. data/docs/usage/applications.rst +111 -0
  32. data/docs/usage/basics.rst +120 -0
  33. data/docs/usage/caller-ids.rst +47 -0
  34. data/docs/usage/conferences.rst +112 -0
  35. data/docs/usage/errors.rst +31 -0
  36. data/docs/usage/messages.rst +142 -0
  37. data/docs/usage/notifications.rst +72 -0
  38. data/docs/usage/phone-calls.rst +193 -0
  39. data/docs/usage/phone-numbers.rst +192 -0
  40. data/docs/usage/queues.rst +117 -0
  41. data/docs/usage/recordings.rst +102 -0
  42. data/docs/usage/sip.rst +108 -0
  43. data/docs/usage/token-generation.rst +96 -0
  44. data/docs/usage/transcriptions.rst +34 -0
  45. data/docs/usage/twiml.rst +69 -0
  46. data/docs/usage/validation.rst +107 -0
  47. data/examples/examples.rb +200 -0
  48. data/examples/print-call-log.rb +25 -0
  49. data/lib/rack/restcomm_webhook_authentication.rb +47 -0
  50. data/lib/restcomm-ruby.rb +103 -0
  51. data/lib/restcomm-ruby/rest/accounts.rb +17 -0
  52. data/lib/restcomm-ruby/rest/addresses.rb +12 -0
  53. data/lib/restcomm-ruby/rest/addresses/dependent_phone_numbers.rb +6 -0
  54. data/lib/restcomm-ruby/rest/applications.rb +6 -0
  55. data/lib/restcomm-ruby/rest/authorized_connect_apps.rb +6 -0
  56. data/lib/restcomm-ruby/rest/available_phone_numbers.rb +13 -0
  57. data/lib/restcomm-ruby/rest/available_phone_numbers/country.rb +10 -0
  58. data/lib/restcomm-ruby/rest/available_phone_numbers/local.rb +11 -0
  59. data/lib/restcomm-ruby/rest/available_phone_numbers/mobile.rb +11 -0
  60. data/lib/restcomm-ruby/rest/available_phone_numbers/toll_free.rb +11 -0
  61. data/lib/restcomm-ruby/rest/call_feedback.rb +28 -0
  62. data/lib/restcomm-ruby/rest/call_feedback_summary.rb +13 -0
  63. data/lib/restcomm-ruby/rest/calls.rb +37 -0
  64. data/lib/restcomm-ruby/rest/client.rb +555 -0
  65. data/lib/restcomm-ruby/rest/conferences.rb +12 -0
  66. data/lib/restcomm-ruby/rest/conferences/participants.rb +23 -0
  67. data/lib/restcomm-ruby/rest/connect_apps.rb +6 -0
  68. data/lib/restcomm-ruby/rest/errors.rb +14 -0
  69. data/lib/restcomm-ruby/rest/incoming_phone_numbers.rb +17 -0
  70. data/lib/restcomm-ruby/rest/incoming_phone_numbers/local.rb +13 -0
  71. data/lib/restcomm-ruby/rest/incoming_phone_numbers/mobile.rb +13 -0
  72. data/lib/restcomm-ruby/rest/incoming_phone_numbers/toll_free.rb +13 -0
  73. data/lib/restcomm-ruby/rest/instance_resource.rb +88 -0
  74. data/lib/restcomm-ruby/rest/list_resource.rb +132 -0
  75. data/lib/restcomm-ruby/rest/media.rb +14 -0
  76. data/lib/restcomm-ruby/rest/messages.rb +23 -0
  77. data/lib/restcomm-ruby/rest/next_gen_list_resource.rb +29 -0
  78. data/lib/restcomm-ruby/rest/notifications.rb +6 -0
  79. data/lib/restcomm-ruby/rest/outgoing_caller_ids.rb +25 -0
  80. data/lib/restcomm-ruby/rest/queues.rb +12 -0
  81. data/lib/restcomm-ruby/rest/queues/members.rb +29 -0
  82. data/lib/restcomm-ruby/rest/recordings.rb +35 -0
  83. data/lib/restcomm-ruby/rest/sandbox.rb +5 -0
  84. data/lib/restcomm-ruby/rest/sip.rb +10 -0
  85. data/lib/restcomm-ruby/rest/sip/credential_lists.rb +11 -0
  86. data/lib/restcomm-ruby/rest/sip/credential_lists/credentials.rb +6 -0
  87. data/lib/restcomm-ruby/rest/sip/domains.rb +12 -0
  88. data/lib/restcomm-ruby/rest/sip/domains/credential_list_mappings.rb +6 -0
  89. data/lib/restcomm-ruby/rest/sip/domains/ip_access_control_list_mappings.rb +6 -0
  90. data/lib/restcomm-ruby/rest/sip/ip_access_control_lists.rb +11 -0
  91. data/lib/restcomm-ruby/rest/sip/ip_access_control_lists/ip_addresses.rb +6 -0
  92. data/lib/restcomm-ruby/rest/sms.rb +11 -0
  93. data/lib/restcomm-ruby/rest/sms/messages.rb +39 -0
  94. data/lib/restcomm-ruby/rest/sms/short_codes.rb +8 -0
  95. data/lib/restcomm-ruby/rest/task_router/activities.rb +8 -0
  96. data/lib/restcomm-ruby/rest/task_router/events.rb +8 -0
  97. data/lib/restcomm-ruby/rest/task_router/reservations.rb +8 -0
  98. data/lib/restcomm-ruby/rest/task_router/task_queues.rb +8 -0
  99. data/lib/restcomm-ruby/rest/task_router/task_queues_statistics.rb +15 -0
  100. data/lib/restcomm-ruby/rest/task_router/tasks.rb +15 -0
  101. data/lib/restcomm-ruby/rest/task_router/workers.rb +8 -0
  102. data/lib/restcomm-ruby/rest/task_router/workers_statistics.rb +8 -0
  103. data/lib/restcomm-ruby/rest/task_router/workflow_statistics.rb +7 -0
  104. data/lib/restcomm-ruby/rest/task_router/workflows.rb +8 -0
  105. data/lib/restcomm-ruby/rest/task_router/workspace_statistics.rb +7 -0
  106. data/lib/restcomm-ruby/rest/task_router/workspaces.rb +15 -0
  107. data/lib/restcomm-ruby/rest/tokens.rb +7 -0
  108. data/lib/restcomm-ruby/rest/transcriptions.rb +6 -0
  109. data/lib/restcomm-ruby/rest/usage.rb +10 -0
  110. data/lib/restcomm-ruby/rest/usage/records.rb +21 -0
  111. data/lib/restcomm-ruby/rest/usage/triggers.rb +12 -0
  112. data/lib/restcomm-ruby/rest/utils.rb +49 -0
  113. data/lib/restcomm-ruby/task_router.rb +0 -0
  114. data/lib/restcomm-ruby/task_router/capability.rb +87 -0
  115. data/lib/restcomm-ruby/twiml/response.rb +16 -0
  116. data/lib/restcomm-ruby/util.rb +15 -0
  117. data/lib/restcomm-ruby/util/capability.rb +64 -0
  118. data/lib/restcomm-ruby/util/configuration.rb +7 -0
  119. data/lib/restcomm-ruby/util/request_validator.rb +37 -0
  120. data/lib/restcomm-ruby/version.rb +3 -0
  121. data/restcomm-ruby.gemspec +34 -0
  122. data/spec/rack/twilio_webhook_authentication_spec.rb +110 -0
  123. data/spec/rest/account_spec.rb +89 -0
  124. data/spec/rest/address_spec.rb +11 -0
  125. data/spec/rest/call_feedback_spec.rb +12 -0
  126. data/spec/rest/call_feedback_summary_spec.rb +9 -0
  127. data/spec/rest/call_spec.rb +22 -0
  128. data/spec/rest/client_spec.rb +258 -0
  129. data/spec/rest/conference_spec.rb +11 -0
  130. data/spec/rest/instance_resource_spec.rb +15 -0
  131. data/spec/rest/message_spec.rb +12 -0
  132. data/spec/rest/numbers_spec.rb +58 -0
  133. data/spec/rest/queue_spec.rb +11 -0
  134. data/spec/rest/recording_spec.rb +11 -0
  135. data/spec/rest/sms/message_spec.rb +37 -0
  136. data/spec/rest/sms/messages_spec.rb +36 -0
  137. data/spec/rest/task_router/reservation_spec.rb +9 -0
  138. data/spec/rest/task_router/task_queue_spec.rb +9 -0
  139. data/spec/rest/token_spec.rb +7 -0
  140. data/spec/rest/utils_spec.rb +45 -0
  141. data/spec/spec_helper.rb +15 -0
  142. data/spec/support/fakeweb.rb +2 -0
  143. data/spec/task_router_spec.rb +114 -0
  144. data/spec/twilio_spec.rb +15 -0
  145. data/spec/util/capability_spec.rb +186 -0
  146. data/spec/util/configuration_spec.rb +13 -0
  147. data/spec/util/request_validator_spec.rb +93 -0
  148. data/spec/util/url_encode_spec.rb +12 -0
  149. metadata +298 -0
@@ -0,0 +1,49 @@
1
+ module Restcomm
2
+ module REST
3
+ module Utils
4
+
5
+ def restify(something)
6
+ return key_map(something, :restify) if something.is_a? Hash
7
+ string = something.to_s
8
+ string.split('_').map do |string_part|
9
+ string_part[0,1].capitalize + string_part[1..-1]
10
+ end.join
11
+ end
12
+
13
+ def derestify(something)
14
+ return key_map(something, :derestify) if something.is_a? Hash
15
+ string = something.to_s
16
+ string = string[0,1].downcase + string[1..-1]
17
+ string.gsub(/[A-Z][a-z]*/) { |s| "_#{s.downcase}" }
18
+ end
19
+
20
+ protected
21
+
22
+ def resource(*resources)
23
+ custom_resource_names = { sms: 'SMS', sip: 'SIP' }
24
+ resources.each do |r|
25
+ resource = restify r
26
+ relative_path = custom_resource_names.fetch(r, resource)
27
+ path = "#{@path}/#{relative_path}"
28
+ enclosing_module = if @submodule == nil
29
+ Restcomm::REST
30
+ else
31
+ Restcomm::REST.const_get(@submodule)
32
+ end
33
+ resource_class = enclosing_module.const_get resource
34
+ instance_variable_set("@#{r}", resource_class.new(path, @client))
35
+ end
36
+ self.class.instance_eval { attr_reader *resources }
37
+ end
38
+
39
+ private
40
+
41
+ def key_map(something, method)
42
+ something = something.to_a.flat_map do |pair|
43
+ [send(method, pair[0]).to_sym, pair[1]]
44
+ end
45
+ Hash[*something]
46
+ end
47
+ end
48
+ end
49
+ end
File without changes
@@ -0,0 +1,87 @@
1
+ module Restcomm
2
+ module TaskRouter
3
+ class Capability
4
+
5
+ TASK_ROUTER_BASE_URL = 'https://taskrouter.restcomm.com'
6
+ TASK_ROUTER_VERSION = 'v1'
7
+ TASK_ROUTER_WEBSOCKET_BASE_URL = 'https://event-bridge.restcomm.com/v1/wschannels'
8
+
9
+ REQUIRED = {required: true}
10
+ OPTIONAL = {required: false}
11
+
12
+ def initialize(account_sid, auth_token, workspace_sid, worker_sid)
13
+ @account_sid = account_sid
14
+ @auth_token = auth_token
15
+ @workspace_sid = workspace_sid
16
+ @worker_sid = worker_sid
17
+ @policies = []
18
+ allow_websocket_requests
19
+ allow_activity_list_fetch
20
+ end
21
+
22
+ def workspace_url
23
+ "#{TASK_ROUTER_BASE_URL}/#{TASK_ROUTER_VERSION}/Workspaces/#{@workspace_sid}"
24
+ end
25
+
26
+ def worker_url
27
+ "#{workspace_url}/Workers/#{@worker_sid}"
28
+ end
29
+
30
+ def allow_worker_activity_updates
31
+ add_policy(worker_url, "POST", nil, {ActivitySid: REQUIRED})
32
+ end
33
+
34
+ def allow_worker_fetch_attributes
35
+ add_policy(worker_url, "GET")
36
+ end
37
+
38
+ def allow_task_reservation_updates
39
+ task_url = "#{workspace_url}/Tasks/**"
40
+ add_policy(task_url, "POST", nil, {ReservationStatus: REQUIRED})
41
+ end
42
+
43
+ def add_policy(url, method, query_filters = nil, post_filters = nil, allowed = true)
44
+ policy = {
45
+ url: url,
46
+ method: method,
47
+ query_filter: query_filters || {},
48
+ post_filter: post_filters || {},
49
+ allow: allowed
50
+ }
51
+
52
+ @policies.push(policy)
53
+ end
54
+
55
+ def generate_token(ttl = 3600)
56
+ payload = {
57
+ iss: @account_sid,
58
+ exp: (Time.now.to_i + ttl),
59
+ version: @version,
60
+ friendly_name: @worker_sid,
61
+ policies: @policies,
62
+ account_sid: @account_sid,
63
+ worker_sid: @worker_sid,
64
+ channel: @worker_sid,
65
+ workspace_sid: @workspace_sid
66
+ }
67
+
68
+ JWT.encode payload, @auth_token
69
+ end
70
+
71
+ protected
72
+
73
+ def allow_websocket_requests
74
+ worker_url = "#{TASK_ROUTER_WEBSOCKET_BASE_URL}/#{@account_sid}/#{@worker_sid}"
75
+ ['GET', 'POST'].each do |meth|
76
+ add_policy(worker_url, meth)
77
+ end
78
+ end
79
+
80
+ def allow_activity_list_fetch
81
+ url = "#{workspace_url}/Activities"
82
+ add_policy(url, 'GET')
83
+ end
84
+
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,16 @@
1
+ module Restcomm
2
+ module RCML
3
+ class Response
4
+
5
+ attr_reader :text
6
+ alias_method :to_xml , :text
7
+
8
+ def initialize(&block)
9
+ xml = Builder::XmlMarkup.new
10
+ xml.instruct!
11
+ @text = xml.Response &block
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,15 @@
1
+ module Restcomm
2
+ module Util
3
+ def url_encode(hash)
4
+ hash.to_a.map {|p| p.map {|e| CGI.escape get_string(e)}.join '='}.join '&'
5
+ end
6
+
7
+ def get_string(obj)
8
+ if obj.respond_to?(:strftime)
9
+ obj.strftime('%Y-%m-%d')
10
+ else
11
+ obj.to_s
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,64 @@
1
+ module Restcomm
2
+ module Util
3
+ class Capability
4
+
5
+ include Restcomm::Util
6
+
7
+ def initialize(account_sid = nil, auth_token = nil)
8
+ @account_sid = account_sid || Restcomm.account_sid
9
+ @auth_token = auth_token || Restcomm.auth_token
10
+ if @account_sid.nil? || @auth_token.nil?
11
+ raise ArgumentError, 'Account SID and auth token are required'
12
+ end
13
+ @capabilities = []
14
+ end
15
+
16
+ def allow_client_incoming(client_name)
17
+ @client_name = client_name # stash for use in outgoing
18
+ scope_params = { 'clientName' => client_name }
19
+ @capabilities << scope_uri_for('client', 'incoming', scope_params)
20
+ end
21
+
22
+ def allow_client_outgoing(app_sid, params = {})
23
+ @allow_client_outgoing = true
24
+ @outgoing_scope_params = { 'appSid' => app_sid }
25
+ unless params.empty?
26
+ @outgoing_scope_params['appParams'] = url_encode params
27
+ end
28
+ end
29
+
30
+ def allow_event_stream(filters = {})
31
+ scope_params = { 'path' => '/2010-04-01/Events' }
32
+ scope_params['params'] = filters unless filters.empty?
33
+ @capabilities << scope_uri_for('stream', 'subscribe', scope_params)
34
+ end
35
+
36
+ def scope_uri_for(service, privilege, params = {})
37
+ scope_uri = "scope:#{service}:#{privilege}"
38
+ scope_uri << "?#{url_encode(params)}" unless params.empty?
39
+ end
40
+
41
+ def generate(ttl = 3600)
42
+
43
+ capabilities = @capabilities.clone # we need a local copy to work on
44
+
45
+ # build the outgoing scope lazily so that we can use @client_name
46
+ if @allow_client_outgoing
47
+ params = @outgoing_scope_params
48
+ params.merge!('clientName' => @client_name) if @client_name
49
+ capabilities << scope_uri_for('client', 'outgoing', params)
50
+ end
51
+
52
+ payload = {
53
+ 'scope' => capabilities.join(' '),
54
+ 'iss' => @account_sid,
55
+ 'exp' => (Time.now.to_i + ttl),
56
+ }
57
+
58
+ JWT.encode payload, @auth_token
59
+
60
+ end
61
+
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,7 @@
1
+ module Restcomm
2
+ module Util
3
+ class Configuration
4
+ attr_accessor :account_sid, :auth_token
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,37 @@
1
+ module Restcomm
2
+ module Util
3
+ class RequestValidator
4
+
5
+ def initialize(auth_token = nil)
6
+ @auth_token = auth_token || Restcomm.auth_token
7
+ raise ArgumentError, 'Auth token is required' if @auth_token.nil?
8
+ end
9
+
10
+ def validate(url, params, signature)
11
+ expected = build_signature_for url, params
12
+ secure_compare(expected, signature)
13
+ end
14
+
15
+ def build_signature_for(url, params)
16
+ data = url + params.sort.join
17
+ digest = OpenSSL::Digest.new('sha1')
18
+ Base64.encode64(OpenSSL::HMAC.digest(digest, @auth_token, data)).strip
19
+ end
20
+
21
+ private
22
+
23
+ # Compares two strings in constant time to avoid timing attacks.
24
+ # Borrowed from ActiveSupport::MessageVerifier.
25
+ # https://github.com/rails/rails/blob/master/activesupport/lib/active_support/message_verifier.rb
26
+ def secure_compare(a, b)
27
+ return false unless a.bytesize == b.bytesize
28
+
29
+ l = a.unpack("C#{a.bytesize}")
30
+
31
+ res = 0
32
+ b.each_byte { |byte| res |= byte ^ l.shift }
33
+ res == 0
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,3 @@
1
+ module Restcomm
2
+ VERSION = '1.2.0'
3
+ end
@@ -0,0 +1,34 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'restcomm-ruby/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'restcomm-ruby'
8
+ spec.version = Restcomm::VERSION
9
+ spec.authors = ['Andrew Benton']
10
+ spec.email = ['andrew@twilio.com']
11
+ spec.summary = 'A simple library for communicating with the Restcomm REST API, building RCML, and generating Restcomm Client Capability Tokens'
12
+ spec.description = 'A simple library for communicating with the Restcomm REST API, building RCML, and generating Restcomm Client Capability Tokens'
13
+ spec.homepage = 'http://github.com/restcomm/restcomm-ruby'
14
+ spec.license = 'MIT'
15
+
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', 'restcomm-ruby', '--main', 'README.md']
23
+
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'
28
+ # Workaround for RBX <= 2.2.1, should be fixed in next version
29
+ spec.add_dependency('rubysl') if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
30
+
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', 'restcomm-ruby', '--main', 'README.md']
34
+ end
@@ -0,0 +1,110 @@
1
+ require 'spec_helper'
2
+ require 'rack/mock'
3
+
4
+ describe Rack::RestcommWebhookAuthentication do
5
+ before do
6
+ @app = lambda {|env| [200, {'Content-Type' => 'text/plain'}, ['Hello']] }
7
+ end
8
+
9
+ describe 'new' do
10
+ it 'should initialize with an app, auth token and a path' do
11
+ expect {
12
+ Rack::RestcommWebhookAuthentication.new(@app, 'ABC', /\/voice/)
13
+ }.not_to raise_error
14
+ end
15
+
16
+ it 'should initialize with an app, auth token and paths' do
17
+ expect {
18
+ Rack::RestcommWebhookAuthentication.new(@app, 'ABC', /\/voice/, /\/sms/)
19
+ }.not_to raise_error
20
+ end
21
+
22
+ it 'should initialize with an app, dynamic token and paths' do
23
+ expect {
24
+ Rack::RestcommWebhookAuthentication.new(@app, nil, /\/voice/, /\/sms/)
25
+ }.not_to raise_error
26
+ end
27
+ end
28
+
29
+ describe 'calling against one path with dynamic auth token' do
30
+ it 'should allow a request through if it validates' do
31
+ auth_token = 'qwerty'
32
+ account_sid = 12345
33
+ expect_any_instance_of(Rack::Request).to receive(:post?).and_return(true)
34
+ expect_any_instance_of(Rack::Request).to receive(:POST).and_return({'AccountSid' => account_sid})
35
+ @middleware = Rack::RestcommWebhookAuthentication.new(@app, nil, /\/voice/) { |asid| auth_token}
36
+ request_validator = double('RequestValidator')
37
+ expect(Restcomm::Util::RequestValidator).to receive(:new).with(auth_token).and_return(request_validator)
38
+ expect(request_validator).to receive(:validate).and_return(true)
39
+ request = Rack::MockRequest.env_for('/voice')
40
+ status, headers, body = @middleware.call(request)
41
+ expect(status).to be(200)
42
+ end
43
+ end
44
+
45
+ describe 'calling against one path' do
46
+ before do
47
+ @middleware = Rack::RestcommWebhookAuthentication.new(
48
+ @app, 'ABC', /\/voice/
49
+ )
50
+ end
51
+
52
+ it 'should not intercept when the path doesn\'t match' do
53
+ expect(Restcomm::Util::RequestValidator).to_not receive(:validate)
54
+ request = Rack::MockRequest.env_for('/sms')
55
+ status, headers, body = @middleware.call(request)
56
+ expect(status).to be(200)
57
+ end
58
+
59
+ it 'should allow a request through if it validates' do
60
+ expect_any_instance_of(Restcomm::Util::RequestValidator).to(
61
+ receive(:validate).and_return(true)
62
+ )
63
+ request = Rack::MockRequest.env_for('/voice')
64
+ status, headers, body = @middleware.call(request)
65
+ expect(status).to be(200)
66
+ end
67
+
68
+ it 'should short circuit a request to 403 if it does not validate' do
69
+ expect_any_instance_of(Restcomm::Util::RequestValidator).to(
70
+ receive(:validate).and_return(false)
71
+ )
72
+ request = Rack::MockRequest.env_for('/voice')
73
+ status, headers, body = @middleware.call(request)
74
+ expect(status).to be(403)
75
+ end
76
+ end
77
+
78
+ describe 'calling against many paths' do
79
+ before do
80
+ @middleware = Rack::RestcommWebhookAuthentication.new(
81
+ @app, 'ABC', /\/voice/, /\/sms/
82
+ )
83
+ end
84
+
85
+ it 'should not intercept when the path doesn\'t match' do
86
+ expect(Restcomm::Util::RequestValidator).to_not receive(:validate)
87
+ request = Rack::MockRequest.env_for('icesms')
88
+ status, headers, body = @middleware.call(request)
89
+ expect(status).to be(200)
90
+ end
91
+
92
+ it 'shold allow a request through if it validates' do
93
+ expect_any_instance_of(Restcomm::Util::RequestValidator).to(
94
+ receive(:validate).and_return(true)
95
+ )
96
+ request = Rack::MockRequest.env_for('/sms')
97
+ status, headers, body = @middleware.call(request)
98
+ expect(status).to be(200)
99
+ end
100
+
101
+ it 'should short circuit a request to 403 if it does not validate' do
102
+ expect_any_instance_of(Restcomm::Util::RequestValidator).to(
103
+ receive(:validate).and_return(false)
104
+ )
105
+ request = Rack::MockRequest.env_for('/sms')
106
+ status, headers, body = @middleware.call(request)
107
+ expect(status).to be(403)
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,89 @@
1
+ require 'spec_helper'
2
+
3
+ describe Restcomm::REST::Account do
4
+
5
+ before do
6
+ @account = Restcomm::REST::Account.new('someUri', 'someClient')
7
+ end
8
+
9
+ it 'sets up incoming phone numbers resources object' do
10
+ expect(@account).to respond_to(:incoming_phone_numbers)
11
+ expect(@account.incoming_phone_numbers.instance_variable_get('@path')).to(
12
+ eq('someUri/IncomingPhoneNumbers')
13
+ )
14
+ end
15
+
16
+ it 'sets up an available phone numbers resources object' do
17
+ expect(@account).to respond_to(:available_phone_numbers)
18
+ expect(@account.available_phone_numbers.instance_variable_get('@path')).to(
19
+ eq('someUri/AvailablePhoneNumbers')
20
+ )
21
+ end
22
+
23
+ it 'sets up an outgoing caller ids resources object' do
24
+ expect(@account).to respond_to(:outgoing_caller_ids)
25
+ expect(@account.outgoing_caller_ids.instance_variable_get('@path')).to eq(
26
+ 'someUri/OutgoingCallerIds'
27
+ )
28
+ end
29
+
30
+ it 'sets up a calls resources object' do
31
+ expect(@account).to respond_to(:calls)
32
+ expect(@account.calls.instance_variable_get('@path')).to eq('someUri/Calls')
33
+ end
34
+
35
+ it 'sets up a conferences resources object' do
36
+ expect(@account).to respond_to(:conferences)
37
+ expect(@account.conferences.instance_variable_get('@path')).to eq(
38
+ 'someUri/Conferences'
39
+ )
40
+ end
41
+
42
+ it 'sets up a queues resources object' do
43
+ expect(@account).to respond_to(:queues)
44
+ expect(@account.queues.instance_variable_get('@path')).to eq(
45
+ 'someUri/Queues'
46
+ )
47
+ end
48
+
49
+ it 'sets up a sms resource object' do
50
+ expect(@account).to respond_to(:sms)
51
+ expect(@account.sms.instance_variable_get('@path')).to eq('someUri/SMS')
52
+ end
53
+
54
+ it 'sets up a recordings resources object' do
55
+ expect(@account).to respond_to(:recordings)
56
+ expect(@account.recordings.instance_variable_get('@path')).to eq(
57
+ 'someUri/Recordings'
58
+ )
59
+ end
60
+
61
+ it 'sets up a transcriptions resources object' do
62
+ expect(@account).to respond_to(:transcriptions)
63
+ expect(@account.transcriptions.instance_variable_get('@path')).to eq(
64
+ 'someUri/Transcriptions'
65
+ )
66
+ end
67
+
68
+ it 'sets up a notifications resources object' do
69
+ expect(@account).to respond_to(:notifications)
70
+ expect(@account.notifications.instance_variable_get('@path')).to eq(
71
+ 'someUri/Notifications'
72
+ )
73
+ end
74
+
75
+ it 'sets up a tokens resources object' do
76
+ expect(@account).to respond_to(:tokens)
77
+ expect(@account.tokens.instance_variable_get('@path')).to eq(
78
+ 'someUri/Tokens'
79
+ )
80
+ end
81
+
82
+ it 'sets up an addresses resources object' do
83
+ expect(@account).to respond_to(:addresses)
84
+ expect(@account.addresses.instance_variable_get('@path')).to eq(
85
+ 'someUri/Addresses'
86
+ )
87
+ end
88
+
89
+ end