twilio-ruby 5.0.0.rc10 → 5.0.0.rc11

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: befdd4f96aa0b5e442b72e11092febd7e239f710
4
- data.tar.gz: 0efa699b3d93dbf76b0252cfb55fb78475c37247
3
+ metadata.gz: 08fdb6eda5b98184a808746fcedbbc14bbed427d
4
+ data.tar.gz: d66ce45e3a0742fe226e45cd515e8cd450bd423e
5
5
  SHA512:
6
- metadata.gz: 8e746dba563996ad009d22c9177ab41d8474a7b65ef149d047235bca7abd2a8204228942bbd1ba8ab3ab7ecf8070c324c8a313089b832d191bc7adb5c4336a0c
7
- data.tar.gz: 2316f5410d312dc300d2ac8e507afe1b869306af9eae5a69ec1116f920258436cc5827591f51bf4033e8223ebe110bf90f6c7f443acc699c0c5bcef1bb50df9e
6
+ metadata.gz: 362332a50a8e5870e1ff80044a1985c6a7241725d947ecb98661fa8b1414e194fea0d882d7cc82c299afe6eb027d51a58169c14c952e767e0c6ae157d4544b63
7
+ data.tar.gz: 0200bd6483b8a7e2ffbdf1a12708ad3df4eb0523e252bba3094940eb4cfe689f01d23452c41bd8a66931a658b6ab2e003659044c4e950edfe601824ef56ff7ea
@@ -25,12 +25,12 @@ module Rack
25
25
  end
26
26
 
27
27
  def call(env)
28
- return @app.call(env) unless env["PATH_INFO"].match(@path_regex)
28
+ return @app.call(env) unless env['PATH_INFO'].match(@path_regex)
29
29
  request = Rack::Request.new(env)
30
30
  original_url = request.url
31
31
  params = request.post? ? request.POST : {}
32
32
  auth_token = @auth_token || get_auth_token(params['AccountSid'])
33
- validator = Twilio::Util::RequestValidator.new(auth_token)
33
+ validator = Twilio::Security::RequestValidator.new(auth_token)
34
34
  signature = env['HTTP_X_TWILIO_SIGNATURE'] || ""
35
35
  if validator.validate(original_url, params, signature)
36
36
  @app.call(env)
@@ -38,7 +38,7 @@ module Rack
38
38
  [
39
39
  403,
40
40
  {'Content-Type' => 'text/plain'},
41
- ["Twilio Request Validation Failed."]
41
+ ['Twilio Request Validation Failed.']
42
42
  ]
43
43
  end
44
44
  end
@@ -0,0 +1,111 @@
1
+ module Twilio
2
+ module JWT
3
+ class AccessToken
4
+ attr_accessor :account_sid,
5
+ :signing_key_id,
6
+ :secret,
7
+ :ttl,
8
+ :identity,
9
+ :nbf
10
+
11
+ def initialize(account_sid, signing_key_id, secret, ttl=3600, identity=nil, nbf=nil)
12
+ @account_sid = account_sid
13
+ @signing_key_sid = signing_key_id
14
+ @secret = secret
15
+ @ttl = ttl
16
+ @identity = identity
17
+ @nbf = nbf
18
+ @grants = []
19
+ end
20
+
21
+ def add_grant(grant)
22
+ @grants.push(grant)
23
+ end
24
+
25
+ def to_jwt(algorithm='HS256')
26
+ now = Time.now.to_i - 1
27
+ headers = {
28
+ cty: 'twilio-fpa;v=1',
29
+ typ: 'JWT'
30
+ }
31
+
32
+ grants = {}
33
+ if @identity
34
+ grants[:identity] = @identity
35
+ end
36
+
37
+ @grants.each { |grant| grants[grant.key] = grant.payload }
38
+
39
+ payload = {
40
+ jti: "#{@signing_key_sid}-#{now}",
41
+ iss: @signing_key_sid,
42
+ sub: @account_sid,
43
+ exp: now + @ttl,
44
+ grants: grants
45
+ }
46
+
47
+ payload[:nbf] = @nbf unless @nbf.nil?
48
+
49
+ ::JWT.encode payload, @secret, algorithm, headers
50
+ end
51
+
52
+ def to_s
53
+ to_jwt
54
+ end
55
+
56
+ class ConversationsGrant
57
+ attr_accessor :configuration_profile_sid
58
+
59
+ def key
60
+ 'rtc'
61
+ end
62
+
63
+ def payload
64
+ payload = {}
65
+
66
+ if configuration_profile_sid
67
+ payload[:configuration_profile_sid] = configuration_profile_sid
68
+ end
69
+
70
+ payload
71
+ end
72
+
73
+ end
74
+
75
+ class IpMessagingGrant
76
+ attr_accessor :service_sid,
77
+ :endpoint_id,
78
+ :deployment_role_sid,
79
+ :push_credential_sid
80
+
81
+ def key
82
+ 'ip_messaging'
83
+ end
84
+
85
+ def payload
86
+ payload = {}
87
+
88
+ if service_sid
89
+ payload[:service_sid] = service_sid
90
+ end
91
+
92
+ if endpoint_id
93
+ payload[:endpoint_id] = endpoint_id
94
+ end
95
+
96
+ if deployment_role_sid
97
+ payload[:deployment_role_sid] = deployment_role_sid
98
+ end
99
+
100
+ if push_credential_sid
101
+ payload[:push_credential_sid] = push_credential_sid
102
+ end
103
+
104
+ payload
105
+ end
106
+
107
+ end
108
+
109
+ end
110
+ end
111
+ end
@@ -1,5 +1,5 @@
1
1
  module Twilio
