hanami-controller 2.3.0.beta2 → 2.3.1
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 +59 -0
- data/README.md +2 -5
- data/hanami-controller.gemspec +3 -4
- data/lib/hanami/action/config.rb +5 -1
- data/lib/hanami/action/csrf_protection.rb +16 -5
- data/lib/hanami/action.rb +9 -2
- data/lib/hanami/controller/version.rb +1 -1
- data/lib/hanami/http/status.rb +4 -1
- metadata +5 -25
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8fe7ba06a133967bb3119f5a4cacd11507d7e0b658dc446088bbb5fbe5f6e109
|
|
4
|
+
data.tar.gz: e86ac135385c01b1da0c9d5c87a461dbc743812ab2b1f0bc44ba347cc7685453
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 74acf00dfb30458595a50e87cb3544be5c181941ac4e94be1e89fc70b02132ec0b41947fb827ee9706a1a1d88f2206f8ce6d0c9eccf50c39ce0a22017f04940b
|
|
7
|
+
data.tar.gz: 283d12b473fac98a5538ef116ac9b7ccc3174d1abeff2c5054a45033a8219f7d0d9c857891221ec93a15b2b54bd4e781b498bcdefc0c7872f3ca2b717cbbe958
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,65 @@
|
|
|
2
2
|
|
|
3
3
|
Complete, fast and testable actions for Rack
|
|
4
4
|
|
|
5
|
+
## [Unreleased]
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
### Deprecated
|
|
12
|
+
|
|
13
|
+
### Removed
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
### Security
|
|
18
|
+
|
|
19
|
+
[Unreleased]: https://github.com/hanami/hanami-controller/compare/v2.3.1...main
|
|
20
|
+
|
|
21
|
+
## [2.3.1] - 2025-12-06
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
- Allow `handle_exception` to receive multiple class names as strings. (@sidane in #495)
|
|
26
|
+
|
|
27
|
+
```ruby
|
|
28
|
+
class MyAction < Hanami::Action
|
|
29
|
+
config.handle_exception(
|
|
30
|
+
"MyException" => 500,
|
|
31
|
+
"MyOtherException" => 501
|
|
32
|
+
)
|
|
33
|
+
end
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
[2.3.1]: https://github.com/hanami/hanami-controller/compare/v2.3.0...v2.3.1
|
|
37
|
+
|
|
38
|
+
## v2.3.0 - 2025-11-12
|
|
39
|
+
|
|
40
|
+
### Added
|
|
41
|
+
|
|
42
|
+
- Fetch CSRF tokens from `X-CSRF-Token` request header, in addition to body params. (@masterT in #422)
|
|
43
|
+
|
|
44
|
+
### Changed
|
|
45
|
+
|
|
46
|
+
- Allow `config.handle_exception` to receive an exception class name as a string. (@mathewdbutton in #488)
|
|
47
|
+
|
|
48
|
+
This allows you to handle exceptions in your actions without having to require the Ruby files that define the exception constants, which is often awkward if those exceptions come from far-removed layers of your app.
|
|
49
|
+
|
|
50
|
+
```ruby
|
|
51
|
+
class MyAction < Hanami::Action
|
|
52
|
+
config.handle_exception "ROM::TupleCountMismatchError" => 404
|
|
53
|
+
end
|
|
54
|
+
```
|
|
55
|
+
- Allow both `:unprocessable_entity` and `:unprocessable_content` and to be used to refer to the 422 HTTP status code (Rack v3 dropped the former and replaced it with the latter). (@alassek in #490)
|
|
56
|
+
|
|
57
|
+
```ruby
|
|
58
|
+
def handle(request, response)
|
|
59
|
+
# Or :unprocessable_content, both work, on all Rack versions
|
|
60
|
+
response.status = :unprocessable_entity
|
|
61
|
+
end
|
|
62
|
+
```
|
|
63
|
+
|
|
5
64
|
## v2.3.0.beta2 - 2025-10-17
|
|
6
65
|
|
|
7
66
|
### Added
|
data/README.md
CHANGED
|
@@ -5,9 +5,8 @@ Complete, fast, and testable actions for Rack and [Hanami](http://hanamirb.org)
|
|
|
5
5
|
## Status
|
|
6
6
|
|
|
7
7
|
[](https://badge.fury.io/rb/hanami-controller)
|
|
8
|
-
[](https://github.com/hanami/controller/actions?query=workflow%3Aci+branch%3Amain)
|
|
9
|
-
[](https://codecov.io/gh/hanami/controller)
|
|
10
|
-
[](https://depfu.com/github/hanami/controller?project=Bundler)
|
|
8
|
+
[](https://github.com/hanami/hanami-controller/actions?query=workflow%3Aci+branch%3Amain)
|
|
9
|
+
[](https://codecov.io/gh/hanami/hanami-controller)
|
|
11
10
|
|
|
12
11
|
## Contact
|
|
13
12
|
|
|
@@ -21,8 +20,6 @@ Complete, fast, and testable actions for Rack and [Hanami](http://hanamirb.org)
|
|
|
21
20
|
|
|
22
21
|
## Installation
|
|
23
22
|
|
|
24
|
-
__Hanami::Controller__ supports Ruby (MRI) 3.1+
|
|
25
|
-
|
|
26
23
|
Add this line to your application's Gemfile:
|
|
27
24
|
|
|
28
25
|
```ruby
|
data/hanami-controller.gemspec
CHANGED
|
@@ -7,8 +7,8 @@ require "hanami/controller/version"
|
|
|
7
7
|
Gem::Specification.new do |spec|
|
|
8
8
|
spec.name = "hanami-controller"
|
|
9
9
|
spec.version = Hanami::Controller::VERSION
|
|
10
|
-
spec.authors = ["
|
|
11
|
-
spec.email = ["
|
|
10
|
+
spec.authors = ["Hanakai team"]
|
|
11
|
+
spec.email = ["info@hanakai.org"]
|
|
12
12
|
spec.description = "Complete, fast and testable actions for Rack"
|
|
13
13
|
spec.summary = "Complete, fast and testable actions for Rack and Hanami"
|
|
14
14
|
spec.homepage = "http://hanamirb.org"
|
|
@@ -21,12 +21,11 @@ Gem::Specification.new do |spec|
|
|
|
21
21
|
spec.required_ruby_version = ">= 3.2"
|
|
22
22
|
|
|
23
23
|
spec.add_dependency "rack", ">= 2.1"
|
|
24
|
-
spec.add_dependency "hanami-utils", "~> 2.3.0
|
|
24
|
+
spec.add_dependency "hanami-utils", "~> 2.3.0"
|
|
25
25
|
spec.add_dependency "dry-configurable", "~> 1.0", "< 2"
|
|
26
26
|
spec.add_dependency "dry-core", "~> 1.0"
|
|
27
27
|
spec.add_dependency "zeitwerk", "~> 2.6"
|
|
28
28
|
|
|
29
|
-
spec.add_development_dependency "bundler", ">= 1.6", "< 3"
|
|
30
29
|
spec.add_development_dependency "rack-test", "~> 2.0"
|
|
31
30
|
spec.add_development_dependency "rake", "~> 13"
|
|
32
31
|
spec.add_development_dependency "rspec", "~> 3.9"
|
data/lib/hanami/action/config.rb
CHANGED
|
@@ -54,7 +54,11 @@ module Hanami
|
|
|
54
54
|
def handle_exception(exceptions)
|
|
55
55
|
self.handled_exceptions = handled_exceptions
|
|
56
56
|
.merge(exceptions)
|
|
57
|
-
.sort
|
|
57
|
+
.sort do |(ex1, _), (ex2, _)|
|
|
58
|
+
next 0 if [ex1, ex2].any?(String)
|
|
59
|
+
|
|
60
|
+
ex1.ancestors.include?(ex2) ? -1 : 1
|
|
61
|
+
end
|
|
58
62
|
.to_h
|
|
59
63
|
end
|
|
60
64
|
|
|
@@ -13,10 +13,11 @@ module Hanami
|
|
|
13
13
|
# This security mechanism is enabled automatically if sessions are turned on.
|
|
14
14
|
#
|
|
15
15
|
# It stores a "challenge" token in session. For each "state changing request"
|
|
16
|
-
# (eg. <tt>POST</tt>, <tt>PATCH</tt> etc..), we should send a special param
|
|
17
|
-
# <tt>_csrf_token</tt
|
|
16
|
+
# (eg. <tt>POST</tt>, <tt>PATCH</tt> etc..), we should send a special param
|
|
17
|
+
# <tt>_csrf_token</tt> or header <tt>X-CSRF-Token</tt> which contain the "challenge"
|
|
18
|
+
# token.
|
|
18
19
|
#
|
|
19
|
-
# If the
|
|
20
|
+
# If the request token matches with the challenge token, the flow can continue.
|
|
20
21
|
# Otherwise the application detects an attack attempt, it reset the session
|
|
21
22
|
# and <tt>Hanami::Action::InvalidCSRFTokenError</tt> is raised.
|
|
22
23
|
#
|
|
@@ -107,6 +108,16 @@ module Hanami
|
|
|
107
108
|
res.session[CSRF_TOKEN] ||= generate_csrf_token
|
|
108
109
|
end
|
|
109
110
|
|
|
111
|
+
# Get CSRF Token in request.
|
|
112
|
+
#
|
|
113
|
+
# Retreives the CSRF token from the request param <tt>_csrf_token</tt> or the request header
|
|
114
|
+
# <tt>X-CSRF-Token</tt>.
|
|
115
|
+
#
|
|
116
|
+
# @api private
|
|
117
|
+
def request_csrf_token(req)
|
|
118
|
+
req.params.raw[CSRF_TOKEN.to_s] || req.get_header("HTTP_X_CSRF_TOKEN")
|
|
119
|
+
end
|
|
120
|
+
|
|
110
121
|
# Verify if CSRF token from params, matches the one stored in session.
|
|
111
122
|
# If not, it raises an error.
|
|
112
123
|
#
|
|
@@ -131,14 +142,14 @@ module Hanami
|
|
|
131
142
|
return false unless verify_csrf_token?(req, res)
|
|
132
143
|
|
|
133
144
|
missing_csrf_token?(req, res) ||
|
|
134
|
-
!::Rack::Utils.secure_compare(req.session[CSRF_TOKEN], req
|
|
145
|
+
!::Rack::Utils.secure_compare(req.session[CSRF_TOKEN], request_csrf_token(req))
|
|
135
146
|
end
|
|
136
147
|
|
|
137
148
|
# Verify the CSRF token was passed in params.
|
|
138
149
|
#
|
|
139
150
|
# @api private
|
|
140
151
|
def missing_csrf_token?(req, *)
|
|
141
|
-
Hanami::Utils::Blank.blank?(req
|
|
152
|
+
Hanami::Utils::Blank.blank?(request_csrf_token(req))
|
|
142
153
|
end
|
|
143
154
|
|
|
144
155
|
# Generates a random CSRF Token
|
data/lib/hanami/action.rb
CHANGED
|
@@ -373,13 +373,15 @@ module Hanami
|
|
|
373
373
|
# Otherwise, it sets the response body with the default message associated
|
|
374
374
|
# to the code (eg 404 will set `"Not Found"`).
|
|
375
375
|
#
|
|
376
|
-
# @param status [
|
|
376
|
+
# @param status [Integer, Symbol] A valid HTTP status code or a symbol representing the HTTP status code
|
|
377
377
|
# @param body [String] the response body
|
|
378
378
|
#
|
|
379
379
|
# @raise [StandardError] if the code isn't valid
|
|
380
380
|
#
|
|
381
381
|
# @since 0.2.0
|
|
382
382
|
#
|
|
383
|
+
# @see https://hanakai.org/learn/hanami/actions/status-codes List of status codes and symbols
|
|
384
|
+
#
|
|
383
385
|
# @see Hanami::Action::Throwable#handle_exception
|
|
384
386
|
# @see Hanami::Http::Status:ALL
|
|
385
387
|
#
|
|
@@ -433,7 +435,12 @@ module Hanami
|
|
|
433
435
|
# @api private
|
|
434
436
|
def exception_handler(exception)
|
|
435
437
|
config.handled_exceptions.each do |exception_class, handler|
|
|
436
|
-
|
|
438
|
+
case exception_class
|
|
439
|
+
when String
|
|
440
|
+
return handler if exception.class.name == exception_class # rubocop:disable Style/ClassEqualityComparison
|
|
441
|
+
else
|
|
442
|
+
return handler if exception.is_a?(exception_class)
|
|
443
|
+
end
|
|
437
444
|
end
|
|
438
445
|
|
|
439
446
|
nil
|
data/lib/hanami/http/status.rb
CHANGED
|
@@ -21,7 +21,10 @@ module Hanami
|
|
|
21
21
|
#
|
|
22
22
|
# @since 2.0.2
|
|
23
23
|
# @api private
|
|
24
|
-
SYMBOLS = ::Rack::Utils::SYMBOL_TO_STATUS_CODE
|
|
24
|
+
SYMBOLS = ::Rack::Utils::SYMBOL_TO_STATUS_CODE.merge(
|
|
25
|
+
unprocessable_content: 422,
|
|
26
|
+
unprocessable_entity: 422
|
|
27
|
+
)
|
|
25
28
|
|
|
26
29
|
# Return a status for the given code
|
|
27
30
|
#
|
metadata
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: hanami-controller
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.3.
|
|
4
|
+
version: 2.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
|
-
-
|
|
7
|
+
- Hanakai team
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
@@ -29,14 +29,14 @@ dependencies:
|
|
|
29
29
|
requirements:
|
|
30
30
|
- - "~>"
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: 2.3.0
|
|
32
|
+
version: 2.3.0
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
36
|
requirements:
|
|
37
37
|
- - "~>"
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: 2.3.0
|
|
39
|
+
version: 2.3.0
|
|
40
40
|
- !ruby/object:Gem::Dependency
|
|
41
41
|
name: dry-configurable
|
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -85,26 +85,6 @@ dependencies:
|
|
|
85
85
|
- - "~>"
|
|
86
86
|
- !ruby/object:Gem::Version
|
|
87
87
|
version: '2.6'
|
|
88
|
-
- !ruby/object:Gem::Dependency
|
|
89
|
-
name: bundler
|
|
90
|
-
requirement: !ruby/object:Gem::Requirement
|
|
91
|
-
requirements:
|
|
92
|
-
- - ">="
|
|
93
|
-
- !ruby/object:Gem::Version
|
|
94
|
-
version: '1.6'
|
|
95
|
-
- - "<"
|
|
96
|
-
- !ruby/object:Gem::Version
|
|
97
|
-
version: '3'
|
|
98
|
-
type: :development
|
|
99
|
-
prerelease: false
|
|
100
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
101
|
-
requirements:
|
|
102
|
-
- - ">="
|
|
103
|
-
- !ruby/object:Gem::Version
|
|
104
|
-
version: '1.6'
|
|
105
|
-
- - "<"
|
|
106
|
-
- !ruby/object:Gem::Version
|
|
107
|
-
version: '3'
|
|
108
88
|
- !ruby/object:Gem::Dependency
|
|
109
89
|
name: rack-test
|
|
110
90
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -163,7 +143,7 @@ dependencies:
|
|
|
163
143
|
version: '1.0'
|
|
164
144
|
description: Complete, fast and testable actions for Rack
|
|
165
145
|
email:
|
|
166
|
-
-
|
|
146
|
+
- info@hanakai.org
|
|
167
147
|
executables: []
|
|
168
148
|
extensions: []
|
|
169
149
|
extra_rdoc_files: []
|