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 +4 -4
- data/CHANGELOG.md +12 -0
- data/README.md +31 -12
- data/lib/action_ip_filter/configuration.rb +17 -2
- data/lib/action_ip_filter/ip_filterable.rb +9 -8
- data/lib/action_ip_filter/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ca72b3ded0f28fecbd905a3d92b1314627bd03347b04a8a5e6e51b37f7bfe74e
|
|
4
|
+
data.tar.gz: a6fbe7fb5cf0007863049a618a6ac0668ff302a577ed3a4932ea2ef313200c54
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
|
10
|
-
|
|
11
|
-
| Layer
|
|
12
|
-
| Granularity | Path/IP based
|
|
13
|
-
| Overhead
|
|
14
|
-
| Use case
|
|
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
|
|
186
|
-
|
|
187
|
-
| `ip_resolver`
|
|
188
|
-
| `on_denied`
|
|
189
|
-
| `logger`
|
|
190
|
-
| `log_denials`
|
|
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 }
|
|
18
|
-
@on_denied = -> { head :forbidden }
|
|
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
|
|
11
|
-
#
|
|
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
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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
|