twilio-ruby 5.0.0.rc10 → 5.0.0.rc11

Sign up to get free protection for your applications and to get access to all the features.
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