action_ip_filter 0.4.0 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dd87d049abbc429bef20f3c4d684efd1f94a97cf9758603e6a404ecc97c487c0
4
- data.tar.gz: 1460f97edeb6ddd39c71190ec07d866c3bc473818ab2ae852624a034027b1d7d
3
+ metadata.gz: ca72b3ded0f28fecbd905a3d92b1314627bd03347b04a8a5e6e51b37f7bfe74e
4
+ data.tar.gz: a6fbe7fb5cf0007863049a618a6ac0668ff302a577ed3a4932ea2ef313200c54
5
5
  SHA512:
6
- metadata.gz: 7e279fadffc67defc41e2447f985780fc0332022a1bce62de27b065f9e715bbf18d173f8c87aa72780d2b8b91b743d45130608235f0b6d7c42cdfa24b699518e
7
- data.tar.gz: e2918f5170516b232838a516e0ddf7c80f81cd5ef7c9359a1c07820e9ec96d1a8d91f9579824df7b535b24064596cd0da2e1d046db63146a4d3c524eeea9c0cb
6
+ metadata.gz: dd7422ec80a6fe13148db4daf70a16657416d6c4b1f13b4699851c8996d42434d60d15c7ba341b4f652ff0775d546c3deb3918b2f8c2ea8b61b97a2040486009
7
+ data.tar.gz: 0773de5c419cdde2693ca64575347df64b4b79647fa34d52d5293c90f0e285f8adc544e20e998d8227356f62c6da68e5a2e1e1a8859485ee5d2af19d5745ee9e
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.5.0] - 2025-12-02
4
+
5
+ ### New Features
6
+
7
+ - Make `log_denial_message` configurable [#9](https://github.com/smartbank-inc/action_ip_filter/pull/9)
8
+
9
+ ## [0.4.1] - 2025-12-01
10
+
11
+ ### Bug Fix
12
+
13
+ - Fix to allow an `Array[String]` to be used as the list of allowed IP addresses [#7](https://github.com/smartbank-inc/action_ip_filter/pull/7)
14
+
3
15
  ## [0.4.0] - 2025-12-01
4
16
 
5
17
  ### Breaking Changes
data/README.md CHANGED
@@ -6,12 +6,12 @@ A lightweight gem that provides IP address restrictions for Rails controllers at
6
6
 
7
7
  Unlike Rack middleware solutions (e.g., `rack-attack`), action_ip_filter operates at the controller level:
8
8
 
9
- | Feature | rack-attack | action_ip_filter |
10
- |---------|-------------|----------------|
11
- | Layer | Rack middleware (all requests) | Controller before_action |
12
- | Granularity | Path/IP based | Controller/Action based |
13
- | Overhead | Every request evaluated | Only specified actions |
14
- | Use case | DDoS protection, rate limiting | Admin panels, webhooks |
9
+ | Feature | rack-attack | action_ip_filter |
10
+ |-------------|--------------------------------|--------------------------|
11
+ | Layer | Rack middleware (all requests) | Controller before_action |
12
+ | Granularity | Path/IP based | Controller/Action based |
13
+ | Overhead | Every request evaluated | Only specified actions |
14
+ | Use case | DDoS protection, rate limiting | Admin panels, webhooks |
15
15
 
16
16
  **Use this gem when you need:**
17
17
  - IP restrictions on specific controller actions only
@@ -177,17 +177,36 @@ ActionIpFilter.configure do |config|
177
177
 
178
178
  # Enable/disable denial logging (default: true)
179
179
  config.log_denials = true
180
+
181
+ # Logging on denied
182
+ # It passes `config.logger` as the first argument (logger) and the actual client IP address as the second argument (client_ip).
183
+ config.log_denial_message = ->(logger, client_ip) {
184
+ logger.error("Blocked IP: #{client_ip}")
185
+ }
180
186
  end
181
187
  ```
182
188
 
183
189
  ### Default Values
184
190
 
185
- | Option | Default | Description |
186
- |--------|-------------------------------------|----------------------------------------------------|
187
- | `ip_resolver` | `-> { request.remote_ip }` | Proc that extracts client IP from request |
188
- | `on_denied` | `-> { head :forbidden }` | Handler called when access is denied (returns 403) |
189
- | `logger` | `Rails.logger` | Logger instance for denied request logging |
190
- | `log_denials` | `true` | Whether to log denied requests as warn level |
191
+ | Option | Default | Description |
192
+ |----------------------|----------------------------|----------------------------------------------------|
193
+ | `ip_resolver` | `-> { request.remote_ip }` | Proc that extracts client IP from request |
194
+ | `on_denied` | `-> { head :forbidden }` | Handler called when access is denied (returns 403) |
195
+ | `logger` | `Rails.logger` | Logger instance for denied request logging |
196
+ | `log_denials` | `true` | Whether to log denied requests as warn level |
197
+ | `log_denial_message` | See below | Proc that formats the denial log message |
198
+
199
+ The default `log_denial_message` is:
200
+
201
+ ```ruby
202
+ ->(logger, client_ip) {
203
+ logger.warn("[ActionIpFilter] Access denied for IP: #{client_ip} on #{self.class.name}##{action_name}")
204
+ }
205
+ ```
206
+
207
+ ### Note on the configurable Proc block
208
+
209
+ The block is executed via `instance_exec` in the controller context, so you may call controller methods such as `request`, `head`, `render`, and others.
191
210
 
192
211
  ## Testing
193
212
 
@@ -6,18 +6,33 @@ module ActionIpFilter
6
6
  # @rbs @on_denied: ^() -> void
7
7
  # @rbs @logger: Logger?
8
8
  # @rbs @log_denials: bool
9
+ # @rbs @log_denial_message: ^(Logger, String?) -> void
10
+
11
+ # @rbs!
12
+ # interface _Request
13
+ # def remote_ip: () -> String
14
+ # end
15
+ #
16
+ # def action_name: () -> String
17
+ # def controller_name: () -> String
18
+ # def head: (Symbol) -> void
19
+ # def request: () -> _Request
9
20
 
10
21
  attr_accessor :ip_resolver #: ^() -> String?
11
22
  attr_accessor :on_denied #: ^() -> void
12
23
  attr_accessor :logger #: Logger?
13
24
  attr_accessor :log_denials #: bool
25
+ attr_accessor :log_denial_message #: ^(Logger, String?) -> void
14
26
 
15
27
  # @rbs return: void
16
28
  def initialize
17
- @ip_resolver = -> { request.remote_ip } # steep:ignore NoMethod
18
- @on_denied = -> { head :forbidden } # steep:ignore NoMethod
29
+ @ip_resolver = -> { request.remote_ip }
30
+ @on_denied = -> { head :forbidden }
19
31
  @logger = nil
20
32
  @log_denials = true
33
+ @log_denial_message = ->(logger, client_ip) {
34
+ logger.warn("[ActionIpFilter] Access denied for IP: #{client_ip} on #{self.class.name}##{action_name}")
35
+ }
21
36
  end
22
37
  end
23
38
 
@@ -7,12 +7,12 @@ module ActionIpFilter
7
7
  extend ActiveSupport::Concern
8
8
 
9
9
  # @rbs!
10
- # def action_name: () -> String
11
- # def instance_exec: [T] (*untyped) { () -> T } -> T
10
+ # def instance_exec: [T] () { () -> T } -> T
11
+ # | (Logger, String?) { (Logger, String?) -> void } -> void
12
12
  # def before_action: (*untyped, **untyped) -> void
13
13
 
14
14
  class_methods do
15
- # @rbs allowed_ips: String | ^() -> Array[String]
15
+ # @rbs allowed_ips: String | Array[String] | ^() -> Array[String]
16
16
  # @rbs on_denied: (^() -> void)?
17
17
  # @rbs only: Array[Symbol]?
18
18
  # @rbs except: Array[Symbol]?
@@ -24,7 +24,7 @@ module ActionIpFilter
24
24
 
25
25
  private
26
26
 
27
- # @rbs allowed_ips: Array[String | ^() -> Array[String]]
27
+ # @rbs allowed_ips: Array[String | Array[String] | ^() -> Array[String]]
28
28
  # @rbs on_denied: (^() -> void)?
29
29
  # @rbs return: void
30
30
  def verify_ip_access(allowed_ips:, on_denied:)
@@ -38,7 +38,7 @@ module ActionIpFilter
38
38
  instance_exec(&allowed_ip)
39
39
  else
40
40
  [allowed_ip]
41
- end
41
+ end.flatten
42
42
 
43
43
  IpMatcher.allowed?(client_ip, ips)
44
44
  end
@@ -57,9 +57,10 @@ module ActionIpFilter
57
57
  logger = ActionIpFilter.configuration.logger
58
58
  return if logger.nil?
59
59
 
60
- logger.warn do
61
- "[ActionIpFilter] Access denied for IP: #{client_ip} on #{self.class.name}##{action_name}"
62
- end
60
+ log_denial_message = ActionIpFilter.configuration.log_denial_message
61
+ return if log_denial_message.nil?
62
+
63
+ instance_exec(logger, client_ip, &log_denial_message)
63
64
  end
64
65
  end
65
66
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActionIpFilter
4
- VERSION = "0.4.0" #: String
4
+ VERSION = "0.5.0" #: String
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: action_ip_filter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - SmartBank, Inc.