better_rate_limit 0.1.2 → 0.1.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b8202a0675862d02c311bc2c05f294d5adf1a1add2e5cf65aa401edcb0c159d5
4
- data.tar.gz: b94eb54339bdd7347dbc83f4ac95f87f413671227c89e072bbc0d56bc5a5fb65
3
+ metadata.gz: 1a5f2843da29693ce0d4c9ea1f12ac6310b4cf69bb135b5a4050a267b620f0ec
4
+ data.tar.gz: 9ad1cecfb14d92490bab3e4eb92d9886142c4cc9cbb3196b4c983934286bde56
5
5
  SHA512:
6
- metadata.gz: '07802df810af301f0d5d1fd8f1bd4f924b535e1dddc98575faa20ec20093d88777f27dc9f99cd6d17d7dd9163ea5760300af5b266ae5a5e120cb03c31c0ee2ea'
7
- data.tar.gz: 2659222d45eb6a1d2a6559ef78c8a64fefd7e0c66a06d38b96810782063059037d6f8da8a6453b55aa8adc9c7d6e70b7c98797405c9b4258b908ed339c788d89
6
+ metadata.gz: 119b058e9262c95a42566a6e4d2eec5b9f710e81d3de68e24623cc775d609d35d42e90dcc6e3975aa580c1a9b1b14884e6adeeaf4f8601856d543d336402eb5d
7
+ data.tar.gz: 5563b6847aa143b96dcf6f9ff2faa72deb41d58158022709a9f2e54880b34695745da4fc189560c84874da7cce1dd40eefd2874867acae3469e37b080f1888ca
data/.gitignore CHANGED
@@ -1,61 +1,3 @@
1
- <<<<<<< HEAD
2
- *.gem
3
- *.rbc
4
- /.config
5
- /coverage/
6
- /InstalledFiles
7
- /pkg/
8
- /spec/reports/
9
- /spec/examples.txt
10
- /test/tmp/
11
- /test/version_tmp/
12
- /tmp/
13
-
14
- # Used by dotenv library to load environment variables.
15
- # .env
16
-
17
- # Ignore Byebug command history file.
18
- .byebug_history
19
-
20
- ## Specific to RubyMotion:
21
- .dat*
22
- .repl_history
23
- build/
24
- *.bridgesupport
25
- build-iPhoneOS/
26
- build-iPhoneSimulator/
27
-
28
- ## Specific to RubyMotion (use of CocoaPods):
29
- #
30
- # We recommend against adding the Pods directory to your .gitignore. However
31
- # you should judge for yourself, the pros and cons are mentioned at:
32
- # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
33
- #
34
- # vendor/Pods/
35
-
36
- ## Documentation cache and generated files:
37
- /.yardoc/
38
- /_yardoc/
39
- /doc/
40
- /rdoc/
41
-
42
- ## Environment normalization:
43
- /.bundle/
44
- /vendor/bundle
45
- /lib/bundler/man/
46
-
47
- # for a library or gem, you might want to ignore these files since the code is
48
- # intended to run in multiple environments; otherwise, check them in:
49
- # Gemfile.lock
50
- # .ruby-version
51
- # .ruby-gemset
52
-
53
- # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
54
- .rvmrc
55
-
56
- # Used by RuboCop. Remote config files pulled in from inherit_from directive.
57
- # .rubocop-https?--*
58
- =======
59
1
  /.bundle/
60
2
  /.yardoc
61
3
  /_yardoc/
@@ -64,7 +6,5 @@ build-iPhoneSimulator/
64
6
  /pkg/
65
7
  /spec/reports/
66
8
  /tmp/
67
-
68
- # rspec failure tracking
69
- .rspec_status
70
- >>>>>>> init gem
9
+ *.gem
10
+ .byebug_history
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- better_rate_limit (0.1.2)
4
+ better_rate_limit (0.1.3)
5
5
  actionpack (>= 5.0)
6
6
  redis (>= 3.3)
7
7
 
