apisonator 2.100.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 (173) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +317 -0
  3. data/Gemfile +11 -0
  4. data/Gemfile.base +65 -0
  5. data/Gemfile.lock +319 -0
  6. data/Gemfile.on_prem +1 -0
  7. data/Gemfile.on_prem.lock +297 -0
  8. data/LICENSE +202 -0
  9. data/NOTICE +15 -0
  10. data/README.md +230 -0
  11. data/Rakefile +287 -0
  12. data/apisonator.gemspec +47 -0
  13. data/app/api/api.rb +13 -0
  14. data/app/api/internal/alert_limits.rb +32 -0
  15. data/app/api/internal/application_keys.rb +49 -0
  16. data/app/api/internal/application_referrer_filters.rb +43 -0
  17. data/app/api/internal/applications.rb +77 -0
  18. data/app/api/internal/errors.rb +54 -0
  19. data/app/api/internal/events.rb +42 -0
  20. data/app/api/internal/internal.rb +104 -0
  21. data/app/api/internal/metrics.rb +40 -0
  22. data/app/api/internal/service_tokens.rb +46 -0
  23. data/app/api/internal/services.rb +58 -0
  24. data/app/api/internal/stats.rb +42 -0
  25. data/app/api/internal/usagelimits.rb +62 -0
  26. data/app/api/internal/utilization.rb +23 -0
  27. data/bin/3scale_backend +223 -0
  28. data/bin/3scale_backend_worker +26 -0
  29. data/config.ru +4 -0
  30. data/config/puma.rb +192 -0
  31. data/config/schedule.rb +9 -0
  32. data/ext/mkrf_conf.rb +64 -0
  33. data/lib/3scale/backend.rb +67 -0
  34. data/lib/3scale/backend/alert_limit.rb +56 -0
  35. data/lib/3scale/backend/alerts.rb +137 -0
  36. data/lib/3scale/backend/analytics/kinesis.rb +3 -0
  37. data/lib/3scale/backend/analytics/kinesis/adapter.rb +180 -0
  38. data/lib/3scale/backend/analytics/kinesis/exporter.rb +86 -0
  39. data/lib/3scale/backend/analytics/kinesis/job.rb +135 -0
  40. data/lib/3scale/backend/analytics/redshift.rb +3 -0
  41. data/lib/3scale/backend/analytics/redshift/adapter.rb +367 -0
  42. data/lib/3scale/backend/analytics/redshift/importer.rb +83 -0
  43. data/lib/3scale/backend/analytics/redshift/job.rb +33 -0
  44. data/lib/3scale/backend/application.rb +330 -0
  45. data/lib/3scale/backend/application_events.rb +76 -0
  46. data/lib/3scale/backend/background_job.rb +65 -0
  47. data/lib/3scale/backend/configurable.rb +20 -0
  48. data/lib/3scale/backend/configuration.rb +151 -0
  49. data/lib/3scale/backend/configuration/loader.rb +42 -0
  50. data/lib/3scale/backend/constants.rb +19 -0
  51. data/lib/3scale/backend/cors.rb +84 -0
  52. data/lib/3scale/backend/distributed_lock.rb +67 -0
  53. data/lib/3scale/backend/environment.rb +21 -0
  54. data/lib/3scale/backend/error_storage.rb +52 -0
  55. data/lib/3scale/backend/errors.rb +343 -0
  56. data/lib/3scale/backend/event_storage.rb +120 -0
  57. data/lib/3scale/backend/experiment.rb +84 -0
  58. data/lib/3scale/backend/extensions.rb +5 -0
  59. data/lib/3scale/backend/extensions/array.rb +19 -0
  60. data/lib/3scale/backend/extensions/hash.rb +26 -0
  61. data/lib/3scale/backend/extensions/nil_class.rb +13 -0
  62. data/lib/3scale/backend/extensions/redis.rb +44 -0
  63. data/lib/3scale/backend/extensions/string.rb +13 -0
  64. data/lib/3scale/backend/extensions/time.rb +110 -0
  65. data/lib/3scale/backend/failed_jobs_scheduler.rb +141 -0
  66. data/lib/3scale/backend/job_fetcher.rb +122 -0
  67. data/lib/3scale/backend/listener.rb +728 -0
  68. data/lib/3scale/backend/listener_metrics.rb +99 -0
  69. data/lib/3scale/backend/logging.rb +48 -0
  70. data/lib/3scale/backend/logging/external.rb +44 -0
  71. data/lib/3scale/backend/logging/external/impl.rb +93 -0
  72. data/lib/3scale/backend/logging/external/impl/airbrake.rb +66 -0
  73. data/lib/3scale/backend/logging/external/impl/bugsnag.rb +69 -0
  74. data/lib/3scale/backend/logging/external/impl/default.rb +18 -0
  75. data/lib/3scale/backend/logging/external/resque.rb +57 -0
  76. data/lib/3scale/backend/logging/logger.rb +18 -0
  77. data/lib/3scale/backend/logging/middleware.rb +62 -0
  78. data/lib/3scale/backend/logging/middleware/json_writer.rb +21 -0
  79. data/lib/3scale/backend/logging/middleware/text_writer.rb +60 -0
  80. data/lib/3scale/backend/logging/middleware/writer.rb +143 -0
  81. data/lib/3scale/backend/logging/worker.rb +107 -0
  82. data/lib/3scale/backend/manifest.rb +80 -0
  83. data/lib/3scale/backend/memoizer.rb +277 -0
  84. data/lib/3scale/backend/metric.rb +275 -0
  85. data/lib/3scale/backend/metric/collection.rb +91 -0
  86. data/lib/3scale/backend/oauth.rb +4 -0
  87. data/lib/3scale/backend/oauth/token.rb +26 -0
  88. data/lib/3scale/backend/oauth/token_key.rb +30 -0
  89. data/lib/3scale/backend/oauth/token_storage.rb +313 -0
  90. data/lib/3scale/backend/oauth/token_value.rb +25 -0
  91. data/lib/3scale/backend/period.rb +3 -0
  92. data/lib/3scale/backend/period/boundary.rb +107 -0
  93. data/lib/3scale/backend/period/cache.rb +28 -0
  94. data/lib/3scale/backend/period/period.rb +402 -0
  95. data/lib/3scale/backend/queue_storage.rb +16 -0
  96. data/lib/3scale/backend/rack.rb +49 -0
  97. data/lib/3scale/backend/rack/exception_catcher.rb +136 -0
  98. data/lib/3scale/backend/rack/internal_error_catcher.rb +23 -0
  99. data/lib/3scale/backend/rack/prometheus.rb +19 -0
  100. data/lib/3scale/backend/saas.rb +6 -0
  101. data/lib/3scale/backend/saas_analytics.rb +4 -0
  102. data/lib/3scale/backend/server.rb +30 -0
  103. data/lib/3scale/backend/server/falcon.rb +52 -0
  104. data/lib/3scale/backend/server/puma.rb +71 -0
  105. data/lib/3scale/backend/service.rb +317 -0
  106. data/lib/3scale/backend/service_token.rb +97 -0
  107. data/lib/3scale/backend/stats.rb +8 -0
  108. data/lib/3scale/backend/stats/aggregator.rb +170 -0
  109. data/lib/3scale/backend/stats/aggregators/base.rb +72 -0
  110. data/lib/3scale/backend/stats/aggregators/response_code.rb +58 -0
  111. data/lib/3scale/backend/stats/aggregators/usage.rb +34 -0
  112. data/lib/3scale/backend/stats/bucket_reader.rb +135 -0
  113. data/lib/3scale/backend/stats/bucket_storage.rb +108 -0
  114. data/lib/3scale/backend/stats/cleaner.rb +195 -0
  115. data/lib/3scale/backend/stats/codes_commons.rb +14 -0
  116. data/lib/3scale/backend/stats/delete_job_def.rb +60 -0
  117. data/lib/3scale/backend/stats/key_generator.rb +73 -0
  118. data/lib/3scale/backend/stats/keys.rb +104 -0
  119. data/lib/3scale/backend/stats/partition_eraser_job.rb +58 -0
  120. data/lib/3scale/backend/stats/partition_generator_job.rb +46 -0
  121. data/lib/3scale/backend/stats/period_commons.rb +34 -0
  122. data/lib/3scale/backend/stats/stats_parser.rb +141 -0
  123. data/lib/3scale/backend/stats/storage.rb +113 -0
  124. data/lib/3scale/backend/statsd.rb +14 -0
  125. data/lib/3scale/backend/storable.rb +35 -0
  126. data/lib/3scale/backend/storage.rb +40 -0
  127. data/lib/3scale/backend/storage_async.rb +4 -0
  128. data/lib/3scale/backend/storage_async/async_redis.rb +21 -0
  129. data/lib/3scale/backend/storage_async/client.rb +205 -0
  130. data/lib/3scale/backend/storage_async/pipeline.rb +79 -0
  131. data/lib/3scale/backend/storage_async/resque_extensions.rb +30 -0
  132. data/lib/3scale/backend/storage_helpers.rb +278 -0
  133. data/lib/3scale/backend/storage_key_helpers.rb +9 -0
  134. data/lib/3scale/backend/storage_sync.rb +43 -0
  135. data/lib/3scale/backend/transaction.rb +62 -0
  136. data/lib/3scale/backend/transactor.rb +177 -0
  137. data/lib/3scale/backend/transactor/limit_headers.rb +54 -0
  138. data/lib/3scale/backend/transactor/notify_batcher.rb +139 -0
  139. data/lib/3scale/backend/transactor/notify_job.rb +47 -0
  140. data/lib/3scale/backend/transactor/process_job.rb +33 -0
  141. data/lib/3scale/backend/transactor/report_job.rb +84 -0
  142. data/lib/3scale/backend/transactor/status.rb +236 -0
  143. data/lib/3scale/backend/transactor/usage_report.rb +182 -0
  144. data/lib/3scale/backend/usage.rb +63 -0
  145. data/lib/3scale/backend/usage_limit.rb +115 -0
  146. data/lib/3scale/backend/use_cases/provider_key_change_use_case.rb +60 -0
  147. data/lib/3scale/backend/util.rb +17 -0
  148. data/lib/3scale/backend/validators.rb +26 -0
  149. data/lib/3scale/backend/validators/base.rb +36 -0
  150. data/lib/3scale/backend/validators/key.rb +17 -0
  151. data/lib/3scale/backend/validators/limits.rb +57 -0
  152. data/lib/3scale/backend/validators/oauth_key.rb +15 -0
  153. data/lib/3scale/backend/validators/oauth_setting.rb +15 -0
  154. data/lib/3scale/backend/validators/redirect_uri.rb +33 -0
  155. data/lib/3scale/backend/validators/referrer.rb +60 -0
  156. data/lib/3scale/backend/validators/service_state.rb +15 -0
  157. data/lib/3scale/backend/validators/state.rb +15 -0
  158. data/lib/3scale/backend/version.rb +5 -0
  159. data/lib/3scale/backend/views/oauth_access_tokens.builder +14 -0
  160. data/lib/3scale/backend/views/oauth_app_id_by_token.builder +4 -0
  161. data/lib/3scale/backend/worker.rb +87 -0
  162. data/lib/3scale/backend/worker_async.rb +88 -0
  163. data/lib/3scale/backend/worker_metrics.rb +44 -0
  164. data/lib/3scale/backend/worker_sync.rb +32 -0
  165. data/lib/3scale/bundler_shim.rb +17 -0
  166. data/lib/3scale/prometheus_server.rb +10 -0
  167. data/lib/3scale/tasks/connectivity.rake +41 -0
  168. data/lib/3scale/tasks/helpers.rb +3 -0
  169. data/lib/3scale/tasks/helpers/environment.rb +23 -0
  170. data/lib/3scale/tasks/stats.rake +131 -0
  171. data/lib/3scale/tasks/swagger.rake +46 -0
  172. data/licenses.xml +1215 -0
  173. metadata +227 -0