2
- module Util
2
+ module JWT
3
3
  class Capability
4
4
 
5
5
  include Twilio::Util
@@ -15,21 +15,21 @@ module Twilio
15
15
 
16
16
  def allow_client_incoming(client_name)
17
17
  @client_name = client_name # stash for use in outgoing
18
- scope_params = { 'clientName' => client_name }
18
+ scope_params = { clientName: client_name }
19
19
  @capabilities << scope_uri_for('client', 'incoming', scope_params)
20
20
  end
21
21
 
22
22
  def allow_client_outgoing(app_sid, params = {})
23
23
  @allow_client_outgoing = true
24
- @outgoing_scope_params = { 'appSid' => app_sid }
24
+ @outgoing_scope_params = { appSid: app_sid }
25
25
  unless params.empty?
26
26
  @outgoing_scope_params['appParams'] = url_encode params
27
27
  end
28
28
  end
29
29
 
30
30
  def allow_event_stream(filters = {})
31
- scope_params = { 'path' => '/2010-04-01/Events' }
32
- scope_params['params'] = filters unless filters.empty?
31
+ scope_params = { path: '/2010-04-01/Events' }
32
+ scope_params[:params] = filters unless filters.empty?
33
33
  @capabilities << scope_uri_for('stream', 'subscribe', scope_params)
34
34
  end
35
35
 
@@ -50,12 +50,12 @@ module Twilio
50
50
  end
51
51
 
52
52
  payload = {
53
- 'scope' => capabilities.join(' '),
54
- 'iss' => @account_sid,
55
- 'exp' => (Time.now.to_i + ttl),
53
+ scope: capabilities.join(' '),
54
+ iss: @account_sid,
55
+ exp: (Time.now.to_i + ttl),
56
56
  }
57
57
 
58
- JWT.encode payload, @auth_token
58
+ ::JWT.encode payload, @auth_token
59
59
 
60
60
  end
61
61
 
