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
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
module ThreeScale
|
|
2
|
+
module Backend
|
|
3
|
+
class Usage
|
|
4
|
+
class << self
|
|
5
|
+
def application_usage(application, timestamp)
|
|
6
|
+
usage(application, timestamp) do |metric_id, instance_period|
|
|
7
|
+
Stats::Keys.application_usage_value_key(
|
|
8
|
+
application.service_id, application.id, metric_id, instance_period)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def is_set?(usage_str)
|
|
13
|
+
usage_str && usage_str[0] == '#'.freeze
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def get_from(usage_str, current_value = 0)
|
|
17
|
+
if is_set? usage_str
|
|
18
|
+
usage_str[1..-1].to_i
|
|
19
|
+
else
|
|
20
|
+
# Note: this relies on the fact that NilClass#to_i returns 0
|
|
21
|
+
# and String#to_i returns 0 on non-numeric contents.
|
|
22
|
+
current_value + usage_str.to_i
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def usage(obj, timestamp)
|
|
29
|
+
# The timestamp does not change, so we can generate all the
|
|
30
|
+
# instantiated periods just once.
|
|
31
|
+
# This is important. Without this, the code can generate many instance
|
|
32
|
+
# periods and it ends up consuming a significant part of the total CPU
|
|
33
|
+
# time.
|
|
34
|
+
instance_periods = Period::instance_periods_for_ts(timestamp)
|
|
35
|
+
|
|
36
|
+
pairs = metric_period_pairs obj.usage_limits
|
|
37
|
+
return {} if pairs.empty?
|
|
38
|
+
|
|
39
|
+
keys = pairs.map do |(metric_id, period)|
|
|
40
|
+
yield metric_id, instance_periods[period]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
values = {}
|
|
44
|
+
pairs.zip(storage.mget(keys)) do |(metric_id, period), value|
|
|
45
|
+
values[period] ||= {}
|
|
46
|
+
values[period][metric_id] = value.to_i
|
|
47
|
+
end
|
|
48
|
+
values
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def metric_period_pairs(usage_limits)
|
|
52
|
+
usage_limits.map do |usage_limit|
|
|
53
|
+
[usage_limit.metric_id, usage_limit.period]
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def storage
|
|
58
|
+
Storage.instance
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
module ThreeScale
|
|
2
|
+
module Backend
|
|
3
|
+
class UsageLimit
|
|
4
|
+
include Storable
|
|
5
|
+
|
|
6
|
+
PERIODS = (Period::ALL_DESC - [Period::Second]).freeze
|
|
7
|
+
|
|
8
|
+
attr_accessor :service_id, :plan_id, :metric_id, :period, :value
|
|
9
|
+
|
|
10
|
+
def metric_name
|
|
11
|
+
Metric.load_name(service_id, metric_id)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# NOTE: validate can ONLY be called with the guarantee that usage_data
|
|
15
|
+
# will have a matching period key.
|
|
16
|
+
def validate(usage_data)
|
|
17
|
+
usage_data[period][metric_id].to_i <= value
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class << self
|
|
21
|
+
include Memoizer::Decorator
|
|
22
|
+
|
|
23
|
+
def load_all(service_id, plan_id)
|
|
24
|
+
metric_ids = Metric.load_all_ids(service_id)
|
|
25
|
+
return metric_ids if metric_ids.empty?
|
|
26
|
+
|
|
27
|
+
results = []
|
|
28
|
+
with_pairs_and_values service_id, plan_id, metric_ids do |pair, value|
|
|
29
|
+
value and results << new(service_id: service_id,
|
|
30
|
+
plan_id: plan_id,
|
|
31
|
+
metric_id: pair[0],
|
|
32
|
+
period: pair[1],
|
|
33
|
+
value: value.to_i)
|
|
34
|
+
end
|
|
35
|
+
results
|
|
36
|
+
end
|
|
37
|
+
memoize :load_all
|
|
38
|
+
|
|
39
|
+
def load_value(service_id, plan_id, metric_id, period)
|
|
40
|
+
raw_value = storage.get(key(service_id, plan_id, metric_id, period))
|
|
41
|
+
raw_value and raw_value.to_i
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def save(attributes)
|
|
45
|
+
service_id = attributes[:service_id]
|
|
46
|
+
plan_id = attributes[:plan_id]
|
|
47
|
+
prefix = key_prefix(service_id, plan_id, attributes[:metric_id])
|
|
48
|
+
storage.pipelined do
|
|
49
|
+
PERIODS.each do |period|
|
|
50
|
+
p_val = attributes[period.to_sym]
|
|
51
|
+
p_val and storage.set(key_for_period(prefix, period), p_val)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
clear_cache(service_id, plan_id)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def delete(service_id, plan_id, metric_id, period)
|
|
58
|
+
storage.del(key(service_id, plan_id, metric_id, period))
|
|
59
|
+
clear_cache(service_id, plan_id)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def key(service_id, plan_id, metric_id, period)
|
|
65
|
+
key_for_period(key_prefix(service_id, plan_id, metric_id), period)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# NOTE: metric_id == nil is an accepted value
|
|
69
|
+
def key_prefix(service_id, plan_id, metric_id = :none)
|
|
70
|
+
"usage_limit/service_id:#{service_id}/plan_id:#{plan_id}/metric_id:" \
|
|
71
|
+
"#{"#{metric_id}/" if metric_id != :none}"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# receives a key prefix and a pair [metric_id, period]
|
|
75
|
+
def key_for_pair(key_pre, pair)
|
|
76
|
+
encode_key("#{key_pre}#{pair[0]}/#{pair[1]}")
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def key_for_period(key_pre, period)
|
|
80
|
+
encode_key(key_pre + period.to_s)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# yields [pair(metric_id, period), value]
|
|
84
|
+
def with_pairs_and_values(service_id, plan_id, metric_ids, &blk)
|
|
85
|
+
pairs, values = get_pairs_and_values_for service_id, plan_id, metric_ids
|
|
86
|
+
pairs.zip values, &blk
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def get_pairs_and_values_for(service_id, plan_id, metric_ids)
|
|
90
|
+
pairs, keys = generate_pairs_and_keys_for service_id, plan_id, metric_ids
|
|
91
|
+
|
|
92
|
+
[pairs, storage.mget(keys)]
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def generate_pairs_and_keys_for(service_id, plan_id, metric_ids)
|
|
96
|
+
pairs = []
|
|
97
|
+
keys = []
|
|
98
|
+
|
|
99
|
+
prefix = key_prefix service_id, plan_id
|
|
100
|
+
metric_ids.product PERIODS do |pair|
|
|
101
|
+
pairs << pair
|
|
102
|
+
keys << key_for_pair(prefix, pair)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
[pairs, keys]
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def clear_cache(service_id, plan_id)
|
|
109
|
+
Memoizer.clear(Memoizer.build_key(self, :load_all, service_id, plan_id))
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
module ThreeScale
|
|
2
|
+
module Backend
|
|
3
|
+
class ProviderKeyChangeUseCase
|
|
4
|
+
|
|
5
|
+
def initialize(old_key, new_key)
|
|
6
|
+
@old_key = old_key
|
|
7
|
+
@new_key = new_key
|
|
8
|
+
|
|
9
|
+
validate_input
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def process
|
|
13
|
+
default_service_id = Service.default_id(@old_key)
|
|
14
|
+
|
|
15
|
+
# Change the provider key on all the services and
|
|
16
|
+
# add all the services to the new provider
|
|
17
|
+
service_ids.each do |service_id|
|
|
18
|
+
storage.set Service.storage_key(service_id, :provider_key), @new_key
|
|
19
|
+
storage.sadd Service.storage_key_by_provider(@new_key, :ids), service_id
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Set the default service id to the new provider
|
|
23
|
+
storage.set Service.storage_key_by_provider(@new_key, :id), default_service_id
|
|
24
|
+
|
|
25
|
+
# Remove the old provider key and services associated to it
|
|
26
|
+
storage.del Service.storage_key_by_provider(@old_key, :id)
|
|
27
|
+
storage.del Service.storage_key_by_provider(@old_key, :ids)
|
|
28
|
+
|
|
29
|
+
clear_cache service_ids
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def service_ids
|
|
35
|
+
@service_ids ||= Service.list(@old_key)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def validate_input
|
|
39
|
+
raise InvalidProviderKeys if [@old_key, @new_key].
|
|
40
|
+
any?{ |key| key.nil? || key.empty? } || @old_key == @new_key
|
|
41
|
+
|
|
42
|
+
raise ProviderKeyExists, @new_key if Service.list(@new_key).size != 0
|
|
43
|
+
|
|
44
|
+
raise ProviderKeyNotFound, @old_key if service_ids.size == 0
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def storage
|
|
48
|
+
Service.storage
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def clear_cache(service_ids)
|
|
52
|
+
service_ids.each do |service_id|
|
|
53
|
+
Service.clear_cache(@old_key, service_id)
|
|
54
|
+
Service.clear_cache(@new_key, service_id)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'pathname'
|
|
2
|
+
require 'etc'
|
|
3
|
+
|
|
4
|
+
module ThreeScale
|
|
5
|
+
module Backend
|
|
6
|
+
module Util
|
|
7
|
+
def self.number_of_cpus
|
|
8
|
+
Etc.nprocessors
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.root_dir
|
|
12
|
+
File.expand_path(File.join(Array.new(4, '..'.freeze)),
|
|
13
|
+
Pathname.new(__FILE__).realpath)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require '3scale/backend/validators/base'
|
|
2
|
+
require '3scale/backend/validators/oauth_setting'
|
|
3
|
+
require '3scale/backend/validators/key'
|
|
4
|
+
require '3scale/backend/validators/oauth_key'
|
|
5
|
+
require '3scale/backend/validators/limits'
|
|
6
|
+
require '3scale/backend/validators/redirect_uri'
|
|
7
|
+
require '3scale/backend/validators/referrer'
|
|
8
|
+
require '3scale/backend/validators/state'
|
|
9
|
+
require '3scale/backend/validators/service_state'
|
|
10
|
+
|
|
11
|
+
module ThreeScale
|
|
12
|
+
module Backend
|
|
13
|
+
module Validators
|
|
14
|
+
COMMON_VALIDATORS = [Validators::Referrer,
|
|
15
|
+
Validators::State, # application state
|
|
16
|
+
Validators::ServiceState, # service state
|
|
17
|
+
Validators::Limits].freeze
|
|
18
|
+
|
|
19
|
+
VALIDATORS = ([Validators::Key] + COMMON_VALIDATORS).freeze
|
|
20
|
+
|
|
21
|
+
OAUTH_VALIDATORS = ([Validators::OauthSetting,
|
|
22
|
+
Validators::OauthKey,
|
|
23
|
+
Validators::RedirectURI] + COMMON_VALIDATORS).freeze
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module ThreeScale
|
|
2
|
+
module Backend
|
|
3
|
+
module Validators
|
|
4
|
+
class Base
|
|
5
|
+
def self.apply(status, params)
|
|
6
|
+
new(status, params).apply
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def initialize(status, params)
|
|
10
|
+
@status = status
|
|
11
|
+
@params = params
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
attr_reader :status
|
|
15
|
+
attr_reader :params
|
|
16
|
+
|
|
17
|
+
def service
|
|
18
|
+
@service ||= Service.load_by_id!(status.service_id)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def application
|
|
22
|
+
status.application
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def succeed!
|
|
26
|
+
true
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def fail!(error)
|
|
30
|
+
status.reject!(error)
|
|
31
|
+
false
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module ThreeScale
|
|
2
|
+
module Backend
|
|
3
|
+
module Validators
|
|
4
|
+
class Key < Base
|
|
5
|
+
def apply
|
|
6
|
+
if service.backend_version.to_i == 1 ||
|
|
7
|
+
application.has_no_keys? ||
|
|
8
|
+
application.has_key?(params[:app_key])
|
|
9
|
+
succeed!
|
|
10
|
+
else
|
|
11
|
+
fail!(ApplicationKeyInvalid.new(params[:app_key]))
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module ThreeScale
|
|
2
|
+
module Backend
|
|
3
|
+
module Validators
|
|
4
|
+
class Limits < Base
|
|
5
|
+
|
|
6
|
+
def apply
|
|
7
|
+
valid_limits? ? succeed! : fail!(LimitsExceeded.new)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def process(values, raw_usage)
|
|
13
|
+
if raw_usage
|
|
14
|
+
metrics = Metric.load_all(status.service_id)
|
|
15
|
+
usage = metrics.process_usage(raw_usage, status.flat_usage)
|
|
16
|
+
values = filter_metrics(values, usage.keys)
|
|
17
|
+
values = increment_or_set(values, usage)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
values
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def valid_limits?
|
|
24
|
+
processed_values = process(status.values, params[:usage])
|
|
25
|
+
status.application.usage_limits.all? do |limit|
|
|
26
|
+
limit.validate(processed_values)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def filter_metrics(values, metric_ids)
|
|
31
|
+
values.inject({}) do |memo, (period, usage)|
|
|
32
|
+
memo[period] = slice_hash(usage, metric_ids)
|
|
33
|
+
memo
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def increment_or_set(values, usage)
|
|
38
|
+
usage.inject(values) do |memo, (metric_id, value)|
|
|
39
|
+
memo.keys.each do |period|
|
|
40
|
+
memo[period][metric_id] = Usage.get_from value, memo[period][metric_id].to_i
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
memo
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# TODO: Move this to extensions/hash.rb
|
|
48
|
+
def slice_hash(hash, keys)
|
|
49
|
+
keys.inject({}) do |memo, key|
|
|
50
|
+
memo[key] = hash[key] if hash.has_key?(key)
|
|
51
|
+
memo
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module ThreeScale
|
|
2
|
+
module Backend
|
|
3
|
+
module Validators
|
|
4
|
+
class OauthKey < Base
|
|
5
|
+
def apply
|
|
6
|
+
if params[:app_key].nil? || (!params[:app_key].empty? && application.has_key?(params[:app_key]))
|
|
7
|
+
succeed!
|
|
8
|
+
else
|
|
9
|
+
fail!(ApplicationKeyInvalid.new(params[:app_key]))
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module ThreeScale
|
|
2
|
+
module Backend
|
|
3
|
+
module Validators
|
|
4
|
+
class RedirectURI < Base
|
|
5
|
+
# This should've been named redirect_uri as per OAuth specs, but was
|
|
6
|
+
# initially named redirect_url. We check both fields, prioritizing the
|
|
7
|
+
# contents in the legacy redirect_url parameter over the "new"
|
|
8
|
+
# redirect_uri one.
|
|
9
|
+
REDIRECT_URL = 'redirect_url'.freeze
|
|
10
|
+
REDIRECT_URI = 'redirect_uri'.freeze
|
|
11
|
+
|
|
12
|
+
def apply
|
|
13
|
+
invalid_exception = RedirectURIInvalid
|
|
14
|
+
redirect_uri = if params.has_key? REDIRECT_URL
|
|
15
|
+
invalid_exception = RedirectURLInvalid
|
|
16
|
+
params[REDIRECT_URL]
|
|
17
|
+
elsif params.has_key? REDIRECT_URI
|
|
18
|
+
status.redirect_uri_field = REDIRECT_URI
|
|
19
|
+
params[REDIRECT_URI]
|
|
20
|
+
else
|
|
21
|
+
nil
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
if redirect_uri.nil? || redirect_uri.empty? || application.redirect_url == redirect_uri
|
|
25
|
+
succeed!
|
|
26
|
+
else
|
|
27
|
+
fail!(invalid_exception.new redirect_uri)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|