rack-attack 6.6.1 → 6.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +12 -8
  3. data/lib/rack/attack/base_proxy.rb +1 -0
  4. data/lib/rack/attack/cache.rb +10 -4
  5. data/lib/rack/attack/configuration.rb +7 -3
  6. data/lib/rack/attack/path_normalizer.rb +3 -1
  7. data/lib/rack/attack/railtie.rb +6 -0
  8. data/lib/rack/attack/store_proxy/redis_cache_store_proxy.rb +16 -10
  9. data/lib/rack/attack/store_proxy/redis_proxy.rb +2 -1
  10. data/lib/rack/attack/throttle.rb +2 -1
  11. data/lib/rack/attack/version.rb +1 -1
  12. data/lib/rack/attack.rb +3 -1
  13. data/spec/acceptance/blocking_ip_spec.rb +13 -8
  14. data/spec/acceptance/blocking_spec.rb +16 -18
  15. data/spec/acceptance/blocking_subnet_spec.rb +7 -8
  16. data/spec/acceptance/cache_store_config_for_allow2ban_spec.rb +5 -3
  17. data/spec/acceptance/cache_store_config_for_fail2ban_spec.rb +7 -5
  18. data/spec/acceptance/cache_store_config_for_throttle_spec.rb +5 -3
  19. data/spec/acceptance/cache_store_config_with_rails_spec.rb +6 -4
  20. data/spec/acceptance/extending_request_object_spec.rb +3 -7
  21. data/spec/acceptance/fail2ban_spec.rb +42 -0
  22. data/spec/acceptance/rails_middleware_spec.rb +1 -1
  23. data/spec/acceptance/safelisting_ip_spec.rb +12 -4
  24. data/spec/acceptance/safelisting_spec.rb +14 -14
  25. data/spec/acceptance/safelisting_subnet_spec.rb +6 -4
  26. data/spec/acceptance/stores/active_support_mem_cache_store_pooled_spec.rb +5 -2
  27. data/spec/acceptance/stores/active_support_mem_cache_store_spec.rb +0 -1
  28. data/spec/acceptance/stores/active_support_memory_store_spec.rb +0 -2
  29. data/spec/acceptance/stores/active_support_redis_cache_store_pooled_spec.rb +5 -2
  30. data/spec/acceptance/stores/active_support_redis_cache_store_spec.rb +0 -1
  31. data/spec/acceptance/stores/connection_pool_dalli_client_spec.rb +0 -1
  32. data/spec/acceptance/stores/dalli_client_spec.rb +0 -1
  33. data/spec/acceptance/stores/redis_spec.rb +0 -1
  34. data/spec/acceptance/stores/redis_store_spec.rb +1 -3
  35. data/spec/acceptance/throttling_spec.rb +14 -23
  36. data/spec/acceptance/track_spec.rb +8 -9
  37. data/spec/acceptance/track_throttle_spec.rb +10 -16
  38. data/spec/configuration_spec.rb +33 -0
  39. data/spec/integration/offline_spec.rb +0 -12
  40. data/spec/rack_attack_instrumentation_spec.rb +25 -28
  41. data/spec/rack_attack_request_spec.rb +2 -4
  42. data/spec/rack_attack_reset_spec.rb +90 -0
  43. data/spec/rack_attack_spec.rb +4 -22
  44. data/spec/rack_attack_throttle_spec.rb +49 -28
  45. data/spec/rack_attack_track_spec.rb +4 -17
  46. data/spec/spec_helper.rb +7 -5
  47. data/spec/support/cache_store_helper.rb +31 -25
  48. data/spec/support/freeze_time_helper.rb +9 -0
  49. metadata +48 -28
  50. data/lib/rack/attack/store_proxy/active_support_redis_store_proxy.rb +0 -39
  51. data/spec/acceptance/stores/active_support_dalli_store_spec.rb +0 -25
  52. data/spec/acceptance/stores/active_support_redis_store_spec.rb +0 -20
@@ -1,10 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'spec_helper'
4
+ require_relative 'support/freeze_time_helper'
4
5
 
5
6
  describe 'Rack::Attack.throttle' do
6
7
  before do
7
- @period = 60 # Use a long period; failures due to cache key rotation less likely
8
+ @period = 60
8
9
  Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