@@ -0,0 +1,203 @@
1
+ module Twilio
2
+ module JWT
3
+ class TaskRouterCapability
4
+ TASK_ROUTER_BASE_URL = 'https://taskrouter.twilio.com'
5
+ TASK_ROUTER_VERSION = 'v1'
6
+ TASK_ROUTER_WEBSOCKET_BASE_URL = 'https://event-bridge.twilio.com/v1/wschannels'
7
+
8
+ REQUIRED = {required: true}
9
+ OPTIONAL = {required: false}
10
+
11
+ def initialize(account_sid, auth_token, workspace_sid, channel_id)
12
+ @account_sid = account_sid
13
+ @auth_token = auth_token
14
+ @policies = []
15
+
16
+ @workspace_sid = workspace_sid
17
+ @channel_id = channel_id
18
+
19
+ @base_url = "#{TASK_ROUTER_BASE_URL}/#{TASK_ROUTER_VERSION}/Workspaces/#{workspace_sid}"
20
+
21
+ validate_jwt
22
+
23
+ setup_resource
24
+
25
+ allow_websocket_requests(@channel_id)
26
+ allow(@resource_url, 'GET')
27
+ end
28
+
29
+ def allow_fetch_subresources
30
+ allow(@resource_url + '/**', 'GET')
31
+ end
32
+
33
+ def allow_updates
34
+ allow(@resource_url, 'POST')
35
+ end
36
+
37
+ def allow_updates_subresources
38
+ allow(@resource_url + '/**', 'POST')
39
+ end
40
+
41
+ def allow_delete
42
+ allow(@resource_url, 'DELETE')
43
+ end
44
+
45
+ def allow_delete_subresources
46
+ allow(@resource_url + '/**', 'DELETE')
47
+ end
48
+
49
+ def add_policy(url, method, allowed = true, query_filters = nil, post_filters = nil)
50
+ policy = {
51
+ url: url,
52
+ method: method,
53
+ query_filter: query_filters || {},
54
+ post_filter: post_filters || {},
55
+ allow: allowed
56
+ }
57
+
58
+ @policies.push(policy)
59
+ end
60
+
61
+ def allow(url, method, query_filters = nil, post_filters = nil)
62
+ add_policy(url, method, true, query_filters, post_filters)
63
+ end
64
+
65
+ def deny(url, method, query_filters = nil, post_filters = nil)
66
+ add_policy(url, method, false, query_filters, post_filters)
67
+ end
68
+
69
+ def generate_token(ttl = 3600)
70
+ task_router_attributes = {
71
+ account_sid: @account_sid,
72
+ workspace_sid: @workspace_sid,
73
+ channel: @channel_id
74
+ }
75
+
76
+ if @channel_id[0..1] == 'WK'
77
+ task_router_attributes[:worker_sid] = @channel_id
78
+ elsif @channel_id[0..1] == 'WQ'
79
+ task_router_attributes[:taskqueue_sid] = @channel_id
80
+ end
81
+
82
+ generate_token_protected(ttl, task_router_attributes)
83
+ end
84
+
85
+ protected
86
+
87
+ def generate_token_protected(ttl = 3600, extra_attributes)
88
+ payload = {
89
+ iss: @account_sid,
90
+ exp: (Time.now.to_i + ttl),
91
+ version: TASK_ROUTER_VERSION,
92
+ friendly_name: @channel_id,
93
+ policies: @policies,
94
+ }
95
+ extra_attributes.each { |key, value|
96
+ payload[key] = value
97
+ }
98
+
99
+ ::JWT.encode payload, @auth_token
100
+ end
101
+
102
+ def setup_resource
103
+ if @channel_id[0..1] == 'WS'
104
+ @resource_url = @base_url
105
+ elsif @channel_id[0..1] == 'WK'
106
+ @resource_url = @base_url + '/Workers/' + @channel_id
107
+
108
+ @activity_url = @base_url + '/Activities'
109
+ allow(@activity_url, 'GET')
110
+
111
+ @tasks_url = @base_url + '/Tasks/**'
112
+ allow(@tasks_url, 'GET')
113
+
114
+ @worker_reservations_url = @resource_url + '/Reservations/**'
115
+ allow(@worker_reservations_url, 'GET')
116
+
117
+ elsif @channel_id[0..1] == 'WQ'
118
+ @resource_url = @base_url + '/TaskQueues/' + @channel_id
119
+ end
120
+ end
121
+
122
+ def allow_websocket_requests(channel_id)
123
+ worker_url = "#{TASK_ROUTER_WEBSOCKET_BASE_URL}/#{@account_sid}/#{channel_id}"
124
+ ['GET', 'POST'].each do |meth|
125
+ add_policy(worker_url, meth)
126
+ end
127
+ end
128
+
129
+ def validate_jwt
130
+ if @account_sid.nil? or @account_sid[0..1] != 'AC'
131
+ raise "Invalid AccountSid provided #{@account_sid}"
132
+ end
133
+ if @workspace_sid.nil? or @workspace_sid[0..1] != 'WS'
134
+ raise "Invalid WorkspaceSid provided #{@workspace_sid}"
135
+ end
136
+ if @channel_id.nil?
137
+ raise 'ChannelId not provided'
138
+ end
139
+ @prefix = @channel_id[0..1]
140
+ if @prefix != 'WS' and @prefix != 'WK' and @prefix != 'WQ'
141
+ raise "Invalid ChannelId provided: #{@channel_id}"
142
+ end
143
+ end
144
+ end
145
+
146
+ class WorkerCapability < TaskRouterCapability
147
+
148
+ def initialize(account_sid, auth_token, workspace_sid, worker_sid)
149
+ super(account_sid, auth_token, workspace_sid, worker_sid)
150
+ @tasks_url = @base_url + '/Tasks/**'
151
+ @activity_url = @base_url + '/Activities'
152
+ @worker_reservations_url = @resource_url + '/Reservations/**'
153
+
154
+ allow(@activity_url, 'GET')
155
+ allow(@tasks_url, 'GET')
156
+ allow(@worker_reservations_url, 'GET')
157
+ end
158
+
159
+ def allow_activity_updates
160
+ allow(@resource_url, 'POST', nil, {ActivitySid: REQUIRED})
161
+ end
162
+
163
+ def allow_reservation_updates
164
+ allow(@tasks_url, 'POST', nil, nil)
165
+ allow(@worker_reservations_url, 'POST', nil, nil)
166
+ end
167
+
168
+ protected
169
+
170
+ def setup_resource
171
+ @resource_url = @base_url + '/Workers/' + @channel_id
172
+ end
173
+
174
+ end
175
+
176
+ class WorkspaceCapability < TaskRouterCapability
177
+
178
+ def initialize(account_sid, auth_token, workspace_sid)
179
+ super(account_sid, auth_token, workspace_sid, workspace_sid)
180
+ end
181
+
182
+ protected
183
+
184
+ def setup_resource
185
+ @resource_url = @base_url
186
+ end
187
+
188
+ end
189
+
190
+ class TaskQueueCapability < TaskRouterCapability
191
+
192
+ def initialize(account_sid, auth_token, workspace_sid, taskqueue_sid)
193
+ super(account_sid, auth_token, workspace_sid, taskqueue_sid)
194
+ end
195
+
196
+ protected
197
+
198
+ def setup_resource
199
+ @resource_url = @base_url + '/TaskQueues/' + @channel_id
200
+ end
201
+ end
202
+ end
203
+ end
@@ -1,5 +1,5 @@
1
1
  module Twilio
