apisonator 2.101.1 → 3.1.0

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
  SHA256:
3
- metadata.gz: 17eddc012f9777873f8bb1eca063c269903980531ae2963e839c265e2cce8ecc
4
- data.tar.gz: f0b5ff06a98132e51dd5ab4bbbcf9322f037ee029487919366fca1eb207c13e8
3
+ metadata.gz: edd1887f6aa71c17fb5279f98988c9a3b5e631e80bc1f4142b6619b5f5e24f48
4
+ data.tar.gz: b6478d14e88a177480396a7d46d5f4e33cea683aea17303175ad18ae646e546f
5
5
  SHA512:
6
- metadata.gz: 81a05e8249f1a354897379fc814a898f712ecc9b5a82e6dd9a28ab21abbdb6bd2e7af65a71cb77571cf476d581a251773a87bc3b489bf5be2d9740d6e3e1812b
7
- data.tar.gz: fe7bd84d54a37680841df80cd405f2b71ff4a1cb936d757df5aa06e484c7c871584101cac6ea3f72eb1b17836b3af188474590a9ab6d40c4919037a8ce1a644e
6
+ metadata.gz: 944b75385817abc4d2f8828c61b2301d5cdfbb6c1bb681b7a3165590f23ad1b6c80451fcf579b8f3cf0010fe5a95e65605998f5d8ec94f1ff4ce690556b3011a
7
+ data.tar.gz: f3f44b1b2ebfe6c8fcbbf36b90dd44e5a7875d997a36b97288417472fa4156689508bfc95afdf196a7a168f768aa6e38521502b93078f128994959d184c1cd37
@@ -2,6 +2,56 @@
2
2
 
3
3
  Notable changes to Apisonator will be tracked in this document.
4
4
 
