rate_limiter 0.0.6 → 0.1.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 +6 -0
- data/LICENSE.txt +20 -0
- data/README.md +18 -11
- data/lib/generators/rate_limiter/install_generator.rb +22 -0
- data/lib/generators/rate_limiter/templates/rate_limiter.rb +6 -0
- data/lib/rate_limiter.rb +51 -51
- data/lib/rate_limiter/config.rb +18 -3
- data/lib/rate_limiter/frameworks/rails.rb +3 -0
- data/lib/rate_limiter/frameworks/rails/controller.rb +69 -0
- data/lib/rate_limiter/model.rb +30 -48
- data/lib/rate_limiter/model_config.rb +34 -0
- data/lib/rate_limiter/request.rb +112 -0
- data/lib/rate_limiter/throttle.rb +79 -0
- data/lib/rate_limiter/validator.rb +29 -0
- data/lib/rate_limiter/version.rb +3 -1
- data/rate_limiter.gemspec +24 -18
- metadata +98 -183
- data/.gitignore +0 -11
- data/.rspec +0 -3
- data/.rvmrc +0 -80
- data/Gemfile +0 -3
- data/Gemfile.lock +0 -150
- data/Rakefile +0 -6
- data/lib/rate_limiter/controller.rb +0 -36
- data/spec/dummy/Rakefile +0 -7
- data/spec/dummy/app/assets/images/rails.png +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +0 -15
- data/spec/dummy/app/assets/stylesheets/application.css +0 -13
- data/spec/dummy/app/controllers/application_controller.rb +0 -7
- data/spec/dummy/app/controllers/messages_controller.rb +0 -75
- data/spec/dummy/app/helpers/application_helper.rb +0 -2
- data/spec/dummy/app/mailers/.gitkeep +0 -0
- data/spec/dummy/app/models/message.rb +0 -5
- data/spec/dummy/app/views/layouts/application.html.erb +0 -15
- data/spec/dummy/app/views/messages/_form.html.erb +0 -22
- data/spec/dummy/app/views/messages/_message.html.erb +0 -8
- data/spec/dummy/app/views/messages/edit.html.erb +0 -3
- data/spec/dummy/app/views/messages/index.html.erb +0 -6
- data/spec/dummy/app/views/messages/new.html.erb +0 -3
- data/spec/dummy/app/views/messages/show.html.erb +0 -4
- data/spec/dummy/config.ru +0 -4
- data/spec/dummy/config/application.rb +0 -70
- data/spec/dummy/config/boot.rb +0 -11
- data/spec/dummy/config/database.yml +0 -25
- data/spec/dummy/config/environment.rb +0 -5
- data/spec/dummy/config/environments/development.rb +0 -37
- data/spec/dummy/config/environments/production.rb +0 -67
- data/spec/dummy/config/environments/test.rb +0 -37
- data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
- data/spec/dummy/config/initializers/inflections.rb +0 -15
- data/spec/dummy/config/initializers/mime_types.rb +0 -5
- data/spec/dummy/config/initializers/secret_token.rb +0 -7
- data/spec/dummy/config/initializers/session_store.rb +0 -8
- data/spec/dummy/config/initializers/wrap_parameters.rb +0 -14
- data/spec/dummy/config/locales/en.yml +0 -5
- data/spec/dummy/config/routes.rb +0 -5
- data/spec/dummy/db/migrate/20121213101512_create_messages.rb +0 -21
- data/spec/dummy/db/schema.rb +0 -33
- data/spec/dummy/db/seeds.rb +0 -7
- data/spec/dummy/lib/assets/.gitkeep +0 -0
- data/spec/dummy/lib/tasks/.gitkeep +0 -0
- data/spec/dummy/log/.gitkeep +0 -0
- data/spec/dummy/public/404.html +0 -26
- data/spec/dummy/public/422.html +0 -26
- data/spec/dummy/public/500.html +0 -25
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +0 -6
- data/spec/rate_limiter/model_spec.rb +0 -20
- data/spec/rate_limiter_spec.rb +0 -10
- data/spec/spec_helper.rb +0 -30
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rate_limiter/validator'
|
4
|
+
|
5
|
+
module RateLimiter
|
6
|
+
# Sets up RateLimiter configuration for an ActiveRecord model.
|
7
|
+
class ModelConfig
|
8
|
+
def initialize(model_class)
|
9
|
+
@model_class = model_class
|
10
|
+
end
|
11
|
+
|
12
|
+
# Set up `@model_class` for RateLimiter. Includes callbacks, class
|
13
|
+
# attributes, instance methods, etc.
|
14
|
+
def setup(options = {})
|
15
|
+
@model_class.send(:include, Model::InstanceMethods)
|
16
|
+
setup_options(options)
|
17
|
+
setup_validations
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def setup_options(options)
|
23
|
+
@model_class.class_attribute :rate_limiter_options
|
24
|
+
@model_class.rate_limiter_options = options.dup
|
25
|
+
end
|
26
|
+
|
27
|
+
def setup_validations
|
28
|
+
# TODO: Maybe make it so the context can be configured.
|
29
|
+
@model_class.validate(on: :create) do |record|
|
30
|
+
Validator.new(record).validate
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'request_store'
|
4
|
+
|
5
|
+
module RateLimiter
|
6
|
+
# Manages configuration and state for the current HTTP request such as
|
7
|
+
# `source`.
|
8
|
+
#
|
9
|
+
# It is recommended you don't use `RateLimiter::Request` directly. Instead
|
10
|
+
# use `RateLimiter.request`.
|
11
|
+
module Request
|
12
|
+
class InvalidOption < RuntimeError; end
|
13
|
+
|
14
|
+
class << self
|
15
|
+
# Turn off RateLimiter for the given model for this request.
|
16
|
+
def disable_model(model_class)
|
17
|
+
enabled_for_model(model_class, false)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Turn on RateLimiter for the given model for this request.
|
21
|
+
def enable_model(model_class)
|
22
|
+
enabled_for_model(model_class, true)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns `true` if RateLimiter is enabled for the current request,
|
26
|
+
# `false` otherwise.
|
27
|
+
def enabled?
|
28
|
+
!!store[:enabled]
|
29
|
+
end
|
30
|
+
|
31
|
+
# Sets whether RateLimiter is enabled or disabled for the current request.
|
32
|
+
def enabled=(value)
|
33
|
+
store[:enabled] = value
|
34
|
+
end
|
35
|
+
|
36
|
+
# Sets wheterh RateLimiter is enabled or disabled for this model for the
|
37
|
+
# current request.
|
38
|
+
def enabled_for_model(model, value)
|
39
|
+
store[:"enabled_for_#{model}"] = value
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns `true` if RateLimiter is enabled for this model for the current
|
43
|
+
# request, `false` otherwise.
|
44
|
+
def enabled_for_model?(model)
|
45
|
+
model.include?(Model::InstanceMethods) && !!store.fetch(:"enabled_for_#{model}", true)
|
46
|
+
end
|
47
|
+
|
48
|
+
def merge(options)
|
49
|
+
options.to_h.each do |k, v|
|
50
|
+
store[k] = v
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def set(options)
|
55
|
+
store.clear
|
56
|
+
merge(options)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns who is responsible for attempting to create a new record.
|
60
|
+
def source
|
61
|
+
who = store[:source]
|
62
|
+
who.respond_to?(:call) ? who.call : who
|
63
|
+
end
|
64
|
+
|
65
|
+
# Sets who is responsible for attempting to create a new record.
|
66
|
+
def source=(value)
|
67
|
+
store[:source] = value
|
68
|
+
end
|
69
|
+
|
70
|
+
# Returns a deep copy of the RequestStore.
|
71
|
+
def to_h
|
72
|
+
store.deep_dup
|
73
|
+
end
|
74
|
+
|
75
|
+
# Temporarily set options and execute a block.
|
76
|
+
def with(options)
|
77
|
+
return unless block_given?
|
78
|
+
|
79
|
+
before = to_h
|
80
|
+
validate_public_options(options)
|
81
|
+
merge(options)
|
82
|
+
yield
|
83
|
+
ensure
|
84
|
+
set(before)
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
# Internal store for the options for this request.
|
90
|
+
def store
|
91
|
+
RequestStore.store[:rate_limiter] ||= {
|
92
|
+
enabled: true
|
93
|
+
}
|
94
|
+
end
|
95
|
+
|
96
|
+
# Double checks that the options passed are known. Does not validate
|
97
|
+
# the values of the options.
|
98
|
+
def validate_public_options(options)
|
99
|
+
options.each do |k, _v|
|
100
|
+
case k
|
101
|
+
when /enabled_for_/,
|
102
|
+
:enabled,
|
103
|
+
:source
|
104
|
+
next
|
105
|
+
else
|
106
|
+
raise InvalidOption, "Invalid option: #{k}"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RateLimiter
|
4
|
+
# Limits the rate at which new records of an ActiveRecord model can be saved.
|
5
|
+
# Checks to see if RateLimiter is enabled and, if all conditions are satisfied
|
6
|
+
# and if any other records have been created within the time interval for rate
|
7
|
+
# limiting.
|
8
|
+
class Throttle
|
9
|
+
DEFAULT_INTERVAL = 1.minute
|
10
|
+
DEFAULT_ON_FIELD = :ip_address
|
11
|
+
DEFAULT_TIMESTAMP_FIELD = :created_at
|
12
|
+
|
13
|
+
def initialize(record, options = {})
|
14
|
+
@record = record
|
15
|
+
@options = options
|
16
|
+
end
|
17
|
+
|
18
|
+
# Has the rate limit been exceeded?
|
19
|
+
def exceeded?
|
20
|
+
enabled? && rate_limit? && others_for_rate_limiting.present?
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
# Is RateLimiter enabled for this particular record?
|
26
|
+
def enabled?
|
27
|
+
RateLimiter.enabled? &&
|
28
|
+
RateLimiter.request.enabled? &&
|
29
|
+
RateLimiter.request.enabled_for_model?(@record.class)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Proc that if present must return true for RateLimiter to be enabled for
|
33
|
+
# this particular record.
|
34
|
+
def if_condition
|
35
|
+
@options[:if_condition]
|
36
|
+
end
|
37
|
+
|
38
|
+
# The time interval (in seconds)
|
39
|
+
def interval
|
40
|
+
@options[:interval] || DEFAULT_INTERVAL
|
41
|
+
end
|
42
|
+
|
43
|
+
# Arel query for finding records within the interval.
|
44
|
+
def interval_query_params
|
45
|
+
@record.class.arel_table[timestamp_field].gteq(Time.current - interval)
|
46
|
+
end
|
47
|
+
|
48
|
+
# An Array of model attribute names to match against.
|
49
|
+
def on
|
50
|
+
Array(@options[:on] || DEFAULT_ON_FIELD)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Arel query for finding records that match the on attributes.
|
54
|
+
def on_query_params
|
55
|
+
on.map { |attr| @record.class.arel_table[attr].eq(@record.send(attr)) }.inject(&:or)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Other records that fall within the time interval.
|
59
|
+
def others_for_rate_limiting
|
60
|
+
@record.class.where(on_query_params).where(interval_query_params)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Are all of the conditions for rate limiting met for this record?
|
64
|
+
def rate_limit?
|
65
|
+
(if_condition.blank? || if_condition.call(@record)) && !unless_condition.try(:call, @record)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Timestamp field to test the interval against.
|
69
|
+
def timestamp_field
|
70
|
+
@options[:timestamp_field] || DEFAULT_TIMESTAMP_FIELD
|
71
|
+
end
|
72
|
+
|
73
|
+
# Proc that if present must return false for RateLimiter to be enabled for
|
74
|
+
# this particular record.
|
75
|
+
def unless_condition
|
76
|
+
@options[:unless_condition]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RateLimiter
|
4
|
+
# Validates whether a model's rate limit has been exceeded.
|
5
|
+
class Validator
|
6
|
+
def initialize(record, options = {})
|
7
|
+
@record = record
|
8
|
+
@options = options
|
9
|
+
end
|
10
|
+
|
11
|
+
def validate
|
12
|
+
return unless @record.rate_limit_exceeded?
|
13
|
+
|
14
|
+
@record.errors.add(:base, I18n.t('rate_limiter.errors.rate_limit_exceeded', object_type: object_type, default: default_error_message))
|
15
|
+
|
16
|
+
false
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def default_error_message
|
22
|
+
"You cannot create a new #{object_type} yet."
|
23
|
+
end
|
24
|
+
|
25
|
+
def object_type
|
26
|
+
@record.class.name
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/rate_limiter/version.rb
CHANGED
data/rate_limiter.gemspec
CHANGED
@@ -1,32 +1,38 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.expand_path('lib', __dir__)
|
4
|
+
|
3
5
|
require 'rate_limiter/version'
|
4
6
|
|
5
7
|
Gem::Specification.new do |s|
|
6
8
|
s.name = 'rate_limiter'
|
7
9
|
s.version = RateLimiter::VERSION
|
8
|
-
s.
|
9
|
-
s.
|
10
|
+
s.platform = Gem::Platform::RUBY
|
11
|
+
s.license = 'MIT'
|
12
|
+
s.author = 'Sean Eshbaugh'
|
13
|
+
s.email = 'seaneshbaugh@gmail.com'
|
10
14
|
s.homepage = 'https://github.com/seaneshbaugh/rate_limiter'
|
11
15
|
s.summary = 'Adds creation rate limiting to ActiveRecord models.'
|
12
16
|
s.description = 'Adds creation rate limiting to ActiveRecord models.'
|
13
17
|
|
14
|
-
s.
|
18
|
+
s.required_ruby_version = '>= 2.5.0'
|
19
|
+
s.required_rubygems_version = '>= 1.8.11'
|
15
20
|
|
16
|
-
s.files =
|
17
|
-
s.
|
18
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
21
|
+
s.files = Dir['lib/**/*', 'CHANGELOG.md', 'LICENSE.txt', 'README.md', 'rate_limiter.gemspec']
|
22
|
+
s.executables = []
|
19
23
|
s.require_paths = ['lib']
|
20
24
|
|
21
|
-
s.add_dependency '
|
22
|
-
s.add_dependency '
|
25
|
+
s.add_dependency 'activerecord', '>= 5.0.0'
|
26
|
+
s.add_dependency 'railties', '>= 5.0.0'
|
27
|
+
s.add_dependency 'request_store', '~> 1.4'
|
23
28
|
|
24
|
-
s.add_development_dependency '
|
25
|
-
s.add_development_dependency '
|
26
|
-
s.add_development_dependency '
|
27
|
-
s.add_development_dependency '
|
28
|
-
s.add_development_dependency '
|
29
|
-
s.add_development_dependency '
|
30
|
-
s.add_development_dependency '
|
31
|
-
s.add_development_dependency 'sqlite3'
|
29
|
+
s.add_development_dependency 'minitest-spec-rails', '6.0.2'
|
30
|
+
s.add_development_dependency 'pry', '0.12.2'
|
31
|
+
s.add_development_dependency 'puma', '4.3.1'
|
32
|
+
s.add_development_dependency 'rails', '6.0.2.1'
|
33
|
+
s.add_development_dependency 'rake', '13.0.1'
|
34
|
+
s.add_development_dependency 'rubocop', '0.79.0'
|
35
|
+
s.add_development_dependency 'simplecov', '0.18.1'
|
36
|
+
s.add_development_dependency 'sqlite3', '1.4.2'
|
37
|
+
s.add_development_dependency 'timecop', '0.9.1'
|
32
38
|
end
|
metadata
CHANGED
@@ -1,311 +1,226 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rate_limiter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
5
|
-
prerelease:
|
4
|
+
version: 0.1.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Sean Eshbaugh
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2020-02-14 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activerecord
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 5.0.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 5.0.0
|
14
27
|
- !ruby/object:Gem::Dependency
|
15
28
|
name: railties
|
16
29
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
30
|
requirements:
|
19
|
-
- -
|
31
|
+
- - ">="
|
20
32
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
33
|
+
version: 5.0.0
|
22
34
|
type: :runtime
|
23
35
|
prerelease: false
|
24
36
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
37
|
requirements:
|
27
|
-
- -
|
38
|
+
- - ">="
|
28
39
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
40
|
+
version: 5.0.0
|
30
41
|
- !ruby/object:Gem::Dependency
|
31
|
-
name:
|
42
|
+
name: request_store
|
32
43
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
44
|
requirements:
|
35
|
-
- -
|
45
|
+
- - "~>"
|
36
46
|
- !ruby/object:Gem::Version
|
37
|
-
version: '
|
47
|
+
version: '1.4'
|
38
48
|
type: :runtime
|
39
49
|
prerelease: false
|
40
50
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
51
|
requirements:
|
43
|
-
- -
|
52
|
+
- - "~>"
|
44
53
|
- !ruby/object:Gem::Version
|
45
|
-
version: '
|
54
|
+
version: '1.4'
|
46
55
|
- !ruby/object:Gem::Dependency
|
47
|
-
name:
|
56
|
+
name: minitest-spec-rails
|
48
57
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
58
|
requirements:
|
51
|
-
- -
|
59
|
+
- - '='
|
52
60
|
- !ruby/object:Gem::Version
|
53
|
-
version:
|
61
|
+
version: 6.0.2
|
54
62
|
type: :development
|
55
63
|
prerelease: false
|
56
64
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
65
|
requirements:
|
59
|
-
- -
|
66
|
+
- - '='
|
60
67
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
68
|
+
version: 6.0.2
|
62
69
|
- !ruby/object:Gem::Dependency
|
63
|
-
name:
|
70
|
+
name: pry
|
64
71
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
72
|
requirements:
|
67
|
-
- -
|
73
|
+
- - '='
|
68
74
|
- !ruby/object:Gem::Version
|
69
|
-
version:
|
75
|
+
version: 0.12.2
|
70
76
|
type: :development
|
71
77
|
prerelease: false
|
72
78
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
79
|
requirements:
|
75
|
-
- -
|
80
|
+
- - '='
|
76
81
|
- !ruby/object:Gem::Version
|
77
|
-
version:
|
82
|
+
version: 0.12.2
|
78
83
|
- !ruby/object:Gem::Dependency
|
79
|
-
name:
|
84
|
+
name: puma
|
80
85
|
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
86
|
requirements:
|
83
|
-
- -
|
87
|
+
- - '='
|
84
88
|
- !ruby/object:Gem::Version
|
85
|
-
version:
|
89
|
+
version: 4.3.1
|
86
90
|
type: :development
|
87
91
|
prerelease: false
|
88
92
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
93
|
requirements:
|
91
|
-
- -
|
94
|
+
- - '='
|
92
95
|
- !ruby/object:Gem::Version
|
93
|
-
version:
|
96
|
+
version: 4.3.1
|
94
97
|
- !ruby/object:Gem::Dependency
|
95
|
-
name:
|
98
|
+
name: rails
|
96
99
|
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
100
|
requirements:
|
99
|
-
- -
|
101
|
+
- - '='
|
100
102
|
- !ruby/object:Gem::Version
|
101
|
-
version:
|
103
|
+
version: 6.0.2.1
|
102
104
|
type: :development
|
103
105
|
prerelease: false
|
104
106
|
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
107
|
requirements:
|
107
|
-
- -
|
108
|
+
- - '='
|
108
109
|
- !ruby/object:Gem::Version
|
109
|
-
version:
|
110
|
+
version: 6.0.2.1
|
110
111
|
- !ruby/object:Gem::Dependency
|
111
|
-
name:
|
112
|
+
name: rake
|
112
113
|
requirement: !ruby/object:Gem::Requirement
|
113
|
-
none: false
|
114
114
|
requirements:
|
115
|
-
- -
|
115
|
+
- - '='
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version:
|
117
|
+
version: 13.0.1
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
none: false
|
122
121
|
requirements:
|
123
|
-
- -
|
122
|
+
- - '='
|
124
123
|
- !ruby/object:Gem::Version
|
125
|
-
version:
|
124
|
+
version: 13.0.1
|
126
125
|
- !ruby/object:Gem::Dependency
|
127
|
-
name:
|
126
|
+
name: rubocop
|
128
127
|
requirement: !ruby/object:Gem::Requirement
|
129
|
-
none: false
|
130
128
|
requirements:
|
131
|
-
- -
|
129
|
+
- - '='
|
132
130
|
- !ruby/object:Gem::Version
|
133
|
-
version:
|
131
|
+
version: 0.79.0
|
134
132
|
type: :development
|
135
133
|
prerelease: false
|
136
134
|
version_requirements: !ruby/object:Gem::Requirement
|
137
|
-
none: false
|
138
135
|
requirements:
|
139
|
-
- -
|
136
|
+
- - '='
|
140
137
|
- !ruby/object:Gem::Version
|
141
|
-
version:
|
138
|
+
version: 0.79.0
|
142
139
|
- !ruby/object:Gem::Dependency
|
143
|
-
name:
|
140
|
+
name: simplecov
|
144
141
|
requirement: !ruby/object:Gem::Requirement
|
145
|
-
none: false
|
146
142
|
requirements:
|
147
|
-
- -
|
143
|
+
- - '='
|
148
144
|
- !ruby/object:Gem::Version
|
149
|
-
version:
|
145
|
+
version: 0.18.1
|
150
146
|
type: :development
|
151
147
|
prerelease: false
|
152
148
|
version_requirements: !ruby/object:Gem::Requirement
|
153
|
-
none: false
|
154
149
|
requirements:
|
155
|
-
- -
|
150
|
+
- - '='
|
156
151
|
- !ruby/object:Gem::Version
|
157
|
-
version:
|
152
|
+
version: 0.18.1
|
158
153
|
- !ruby/object:Gem::Dependency
|
159
154
|
name: sqlite3
|
160
155
|
requirement: !ruby/object:Gem::Requirement
|
161
|
-
none: false
|
162
156
|
requirements:
|
163
|
-
- -
|
157
|
+
- - '='
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: 1.4.2
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - '='
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: 1.4.2
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: timecop
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - '='
|
164
172
|
- !ruby/object:Gem::Version
|
165
|
-
version:
|
173
|
+
version: 0.9.1
|
166
174
|
type: :development
|
167
175
|
prerelease: false
|
168
176
|
version_requirements: !ruby/object:Gem::Requirement
|
169
|
-
none: false
|
170
177
|
requirements:
|
171
|
-
- -
|
178
|
+
- - '='
|
172
179
|
- !ruby/object:Gem::Version
|
173
|
-
version:
|
180
|
+
version: 0.9.1
|
174
181
|
description: Adds creation rate limiting to ActiveRecord models.
|
175
|
-
email:
|
176
|
-
- seaneshbaugh@gmail.com
|
182
|
+
email: seaneshbaugh@gmail.com
|
177
183
|
executables: []
|
178
184
|
extensions: []
|
179
185
|
extra_rdoc_files: []
|
180
186
|
files:
|
181
|
-
- .gitignore
|
182
|
-
- .rspec
|
183
|
-
- .rvmrc
|
184
187
|
- CHANGELOG.md
|
185
|
-
-
|
186
|
-
- Gemfile.lock
|
188
|
+
- LICENSE.txt
|
187
189
|
- README.md
|
188
|
-
-
|
190
|
+
- lib/generators/rate_limiter/install_generator.rb
|
191
|
+
- lib/generators/rate_limiter/templates/rate_limiter.rb
|
189
192
|
- lib/rate_limiter.rb
|
190
193
|
- lib/rate_limiter/config.rb
|
191
|
-
- lib/rate_limiter/
|
194
|
+
- lib/rate_limiter/frameworks/rails.rb
|
195
|
+
- lib/rate_limiter/frameworks/rails/controller.rb
|
192
196
|
- lib/rate_limiter/model.rb
|
197
|
+
- lib/rate_limiter/model_config.rb
|
198
|
+
- lib/rate_limiter/request.rb
|
199
|
+
- lib/rate_limiter/throttle.rb
|
200
|
+
- lib/rate_limiter/validator.rb
|
193
201
|
- lib/rate_limiter/version.rb
|
194
202
|
- rate_limiter.gemspec
|
195
|
-
- spec/dummy/Rakefile
|
196
|
-
- spec/dummy/app/assets/images/rails.png
|
197
|
-
- spec/dummy/app/assets/javascripts/application.js
|
198
|
-
- spec/dummy/app/assets/stylesheets/application.css
|
199
|
-
- spec/dummy/app/controllers/application_controller.rb
|
200
|
-
- spec/dummy/app/controllers/messages_controller.rb
|
201
|
-
- spec/dummy/app/helpers/application_helper.rb
|
202
|
-
- spec/dummy/app/mailers/.gitkeep
|
203
|
-
- spec/dummy/app/models/message.rb
|
204
|
-
- spec/dummy/app/views/layouts/application.html.erb
|
205
|
-
- spec/dummy/app/views/messages/_form.html.erb
|
206
|
-
- spec/dummy/app/views/messages/_message.html.erb
|
207
|
-
- spec/dummy/app/views/messages/edit.html.erb
|
208
|
-
- spec/dummy/app/views/messages/index.html.erb
|
209
|
-
- spec/dummy/app/views/messages/new.html.erb
|
210
|
-
- spec/dummy/app/views/messages/show.html.erb
|
211
|
-
- spec/dummy/config.ru
|
212
|
-
- spec/dummy/config/application.rb
|
213
|
-
- spec/dummy/config/boot.rb
|
214
|
-
- spec/dummy/config/database.yml
|
215
|
-
- spec/dummy/config/environment.rb
|
216
|
-
- spec/dummy/config/environments/development.rb
|
217
|
-
- spec/dummy/config/environments/production.rb
|
218
|
-
- spec/dummy/config/environments/test.rb
|
219
|
-
- spec/dummy/config/initializers/backtrace_silencers.rb
|
220
|
-
- spec/dummy/config/initializers/inflections.rb
|
221
|
-
- spec/dummy/config/initializers/mime_types.rb
|
222
|
-
- spec/dummy/config/initializers/secret_token.rb
|
223
|
-
- spec/dummy/config/initializers/session_store.rb
|
224
|
-
- spec/dummy/config/initializers/wrap_parameters.rb
|
225
|
-
- spec/dummy/config/locales/en.yml
|
226
|
-
- spec/dummy/config/routes.rb
|
227
|
-
- spec/dummy/db/migrate/20121213101512_create_messages.rb
|
228
|
-
- spec/dummy/db/schema.rb
|
229
|
-
- spec/dummy/db/seeds.rb
|
230
|
-
- spec/dummy/lib/assets/.gitkeep
|
231
|
-
- spec/dummy/lib/tasks/.gitkeep
|
232
|
-
- spec/dummy/log/.gitkeep
|
233
|
-
- spec/dummy/public/404.html
|
234
|
-
- spec/dummy/public/422.html
|
235
|
-
- spec/dummy/public/500.html
|
236
|
-
- spec/dummy/public/favicon.ico
|
237
|
-
- spec/dummy/script/rails
|
238
|
-
- spec/rate_limiter/model_spec.rb
|
239
|
-
- spec/rate_limiter_spec.rb
|
240
|
-
- spec/spec_helper.rb
|
241
203
|
homepage: https://github.com/seaneshbaugh/rate_limiter
|
242
|
-
licenses:
|
204
|
+
licenses:
|
205
|
+
- MIT
|
206
|
+
metadata: {}
|
243
207
|
post_install_message:
|
244
208
|
rdoc_options: []
|
245
209
|
require_paths:
|
246
210
|
- lib
|
247
211
|
required_ruby_version: !ruby/object:Gem::Requirement
|
248
|
-
none: false
|
249
212
|
requirements:
|
250
|
-
- -
|
213
|
+
- - ">="
|
251
214
|
- !ruby/object:Gem::Version
|
252
|
-
version:
|
215
|
+
version: 2.5.0
|
253
216
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
254
|
-
none: false
|
255
217
|
requirements:
|
256
|
-
- -
|
218
|
+
- - ">="
|
257
219
|
- !ruby/object:Gem::Version
|
258
|
-
version:
|
220
|
+
version: 1.8.11
|
259
221
|
requirements: []
|
260
|
-
|
261
|
-
rubygems_version: 1.8.24
|
222
|
+
rubygems_version: 3.1.2
|
262
223
|
signing_key:
|
263
|
-
specification_version:
|
224
|
+
specification_version: 4
|
264
225
|
summary: Adds creation rate limiting to ActiveRecord models.
|
265
|
-
test_files:
|
266
|
-
- spec/dummy/Rakefile
|
267
|
-
- spec/dummy/app/assets/images/rails.png
|
268
|
-
- spec/dummy/app/assets/javascripts/application.js
|
269
|
-
- spec/dummy/app/assets/stylesheets/application.css
|
270
|
-
- spec/dummy/app/controllers/application_controller.rb
|
271
|
-
- spec/dummy/app/controllers/messages_controller.rb
|
272
|
-
- spec/dummy/app/helpers/application_helper.rb
|
273
|
-
- spec/dummy/app/mailers/.gitkeep
|
274
|
-
- spec/dummy/app/models/message.rb
|
275
|
-
- spec/dummy/app/views/layouts/application.html.erb
|
276
|
-
- spec/dummy/app/views/messages/_form.html.erb
|
277
|
-
- spec/dummy/app/views/messages/_message.html.erb
|
278
|
-
- spec/dummy/app/views/messages/edit.html.erb
|
279
|
-
- spec/dummy/app/views/messages/index.html.erb
|
280
|
-
- spec/dummy/app/views/messages/new.html.erb
|
281
|
-
- spec/dummy/app/views/messages/show.html.erb
|
282
|
-
- spec/dummy/config.ru
|
283
|
-
- spec/dummy/config/application.rb
|
284
|
-
- spec/dummy/config/boot.rb
|
285
|
-
- spec/dummy/config/database.yml
|
286
|
-
- spec/dummy/config/environment.rb
|
287
|
-
- spec/dummy/config/environments/development.rb
|
288
|
-
- spec/dummy/config/environments/production.rb
|
289
|
-
- spec/dummy/config/environments/test.rb
|
290
|
-
- spec/dummy/config/initializers/backtrace_silencers.rb
|
291
|
-
- spec/dummy/config/initializers/inflections.rb
|
292
|
-
- spec/dummy/config/initializers/mime_types.rb
|
293
|
-
- spec/dummy/config/initializers/secret_token.rb
|
294
|
-
- spec/dummy/config/initializers/session_store.rb
|
295
|
-
- spec/dummy/config/initializers/wrap_parameters.rb
|
296
|
-
- spec/dummy/config/locales/en.yml
|
297
|
-
- spec/dummy/config/routes.rb
|
298
|
-
- spec/dummy/db/migrate/20121213101512_create_messages.rb
|
299
|
-
- spec/dummy/db/schema.rb
|
300
|
-
- spec/dummy/db/seeds.rb
|
301
|
-
- spec/dummy/lib/assets/.gitkeep
|
302
|
-
- spec/dummy/lib/tasks/.gitkeep
|
303
|
-
- spec/dummy/log/.gitkeep
|
304
|
-
- spec/dummy/public/404.html
|
305
|
-
- spec/dummy/public/422.html
|
306
|
-
- spec/dummy/public/500.html
|
307
|
-
- spec/dummy/public/favicon.ico
|
308
|
-
- spec/dummy/script/rails
|
309
|
-
- spec/rate_limiter/model_spec.rb
|
310
|
-
- spec/rate_limiter_spec.rb
|
311
|
-
- spec/spec_helper.rb
|
226
|
+
test_files: []
|