9
10
  Rack::Attack.throttle('ip/sec', limit: 1, period: @period) { |req| req.ip }
10
11
  end
@@ -14,14 +15,18 @@ describe 'Rack::Attack.throttle' do
14
15
  it_allows_ok_requests
15
16
 
16
17
  describe 'a single request' do
17
- before { get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' }
18
-
19
18
  it 'should set the counter for one request' do
20
- key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4"
21
- _(Rack::Attack.cache.store.read(key)).must_equal 1
19
+ within_same_period do
20
+ get '/', {}, 'REMOTE_ADDR' => '1.2.3.4'
21
+
22
+ key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4"
23
+ _(Rack::Attack.cache.store.read(key)).must_equal 1
24
+ end
22
25
  end
23
26
 
24
27
  it 'should populate throttle data' do
28
+ get '/', {}, 'REMOTE_ADDR' => '1.2.3.4'
29
+
25
30
  data = {
26
31
  count: 1,
27
32
  limit: 1,
@@ -36,7 +41,9 @@ describe 'Rack::Attack.throttle' do
36
41
 
37
42
  describe "with 2 requests" do
38
43
  before do
39
- 2.times { get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' }
44
+ within_same_period do
45
+ 2.times { get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' }
46
+ end
40
47
  end
41
48
 
42
49
  it 'should block the last request' do
@@ -62,7 +69,7 @@ end
62
69
 
63
70
  describe 'Rack::Attack.throttle with limit as proc' do
64
71
  before do
65
- @period = 60 # Use a long period; failures due to cache key rotation less likely
72
+ @period = 60
66
73
  Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
67
74
  Rack::Attack.throttle('ip/sec', limit: lambda { |_req| 1 }, period: @period) { |req| req.ip }
68
75
  end
@@ -70,14 +77,17 @@ describe 'Rack::Attack.throttle with limit as proc' do
70
77
  it_allows_ok_requests
71
78
 
72
79
  describe 'a single request' do
73
- before { get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' }
74
-
75
80
  it 'should set the counter for one request' do
76
- key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4"
77
- _(Rack::Attack.cache.store.read(key)).must_equal 1
81
+ within_same_period do
82
+ get '/', {}, 'REMOTE_ADDR' => '1.2.3.4'
83
+
84
+ key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4"
85
+ _(Rack::Attack.cache.store.read(key)).must_equal 1
86
+ end
78
87
  end
79
88
 
80
89
  it 'should populate throttle data' do
90
+ get '/', {}, 'REMOTE_ADDR' => '1.2.3.4'
81
91
  data = {
82
92
  count: 1,
83
93
  limit: 1,
@@ -93,7 +103,7 @@ end
93
103
 
94
104
  describe 'Rack::Attack.throttle with period as proc' do
95
105
  before do
96
- @period = 60 # Use a long period; failures due to cache key rotation less likely
106
+ @period = 60
97
107
  Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
98
108
  Rack::Attack.throttle('ip/sec', limit: lambda { |_req| 1 }, period: lambda { |_req| @period }) { |req| req.ip }
99
109
  end
@@ -101,14 +111,18 @@ describe 'Rack::Attack.throttle with period as proc' do
101
111
  it_allows_ok_requests
102
112
 
103
113
  describe 'a single request' do
104
- before { get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' }
105
-
106
114
  it 'should set the counter for one request' do
107
- key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4"
108
- _(Rack::Attack.cache.store.read(key)).must_equal 1
115
+ within_same_period do
116
+ get '/', {}, 'REMOTE_ADDR' => '1.2.3.4'
117
+
118
+ key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4"
119
+ _(Rack::Attack.cache.store.read(key)).must_equal 1
120
+ end
109
121
  end
110
122
 
111
123
  it 'should populate throttle data' do
124
+ get '/', {}, 'REMOTE_ADDR' => '1.2.3.4'
125
+
112
126
  data = {
113
127
  count: 1,
114
128
  limit: 1,
@@ -122,7 +136,7 @@ describe 'Rack::Attack.throttle with period as proc' do
122
136
  end
123
137
  end
124
138
 
125
- describe 'Rack::Attack.throttle with block retuning nil' do
139
+ describe 'Rack::Attack.throttle with block returning nil' do
126
140
  before do
127
141
  @period = 60
128
142
  Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
@@ -132,14 +146,17 @@ describe 'Rack::Attack.throttle with block retuning nil' do
132
146
  it_allows_ok_requests
133
147
 
134
148
  describe 'a single request' do
135
- before { get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' }
136
-
137
149
  it 'should not set the counter' do
138
- key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4"
139
- assert_nil Rack::Attack.cache.store.read(key)
150
+ within_same_period do
151
+ get '/', {}, 'REMOTE_ADDR' => '1.2.3.4'
152
+
153
+ key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4"
154
+ assert_nil Rack::Attack.cache.store.read(key)
155
+ end
140
156
  end
141
157
 
142
158
  it 'should not populate throttle data' do
159
+ get '/', {}, 'REMOTE_ADDR' => '1.2.3.4'
143
160
  assert_nil last_request.env['rack.attack.throttle_data']
144
161
  end
145
162
  end
@@ -162,9 +179,11 @@ describe 'Rack::Attack.throttle with throttle_discriminator_normalizer' do
162
179
  end
163
180
 
164
181
  it 'should not differentiate requests when throttle_discriminator_normalizer is enabled' do
165
- post_logins
166
- key = "rack::attack:#{Time.now.to_i / @period}:logins/email:person@example.com"
167
- _(Rack::Attack.cache.store.read(key)).must_equal 3
182
+ within_same_period do
183
+ post_logins
184
+ key = "rack::attack:#{Time.now.to_i / @period}:logins/email:person@example.com"
185
+ _(Rack::Attack.cache.store.read(key)).must_equal 3
186
+ end
168
187
  end
169
188
 
170
189
  it 'should differentiate requests when throttle_discriminator_normalizer is disabled' do
@@ -172,10 +191,12 @@ describe 'Rack::Attack.throttle with throttle_discriminator_normalizer' do
172
191
  prev = Rack::Attack.throttle_discriminator_normalizer
173
192
  Rack::Attack.throttle_discriminator_normalizer = nil
174
193
 
175
- post_logins
176
- @emails.each do |email|
177
- key = "rack::attack:#{Time.now.to_i / @period}:logins/email:#{email}"
178
- _(Rack::Attack.cache.store.read(key)).must_equal 1
194
+ within_same_period do
195
+ post_logins
196
+ @emails.each do |email|
197
+ key = "rack::attack:#{Time.now.to_i / @period}:logins/email:#{email}"
198
+ _(Rack::Attack.cache.store.read(key)).must_equal 1
199
+ end
179
200
  end
180
201
  ensure
181
202
  Rack::Attack.throttle_discriminator_normalizer = prev
@@ -3,19 +3,7 @@
3
3
  require_relative 'spec_helper'
4
4
 
5
5
  describe 'Rack::Attack.track' do
6
- class Counter
7
- def self.incr
8
- @counter += 1
9
- end
10
-
11
- def self.reset
12
- @counter = 0
13
- end
14
-
15
- def self.check
16
- @counter
17
- end
18
- end
6
+ let(:notifications) { [] }
19
7
 
20
8
  before do
21
9
  Rack::Attack.track("everything") { |_req| true }
@@ -32,19 +20,18 @@ describe 'Rack::Attack.track' do
32
20
 
33
21
  describe "with a notification subscriber and two tracks" do
34
22
  before do
35
- Counter.reset
36
23
  # A second track
37
24
  Rack::Attack.track("homepage") { |req| req.path == "/" }
38
25
 
39
- ActiveSupport::Notifications.subscribe("track.rack_attack") do |*_args|
40
- Counter.incr
26
+ ActiveSupport::Notifications.subscribe("track.rack_attack") do |_name, _start, _finish, _id, payload|
27
+ notifications.push(payload)
41
28
  end
42
29
 
43
30
  get "/"
44
31
  end
45
32
 
46
33
  it "should notify twice" do
47
- _(Counter.check).must_equal 2
34
+ _(notifications.size).must_equal 2
48
35
  end
49
36
  end
50
37
 
data/spec/spec_helper.rb CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  require "bundler/setup"
4
4
 
5
+ require "logger"
5
6
  require "minitest/autorun"
6
7
  require "minitest/pride"
7
8
  require "rack/test"
8
- require "rails"
9
-
9
+ require "active_support"
10
10
  require "rack/attack"
11
11
 
12
12
  if RUBY_ENGINE == "ruby"
@@ -21,15 +21,17 @@ end
21
21
 
22
22
  safe_require "connection_pool"
23
23
  safe_require "dalli"
24
+ safe_require "rails"
24
25
  safe_require "redis"
25
- safe_require "redis-activesupport"
26
26
  safe_require "redis-store"
27
27
 
28
- class MiniTest::Spec
28
+ class Minitest::Spec
29
29
  include Rack::Test::Methods
30
30
 
31
31
  before do
32
- Rails.cache = nil
32
+ if Object.const_defined?(:Rails) && Rails.respond_to?(:cache) && Rails.cache.respond_to?(:clear)
33
+ Rails.cache.clear
34
+ end
33
35
  end
34
36
 
35
37
  after do
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'freeze_time_helper'
4
+
3
5
  class Minitest::Spec
4
6
  def self.it_works_for_cache_backed_features(options)
5
7
  fetch_from_store = options.fetch(:fetch_from_store)
@@ -9,11 +11,13 @@ class Minitest::Spec
9
11
  request.ip
10
12
  end
11
13
 
12
- get "/", {}, "REMOTE_ADDR" => "1.2.3.4"
13
- assert_equal 200, last_response.status
14
+ within_same_period do
15
+ get "/", {}, "REMOTE_ADDR" => "1.2.3.4"
16
+ assert_equal 200, last_response.status
14
17
 
15
- get "/", {}, "REMOTE_ADDR" => "1.2.3.4"
16
- assert_equal 429, last_response.status
18
+ get "/", {}, "REMOTE_ADDR" => "1.2.3.4"
19
+ assert_equal 429, last_response.status
20
+ end
17
21
  end
18
22
 
19
23
  it "works for fail2ban" do
@@ -23,17 +27,19 @@ class Minitest::Spec
23
27
  end
24
28
  end
25
29
 
26
- get "/"
27
- assert_equal 200, last_response.status
30
+ within_same_period do
31
+ get "/"
32
+ assert_equal 200, last_response.status
28
33
 
29
- get "/private-place"
30
- assert_equal 403, last_response.status
34
+ get "/private-place"
35
+ assert_equal 403, last_response.status
31
36
 
32
- get "/private-place"
33
- assert_equal 403, last_response.status
37
+ get "/private-place"
38
+ assert_equal 403, last_response.status
34
39
 
35
- get "/"
36
- assert_equal 403, last_response.status
40
+ get "/"
41
+ assert_equal 403, last_response.status
42
+ end
37
43
  end
38
44
 
39
45
  it "works for allow2ban" do
@@ -43,20 +49,22 @@ class Minitest::Spec
43
49
  end
44
50
  end
45
51
 
46
- get "/"
47
- assert_equal 200, last_response.status
52
+ within_same_period do
53
+ get "/"
54
+ assert_equal 200, last_response.status
48
55
 
49
- get "/scarce-resource"
50
- assert_equal 200, last_response.status
56
+ get "/scarce-resource"
57
+ assert_equal 200, last_response.status
51
58
 
52
- get "/scarce-resource"
53
- assert_equal 200, last_response.status
59
+ get "/scarce-resource"
60
+ assert_equal 200, last_response.status
54
61
 
55
- get "/scarce-resource"
56
- assert_equal 403, last_response.status
62
+ get "/scarce-resource"
63
+ assert_equal 403, last_response.status
57
64
 
58
- get "/"
59
- assert_equal 403, last_response.status
65
+ get "/"
66
+ assert_equal 403, last_response.status
67
+ end
60
68
  end
61
69
 
62
70
  it "doesn't leak keys" do
@@ -66,9 +74,7 @@ class Minitest::Spec
66
74
 
67
75
  key = nil
68
76
 
69
- # Freeze time during these statement to be sure that the key used by rack attack is the same
70
- # we pre-calculate in local variable `key`
71
- Timecop.freeze do
77
+ within_same_period do
72
78
  key = "rack::attack:#{Time.now.to_i}:by ip:1.2.3.4"
73
79
 
74
80
  get "/", {}, "REMOTE_ADDR" => "1.2.3.4"
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "timecop"
4
+
5
+ class Minitest::Spec
6
+ def within_same_period(&block)
7
+ Timecop.freeze(&block)
8
+ end
9
+ end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-attack
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.6.1
4
+ version: 6.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Suggs
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2022-04-14 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: rack
@@ -19,7 +18,7 @@ dependencies:
19
18
  version: '1.0'
20
19
  - - "<"
21
20
  - !ruby/object:Gem::Version
22
- version: '3'
21
+ version: '4'
23
22
  type: :runtime
24
23
  prerelease: false
25
24
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,7 +28,7 @@ dependencies:
29
28
  version: '1.0'
30
29
  - - "<"
31
30
  - !ruby/object:Gem::Version
32
- version: '3'
31
+ version: '4'
33
32
  - !ruby/object:Gem::Dependency
34
33
  name: appraisal
35
34
  requirement: !ruby/object:Gem::Requirement
@@ -98,14 +97,14 @@ dependencies:
98
97
  requirements:
99
98
  - - "~>"
100
99
  - !ruby/object:Gem::Version
101
- version: '1.0'
100
+ version: '2.0'
102
101
  type: :development
103
102
  prerelease: false
104
103
  version_requirements: !ruby/object:Gem::Requirement
105
104
  requirements:
106
105
  - - "~>"
107
106
  - !ruby/object:Gem::Version
108
- version: '1.0'
107
+ version: '2.0'
109
108
  - !ruby/object:Gem::Dependency
110
109
  name: rake
111
110
  requirement: !ruby/object:Gem::Requirement
@@ -126,28 +125,56 @@ dependencies:
126
125
  requirements:
127
126
  - - '='
128
127
  - !ruby/object:Gem::Version
129
- version: 0.89.1
128
+ version: 1.12.1
130
129
  type: :development
131
130
  prerelease: false
132
131
  version_requirements: !ruby/object:Gem::Requirement
133
132
  requirements:
134
133
  - - '='
135
134
  - !ruby/object:Gem::Version
136
- version: 0.89.1
135
+ version: 1.12.1
136
+ - !ruby/object:Gem::Dependency
137
+ name: rubocop-minitest
138
+ requirement: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - "~>"
141
+ - !ruby/object:Gem::Version
142
+ version: 0.11.1
143
+ type: :development
144
+ prerelease: false
145
+ version_requirements: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - "~>"
148
+ - !ruby/object:Gem::Version
149
+ version: 0.11.1
137
150
  - !ruby/object:Gem::Dependency
138
151
  name: rubocop-performance
139
152
  requirement: !ruby/object:Gem::Requirement
140
153
  requirements:
141
154
  - - "~>"
142
155
  - !ruby/object:Gem::Version
143
- version: 1.5.0
156
+ version: 1.10.2
157
+ type: :development
158
+ prerelease: false
159
+ version_requirements: !ruby/object:Gem::Requirement
160
+ requirements:
161
+ - - "~>"
162
+ - !ruby/object:Gem::Version
163
+ version: 1.10.2
164
+ - !ruby/object:Gem::Dependency
165
+ name: rubocop-rake
166
+ requirement: !ruby/object:Gem::Requirement
167
+ requirements:
168
+ - - "~>"
169
+ - !ruby/object:Gem::Version
170
+ version: 0.5.1
144
171
  type: :development
145
172
  prerelease: false
146
173
  version_requirements: !ruby/object:Gem::Requirement
147
174
  requirements:
148
175
  - - "~>"
149
176
  - !ruby/object:Gem::Version
150
- version: 1.5.0
177
+ version: 0.5.1
151
178
  - !ruby/object:Gem::Dependency
152
179
  name: timecop
153
180
  requirement: !ruby/object:Gem::Requirement
@@ -177,25 +204,19 @@ dependencies:
177
204
  - !ruby/object:Gem::Version
178
205
  version: '11.0'
179
206
  - !ruby/object:Gem::Dependency
180
- name: railties
207
+ name: activesupport
181
208
  requirement: !ruby/object:Gem::Requirement
182
209
  requirements:
183
210
  - - ">="
184
211
  - !ruby/object:Gem::Version
185
- version: '4.2'
186
- - - "<"
187
- - !ruby/object:Gem::Version
188
- version: '7.1'
212
+ version: '0'
189
213
  type: :development
190
214
  prerelease: false
191
215
  version_requirements: !ruby/object:Gem::Requirement
192
216
  requirements:
193
217
  - - ">="
194
218
  - !ruby/object:Gem::Version
195
- version: '4.2'
196
- - - "<"
197
- - !ruby/object:Gem::Version
198
- version: '7.1'
219
+ version: '0'
199
220
  description: A rack middleware for throttling and blocking abusive requests
200
221
  email: aaron@ktheory.com
201
222
  executables: []
@@ -217,7 +238,6 @@ files:
217
238
  - lib/rack/attack/railtie.rb
218
239
  - lib/rack/attack/request.rb
219
240
  - lib/rack/attack/safelist.rb
220
- - lib/rack/attack/store_proxy/active_support_redis_store_proxy.rb
221
241
  - lib/rack/attack/store_proxy/dalli_proxy.rb
222
242
  - lib/rack/attack/store_proxy/mem_cache_store_proxy.rb
223
243
  - lib/rack/attack/store_proxy/redis_cache_store_proxy.rb
@@ -242,13 +262,11 @@ files:
242
262
  - spec/acceptance/safelisting_ip_spec.rb
243
263
  - spec/acceptance/safelisting_spec.rb
244
264
  - spec/acceptance/safelisting_subnet_spec.rb
245
- - spec/acceptance/stores/active_support_dalli_store_spec.rb
246
265
  - spec/acceptance/stores/active_support_mem_cache_store_pooled_spec.rb
247
266
  - spec/acceptance/stores/active_support_mem_cache_store_spec.rb
248
267
  - spec/acceptance/stores/active_support_memory_store_spec.rb
249
268
  - spec/acceptance/stores/active_support_redis_cache_store_pooled_spec.rb
250
269
  - spec/acceptance/stores/active_support_redis_cache_store_spec.rb
251
- - spec/acceptance/stores/active_support_redis_store_spec.rb
252
270
  - spec/acceptance/stores/connection_pool_dalli_client_spec.rb
253
271
  - spec/acceptance/stores/dalli_client_spec.rb
254
272
  - spec/acceptance/stores/redis_spec.rb
@@ -257,17 +275,20 @@ files:
257
275
  - spec/acceptance/track_spec.rb
258
276
  - spec/acceptance/track_throttle_spec.rb
259
277
  - spec/allow2ban_spec.rb
278
+ - spec/configuration_spec.rb
260
279
  - spec/fail2ban_spec.rb
261
280
  - spec/integration/offline_spec.rb
262
281
  - spec/rack_attack_dalli_proxy_spec.rb
263
282
  - spec/rack_attack_instrumentation_spec.rb
264
283
  - spec/rack_attack_path_normalizer_spec.rb
265
284
  - spec/rack_attack_request_spec.rb
285
+ - spec/rack_attack_reset_spec.rb
266
286
  - spec/rack_attack_spec.rb
267
287
  - spec/rack_attack_throttle_spec.rb
268
288
  - spec/rack_attack_track_spec.rb
269
289
  - spec/spec_helper.rb
270
290
  - spec/support/cache_store_helper.rb
291
+ - spec/support/freeze_time_helper.rb
271
292
  homepage: https://github.com/rack/rack-attack
272
293
  licenses:
273
294
  - MIT
@@ -275,7 +296,6 @@ metadata:
275
296
  bug_tracker_uri: https://github.com/rack/rack-attack/issues
276
297
  changelog_uri: https://github.com/rack/rack-attack/blob/main/CHANGELOG.md
277
298
  source_code_uri: https://github.com/rack/rack-attack
278
- post_install_message:
279
299
  rdoc_options:
280
300
  - "--charset=UTF-8"
281
301
  require_paths:
@@ -291,8 +311,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
291
311
  - !ruby/object:Gem::Version
292
312
  version: '0'
293
313
  requirements: []
294
- rubygems_version: 3.3.11
295
- signing_key:
314
+ rubygems_version: 3.6.9
296
315
  specification_version: 4
297
316
  summary: Block & throttle abusive requests
298
317
  test_files:
@@ -312,13 +331,11 @@ test_files:
312
331
  - spec/acceptance/safelisting_ip_spec.rb
313
332
  - spec/acceptance/safelisting_spec.rb
314
333
  - spec/acceptance/safelisting_subnet_spec.rb
315
- - spec/acceptance/stores/active_support_dalli_store_spec.rb
316
334
  - spec/acceptance/stores/active_support_mem_cache_store_pooled_spec.rb
317
335
  - spec/acceptance/stores/active_support_mem_cache_store_spec.rb
318
336
  - spec/acceptance/stores/active_support_memory_store_spec.rb
319
337
  - spec/acceptance/stores/active_support_redis_cache_store_pooled_spec.rb
320
338
  - spec/acceptance/stores/active_support_redis_cache_store_spec.rb
321
- - spec/acceptance/stores/active_support_redis_store_spec.rb
322
339
  - spec/acceptance/stores/connection_pool_dalli_client_spec.rb
323
340
  - spec/acceptance/stores/dalli_client_spec.rb
324
341
  - spec/acceptance/stores/redis_spec.rb
@@ -327,14 +344,17 @@ test_files:
327
344
  - spec/acceptance/track_spec.rb
328
345
  - spec/acceptance/track_throttle_spec.rb
329
346
  - spec/allow2ban_spec.rb
347
+ - spec/configuration_spec.rb
330
348
  - spec/fail2ban_spec.rb
331
349
  - spec/integration/offline_spec.rb
332
350
  - spec/rack_attack_dalli_proxy_spec.rb
333
351
  - spec/rack_attack_instrumentation_spec.rb
334
352
  - spec/rack_attack_path_normalizer_spec.rb
335
353
  - spec/rack_attack_request_spec.rb
354
+ - spec/rack_attack_reset_spec.rb
336
355
  - spec/rack_attack_spec.rb
337
356
  - spec/rack_attack_throttle_spec.rb
338
357
  - spec/rack_attack_track_spec.rb
339
358
  - spec/spec_helper.rb
340
359
  - spec/support/cache_store_helper.rb
360
+ - spec/support/freeze_time_helper.rb
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rack/attack/base_proxy'
4
-
5
- module Rack
6
- class Attack
7
- module StoreProxy
8
- class ActiveSupportRedisStoreProxy < BaseProxy
9
- def self.handle?(store)
10
- defined?(::Redis) &&
11
- defined?(::ActiveSupport::Cache::RedisStore) &&
12
- store.is_a?(::ActiveSupport::Cache::RedisStore)
13
- end
14
-
15
- def increment(name, amount = 1, options = {})
16
- # #increment ignores options[:expires_in].
17
- #
18
- # So in order to workaround this we use #write (which sets expiration) to initialize
19
- # the counter. After that we continue using the original #increment.
20
- if options[:expires_in] && !read(name)
21
- write(name, amount, options)
22
-
23
- amount
24
- else
25
- super
26
- end
27
- end
28
-
29
- def read(name, options = {})
30
- super(name, options.merge!(raw: true))
31
- end
32
-
33
- def write(name, value, options = {})
34
- super(name, value, options.merge!(raw: true))
35
- end
36
- end
37
- end
38
- end
39
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../../spec_helper"
4
-
5
- should_run =
6
- defined?(::Dalli) &&
7
- Gem::Version.new(::Dalli::VERSION) < Gem::Version.new("3")
8
-
9
- if should_run
10
- require_relative "../../support/cache_store_helper"
11
- require "active_support/cache/dalli_store"
12
- require "timecop"
13
-
14
- describe "ActiveSupport::Cache::DalliStore as a cache backend" do
15
- before do
16
- Rack::Attack.cache.store = ActiveSupport::Cache::DalliStore.new
17
- end
18
-
19
- after do
20
- Rack::Attack.cache.store.clear
21
- end
22
-
23
- it_works_for_cache_backed_features(fetch_from_store: ->(key) { Rack::Attack.cache.store.fetch(key) })
24
- end
25
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../../spec_helper"
4
-
5
- if defined?(::ActiveSupport::Cache::RedisStore)
6
- require_relative "../../support/cache_store_helper"
7
- require "timecop"
8
-
9
- describe "ActiveSupport::Cache::RedisStore as a cache backend" do
10
- before do
11
- Rack::Attack.cache.store = ActiveSupport::Cache::RedisStore.new
12
- end
13
-
14
- after do
15
- Rack::Attack.cache.store.clear
16
- end
17
-
18
- it_works_for_cache_backed_features(fetch_from_store: ->(key) { Rack::Attack.cache.store.read(key) })
19
- end
20
- end