5
+ ## 3.1.0 - 2020-10-14
6
+
7
+ ### Added
8
+
9
+ - Prometheus metrics for the internal API
10
+ ([#236](https://github.com/3scale/apisonator/pull/236)).
11
+ - Docs with a detailed explanation about how counter updates are performed
12
+ ([#239](https://github.com/3scale/apisonator/pull/239)).
13
+
14
+ ### Changed
15
+
16
+ - NotifyJobs are run only when the service ID is explicitly defined
17
+ ([#238](https://github.com/3scale/apisonator/pull/238)).
18
+
19
+ ### Fixed
20
+
21
+ - Fixed corner case that raised "TransactionTimestampNotWithinRange" in notify
22
+ jobs ([#235](https://github.com/3scale/apisonator/pull/235)).
23
+
24
+
25
+ ## 3.0.1.1 - 2020-07-28
26
+
27
+ ### Changed
28
+
29
+ - Updated json gem to v2.3.1
30
+ ([#232](https://github.com/3scale/apisonator/pull/232)).
31
+
32
+ ## 3.0.1 - 2020-07-14
33
+
34
+ ### Fixed
35
+
36
+ - The Prometheus counter of "5xx" errors has been fixed
37
+ ([#230](https://github.com/3scale/apisonator/pull/230)).
38
+
39
+ ### Changed
40
+
41
+ - Gem updates: rack to v2.1.4
42
+ ([#228](https://github.com/3scale/apisonator/pull/228)) and async-redis to
43
+ v0.5.0 ([#229](https://github.com/3scale/apisonator/pull/229)).
44
+
45
+
46
+ ## 3.0.0 - 2020-06-19
47
+
48
+ ### Removed
49
+
50
+ - Apisonator no longer supports the native oauth authorization mode. This is a
51
+ feature that was deprecated a long time ago
52
+ ([#226](https://github.com/3scale/apisonator/pull/226)).
53
+
54
+
5
55
  ## 2.101.1 - 2020-06-05
6
56
 
7
57
  ### Fixed
@@ -53,13 +53,13 @@ gem 'rake', '~> 13.0'
53
53
  gem 'builder', '= 3.2.3'
54
54
  # Use a patched resque to allow reusing their Airbrake Failure class
55
55
  gem 'resque', git: 'https://github.com/3scale/resque', branch: '3scale'
56
- gem 'rack', '~> 2.0.8'
56
+ gem 'rack', '~> 2.1.4'
57
57
  gem 'sinatra', '~> 2.0.3'
58
58
  gem 'sinatra-contrib', '~> 2.0.3'
59
59
  # Optional external error logging services
60
60
  gem 'bugsnag', '~> 6', require: nil
61
61
  gem 'yabeda-prometheus', '~> 0.5.0'
62
- gem 'async-redis', '~> 0.4.1'
62
+ gem 'async-redis', '~> 0.5'
63
63
  gem 'falcon', '~> 0.35'
64
64
 
65
65
  # Use a patched redis-rb that fixes an issue when trying to connect with
@@ -35,7 +35,7 @@ GIT
35
35
  PATH
36
36
  remote: .
37
37
  specs:
38
- apisonator (2.101.1)
38
+ apisonator (3.1.0)
39
39
 
40
40
  GEM
41
41
  remote: https://rubygems.org/
@@ -66,14 +66,15 @@ GEM
66
66
  async-http-cache (0.1.5)
67
67
  async-http
68
68
  protocol-http (~> 0.14)
69
- async-io (1.27.5)
69
+ async-io (1.27.7)
70
70
  async (~> 1.14)
71
71
  async-pool (0.2.0)
72
72
  async (~> 1.8)
73
- async-redis (0.4.1)
73
+ async-redis (0.5.0)
74
74
  async (~> 1.8)
75
75
  async-io (~> 1.10)
76
- protocol-redis (~> 0.2.0)
76
+ async-pool (~> 0.2)
77
+ protocol-redis (~> 0.5.0)
77
78
  async-rspec (1.13.0)
78
79
  rspec (~> 3.0)
79
80
  rspec-files (~> 1.0)
@@ -118,7 +119,7 @@ GEM
118
119
  i18n (1.8.2)
119
120
  concurrent-ruby (~> 1.0)
120
121
  jmespath (1.3.1)
121
- json (2.1.0)
122
+ json (2.3.1)
122
123
  license_finder (5.9.2)
123
124
  bundler
124
125
  rubyzip
@@ -161,7 +162,7 @@ GEM
161
162
  protocol-http2 (0.11.6)
162
163
  protocol-hpack (~> 1.4)
163
164
  protocol-http (~> 0.15)
164
- protocol-redis (0.2.0)
165
+ protocol-redis (0.5.0)
165
166
  pry (0.11.3)
166
167
  coderay (~> 1.1.0)
167
168
  method_source (~> 0.9.0)
@@ -171,7 +172,7 @@ GEM
171
172
  pry-doc (0.11.1)
172
173
  pry (~> 0.9)
173
174
  yard (~> 0.9)
174
- rack (2.0.9)
175
+ rack (2.1.4)
175
176
  rack-protection (2.0.3)
176
177
  rack
177
178
  rack-test (0.8.2)
@@ -266,7 +267,7 @@ PLATFORMS
266
267
  DEPENDENCIES
267
268
  airbrake (= 4.3.1)
268
269
  apisonator!
269
- async-redis (~> 0.4.1)
270
+ async-redis (~> 0.5)
270
271
  async-rspec
271
272
  aws-sdk (= 2.4.2)
272
273
  benchmark-ips (~> 2.7.2)
@@ -286,7 +287,7 @@ DEPENDENCIES
286
287
  pry-byebug (~> 3.5.1)
287
288
  pry-doc (~> 0.11.1)
288
289
  puma!
289
- rack (~> 2.0.8)
290
+ rack (~> 2.1.4)
290
291
  rack-test (~> 0.8.2)
291
292
  rake (~> 13.0)
292
293
  redis!
@@ -35,7 +35,7 @@ GIT
35
35
  PATH
36
36
  remote: .
37
37
  specs:
38
- apisonator (2.101.1)
38
+ apisonator (3.1.0)
39
39
 
40
40
  GEM
41
41
  remote: https://rubygems.org/
@@ -63,14 +63,15 @@ GEM
63
63
  async-http-cache (0.1.5)
64
64
  async-http
65
65
  protocol-http (~> 0.14)
66
- async-io (1.27.5)
66
+ async-io (1.27.7)
67
67
  async (~> 1.14)
68
68
  async-pool (0.2.0)
69
69
  async (~> 1.8)
70
- async-redis (0.4.1)
70
+ async-redis (0.5.0)
71
71
  async (~> 1.8)
72
72
  async-io (~> 1.10)
73
- protocol-redis (~> 0.2.0)
73
+ async-pool (~> 0.2)
74
+ protocol-redis (~> 0.5.0)
74
75
  async-rspec (1.13.0)
75
76
  rspec (~> 3.0)
76
77
  rspec-files (~> 1.0)
@@ -107,7 +108,7 @@ GEM
107
108
  hiredis (0.6.3)
108
109
  i18n (1.8.2)
109
110
  concurrent-ruby (~> 1.0)
110
- json (2.1.0)
111
+ json (2.3.1)
111
112
  license_finder (5.9.2)
112
113
  bundler
113
114
  rubyzip
@@ -149,7 +150,7 @@ GEM
149
150
  protocol-http2 (0.11.6)
150
151
  protocol-hpack (~> 1.4)
151
152
  protocol-http (~> 0.15)
152
- protocol-redis (0.2.0)
153
+ protocol-redis (0.5.0)
153
154
  pry (0.11.3)
154
155
  coderay (~> 1.1.0)
155
156
  method_source (~> 0.9.0)
@@ -159,7 +160,7 @@ GEM
159
160
  pry-doc (0.11.1)
160
161
  pry (~> 0.9)
161
162
  yard (~> 0.9)
162
- rack (2.0.9)
163
+ rack (2.1.4)
163
164
  rack-protection (2.0.3)
164
165
  rack
165
166
  rack-test (0.8.2)
@@ -249,7 +250,7 @@ PLATFORMS
249
250
 
250
251
  DEPENDENCIES
251
252
  apisonator!
252
- async-redis (~> 0.4.1)
253
+ async-redis (~> 0.5)
253
254
  async-rspec
254
255
  benchmark-ips (~> 2.7.2)
255
256
  bugsnag (~> 6)
@@ -267,7 +268,7 @@ DEPENDENCIES
267
268
  pry-byebug (~> 3.5.1)
268
269
  pry-doc (~> 0.11.1)
269
270
  puma!
270
- rack (~> 2.0.8)
271
+ rack (~> 2.1.4)
271
272
  rack-test (~> 0.8.2)
272
273
  rake (~> 13.0)
273
274
  redis!
@@ -35,7 +35,6 @@ require '3scale/backend/rack'
35
35
  require '3scale/backend/extensions'
36
36
  require '3scale/backend/background_job'
37
37
  require '3scale/backend/storage'
38
- require '3scale/backend/oauth'
39
38
  require '3scale/backend/memoizer'
40
39
  require '3scale/backend/application'
41
40
  require '3scale/backend/error_storage'
@@ -91,8 +91,8 @@ module ThreeScale
91
91
  end
92
92
  end
93
93
 
94
- def extract_id!(service_id, app_id, user_key, access_token)
95
- with_app_id_from_params service_id, app_id, user_key, access_token do |appid|
94
+ def extract_id!(service_id, app_id, user_key)
95
+ with_app_id_from_params service_id, app_id, user_key do |appid|
96
96
  exists? service_id, appid and appid
97
97
  end
98
98
  end
@@ -106,7 +106,6 @@ module ThreeScale
106
106
  raise ApplicationNotFound, id unless exists?(service_id, id)
107
107
  delete_data service_id, id
108
108
  clear_cache service_id, id
109
- OAuth::Token::Storage.remove_tokens(service_id, id)
110
109
  end
111
110
 
112
111
  def delete_data(service_id, id)
@@ -157,14 +156,12 @@ module ThreeScale
157
156
  )
158
157
  end
159
158
 
160
- def with_app_id_from_params(service_id, app_id, user_key, access_token = nil)
159
+ def with_app_id_from_params(service_id, app_id, user_key)
161
160
  if app_id
162
161
  raise AuthenticationError unless user_key.nil?
163
162
  elsif user_key
164
163
  app_id = load_id_by_key(service_id, user_key)
165
164
  raise UserKeyInvalid, user_key if app_id.nil?
166
- elsif access_token
167
- app_id, * = OAuth::Token::Storage.get_credentials access_token, service_id
168
165
  else
169
166
  raise ApplicationNotFound
170
167
  end
@@ -1,6 +1,7 @@
1
1
  require '3scale/backend/configuration/loader'
2
2
  require '3scale/backend/environment'
3
3
  require '3scale/backend/configurable'
4
+ require '3scale/backend/errors'
4
5
 
5
6
  module ThreeScale
6
7
  module Backend
@@ -57,7 +58,6 @@ module ThreeScale
57
58
  config.add_section(:redshift, :host, :port, :dbname, :user, :password)
58
59
  config.add_section(:statsd, :host, :port)
59
60
  config.add_section(:internal_api, :user, :password)
60
- config.add_section(:oauth, :max_token_size)
61
61
  config.add_section(:master, :metrics)
62
62
  config.add_section(:worker_prometheus_metrics, :enabled, :port)
63
63
  config.add_section(:listener_prometheus_metrics, :enabled, :port)
@@ -78,9 +78,6 @@ module ThreeScale
78
78
  master_metrics = [:transactions, :transactions_authorize]
79
79
  config.master.metrics = Struct.new(*master_metrics).new
80
80
 
81
- # Default config
82
- config.master_service_id = 1
83
-
84
81
  # This setting controls whether the listener can create event buckets in
85
82
  # Redis. We do not want all the listeners creating buckets yet, as we do
86
83
  # not know exactly the rate at which we can send events to Kinesis
@@ -73,36 +73,6 @@ module ThreeScale
73
73
  end
74
74
  end
75
75
 
76
- class AccessTokenInvalid < NotFound
77
- def initialize(id = nil)
78
- super %(token "#{id}" is invalid: expired or never defined)
79
- end
80
- end
81
-
82
- class AccessTokenAlreadyExists < Error
83
- def initialize(id = nil)
84
- super %(token "#{id}" already exists)
85
- end
86
- end
87
-
88
- class AccessTokenStorageError < Error
89
- def initialize(id = nil)
90
- super %(storage error when saving token "#{id}")
91
- end
92
- end
93
-
94
- class AccessTokenFormatInvalid < Invalid
95
- def initialize
96
- super 'token is either too big or has an invalid format'.freeze
97
- end
98
- end
99
-
100
- class AccessTokenInvalidTTL < Invalid
101
- def initialize
102
- super 'the specified TTL should be a positive integer'.freeze
103
- end
104
- end
105
-
106
76
  class ServiceNotActive < Error
107
77
  def initialize
108
78
  super 'service is not active'.freeze
@@ -182,12 +152,6 @@ module ThreeScale
182
152
  end
183
153
  end
184
154
 
185
- class RequiredParamsMissing < Invalid
186
- def initialize
187
- super 'missing required parameters'.freeze
188
- end
189
- end
190
-
191
155
  class UsageValueInvalid < Error
192
156
  def initialize(metric_name, value)
193
157
  if !value.is_a?(String) || value.blank?
@@ -30,9 +30,6 @@ module ThreeScale
30
30
  ##~ @parameter_app_id_inline = @parameter_app_id.clone
31
31
  ##~ @parameter_app_id_inline["description_inline"] = true
32
32
  ##
33
- ##~ @parameter_access_token = {"name" => "access_token", "dataType" => "string", "required" => false, "paramType" => "query", "threescale_name" => "access_tokens"}
34
- ##~ @parameter_access_token["description"] = "OAuth token used for authorizing if you don't use client_id with client_secret."
35
- ##
36
33
  ##~ @parameter_client_id = {"name" => "app_id", "dataType" => "string", "required" => false, "paramType" => "query", "threescale_name" => "app_ids"}
37
34
  ##~ @parameter_client_id["description"] = "Client Id (identifier of the application if the auth. pattern is OAuth, note that client_id == app_id)"
38
35
  ##~ @parameter_client_id_inline = @parameter_client_id.clone
@@ -114,8 +111,7 @@ module ThreeScale
114
111
 
115
112
 
116
113
  AUTH_AUTHREP_COMMON_PARAMS = ['service_id'.freeze, 'app_id'.freeze, 'app_key'.freeze,
117
- 'user_key'.freeze, 'provider_key'.freeze,
118
- 'access_token'.freeze].freeze
114
+ 'user_key'.freeze, 'provider_key'.freeze].freeze
119
115
  private_constant :AUTH_AUTHREP_COMMON_PARAMS
120
116
 
121
117
  REPORT_EXPECTED_PARAMS = ['provider_key'.freeze,
@@ -128,8 +124,6 @@ module ThreeScale
128
124
  disable :dump_errors
129
125
  end
130
126
 
131
- set :views, File.dirname(__FILE__) + '/views'
132
-
133
127
  use Backend::Rack::ExceptionCatcher
134
128
 
135
129
  before do
@@ -252,7 +246,7 @@ module ThreeScale
252
246
  ##~ op.summary = "Authorize (OAuth authentication mode pattern)"
253
247
  ##
254
248
  ##~ op.description = "<p>Read-only operation to authorize an application in the OAuth authentication pattern."
255
- ##~ @oauth_security = "<p>When using this endpoint please pay attention at your handling of app_id and app_key parameters. If you don't specify an app_key, the endpoint assumes the app_id specified has already been authenticated by other means. If you specify the app_key parameter, even if it is empty, it will be checked against the application's keys. If you don't trust the app_id value you have, either use app keys and specify one or use access_token and avoid the app_id parameter."
249
+ ##~ @oauth_security = "<p>When using this endpoint please pay attention at your handling of app_id and app_key parameters. If you don't specify an app_key, the endpoint assumes the app_id specified has already been authenticated by other means. If you specify the app_key parameter, even if it is empty, it will be checked against the application's keys. If you don't trust the app_id value you have, use app keys and specify one."
256
250
  ##~ @oauth_desc_response = "<p>This call returns extra data (secret and redirect_url) needed to power OAuth APIs. It's only available for users with OAuth enabled APIs."
257
251
  ##~ op.description = op.description + @oauth_security + @oauth_desc_response
258
252
  ##~ op.description = op.description + " " + @authorize_desc + " " + @authorize_desc_response
@@ -263,7 +257,6 @@ module ThreeScale
263
257
  ##
264
258
  ##~ op.parameters.add @parameter_service_token
265
259
  ##~ op.parameters.add @parameter_service_id
266
- ##~ op.parameters.add @parameter_access_token
267
260
  ##~ op.parameters.add @parameter_client_id
268
261
  ##~ op.parameters.add @parameter_app_key_oauth
269
262
  ##~ op.parameters.add @parameter_referrer
@@ -337,7 +330,6 @@ module ThreeScale
337
330
  ##
338
331
  ##~ op.parameters.add @parameter_service_token
339
332
  ##~ op.parameters.add @parameter_service_id
340
- ##~ op.parameters.add @parameter_access_token
341
333
  ##~ op.parameters.add @parameter_client_id
342
334
  ##~ op.parameters.add @parameter_app_key_oauth
343
335
  ##~ op.parameters.add @parameter_referrer
@@ -430,62 +422,6 @@ module ThreeScale
430
422
  202
431
423
  end
432
424
 
433
- ## OAUTH ACCESS TOKENS
434
-
435
- # These endpoints are deprecated and are going to be removed. For now,
436
- # let's disable them.
437
- if Backend.test?
438
- post '/services/:service_id/oauth_access_tokens.xml' do
439
- check_post_content_type!
440
- require_params! :service_id, :token
441
-
442
- service_id = params[:service_id]
443
- ensure_authenticated!(params[:provider_key], params[:service_token], service_id)
444
-
445
- app_id = params[:app_id]
446
- raise ApplicationNotFound, app_id unless Application.exists?(service_id, app_id)
447
-
448
- OAuth::Token::Storage.create(params[:token], service_id, app_id, params[:ttl])
449
- end
450
-
451
- delete '/services/:service_id/oauth_access_tokens/:token.xml' do
452
- require_params! :service_id, :token
453
-
454
- service_id = params[:service_id]
455
- ensure_authenticated!(params[:provider_key], params[:service_token], service_id)
456
-
457
- token = params[:token]
458
-
459
- # TODO: perhaps improve this to list the deleted tokens?
460
- raise AccessTokenInvalid, token unless OAuth::Token::Storage.delete(token, service_id)
461
- end
462
-
463
- get '/services/:service_id/applications/:app_id/oauth_access_tokens.xml' do
464
- require_params! :service_id, :app_id
465
-
466
- service_id = params[:service_id]
467
- ensure_authenticated!(params[:provider_key], params[:service_token], service_id)
468
-
469
- app_id = params[:app_id]
470
-
471
- raise ApplicationNotFound, app_id unless Application.exists?(service_id, app_id)
472
-
473
- @tokens = OAuth::Token::Storage.all_by_service_and_app service_id, app_id
474
- builder :oauth_access_tokens
475
- end
476
-
477
- get '/services/:service_id/oauth_access_tokens/:token.xml' do
478
- require_params! :service_id, :token
479
-
480
- service_id = params[:service_id]
481
- ensure_authenticated!(params[:provider_key], params[:service_token], service_id)
482
-
483
- @token_to_app_id = OAuth::Token::Storage.get_credentials(params[:token], service_id)
484
-
485
- builder :oauth_app_id_by_token
486
- end
487
- end
488
-
489
425
  get '/check.txt' do
490
426
  content_type 'text/plain'
491
427
  body 'ok'
@@ -518,10 +454,6 @@ module ThreeScale
518
454
  params[:usage].nil? || params[:usage].is_a?(Hash)
519
455
  end
520
456
 
521
- def require_params!(*keys)
522
- raise RequiredParamsMissing unless params && keys.all? { |key| !blank?(params[key]) }
523
- end
524
-
525
457
  def check_params_value_encoding!(input_params, params_to_validate)
526
458
  params_to_validate.each do |p|
527
459
  param_value = input_params[p]
@@ -651,15 +583,6 @@ module ThreeScale
651
583
  raise ServiceTokenInvalid.new(token, id)
652
584
  end
653
585
 
654
- def ensure_authenticated!(provider_key, service_token, service_id)
655
- if blank?(provider_key)
656
- key = provider_key_from(service_token, service_id)
657
- raise_provider_key_error(params) if blank?(key)
658
- elsif !Service.authenticate_service_id(service_id, provider_key)
659
- raise ProviderKeyInvalid, provider_key
660
- end
661
- end
662
-
663
586
  def response_auth_call(auth_status)
664
587
  status(auth_status.authorized? ? 200 : 409)
665
588
  optionally_set_headers(auth_status)
@@ -4,14 +4,34 @@ require 'rack'
4
4
  module ThreeScale
5
5
  module Backend
6
6
  class ListenerMetrics
7
- REQUEST_TYPES = {
7
+ AUTH_AND_REPORT_REQUEST_TYPES = {
8
8
  '/transactions/authorize.xml' => 'authorize',
9
9
  '/transactions/oauth_authorize.xml' => 'authorize_oauth',
10
10
  '/transactions/authrep.xml' => 'authrep',
11
11
  '/transactions/oauth_authrep.xml' => 'authrep_oauth',
12
12
  '/transactions.xml' => 'report'
13
13
  }
14
- private_constant :REQUEST_TYPES
14
+ private_constant :AUTH_AND_REPORT_REQUEST_TYPES
15
+
16
+ INTERNAL_API_PATHS = [
17
+ [/\/services\/.*\/alert_limits/, 'alerts'],
18
+ [/\/services\/.*\/applications\/.*\/keys/, 'application_keys'],
19
+ [/\/services\/.*\/applications\/.*\/referrer_filters/, 'application_referrer_filters'],
20
+ [/\/services\/.*\/applications/, 'applications'],
21
+ [/\/services\/.*\/errors/, 'errors'],
22
+ [/\/events/, 'events'],
23
+ [/\/services\/.*\/metrics/, 'metrics'],
24
+ [/\/service_tokens/, 'service_tokens'],
25
+ [/\/services/, 'services'],
26
+ [/\/services\/.*\/stats/, 'stats'],
27
+ [/\/services\/.*\/plans\/.*\/usagelimits/, 'usage_limits'],
28
+ [/\/services\/.*\/applications\/.*\/utilization/, 'utilization'],
29
+ ].freeze
30
+ private_constant :INTERNAL_API_PATHS
31
+
32
+ # Most requests will be under 100ms, so use a higher granularity from there
33
+ TIME_BUCKETS = [0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1, 0.25, 0.5, 0.75, 1]
34
+ private_constant :TIME_BUCKETS
15
35
 
16
36
  class << self
17
37
  ERRORS_4XX_TO_TRACK = Set[403, 404, 409].freeze
@@ -27,9 +47,12 @@ module ThreeScale
27
47
  end
28
48
 
29
49
  def report_resp_code(path, resp_code)
30
- Yabeda.apisonator_listener.response_codes.increment(
50
+ req_type = req_type(path)
51
+ prometheus_group = prometheus_group(req_type)
52
+
53
+ Yabeda.send(prometheus_group).response_codes.increment(
31
54
  {
32
- request_type: REQUEST_TYPES[path],
55
+ request_type: req_type,
33
56
  resp_code: code_group(resp_code)
34
57
  },
35
58
  by: 1
@@ -37,8 +60,11 @@ module ThreeScale
37
60
  end
38
61
 
39
62
  def report_response_time(path, request_time)
40
- Yabeda.apisonator_listener.response_times.measure(
41
- { request_type: REQUEST_TYPES[path] },
63
+ req_type = req_type(path)
64
+ prometheus_group = prometheus_group(req_type)
65
+
66
+ Yabeda.send(prometheus_group).response_times.measure(
67
+ { request_type: req_type },
42
68
  request_time
43
69
  )
44
70
  end
@@ -69,8 +95,21 @@ module ThreeScale
69
95
  comment 'Response times'
70
96
  unit :seconds
71
97
  tags %i[request_type]
72
- # Most requests will be under 100ms, so use a higher granularity from there
73
- buckets [0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1, 0.25, 0.5, 0.75, 1]
98
+ buckets TIME_BUCKETS
99
+ end
100
+ end
101
+
102
+ group :apisonator_listener_internal_api do
103
+ counter :response_codes do
104
+ comment 'Response codes'
105
+ tags %i[request_type resp_code]
106
+ end
107
+
108
+ histogram :response_times do
109
+ comment 'Response times'
110
+ unit :seconds
111
+ tags %i[request_type]
112
+ buckets TIME_BUCKETS
74
113
  end
75
114
  end
76
115
  end
@@ -93,6 +132,24 @@ module ThreeScale
93
132
  'unknown'.freeze
94
133
  end
95
134
  end
135
+
136
+ def req_type(path)
137
+ AUTH_AND_REPORT_REQUEST_TYPES[path] || internal_api_req_type(path)
138
+ end
139
+
140
+ def internal_api_req_type(path)
141
+ (_regex, type) = INTERNAL_API_PATHS.find { |(regex, _)| regex.match path }
142
+ type
143
+ end
144
+
145
+ # Returns the group as defined in .define_metrics
146
+ def prometheus_group(request_type)
147
+ if AUTH_AND_REPORT_REQUEST_TYPES.values.include? request_type
148
+ :apisonator_listener
149
+ else
150
+ :apisonator_listener_internal_api
151
+ end
152
+ end
96
153
  end
97
154
  end
98
155
  end
@@ -8,7 +8,15 @@ module ThreeScale
8
8
 
9
9
  def call(env)
10
10
  began_at = Time.now.getutc
11
- status, header, body = @app.call(env)
11
+
12
+ begin
13
+ status, header, body = @app.call(env)
14
+ rescue Exception => e
15
+ ListenerMetrics.report_resp_code(env['REQUEST_PATH'], 500)
16
+ ListenerMetrics.report_response_time(env['REQUEST_PATH'], Time.now - began_at)
17
+ raise e
18
+ end
19
+
12
20
  ListenerMetrics.report_resp_code(env['REQUEST_PATH'], status)
13
21
  ListenerMetrics.report_response_time(env['REQUEST_PATH'], Time.now - began_at)
14
22
  [status, header, body]
@@ -47,7 +47,7 @@ module ThreeScale
47
47
 
48
48
  endpoint = Async::IO::Endpoint.tcp(host, port)
49
49
  @redis_async = Async::Redis::Client.new(
50
- endpoint, connection_limit: opts[:max_connections]
50
+ endpoint, limit: opts[:max_connections]
51
51
  )
52
52
  @building_pipeline = false
53
53
  end
@@ -65,19 +65,7 @@ module ThreeScale
65
65
  params[:app_id] = nil if app_id && app_id.empty?
66
66
 
67
67
  if oauth
68
- if app_id.nil?
69
- access_token = params[:access_token]
70
- access_token = nil if access_token && access_token.empty?
71
-
72
- if access_token.nil?
73
- raise ApplicationNotFound.new nil if app_id.nil?
74
- else
75
- app_id = get_token_ids(access_token, service_id, app_id)
76
- # update params, since they are checked elsewhere
77
- params[:app_id] = app_id
78
- end
79
- end
80
-
68
+ raise ApplicationNotFound.new nil if app_id.nil?
81
69
  validators = Validators::OAUTH_VALIDATORS
82
70
  else
83
71
  validators = Validators::VALIDATORS
@@ -30,9 +30,13 @@ module ThreeScale
30
30
  end
31
31
 
32
32
  def notify(provider_key, usage)
33
- # batch several notifications together so that we can process just one
33
+ # We need the master service ID to report its metrics. If it's not
34
+ # set, we don't need to notify anything.
35
+ # Batch several notifications together so that we can process just one
34
36
  # job for a group of them.
35
- notify_batch(provider_key, usage)
37
+ unless configuration.master_service_id.to_s.empty?
38
+ notify_batch(provider_key, usage)
39
+ end
36
40
  end
37
41
 
38
42
  def notify_batch(provider_key, usage)
@@ -7,8 +7,6 @@ module ThreeScale
7
7
  extend Configurable
8
8
  @queue = :main
9
9
 
10
- InvalidMasterServiceId = Class.new(ThreeScale::Backend::Error)
11
-
12
10
  class << self
13
11
  def perform_logged(provider_key, usage, timestamp, _enqueue_time)
14
12
  application_id = Application.load_id_by_key(master_service_id, provider_key)
@@ -16,12 +14,42 @@ module ThreeScale
16
14
  if application_id && Application.exists?(master_service_id, application_id)
17
15
  master_metrics = Metric.load_all(master_service_id)
18
16
 
19
- ProcessJob.perform([{
20
- service_id: master_service_id,
21
- application_id: application_id,
22
- timestamp: timestamp,
23
- usage: master_metrics.process_usage(usage)
24
- }])
17
+ begin
18
+ ProcessJob.perform([{
19
+ service_id: master_service_id,
20
+ application_id: application_id,
21
+ timestamp: timestamp,
22
+ usage: master_metrics.process_usage(usage)
23
+ }])
24
+ rescue MetricInvalid => e
25
+ # This happens when the master account in Porta does not have
26
+ # the notify metrics defined (by default "transactions" and
27
+ # "transactions/authorize"). These metrics need to be created in
28
+ # Porta, Apisonator does not have a way to guarantee that
29
+ # they're defined.
30
+ # Notice that this rescue prevents the job from being retried.
31
+ # Apisonator can't know when the metrics will be created (if
32
+ # ever) so it's better to log the error rather than retrying
33
+ # these jobs for an undefined period of time.
34
+ Worker.logger.notify(e)
35
+ return [false, "#{e}"]
36
+ rescue TransactionTimestampNotWithinRange => e
37
+ # This is very unlikely to happen. The timestamps in a notify
38
+ # job are not set by users, they are set by the listeners. If
39
+ # this error happens it might mean that:
40
+ # a) The worker started processing this job way after the
41
+ # listener produced it. This can happen for example if we make
42
+ # some requests to a listener with no workers. The listeners
43
+ # will enqueue some notify jobs. If we start a worker hours
44
+ # later, we might see this error.
45
+ # b) There's some kind of clock skew issue.
46
+ # c) There's a bug.
47
+ #
48
+ # We can't raise here, because then, the job will be retried,
49
+ # but it's going to fail always if it has an old timestamp.
50
+ Worker.logger.notify(e)
51
+ return [false, "#{provider_key} #{application_id} #{e}"]
52
+ end
25
53
  end
26
54
  [true, "#{provider_key} #{application_id || '--'}"]
27
55
  end
@@ -29,15 +57,7 @@ module ThreeScale
29
57
  private
30
58
 
31
59
  def master_service_id
32
- value = configuration.master_service_id
33
-
34
- unless value
35
- raise InvalidMasterServiceId,
36
- "Can't find master service id. Make sure the \"master_service_id\" "\
37
- 'configuration value is set correctly'
38
- end
39
-
40
- value.to_s
60
+ configuration.master_service_id.to_s
41
61
  end
42
62
  end
43
63
  end
@@ -59,7 +59,7 @@ module ThreeScale
59
59
  return [] if transactions.empty?
60
60
  transactions = transactions.values if transactions.respond_to?(:values)
61
61
  transactions.group_by do |transaction|
62
- Application.extract_id!(service_id, transaction['app_id'], transaction['user_key'], transaction['access_token'])
62
+ Application.extract_id!(service_id, transaction['app_id'], transaction['user_key'])
63
63
  end.each(&block)
64
64
  end
65
65
 
@@ -1,5 +1,5 @@
1
1
  module ThreeScale
2
2
  module Backend
3
- VERSION = '2.101.1'
3
+ VERSION = '3.1.0'
4
4
  end
5
5
  end
@@ -23,7 +23,7 @@
23
23
  </dependency>
24
24
  <dependency>
25
25
  <packageName>apisonator</packageName>
26
- <version>2.101.1</version>
26
+ <version>3.1.0</version>
27
27
  <licenses>
28
28
  <license>
29
29
  <name>Apache 2.0</name>
@@ -73,7 +73,7 @@
73
73
  </dependency>
74
74
  <dependency>
75
75
  <packageName>async-io</packageName>
76
- <version>1.27.5</version>
76
+ <version>1.27.7</version>
77
77
  <licenses>
78
78
  <license>
79
79
  <name>MIT</name>
@@ -93,7 +93,7 @@
93
93
  </dependency>
94
94
  <dependency>
95
95
  <packageName>async-redis</packageName>
96
- <version>0.4.1</version>
96
+ <version>0.5.0</version>
97
97
  <licenses>
98
98
  <license>
99
99
  <name>MIT</name>
@@ -371,7 +371,7 @@
371
371
  </dependency>
372
372
  <dependency>
373
373
  <packageName>json</packageName>
374
- <version>2.1.0</version>
374
+ <version>2.3.1</version>
375
375
  <licenses>
376
376
  <license>
377
377
  <name>ruby</name>
@@ -669,7 +669,7 @@
669
669
  </dependency>
670
670
  <dependency>
671
671
  <packageName>protocol-redis</packageName>
672
- <version>0.2.0</version>
672
+ <version>0.5.0</version>
673
673
  <licenses>
674
674
  <license>
675
675
  <name>MIT</name>
@@ -719,7 +719,7 @@
719
719
  </dependency>
720
720
  <dependency>
721
721
  <packageName>rack</packageName>
722
- <version>2.0.9</version>
722
+ <version>2.1.4</version>
723
723
  <licenses>
724
724
  <license>
725
725
  <name>MIT</name>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: apisonator
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.101.1
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Ciganek
@@ -16,7 +16,7 @@ authors:
16
16
  autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
- date: 2020-06-05 00:00:00.000000000 Z
19
+ date: 2020-10-14 00:00:00.000000000 Z
20
20
  dependencies: []
21
21
  description: This gem provides a daemon that handles authorization and reporting of
22
22
  web services managed by 3scale.
@@ -111,11 +111,6 @@ files:
111
111
  - lib/3scale/backend/memoizer.rb
112
112
  - lib/3scale/backend/metric.rb
113
113
  - lib/3scale/backend/metric/collection.rb
114
- - lib/3scale/backend/oauth.rb
115
- - lib/3scale/backend/oauth/token.rb
116
- - lib/3scale/backend/oauth/token_key.rb
117
- - lib/3scale/backend/oauth/token_storage.rb
118
- - lib/3scale/backend/oauth/token_value.rb
119
114
  - lib/3scale/backend/period.rb
120
115
  - lib/3scale/backend/period/boundary.rb
121
116
  - lib/3scale/backend/period/cache.rb
@@ -184,8 +179,6 @@ files:
184
179
  - lib/3scale/backend/validators/service_state.rb
185
180
  - lib/3scale/backend/validators/state.rb
186
181
  - lib/3scale/backend/version.rb
187
- - lib/3scale/backend/views/oauth_access_tokens.builder
188
- - lib/3scale/backend/views/oauth_app_id_by_token.builder
189
182
  - lib/3scale/backend/worker.rb
190
183
  - lib/3scale/backend/worker_async.rb
191
184
  - lib/3scale/backend/worker_metrics.rb
@@ -1,4 +0,0 @@
1
- require '3scale/backend/oauth/token'
2
- require '3scale/backend/oauth/token_key'
3
- require '3scale/backend/oauth/token_value'
4
- require '3scale/backend/oauth/token_storage'
@@ -1,26 +0,0 @@
1
- module ThreeScale
2
- module Backend
3
- module OAuth
4
- class Token
5
- attr_reader :service_id, :token, :key
6
- attr_accessor :ttl, :app_id
7
-
8
- def initialize(token, service_id, app_id, ttl)
9
- @token = token
10
- @service_id = service_id
11
- @app_id = app_id
12
- @ttl = ttl
13
- @key = Key.for token, service_id
14
- end
15
-
16
- def value
17
- Value.for app_id
18
- end
19
-
20
- def self.from_value(token, service_id, value, ttl)
21
- new token, service_id, *Value.from(value), ttl
22
- end
23
- end
24
- end
25
- end
26
- end
@@ -1,30 +0,0 @@
1
- # This module defines the format of the keys for OAuth tokens and token sets.
2
- #
3
- # Note that while we can build the key easily, we cannot reliably obtain a token
4
- # and a service_id out of the key, because there are no constraints on them:
5
- #
6
- # "oauth_access_tokens/service:some/servicegoeshere/andthisis_a_/valid_token"
7
- #
8
- module ThreeScale
9
- module Backend
10
- module OAuth
11
- class Token
12
- module Key
13
- class << self
14
- def for(token, service_id)
15
- "oauth_access_tokens/service:#{service_id}/#{token}"
16
- end
17
- end
18
-
19
- module Set
20
- class << self
21
- def for(service_id, app_id)
22
- "oauth_access_tokens/service:#{service_id}/app:#{app_id}/"
23
- end
24
- end
25
- end
26
- end
27
- end
28
- end
29
- end
30
- end
@@ -1,313 +0,0 @@
1
- module ThreeScale
2
- module Backend
3
- module OAuth
4
- class Token
5
- module Storage
6
- include Configurable
7
-
8
- # Default token size is 4K - 512 (to allow for some metadata)
9
- MAXIMUM_TOKEN_SIZE = configuration.oauth.max_token_size || 3584
10
- private_constant :MAXIMUM_TOKEN_SIZE
11
- TOKEN_MAX_REDIS_SLICE_SIZE = 500
12
- private_constant :TOKEN_MAX_REDIS_SLICE_SIZE
13
- TOKEN_TTL_DEFAULT = 86400
14
- private_constant :TOKEN_TTL_DEFAULT
15
- TOKEN_TTL_PERMANENT = 0
16
- private_constant :TOKEN_TTL_PERMANENT
17
-
18
- Error = Class.new StandardError
19
- InconsistencyError = Class.new Error
20
-
21
- class << self
22
- include Backend::Logging
23
- include Backend::StorageHelpers
24
-
25
- def create(token, service_id, app_id, ttl = nil)
26
- raise AccessTokenFormatInvalid if token.nil? || token.empty? ||
27
- !token.is_a?(String) || token.bytesize > MAXIMUM_TOKEN_SIZE
28
-
29
- # raises if TTL is invalid
30
- ttl = sanitized_ttl ttl
31
-
32
- key = Key.for token, service_id
33
- raise AccessTokenAlreadyExists.new(token) unless storage.get(key).nil?
34
-
35
- value = Value.for app_id
36
- token_set = Key::Set.for(service_id, app_id)
37
-
38
- store_token token, token_set, key, value, ttl
39
- ensure_stored! token, token_set, key, value
40
- end
41
-
42
- # Deletes a token
43
- #
44
- # Returns the associated app_id or nil
45
- #
46
- def delete(token, service_id)
47
- key = Key.for token, service_id
48
- val = storage.get key
49
- if val
50
- app_id = Value.from val
51
- token_set = Key::Set.for(service_id, app_id)
52
-
53
- existed, * = remove_a_token token_set, token, key
54
-
55
- unless existed
56
- logger.notify(InconsistencyError.new("Found OAuth token " \
57
- "#{token} for service #{service_id} and app #{app_id} as " \
58
- "key but not in set!"))
59
- end
60
- end
61
-
62
- val
63
- end
64
-
65
- # Get a token's associated app_id
66
- def get_credentials(token, service_id)
67
- app_id = Value.from(storage.get(Key.for(token, service_id)))
68
- raise AccessTokenInvalid.new token if app_id.nil?
69
- app_id
70
- end
71
-
72
- # This is used to list tokens by service and app.
73
- #
74
- # Note: this deletes tokens that have not been found from the set of
75
- # tokens for the given app - those have to be expired tokens.
76
- def all_by_service_and_app(service_id, app_id)
77
- token_set = Key::Set.for(service_id, app_id)
78
- deltokens = []
79
- tokens_n_values_flat(token_set, service_id)
80
- .select do |(token, _key, value, _ttl)|
81
- app_id = Value.from value
82
- if app_id.nil?
83
- deltokens << token
84
- false
85
- else
86
- true
87
- end
88
- end
89
- .map do |(token, _key, value, ttl)|
90
- Token.from_value token, service_id, value, ttl
91
- end
92
- .tap do
93
- # delete expired tokens (nil values) from token set
94
- deltokens.each_slice(TOKEN_MAX_REDIS_SLICE_SIZE) do |delgrp|
95
- storage.srem token_set, delgrp
96
- end
97
- end
98
- end
99
-
100
- # Remove tokens by app_id.
101
- #
102
- # Triggered by Application deletion.
103
- #
104
- def remove_tokens(service_id, app_id)
105
- remove_tokens_by service_id, app_id
106
- end
107
-
108
-
109
- private
110
-
111
- # Remove all tokens
112
- #
113
- # I thought of leaving this one public, but remove_*_tokens removed
114
- # my use cases for the time being.
115
- def remove_tokens_by(service_id, app_id)
116
- token_set = Key::Set.for(service_id, app_id)
117
-
118
- remove_whole_token_set(token_set, service_id)
119
- end
120
-
121
- def remove_token_set_by(token_set, service_id, &blk)
122
- # Get tokens. Filter them. Group them into manageable groups.
123
- # Extract tokens and keys into separate arrays, one for each.
124
- # Remove tokens from token set (they are keys in a set) and token
125
- # keys themselves.
126
- tokens_n_values_flat(token_set, service_id, false)
127
- .select(&blk)
128
- .each_slice(TOKEN_MAX_REDIS_SLICE_SIZE)
129
- .inject([[], []]) do |acc, groups|
130
- groups.each do |token, key, _value|
131
- acc[0] << token
132
- acc[1] << key
133
- end
134
- acc
135
- end
136
- .each_slice(2)
137
- .inject([]) do |acc, (tokens, keys)|
138
- storage.pipelined do
139
- if tokens && !tokens.empty?
140
- storage.srem token_set, tokens
141
- acc.concat tokens
142
- end
143
- storage.del keys if keys && !keys.empty?
144
- end
145
- acc
146
- end
147
- end
148
-
149
- def remove_a_token(token_set, token, key)
150
- storage.pipelined do
151
- storage.srem token_set, token
152
- storage.del key
153
- end
154
- end
155
-
156
- def remove_whole_token_set(token_set, service_id)
157
- _token_groups, key_groups = tokens_n_keys(token_set, service_id)
158
- storage.pipelined do
159
- storage.del token_set
160
- # remove all tokens for this app
161
- key_groups.each do |keys|
162
- storage.del keys
163
- end
164
- end
165
- end
166
-
167
- # TODO: provide a SSCAN interface with lazy enums because SMEMBERS
168
- # is prone to DoSing and timeouts
169
- def tokens_from(token_set)
170
- storage.smembers(token_set)
171
- end
172
-
173
- def tokens_n_keys(token_set, service_id)
174
- token_groups = tokens_from(token_set).each_slice(TOKEN_MAX_REDIS_SLICE_SIZE)
175
- key_groups = token_groups.map do |tokens|
176
- tokens.map do |token|
177
- Key.for token, service_id
178
- end
179
- end
180
-
181
- [token_groups, key_groups]
182
- end
183
-
184
- # Provides grouped data which matches respectively in each array
185
- # position, ie. 1st group of data contains a group of tokens, keys
186
- # and values with ttls, and position N of the tokens group has key
187
- # in position N of the keys group, and so on.
188
- #
189
- # [[[token group], [key group], [value_with_ttls_group]], ...]
190
- #
191
- def tokens_n_values_groups(token_set, service_id, with_ttls)
192
- token_groups, key_groups = tokens_n_keys(token_set, service_id)
193
- value_ttl_groups = key_groups.map do |keys|
194
- # pipelining will create an array with the results of commands
195
- res = storage.pipelined do
196
- storage.mget(keys)
197
- if with_ttls
198
- keys.map do |key|
199
- storage.ttl key
200
- end
201
- end
202
- end
203
- # [mget array, 0..n ttls] => [mget array, ttls array]
204
- [res.shift, res]
205
- end
206
- token_groups.zip(key_groups, value_ttl_groups)
207
- end
208
-
209
- # Zips the data provided by tokens_n_values_groups so that you stop
210
- # looking at indexes in the respective arrays and instead have:
211
- #
212
- # [group 0, ..., group N] where each group is made of:
213
- # [[token 0, key 0, value 0, ttl 0], ..., [token N, key N, value
214
- # N, ttl N]]
215
- #
216
- def tokens_n_values_zipped_groups(token_set, service_id, with_ttls = true)
217
- tokens_n_values_groups(token_set,
218
- service_id,
219
- with_ttls).map do |tokens, keys, (values, ttls)|
220
- tokens.zip keys, values, ttls
221
- end
222
- end
223
-
224
- # Flattens the data provided by tokens_n_values_zipped_groups so
225
- # that you have a transparent iterator with all needed data and can
226
- # stop worrying about streaming groups of elements.
227
- #
228
- def tokens_n_values_flat(token_set, service_id, with_ttls = true)
229
- tokens_n_values_zipped_groups(token_set,
230
- service_id,
231
- with_ttls).flat_map do |groups|
232
- groups.map do |token, key, value, ttl|
233
- [token, key, value, ttl]
234
- end
235
- end
236
- end
237
-
238
- # Store the specified token in Redis
239
- #
240
- # TTL specified in seconds.
241
- # A TTL of 0 stores a permanent token
242
- def store_token(token, token_set, key, value, ttl)
243
- # build the storage command so that we can pipeline everything cleanly
244
- command = :set
245
- args = [key]
246
-
247
- if !permanent_ttl? ttl
248
- command = :setex
249
- args << ttl
250
- end
251
-
252
- args << value
253
-
254
- # pipelined will return nil if it is embedded into another
255
- # pipeline(which would be an error at this point) or if shutting
256
- # down and a connection error happens. Both things being abnormal
257
- # means we should just raise a storage error.
258
- raise AccessTokenStorageError, token unless storage.pipelined do
259
- storage.send(command, *args)
260
- storage.sadd(token_set, token)
261
- end
262
- end
263
-
264
-
265
- # Make sure everything ended up there
266
- #
267
- # TODO: review and possibly reimplement trying to leave it
268
- # consistent as much as possible.
269
- #
270
- # Note that we have a sharding proxy and pipelines can't be guaranteed
271
- # to behave like transactions, since we might have one non-working
272
- # shard. Instead of relying on proxy-specific responses, we just check
273
- # that the data we should have in the store is really there.
274
- def ensure_stored!(token, token_set, key, value)
275
- results = storage.pipelined do
276
- storage.get(key)
277
- storage.sismember(token_set, token)
278
- end
279
-
280
- results.last && results.first == value ||
281
- raise(AccessTokenStorageError, token)
282
- end
283
-
284
- # Validation for the TTL value
285
- #
286
- # 0 is accepted (understood as permanent token)
287
- # Negative values are not accepted
288
- # Integer(ttl) validation is required (if input is nil, default applies)
289
- def sanitized_ttl(ttl)
290
- ttl = begin
291
- Integer(ttl)
292
- rescue TypeError
293
- # ttl is nil
294
- TOKEN_TTL_DEFAULT
295
- rescue
296
- # NaN
297
- -1
298
- end
299
- raise AccessTokenInvalidTTL if ttl < 0
300
-
301
- ttl
302
- end
303
-
304
- # Check whether a TTL has the magic value for a permanent token
305
- def permanent_ttl?(ttl)
306
- ttl == TOKEN_TTL_PERMANENT
307
- end
308
- end
309
- end
310
- end
311
- end
312
- end
313
- end
@@ -1,25 +0,0 @@
1
- # This module encodes values in Redis for our tokens
2
- module ThreeScale
3
- module Backend
4
- module OAuth
5
- class Token
6
- module Value
7
- # Note: this module made more sense when it also supported end-users.
8
- # Given how simple the module is, we could get rid of it in a future
9
- # refactor.
10
-
11
- class << self
12
- # this method is used when creating tokens
13
- def for(app_id)
14
- app_id
15
- end
16
-
17
- def from(value)
18
- value
19
- end
20
- end
21
- end
22
- end
23
- end
24
- end
25
- end
@@ -1,14 +0,0 @@
1
- xml.instruct!
2
- xml.oauth_access_tokens do
3
- @tokens.each do |t|
4
- # Some bright head leaked the -1 that Redis uses to indicate there is no TTL
5
- # associated with a key. The behaviour is inconsistent because somehow we
6
- # BOTH expect that a token with no TTL does not have a "ttl" attribute in
7
- # the generated XML and at the same time we expect (in some tests) that such
8
- # tokens have this field with a -1 value.
9
- #
10
- # Just enforce the ttl to be -1 when there is none.
11
- attrs = { :ttl => t.ttl || -1 }
12
- xml.oauth_access_token t.token, attrs
13
- end
14
- end
@@ -1,4 +0,0 @@
1
- xml.instruct!
2
- xml.application do
3
- xml.app_id @token_to_app_id
4
- end