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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +317 -0
- data/Gemfile +11 -0
- data/Gemfile.base +65 -0
- data/Gemfile.lock +319 -0
- data/Gemfile.on_prem +1 -0
- data/Gemfile.on_prem.lock +297 -0
- data/LICENSE +202 -0
- data/NOTICE +15 -0
- data/README.md +230 -0
- data/Rakefile +287 -0
- data/apisonator.gemspec +47 -0
- data/app/api/api.rb +13 -0
- data/app/api/internal/alert_limits.rb +32 -0
- data/app/api/internal/application_keys.rb +49 -0
- data/app/api/internal/application_referrer_filters.rb +43 -0
- data/app/api/internal/applications.rb +77 -0
- data/app/api/internal/errors.rb +54 -0
- data/app/api/internal/events.rb +42 -0
- data/app/api/internal/internal.rb +104 -0
- data/app/api/internal/metrics.rb +40 -0
- data/app/api/internal/service_tokens.rb +46 -0
- data/app/api/internal/services.rb +58 -0
- data/app/api/internal/stats.rb +42 -0
- data/app/api/internal/usagelimits.rb +62 -0
- data/app/api/internal/utilization.rb +23 -0
- data/bin/3scale_backend +223 -0
- data/bin/3scale_backend_worker +26 -0
- data/config.ru +4 -0
- data/config/puma.rb +192 -0
- data/config/schedule.rb +9 -0
- data/ext/mkrf_conf.rb +64 -0
- data/lib/3scale/backend.rb +67 -0
- data/lib/3scale/backend/alert_limit.rb +56 -0
- data/lib/3scale/backend/alerts.rb +137 -0
- data/lib/3scale/backend/analytics/kinesis.rb +3 -0
- data/lib/3scale/backend/analytics/kinesis/adapter.rb +180 -0
- data/lib/3scale/backend/analytics/kinesis/exporter.rb +86 -0
- data/lib/3scale/backend/analytics/kinesis/job.rb +135 -0
- data/lib/3scale/backend/analytics/redshift.rb +3 -0
- data/lib/3scale/backend/analytics/redshift/adapter.rb +367 -0
- data/lib/3scale/backend/analytics/redshift/importer.rb +83 -0
- data/lib/3scale/backend/analytics/redshift/job.rb +33 -0
- data/lib/3scale/backend/application.rb +330 -0
- data/lib/3scale/backend/application_events.rb +76 -0
- data/lib/3scale/backend/background_job.rb +65 -0
- data/lib/3scale/backend/configurable.rb +20 -0
- data/lib/3scale/backend/configuration.rb +151 -0
- data/lib/3scale/backend/configuration/loader.rb +42 -0
- data/lib/3scale/backend/constants.rb +19 -0
- data/lib/3scale/backend/cors.rb +84 -0
- data/lib/3scale/backend/distributed_lock.rb +67 -0
- data/lib/3scale/backend/environment.rb +21 -0
- data/lib/3scale/backend/error_storage.rb +52 -0
- data/lib/3scale/backend/errors.rb +343 -0
- data/lib/3scale/backend/event_storage.rb +120 -0
- data/lib/3scale/backend/experiment.rb +84 -0
- data/lib/3scale/backend/extensions.rb +5 -0
- data/lib/3scale/backend/extensions/array.rb +19 -0
- data/lib/3scale/backend/extensions/hash.rb +26 -0
- data/lib/3scale/backend/extensions/nil_class.rb +13 -0
- data/lib/3scale/backend/extensions/redis.rb +44 -0
- data/lib/3scale/backend/extensions/string.rb +13 -0
- data/lib/3scale/backend/extensions/time.rb +110 -0
- data/lib/3scale/backend/failed_jobs_scheduler.rb +141 -0
- data/lib/3scale/backend/job_fetcher.rb +122 -0
- data/lib/3scale/backend/listener.rb +728 -0
- data/lib/3scale/backend/listener_metrics.rb +99 -0
- data/lib/3scale/backend/logging.rb +48 -0
- data/lib/3scale/backend/logging/external.rb +44 -0
- data/lib/3scale/backend/logging/external/impl.rb +93 -0
- data/lib/3scale/backend/logging/external/impl/airbrake.rb +66 -0
- data/lib/3scale/backend/logging/external/impl/bugsnag.rb +69 -0
- data/lib/3scale/backend/logging/external/impl/default.rb +18 -0
- data/lib/3scale/backend/logging/external/resque.rb +57 -0
- data/lib/3scale/backend/logging/logger.rb +18 -0
- data/lib/3scale/backend/logging/middleware.rb +62 -0
- data/lib/3scale/backend/logging/middleware/json_writer.rb +21 -0
- data/lib/3scale/backend/logging/middleware/text_writer.rb +60 -0
- data/lib/3scale/backend/logging/middleware/writer.rb +143 -0
- data/lib/3scale/backend/logging/worker.rb +107 -0
- data/lib/3scale/backend/manifest.rb +80 -0
- data/lib/3scale/backend/memoizer.rb +277 -0
- data/lib/3scale/backend/metric.rb +275 -0
- data/lib/3scale/backend/metric/collection.rb +91 -0
- data/lib/3scale/backend/oauth.rb +4 -0
- data/lib/3scale/backend/oauth/token.rb +26 -0
- data/lib/3scale/backend/oauth/token_key.rb +30 -0
- data/lib/3scale/backend/oauth/token_storage.rb +313 -0
- data/lib/3scale/backend/oauth/token_value.rb +25 -0
- data/lib/3scale/backend/period.rb +3 -0
- data/lib/3scale/backend/period/boundary.rb +107 -0
- data/lib/3scale/backend/period/cache.rb +28 -0
- data/lib/3scale/backend/period/period.rb +402 -0
- data/lib/3scale/backend/queue_storage.rb +16 -0
- data/lib/3scale/backend/rack.rb +49 -0
- data/lib/3scale/backend/rack/exception_catcher.rb +136 -0
- data/lib/3scale/backend/rack/internal_error_catcher.rb +23 -0
- data/lib/3scale/backend/rack/prometheus.rb +19 -0
- data/lib/3scale/backend/saas.rb +6 -0
- data/lib/3scale/backend/saas_analytics.rb +4 -0
- data/lib/3scale/backend/server.rb +30 -0
- data/lib/3scale/backend/server/falcon.rb +52 -0
- data/lib/3scale/backend/server/puma.rb +71 -0
- data/lib/3scale/backend/service.rb +317 -0
- data/lib/3scale/backend/service_token.rb +97 -0
- data/lib/3scale/backend/stats.rb +8 -0
- data/lib/3scale/backend/stats/aggregator.rb +170 -0
- data/lib/3scale/backend/stats/aggregators/base.rb +72 -0
- data/lib/3scale/backend/stats/aggregators/response_code.rb +58 -0
- data/lib/3scale/backend/stats/aggregators/usage.rb +34 -0
- data/lib/3scale/backend/stats/bucket_reader.rb +135 -0
- data/lib/3scale/backend/stats/bucket_storage.rb +108 -0
- data/lib/3scale/backend/stats/cleaner.rb +195 -0
- data/lib/3scale/backend/stats/codes_commons.rb +14 -0
- data/lib/3scale/backend/stats/delete_job_def.rb +60 -0
- data/lib/3scale/backend/stats/key_generator.rb +73 -0
- data/lib/3scale/backend/stats/keys.rb +104 -0
- data/lib/3scale/backend/stats/partition_eraser_job.rb +58 -0
- data/lib/3scale/backend/stats/partition_generator_job.rb +46 -0
- data/lib/3scale/backend/stats/period_commons.rb +34 -0
- data/lib/3scale/backend/stats/stats_parser.rb +141 -0
- data/lib/3scale/backend/stats/storage.rb +113 -0
- data/lib/3scale/backend/statsd.rb +14 -0
- data/lib/3scale/backend/storable.rb +35 -0
- data/lib/3scale/backend/storage.rb +40 -0
- data/lib/3scale/backend/storage_async.rb +4 -0
- data/lib/3scale/backend/storage_async/async_redis.rb +21 -0
- data/lib/3scale/backend/storage_async/client.rb +205 -0
- data/lib/3scale/backend/storage_async/pipeline.rb +79 -0
- data/lib/3scale/backend/storage_async/resque_extensions.rb +30 -0
- data/lib/3scale/backend/storage_helpers.rb +278 -0
- data/lib/3scale/backend/storage_key_helpers.rb +9 -0
- data/lib/3scale/backend/storage_sync.rb +43 -0
- data/lib/3scale/backend/transaction.rb +62 -0
- data/lib/3scale/backend/transactor.rb +177 -0
- data/lib/3scale/backend/transactor/limit_headers.rb +54 -0
- data/lib/3scale/backend/transactor/notify_batcher.rb +139 -0
- data/lib/3scale/backend/transactor/notify_job.rb +47 -0
- data/lib/3scale/backend/transactor/process_job.rb +33 -0
- data/lib/3scale/backend/transactor/report_job.rb +84 -0
- data/lib/3scale/backend/transactor/status.rb +236 -0
- data/lib/3scale/backend/transactor/usage_report.rb +182 -0
- data/lib/3scale/backend/usage.rb +63 -0
- data/lib/3scale/backend/usage_limit.rb +115 -0
- data/lib/3scale/backend/use_cases/provider_key_change_use_case.rb +60 -0
- data/lib/3scale/backend/util.rb +17 -0
- data/lib/3scale/backend/validators.rb +26 -0
- data/lib/3scale/backend/validators/base.rb +36 -0
- data/lib/3scale/backend/validators/key.rb +17 -0
- data/lib/3scale/backend/validators/limits.rb +57 -0
- data/lib/3scale/backend/validators/oauth_key.rb +15 -0
- data/lib/3scale/backend/validators/oauth_setting.rb +15 -0
- data/lib/3scale/backend/validators/redirect_uri.rb +33 -0
- data/lib/3scale/backend/validators/referrer.rb +60 -0
- data/lib/3scale/backend/validators/service_state.rb +15 -0
- data/lib/3scale/backend/validators/state.rb +15 -0
- data/lib/3scale/backend/version.rb +5 -0
- data/lib/3scale/backend/views/oauth_access_tokens.builder +14 -0
- data/lib/3scale/backend/views/oauth_app_id_by_token.builder +4 -0
- data/lib/3scale/backend/worker.rb +87 -0
- data/lib/3scale/backend/worker_async.rb +88 -0
- data/lib/3scale/backend/worker_metrics.rb +44 -0
- data/lib/3scale/backend/worker_sync.rb +32 -0
- data/lib/3scale/bundler_shim.rb +17 -0
- data/lib/3scale/prometheus_server.rb +10 -0
- data/lib/3scale/tasks/connectivity.rake +41 -0
- data/lib/3scale/tasks/helpers.rb +3 -0
- data/lib/3scale/tasks/helpers/environment.rb +23 -0
- data/lib/3scale/tasks/stats.rake +131 -0
- data/lib/3scale/tasks/swagger.rake +46 -0
- data/licenses.xml +1215 -0
- metadata +227 -0
data/apisonator.gemspec
ADDED
|
@@ -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
|
data/app/api/api.rb
ADDED
|
@@ -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
|