apisonator 2.100.0

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