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.
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