@@ -0,0 +1,47 @@
1
+ # encoding: UTF-8
2
+ lib = File.expand_path('../lib/', __FILE__)
3
+ $:.unshift lib unless $:.include?(lib)
4
+
5
+ require '3scale/backend/version'
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = 'apisonator'
9
+ s.version = ThreeScale::Backend::VERSION
10
+ s.platform = Gem::Platform::RUBY
11
+ s.authors = ["Adam Ciganek", "Tiago Macedo", "Josep M. Pujol",
12
+ "Toni Reina", "Wojciech Ogrodowczyk",
13
+ "Alejandro Martinez Ruiz", "David Ortiz Lopez",
14
+ "Eguzki Astiz Lezaun", "Miguel Soriano Domenech"]
15
+ s.email = 'backend@3scale.net'
16
+ s.homepage = 'http://www.3scale.net'
17
+ s.summary = '3scale web service management system backend'
18
+ s.description = 'This gem provides a daemon that handles authorization and reporting of web services managed by 3scale.'
19
+ s.license = 'Apache-2.0'
20
+ s.metadata = { 'source_code_uri' => 'https://github.com/3scale/apisonator' }
21
+
22
+ s.required_ruby_version = ">= 2.4.0"
23
+ s.required_rubygems_version = ">= 1.3.7"
24
+
25
+ s.files = Dir.glob('{lib,bin,app,config}/**/*')
26
+ s.files << 'README.md'
27
+ s.files << 'CHANGELOG.md'
28
+ s.files << 'Rakefile'
29
+ s.files << 'config.ru'
30
+ # Gemfile* and gemspec are included here to support
31
+ # running Bundler at gem install time.
32
+ s.files << 'Gemfile.base'
33
+ s.files << 'Gemfile'
34
+ s.files << 'Gemfile.lock'
35
+ s.files << 'Gemfile.on_prem'
36
+ s.files << 'Gemfile.on_prem.lock'
37
+ s.files << 'licenses.xml'
38
+ # License
39
+ s.files << 'LICENSE'
40
+ s.files << 'NOTICE'
41
+ s.files << __FILE__
42
+
43
+ s.executables = ['3scale_backend', '3scale_backend_worker']
44
+ s.require_path = 'lib'
45
+
46
+ s.extensions = 'ext/mkrf_conf.rb'
47
+ end
@@ -0,0 +1,13 @@
1
+ require_relative 'internal/internal'
2
+ require_relative 'internal/services'
3
+ require_relative 'internal/applications'
4
+ require_relative 'internal/metrics'
5
+ require_relative 'internal/usagelimits'
6
+ require_relative 'internal/events'
7
+ require_relative 'internal/alert_limits'
8
+ require_relative 'internal/application_keys'
9
+ require_relative 'internal/application_referrer_filters'
10
+ require_relative 'internal/errors'
11
+ require_relative 'internal/utilization'
12
+ require_relative 'internal/service_tokens'
13
+ require_relative 'internal/stats'
@@ -0,0 +1,32 @@
1
+ require '3scale/backend/alert_limit'
2
+
3
+ module ThreeScale
4
+ module Backend
5
+ module API
6
+ internal_api '/services/:service_id/alert_limits' do
7
+ get '/' do |service_id|
8
+ limits = AlertLimit.load_all(service_id)
9
+ { status: :found, alert_limits: limits.map(&:to_hash) }.to_json
10
+ end
11
+
12
+ post '/' do |service_id|
13
+ value = params.fetch(:alert_limit, {}).fetch(:value, nil)
14
+ limit = AlertLimit.save(service_id, value)
15
+ if limit
16
+ [201, headers, { status: :created, alert_limit: limit.to_hash }.to_json]
17
+ else
18
+ halt 400, { error: "alert limit is invalid" }.to_json
19
+ end
20
+ end
21
+
22
+ delete '/:value' do |service_id, value|
23
+ if AlertLimit.delete(service_id, value)
24
+ { status: :deleted }.to_json
25
+ else
26
+ [404, headers, { status: :not_found, error: 'alert limit not found' }.to_json]
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,49 @@
1
+ module ThreeScale
2
+ module Backend
3
+ module API
4
+ internal_api '/services/:service_id/applications/:app_id/keys' do
5
+ module ApplicationKeysHelper
6
+ def self.to_hash(app, value)
7
+ {
8
+ service_id: app.service_id,
9
+ app_id: app.id,
10
+ value: value,
11
+ }
12
+ end
13
+ end
14
+
15
+ before do
16
+ @app = Application.load(params[:service_id], params[:app_id])
17
+ respond_with_404 'application not found' unless @app
18
+ end
19
+
20
+ get '/' do |service_id, app_id|
21
+ keys = @app.keys.map do |key|
22
+ ApplicationKeysHelper.to_hash(@app, key)
23
+ end
24
+
25
+ { status: :found, application_keys: keys }.to_json
26
+ end
27
+
28
+ post '/' do |service_id, app_id|
29
+ value = params.fetch(:application_key, {}).fetch(:value, nil)
30
+ key = { app_id: @app.id }
31
+ if value.nil? || value.empty?
32
+ key.merge!(value: @app.create_key)
33
+ else
34
+ key.merge!(value: @app.create_key(value))
35
+ end
36
+ [201, headers, { status: :created, application_key: key }.to_json]
37
+ end
38
+
39
+ delete '/:id' do |service_id, app_id, id|
40
+ if @app.delete_key(id)
41
+ { status: :deleted }.to_json
42
+ else
43
+ respond_with_404("application key not found")
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,43 @@
1
+ require 'base64'
2
+
3
+ module ThreeScale
4
+ module Backend
5
+ module API
6
+ internal_api '/services/:service_id/applications/:app_id/referrer_filters' do
7
+ before do
8
+ @app = Application.load params[:service_id], params[:app_id]
9
+ respond_with_404 'application not found' unless @app
10
+ end
11
+
12
+ get '' do
13
+ filters = @app.referrer_filters.sort
14
+ {status: :found, referrer_filters: filters}.to_json
15
+ end
16
+
17
+ post '' do
18
+ begin
19
+ value = params.fetch(:referrer_filter, nil)
20
+ filter = @app.create_referrer_filter(value)
21
+
22
+ [201, headers, {status: :created, referrer_filter: filter}.to_json]
23
+ rescue ReferrerFilterInvalid => e
24
+ respond_with_400 e
25
+ end
26
+ end
27
+
28
+ delete '/:value' do
29
+ filter = begin
30
+ Base64.urlsafe_decode64 params[:value]
31
+ rescue ArgumentError
32
+ params[:value]
33
+ end
34
+ @app.delete_referrer_filter filter
35
+
36
+ {status: :deleted}.to_json
37
+ end
38
+
39
+ end
40
+ end
41
+ end
42
+ end
43
+
@@ -0,0 +1,77 @@
1
+ module ThreeScale
2
+ module Backend
3
+ module API
4
+ internal_api '/services/:service_id/applications' do
5
+ get '/:id' do |service_id, id|
6
+ app = Application.load(service_id, id)
7
+ if app
8
+ { status: :found, application: app.to_hash }.to_json
9
+ else
10
+ [404, headers, { status: :not_found, error: 'application not found' }.to_json]
11
+ end
12
+ end
13
+
14
+ post '/:id' do |service_id, id|
15
+ app_attrs = api_params Application
16
+ if Application.exists?(service_id, id)
17
+ halt 405, { status: :exists, error: 'application cannot be created, exists already' }.to_json
18
+ end
19
+ app_attrs[:service_id] = service_id
20
+ app_attrs[:id] = id
21
+ begin
22
+ app = Application.save(app_attrs)
23
+ rescue ApplicationHasNoState => e
24
+ [400, headers, { status: :bad_request, error: e.message }.to_json]
25
+ else
26
+ [201, headers, { status: :created, application: app.to_hash }.to_json]
27
+ end
28
+ end
29
+
30
+ put '/:id' do |service_id, id|
31
+ app_attrs = api_params Application
32
+ modified = Application.exists?(service_id, id)
33
+ app_attrs[:service_id] = service_id
34
+ app_attrs[:id] = id
35
+ begin
36
+ app = Application.save(app_attrs)
37
+ rescue ApplicationHasNoState => e
38
+ [400, headers, { status: :bad_request, error: e.message }.to_json]
39
+ else
40
+ { status: modified ? :modified : :created, application: app.to_hash }.to_json
41
+ end
42
+ end
43
+
44
+ delete '/:id' do |service_id, id|
45
+ begin
46
+ Application.delete(service_id, id)
47
+ { status: :deleted }.to_json
48
+ rescue ApplicationNotFound
49
+ [404, headers, { status: :not_found, error: 'application not found' }.to_json]
50
+ end
51
+ end
52
+
53
+ # XXX Old API. DEPRECATED.
54
+ #
55
+ # We will NOT be loading the whole app for the key requested, which we
56
+ # would probably do otherwise, since users are only marginal, do not
57
+ # need it anyway, and are to be removed in the future.
58
+ #
59
+ get '/key/:user_key' do |service_id, user_key|
60
+ id = Application.load_id_by_key(service_id, user_key)
61
+ halt 404, { status: :not_found, error: 'application key not found' }.to_json unless id
62
+ { status: :found, application: { id: id } }.to_json
63
+ end
64
+
65
+ put '/:id/key/:user_key' do |service_id, id, user_key|
66
+ Application.save_id_by_key(service_id, user_key, id)
67
+ { status: :modified, application: { id: id } }.to_json
68
+ end
69
+
70
+ delete '/key/:user_key' do |service_id, user_key|
71
+ Application.delete_id_by_key(service_id, user_key)
72
+ { status: :deleted }.to_json
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,54 @@
1
+ module ThreeScale
2
+ module Backend
3
+ module API
4
+ internal_api '/services/:service_id/errors' do
5
+ before do
6
+ unless Service.exists?(params[:service_id])
7
+ respond_with_404('service not found')
8
+ end
9
+ end
10
+
11
+ get '/' do |service_id|
12
+ if params[:per_page] && params[:per_page].to_i <= 0
13
+ halt(400, { error: 'per_page needs to be > 0' }.to_json)
14
+ end
15
+
16
+ errors = ErrorStorage.list(service_id,
17
+ page: params[:page],
18
+ per_page: params[:per_page])
19
+ errors.each { |error| error[:timestamp] = error[:timestamp].to_s }
20
+ { status: :found, errors: errors,
21
+ count: ErrorStorage.count(service_id) }.to_json
22
+ end
23
+
24
+ delete '/' do |service_id|
25
+ ErrorStorage.delete_all(service_id)
26
+ { status: :deleted }.to_json
27
+ end
28
+
29
+ if define_private_endpoints?
30
+ # Receives a parameter 'errors' which is an Array of Strings
31
+ # representing error messages.
32
+ # In this endpoint, we create errors of the generic type Error to
33
+ # keep things simple because we do not care about the type.
34
+ # If this changes in the future we might need to create errors
35
+ # of other types such as: ProviderKeyInvalid, KeyInvalid...
36
+ post '/' do |service_id|
37
+ errors = params[:errors]
38
+
39
+ unless errors
40
+ halt 400, { status: :error,
41
+ error: 'missing parameter \'errors\'' }.to_json
42
+ end
43
+
44
+ errors.each do |error|
45
+ ErrorStorage.store(service_id, Error.new(error))
46
+ end
47
+
48
+ [201, headers, { status: :created }.to_json]
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,42 @@
1
+ module ThreeScale
2
+ module Backend
3
+ module API
4
+ internal_api '/events' do
5
+ get '/' do
6
+ { status: :found, events: EventStorage.list }.to_json
7
+ end
8
+
9
+ delete '/:id' do
10
+ result = EventStorage.delete(params[:id])
11
+ if result > 0
12
+ { status: :deleted }.to_json
13
+ else
14
+ [404, headers, { status: :not_found, error: 'event not found' }.to_json]
15
+ end
16
+ end
17
+
18
+ delete '/' do
19
+ result = EventStorage.delete_range(params[:upto_id])
20
+ { status: :deleted, num_events: result }.to_json
21
+ end
22
+
23
+ if define_private_endpoints?
24
+ post '/' do
25
+ events = params[:events]
26
+
27
+ unless events
28
+ halt 400, { status: :error,
29
+ error: 'missing parameter \'events\'' }.to_json
30
+ end
31
+
32
+ events.each do |event|
33
+ EventStorage.store(event[:type].to_sym, event[:object])
34
+ end
35
+
36
+ [201, headers, { status: :created }.to_json]
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,104 @@
1
+ require '3scale/backend/version'
2
+ require 'sinatra/namespace'
3
+ require 'json'
4
+
5
+ module ThreeScale
6
+ module Backend
7
+ module API
8
+ class InvalidCredentials < RuntimeError
9
+ def initialize(msg = 'Internal API credentials not provided.'.freeze)
10
+ super(msg)
11
+ end
12
+ end
13
+
14
+ def self.internal_api(ns, &blk)
15
+ Internal.class_eval { namespace ns, &blk }
16
+ end
17
+
18
+ class Internal < Sinatra::Base
19
+
20
+ register Sinatra::Namespace
21
+
22
+ # using a class variable instead of settings because we want this to be
23
+ # as fast as possible when responding, since we hit /status a lot.
24
+ @@status = { status: :ok,
25
+ version: { backend: ThreeScale::Backend::VERSION } }.to_json
26
+
27
+ before do
28
+ content_type 'application/json'
29
+ parse_json_params params
30
+ end
31
+
32
+ error Sinatra::NotFound do
33
+ { status: :not_found, error: 'Not found'}.to_json
34
+ end
35
+
36
+ get '/check.json' do
37
+ {status: :ok}.to_json
38
+ end
39
+
40
+ get '/status' do
41
+ @@status
42
+ end
43
+
44
+ def self.define_private_endpoints?
45
+ ThreeScale::Backend.test? || ThreeScale::Backend.development?
46
+ end
47
+
48
+ def initialize(username: nil, password: nil, allow_insecure: false)
49
+ @username = username
50
+ @password = password
51
+ raise InvalidCredentials unless allow_insecure or credentials_set?
52
+ super()
53
+ end
54
+
55
+ # the two methods below are used by the Rack application for auth
56
+ # you can access them through the .helpers method after calling .new
57
+ def credentials_set?
58
+ (!@username.nil? && !@username.empty?) ||
59
+ (!@password.nil? && !@password.empty?)
60
+ end
61
+
62
+ def check_password(username, password)
63
+ username == @username && password == @password
64
+ end
65
+
66
+ private
67
+
68
+ def parse_json_params(params)
69
+ body = request.body.read
70
+ params.merge! JSON.parse(body, symbolize_names: true) unless body.empty?
71
+ end
72
+
73
+ # Return hash with item keys from the white_list when
74
+ # request parameter value is not nil for the given key
75
+ def valid_request_attrs(req_attrs, white_list)
76
+ white_list.each_with_object({}) do |elem, res|
77
+ res[elem] = req_attrs[elem] unless req_attrs[elem].nil?
78
+ end
79
+ end
80
+
81
+ def api_params(klass, api_scope = nil)
82
+ api_scope ||= klass.name.split('::'.freeze).last.downcase
83
+ attributes = params[api_scope]
84
+ # Checked both key does not exist and key exists but nil stored
85
+ halt 400, { status: :error, error: "missing parameter '#{api_scope}'" }.to_json unless attributes
86
+ valid_request_attrs(attributes, klass.attribute_names)
87
+ end
88
+
89
+ def filter_params(params)
90
+ params.reject!{ |k, v| !ACCEPTED_PARAMS.include? k }
91
+ end
92
+
93
+ def respond_with_400(exception)
94
+ halt 400, {error: exception.message}.to_json
95
+ end
96
+
97
+ def respond_with_404(message)
98
+ halt 404, {status: :not_found, error: message}.to_json
99
+ end
100
+
101
+ end
102
+ end
103
+ end
104
+ end