data/README.md CHANGED
@@ -1,4 +1,6 @@
1
1
  # BetterRateLimit
2
+ [![Build Status](https://travis-ci.org/upscopeio/better_rate_limit.svg?branch=master)](https://travis-ci.org/upscopeio/better_rate_limit)
3
+ [![Gem Version](https://badge.fury.io/rb/better_rate_limit.svg)](https://badge.fury.io/rb/better_rate_limit)
2
4
 
3
5
  Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/better_rate_limit`. To experiment with that code, run `bin/console` for an interactive prompt.
4
6
 
@@ -7,7 +9,7 @@ Welcome to your new gem! In this directory, you'll find the files you need to be
7
9
  Add this line to your application's Gemfile:
8
10
 
9
11
  ```ruby
10
- gem 'better_rate_limit', git: 'https://github.com/upscopeio/better_rate_limit'
12
+ gem 'better_rate_limit'
11
13
  ```
12
14
 
13
15
  And then execute:
@@ -1,23 +1,26 @@
1
1
  require 'ostruct'
2
2
  require 'better_rate_limit/throttle'
3
+ require 'better_rate_limit/limit'
3
4
 
4
5
  module ActionController
5
6
  module BetterRateLimit
6
7
  extend ActiveSupport::Concern
7
8
 
8
9
  module ClassMethods
9
- def rate_limit(max, every:, name: nil, scope: -> { real_ip }, only: [], except: [])
10
- rate_limits << OpenStruct.new({
11
- max: max,
12
- every: every,
13
- name: name || controller_path,
14
- scope: scope,
15
- only: only,
16
- except: except,
17
- controller_path: controller_path
10
+ def rate_limit(max, options)
11
+ rate_limits << Limit.build(max, controller_path, {
12
+ if: options[:if],
13
+ unless: options[:unless],
14
+ every: options[:every],
15
+ name: options[:name] || controller_path,
16
+ scope: options[:scope] || -> { real_ip },
17
+ only: options[:only] || [],
18
+ except: options[:except] || [],
19
+ clear_if: options[:clear_if]
18
20
  })
19
21
 
20
22
  before_action :perform_rate_limiting
23
+ after_action :clear_keys
21
24
  end
22
25
 
23
26
  def rate_limits
@@ -41,6 +44,20 @@ module ActionController
41
44
  render file: 'public/429.html', status: :too_many_requests, layout: false
42
45
  end
43
46
 
47
+ def clear_keys
48
+ rate_limits = self.class.all_rate_limits.filter(&:clear_if_present?)
49
+ return if rate_limits.empty?
50
+
51
+ rate_limits.each do |rate_limit|
52
+ should_clear = rate_limit.clear_if.is_a?(Proc) ? instance_exec(&rate_limit.clear_if) : send(rate_limit.clear_if)
53
+ next unless should_clear
54
+
55
+ scope = rate_limit.scope.is_a?(Proc) ? instance_exec(&rate_limit.scope) : send(rate_limit.scope)
56
+ scope = scope.to_param if scope.respond_to?(:to_param)
57
+ ::BetterRateLimit::Throttle.clear(rate_limit.key(scope))
58
+ end
59
+ end
60
+
44
61
  private
45
62
 
46
63
  def json?
@@ -52,7 +69,17 @@ module ActionController
52
69
  end
53
70
 
54
71
  def under_rate_limit?(limit)
55
- if limit.controller_path == controller_path
72
+ if limit.has_if_condition?
73
+ if_condition = limit._if.is_a?(Proc) ? instance_exec(&limit._if) : send(limit._if)
74
+ return true unless if_condition
75
+ end
76
+
77
+ if limit.has_unless_condition?
78
+ unless_condition = limit._unless.is_a?(Proc) ? instance_exec(&limit._unless) : send(limit._unless)
79
+ return true if unless_condition
80
+ end
81
+
82
+ if limit.controller_path_is?(controller_path)
56
83
  return true if action_name.to_sym.in?([limit.except].flatten)
57
84
  return true if !limit.only.empty? && !action_name.to_sym.in?([limit.only].flatten)
58
85
  end
@@ -60,9 +87,7 @@ module ActionController
60
87
  scope = limit.scope.is_a?(Proc) ? instance_exec(&limit.scope) : send(limit.scope)
61
88
  scope = scope.to_param if scope.respond_to?(:to_param)
62
89
 
63
- key = ['controller_throttle', limit.name, limit.max, limit.every, scope].join(':')
64
-
65
- ::BetterRateLimit::Throttle.allow? key, limit: limit.max, time_window: limit.every
90
+ ::BetterRateLimit::Throttle.allow? limit.key(scope), limit: limit.max, time_window: limit.every
66
91
  end
67
92
  end
68
93
  end
@@ -0,0 +1,71 @@
1
+ class Limit
2
+ def self.build(max, controller_path, options)
3
+ options.assert_valid_keys(:if, :unless, :every, :name, :scope, :only, :except, :clear_if)
4
+ new(max, controller_path, {
5
+ if: options[:if],
6
+ unless: options[:unless],
7
+ every: options[:every],
8
+ name: options[:name],
9
+ scope: options[:scope],
10
+ only: options[:only],
11
+ except: options[:except],
12
+ clear_if: options[:clear_if]
13
+ })
14
+ end
15
+
16
+ attr_reader :max, :controller_path
17
+
18
+ def initialize(max, controller_path, options)
19
+ @max = max
20
+ @controller_path = controller_path
21
+ @options = options
22
+ end
23
+
24
+ def _if
25
+ @options[:if]
26
+ end
27
+
28
+ def name
29
+ @options[:name]
30
+ end
31
+
32
+ def every
33
+ @options[:every]
34
+ end
35
+
36
+ def _unless
37
+ @options[:unless]
38
+ end
39
+
40
+ def except
41
+ @options[:except]
42
+ end
43
+
44
+ def only
45
+ @options[:only]
46
+ end
47
+
48
+ def scope
49
+ @options[:scope]
50
+ end
51
+
52
+ def clear_if_present?
53
+ @options[:clear_if].present?
54
+ end
55
+
56
+ def has_if_condition?
57
+ _if.present?
58
+ end
59
+
60
+ def has_unless_condition?
61
+ _unless.present?
62
+ end
63
+
64
+ def controller_path_is?(controller_path)
65
+ self.controller_path == controller_path
66
+ end
67
+
68
+ def key(key_scope)
69
+ ['controller_throttle', name, max, every, key_scope].join(':')
70
+ end
71
+ end
@@ -37,6 +37,11 @@ module BetterRateLimit
37
37
  end
38
38
  end
39
39
 
40
+ def clear(key)
41
+ redis_client.del(key)
42
+ redis_client.del("failing-rate-limits:#{key}")
43
+ end
44
+
40
45
  alias allow? throttle
41
46
 
42
47
  def notify(key)
@@ -1,3 +1,3 @@
1
1
  module BetterRateLimit
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.3"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: better_rate_limit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pablo Fonseca
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2020-08-10 00:00:00.000000000 Z
12
+ date: 2021-02-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: redis
@@ -58,6 +58,7 @@ files:
58
58
  - bin/setup
59
59
  - lib/action_controller/better_rate_limit.rb
60
60
  - lib/better_rate_limit.rb
61
+ - lib/better_rate_limit/limit.rb
61
62
  - lib/better_rate_limit/redis_connection.rb
62
63
  - lib/better_rate_limit/throttle.rb
63
64
  - lib/better_rate_limit/version.rb
@@ -82,7 +83,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
82
83
  - !ruby/object:Gem::Version
83
84
  version: '0'
84
85
  requirements: []
85
- rubygems_version: 3.1.4
86
+ rubygems_version: 3.0.8
86
87
  signing_key:
87
88
  specification_version: 4
88
89
  summary: Rate limit requests