2
- module Util
2
+ module Security
3
3
  class RequestValidator
4
4
 
5
5
  def initialize(auth_token = nil)
@@ -1,3 +1,3 @@
1
1
  module Twilio
2
- VERSION = '5.0.0.rc10'
2
+ VERSION = '5.0.0.rc11'
3
3
  end
data/lib/twilio-ruby.rb CHANGED
@@ -6,38 +6,36 @@ require 'openssl'
6
6
  require 'base64'
7
7
  require 'forwardable'
8
8
  require 'jwt'
9
+ require 'time'
9
10
 
10
11
  require 'twilio-ruby/version' unless defined?(Twilio::VERSION)
11
12
  require 'rack/twilio_webhook_authentication'
12
13
 
13
14
  require 'twilio-ruby/util'
14
- require 'twilio-ruby/util/capability'
15
- require 'twilio-ruby/util/client_config'
15
+ require 'twilio-ruby/jwt/access_token'
16
+ require 'twilio-ruby/jwt/capability'
17
+ require 'twilio-ruby/jwt/task_router'
18
+ require 'twilio-ruby/security/request_validator'
16
19
  require 'twilio-ruby/util/configuration'
17
- require 'twilio-ruby/util/request_validator'
18
- require 'twilio-ruby/util/access_token'
20
+
19
21
  require 'twilio-ruby/twiml/response'
20
22
 
21
- Dir[File.dirname(__FILE__) + "/twilio-ruby/http/**/*.rb"].each do |file|
22
- require file
23
- end
24
- Dir[File.dirname(__FILE__) + "/twilio-ruby/framework/**/*.rb"].each do |file|
23
+ Dir[File.dirname(__FILE__) + '/twilio-ruby/http/**/*.rb'].each do |file|
25
24
  require file
26
25
  end
27
- Dir[File.dirname(__FILE__) + "/twilio-ruby/rest/*.rb"].each do |file|
26
+ Dir[File.dirname(__FILE__) + '/twilio-ruby/framework/**/*.rb'].each do |file|
28
27
  require file
29
28
  end
30
- Dir[File.dirname(__FILE__) + "/twilio-ruby/rest/**/*.rb"].each do |file|
29
+ Dir[File.dirname(__FILE__) + '/twilio-ruby/rest/*.rb'].each do |file|
31
30
  require file
32
31
  end
33
- Dir[File.dirname(__FILE__) + "/twilio-ruby/compatibility/**/*.rb"].each do |file|
32
+ Dir[File.dirname(__FILE__) + '/twilio-ruby/rest/**/*.rb'].each do |file|
34
33
  require file
35
34
  end
36
- Dir[File.dirname(__FILE__) + "/twilio-ruby/task_router/**/*.rb"].each do |file|
35
+ Dir[File.dirname(__FILE__) + '/twilio-ruby/compatibility/**/*.rb'].each do |file|
37
36
  require file
38
37
  end
39
38
 
40
-
41
39
  module Twilio
42
40
  extend SingleForwardable
43
41