hanami 2.2.0 → 2.3.0.beta1

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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +47 -1
  3. data/README.md +20 -35
  4. data/hanami.gemspec +3 -2
  5. data/lib/hanami/app.rb +2 -0
  6. data/lib/hanami/config/actions/content_security_policy.rb +23 -0
  7. data/lib/hanami/config/actions.rb +21 -0
  8. data/lib/hanami/config/console.rb +79 -0
  9. data/lib/hanami/config/logger.rb +1 -1
  10. data/lib/hanami/config.rb +13 -0
  11. data/lib/hanami/constants.rb +3 -0
  12. data/lib/hanami/extensions/db/repo.rb +11 -6
  13. data/lib/hanami/extensions/operation.rb +1 -1
  14. data/lib/hanami/extensions/view/context.rb +10 -0
  15. data/lib/hanami/helpers/assets_helper.rb +92 -25
  16. data/lib/hanami/middleware/content_security_policy_nonce.rb +53 -0
  17. data/lib/hanami/slice.rb +22 -6
  18. data/lib/hanami/slice_registrar.rb +1 -1
  19. data/lib/hanami/version.rb +1 -1
  20. data/lib/hanami.rb +10 -2
  21. data/spec/integration/assets/cross_slice_assets_helpers_spec.rb +0 -1
  22. data/spec/integration/assets/serve_static_assets_spec.rb +1 -1
  23. data/spec/integration/container/autoloader_spec.rb +2 -0
  24. data/spec/integration/db/db_spec.rb +1 -1
  25. data/spec/integration/db/logging_spec.rb +63 -0
  26. data/spec/integration/db/repo_spec.rb +87 -2
  27. data/spec/integration/logging/exception_logging_spec.rb +6 -1
  28. data/spec/integration/rack_app/middleware_spec.rb +4 -11
  29. data/spec/integration/view/helpers/form_helper_spec.rb +1 -1
  30. data/spec/integration/web/content_security_policy_nonce_spec.rb +251 -0
  31. data/spec/support/app_integration.rb +2 -1
  32. data/spec/unit/hanami/config/actions/content_security_policy_spec.rb +7 -0
  33. data/spec/unit/hanami/config/console_spec.rb +22 -0
  34. data/spec/unit/hanami/env_spec.rb +10 -13
  35. data/spec/unit/hanami/slice_spec.rb +18 -0
  36. data/spec/unit/hanami/version_spec.rb +1 -1
  37. data/spec/unit/hanami/web/rack_logger_spec.rb +11 -4
  38. metadata +27 -18
  39. data/spec/support/shared_examples/cli/generate/app.rb +0 -494
  40. data/spec/support/shared_examples/cli/generate/migration.rb +0 -32
  41. data/spec/support/shared_examples/cli/generate/model.rb +0 -81
  42. data/spec/support/shared_examples/cli/new.rb +0 -97
@@ -507,7 +507,7 @@ RSpec.describe "Hanami web app", :app_integration do
507
507
  write "lib/test_app/middleware/api_version.rb", <<~RUBY
508
508
  module TestApp
509
509
  module Middleware
510
- class ApiVersion
510
+ class APIVersion
511
511
  def self.inspect
512
512
  "<Middleware::API::Version>"
513
513
  end
@@ -530,7 +530,7 @@ RSpec.describe "Hanami web app", :app_integration do
530
530
  write "lib/test_app/middleware/api_deprecation.rb", <<~RUBY
531
531
  module TestApp
532
532
  module Middleware
533
- class ApiDeprecation
533
+ class APIDeprecation
534
534
  def self.inspect
535
535
  "<Middleware::API::Deprecation>"
536
536
  end
@@ -578,13 +578,6 @@ RSpec.describe "Hanami web app", :app_integration do
578
578
  RUBY
579
579
 
580
580
  write "config/routes.rb", <<~RUBY
581
- require "test_app/middleware/elapsed"
582
- require "test_app/middleware/authentication"
583
- require "test_app/middleware/rate_limiter"
584
- require "test_app/middleware/api_version"
585
- require "test_app/middleware/api_deprecation"
586
- require "test_app/middleware/scope_identifier"
587
-
588
581
  module TestApp
589
582
  class Routes < Hanami::Routes
590
583
  use TestApp::Middleware::Elapsed
@@ -609,8 +602,8 @@ RSpec.describe "Hanami web app", :app_integration do
609
602
  root to: ->(*) { [200, {"Content-Length" => "3"}, ["API"]] }
610
603
 
611
604
  slice :api_v1, at: "/v1" do
612
- use TestApp::Middleware::ApiVersion
613
- use TestApp::Middleware::ApiDeprecation
605
+ use TestApp::Middleware::APIVersion
606
+ use TestApp::Middleware::APIDeprecation
614
607
  use TestApp::Middleware::ScopeIdentifier, "API-V1"
615
608
 
616
609
  root to: "home.show"
@@ -156,7 +156,7 @@ RSpec.describe "Helpers / FormHelper", :app_integration do
156
156
  module TestApp
157
157
  class App < Hanami::App
158
158
  config.logger.stream = StringIO.new
159
- config.actions.sessions = :cookie, {secret: "xyz"}
159
+ config.actions.sessions = :cookie, {secret: "wxyz"*16} # Rack demands >=64 characters
160
160
  end
161
161
  end
162
162
  RUBY
@@ -0,0 +1,251 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rack/test"
4
+
5
+ RSpec.describe "Web / Content security policy nonce", :app_integration do
6
+ include Rack::Test::Methods
7
+
8
+ let(:app) { Hanami.app }
9
+
10
+ before do
11
+ with_directory(@dir = make_tmp_directory) do
12
+ write "config/routes.rb", <<~RUBY
13
+ module TestApp
14
+ class Routes < Hanami::Routes
15
+ get "index", to: "index"
16
+ end
17
+ end
18
+ RUBY
19
+
20
+ write "app/actions/index.rb", <<~RUBY
21
+ module TestApp
22
+ module Actions
23
+ class Index < Hanami::Action
24
+ end
25
+ end
26
+ end
27
+ RUBY
28
+
29
+ write "app/views/index.rb", <<~RUBY
30
+ module TestApp
31
+ module Views
32
+ class Index < Hanami::View
33
+ config.layout = false
34
+ end
35
+ end
36
+ end
37
+ RUBY
38
+
39
+ write "app/templates/index.html.erb", <<~HTML
40
+ <!DOCTYPE html>
41
+ <html lang="en">
42
+ <head>
43
+ <%= stylesheet_tag "app", class: "nonce-true", nonce: true %>
44
+ <%= stylesheet_tag "app", class: "nonce-false", nonce: false %>
45
+ <%= stylesheet_tag "app", class: "nonce-explicit", nonce: "explicit" %>
46
+ <%= stylesheet_tag "app", class: "nonce-generated" %>
47
+ <%= stylesheet_tag "https://example.com/app.css", class: "nonce-absolute" %>
48
+ </head>
49
+ <body>
50
+ <style nonce="<%= content_security_policy_nonce %>"></style>
51
+ <%= javascript_tag "app", class: "nonce-true", nonce: true %>
52
+ <%= javascript_tag "app", class: "nonce-false", nonce: false %>
53
+ <%= javascript_tag "app", class: "nonce-explicit", nonce: "explicit" %>
54
+ <%= javascript_tag "app", class: "nonce-generated" %>
55
+ <%= javascript_tag "https://example.com/app.js", class: "nonce-absolute" %>
56
+ </body>
57
+ </html>
58
+ HTML
59
+
60
+ write "package.json", <<~JSON
61
+ {
62
+ "type": "module"
63
+ }
64
+ JSON
65
+
66
+ write "config/assets.js", <<~JS
67
+ import * as assets from "hanami-assets";
68
+ await assets.run();
69
+ JS
70
+
71
+ write "app/assets/js/app.js", <<~JS
72
+ import "../css/app.css";
73
+ JS
74
+
75
+ write "app/assets/css/app.css", ""
76
+
77
+ before_prepare if respond_to?(:before_prepare)
78
+ require "hanami/prepare"
79
+ compile_assets!
80
+ end
81
+ end
82
+
83
+ describe "HTML request" do
84
+ context "CSP enabled" do
85
+ def before_prepare
86
+ write "config/app.rb", <<~RUBY
87
+ require "hanami"
88
+
89
+ module TestApp
90
+ class App < Hanami::App
91
+ config.actions.content_security_policy[:script_src] = "'self' 'nonce'"
92
+
93
+ config.logger.stream = File::NULL
94
+ end
95
+ end
96
+ RUBY
97
+ end
98
+
99
+ it "sets unique and per-request hanami.content_security_policy_nonce in Rack env" do
100
+ previous_nonces = []
101
+ 3.times do
102
+ get "/index"
103
+ nonce = last_request.env["hanami.content_security_policy_nonce"]
104
+
105
+ expect(nonce).to match(/\A[A-Za-z0-9\-_]{22}\z/)
106
+ expect(previous_nonces).not_to include nonce
107
+
108
+ previous_nonces << nonce
109
+ end
110
+ end
111
+
112
+ it "accepts custom nonce generator proc without arguments" do
113
+ Hanami.app.config.actions.content_security_policy_nonce_generator = -> { "foobar" }
114
+
115
+ get "/index"
116
+
117
+ expect(last_request.env["hanami.content_security_policy_nonce"]).to eql("foobar")
118
+ end
119
+
120
+ it "accepts custom nonce generator proc with Rack request as argument" do
121
+ Hanami.app.config.actions.content_security_policy_nonce_generator = ->(request) { request }
122
+
123
+ get "/index"
124
+
125
+ expect(last_request.env["hanami.content_security_policy_nonce"]).to be_a(Rack::Request)
126
+ end
127
+
128
+ it "substitutes 'nonce' in the CSP header" do
129
+ get "/index"
130
+ nonce = last_request.env["hanami.content_security_policy_nonce"]
131
+
132
+ expect(last_response.get_header("Content-Security-Policy")).to match(/script-src 'self' 'nonce-#{nonce}'/)
133
+ end
134
+
135
+ it "behaves the same with explicitly added middleware" do
136
+ Hanami.app.config.middleware.use Hanami::Middleware::ContentSecurityPolicyNonce
137
+ get "/index"
138
+
139
+ expect(last_request.env["hanami.content_security_policy_nonce"]).to match(/\A[A-Za-z0-9\-_]{22}\z/)
140
+ end
141
+
142
+ describe "content_security_policy_nonce" do
143
+ it "renders the current nonce" do
144
+ get "/index"
145
+ nonce = last_request.env["hanami.content_security_policy_nonce"]
146
+
147
+ expect(last_response.body).to include(%(<style nonce="#{nonce}">))
148
+ end
149
+ end
150
+
151
+ describe "stylesheet_tag" do
152
+ it "renders the correct nonce unless remote URL or nonce set to false" do
153
+ get "/index"
154
+ nonce = last_request.env["hanami.content_security_policy_nonce"]
155
+
156
+ expect(last_response.body).to include(%(<link href="/assets/app-KUHJPSX7.css" type="text/css" rel="stylesheet" nonce="#{nonce}" class="nonce-true">))
157
+ expect(last_response.body).to include(%(<link href="/assets/app-KUHJPSX7.css" type="text/css" rel="stylesheet" class="nonce-false">))
158
+ expect(last_response.body).to include(%(<link href="/assets/app-KUHJPSX7.css" type="text/css" rel="stylesheet" nonce="explicit" class="nonce-explicit">))
159
+ expect(last_response.body).to include(%(<link href="/assets/app-KUHJPSX7.css" type="text/css" rel="stylesheet" nonce="#{nonce}" class="nonce-generated">))
160
+ expect(last_response.body).to include(%(<link href="https://example.com/app.css" type="text/css" rel="stylesheet" class="nonce-absolute">))
161
+ end
162
+ end
163
+
164
+ describe "javascript_tag" do
165
+ it "renders the correct nonce unless remote URL or nonce set to false" do
166
+ get "/index"
167
+ nonce = last_request.env["hanami.content_security_policy_nonce"]
168
+
169
+ expect(last_response.body).to include(%(<script src="/assets/app-LSLFPUMX.js" type="text/javascript" nonce="#{nonce}" class="nonce-true"></script>))
170
+ expect(last_response.body).to include(%(<script src="/assets/app-LSLFPUMX.js" type="text/javascript" class="nonce-false"></script>))
171
+ expect(last_response.body).to include(%(<script src="/assets/app-LSLFPUMX.js" type="text/javascript" nonce="explicit" class="nonce-explicit"></script>))
172
+ expect(last_response.body).to include(%(<script src="/assets/app-LSLFPUMX.js" type="text/javascript" nonce="#{nonce}" class="nonce-generated"></script>))
173
+ expect(last_response.body).to include(%(<script src="https://example.com/app.js" type="text/javascript" class="nonce-absolute"></script>))
174
+ end
175
+ end
176
+ end
177
+
178
+ context "CSP disabled" do
179
+ def before_prepare
180
+ write "config/app.rb", <<~RUBY
181
+ require "hanami"
182
+
183
+ module TestApp
184
+ class App < Hanami::App
185
+ config.actions.content_security_policy = false
186
+
187
+ config.logger.stream = File::NULL
188
+ end
189
+ end
190
+ RUBY
191
+ end
192
+
193
+ it "does not set hanami.content_security_policy_nonce in Rack env" do
194
+ get "/index"
195
+
196
+ expect(last_request.env).to_not have_key "hanami.content_security_policy_nonce"
197
+ end
198
+
199
+ it "does not produce a CSP header" do
200
+ get "/index"
201
+
202
+ expect(last_response.headers).to_not have_key "Content-Security-Policy"
203
+ end
204
+
205
+ it "disables the content_security_policy_nonce helper" do
206
+ get "/index"
207
+
208
+ expect(last_response.body).to match(/<style nonce="">/)
209
+ end
210
+
211
+ it "behaves the same with explicitly added middleware" do
212
+ Hanami.app.config.middleware.use Hanami::Middleware::ContentSecurityPolicyNonce
213
+ get "/index"
214
+
215
+ expect(last_response.headers).to_not have_key "Content-Security-Policy"
216
+ end
217
+
218
+ describe "content_security_policy_nonce" do
219
+ it "renders nothing" do
220
+ get "/index"
221
+
222
+ expect(last_response.body).to include(%(<style nonce="">))
223
+ end
224
+ end
225
+
226
+ describe "stylesheet_tag" do
227
+ it "renders the correct explicit nonce only" do
228
+ get "/index"
229
+
230
+ expect(last_response.body).to include(%(<link href="/assets/app-KUHJPSX7.css" type="text/css" rel="stylesheet" class="nonce-true">))
231
+ expect(last_response.body).to include(%(<link href="/assets/app-KUHJPSX7.css" type="text/css" rel="stylesheet" class="nonce-false">))
232
+ expect(last_response.body).to include(%(<link href="/assets/app-KUHJPSX7.css" type="text/css" rel="stylesheet" nonce="explicit" class="nonce-explicit">))
233
+ expect(last_response.body).to include(%(<link href="/assets/app-KUHJPSX7.css" type="text/css" rel="stylesheet" class="nonce-generated">))
234
+ expect(last_response.body).to include(%(<link href="https://example.com/app.css" type="text/css" rel="stylesheet" class="nonce-absolute">))
235
+ end
236
+ end
237
+
238
+ describe "javascript_tag" do
239
+ it "renders the correct explicit nonce only" do
240
+ get "/index"
241
+
242
+ expect(last_response.body).to include(%(<script src="/assets/app-LSLFPUMX.js" type="text/javascript" class="nonce-true"></script>))
243
+ expect(last_response.body).to include(%(<script src="/assets/app-LSLFPUMX.js" type="text/javascript" class="nonce-false"></script>))
244
+ expect(last_response.body).to include(%(<script src="/assets/app-LSLFPUMX.js" type="text/javascript" nonce="explicit" class="nonce-explicit"></script>))
245
+ expect(last_response.body).to include(%(<script src="/assets/app-LSLFPUMX.js" type="text/javascript" class="nonce-generated"></script>))
246
+ expect(last_response.body).to include(%(<script src="https://example.com/app.js" type="text/javascript" class="nonce-absolute"></script>))
247
+ end
248
+ end
249
+ end
250
+ end
251
+ end
@@ -118,7 +118,8 @@ RSpec.configure do |config|
118
118
  Hanami.instance_variable_set(:@_bundled, {})
119
119
  Hanami.remove_instance_variable(:@_app) if Hanami.instance_variable_defined?(:@_app)
120
120
 
121
- # Clear cached DB gateways across slices
121
+ # Disconnect and clear cached DB gateways across slices
122
+ Hanami::Providers::DB.cache.values.map(&:disconnect)
122
123
  Hanami::Providers::DB.cache.clear
123
124
 
124
125
  $LOAD_PATH.replace(@load_paths)
@@ -28,6 +28,7 @@ RSpec.describe Hanami::Config::Actions, "#content_security_policy" do
28
28
  ].join(";")
29
29
 
30
30
  expect(content_security_policy.to_s).to eq(expected)
31
+ expect(content_security_policy.nonce?).to be(false)
31
32
  end
32
33
  end
33
34
 
@@ -68,6 +69,12 @@ RSpec.describe Hanami::Config::Actions, "#content_security_policy" do
68
69
  expect(content_security_policy[:a_custom_key]).to eq("foo")
69
70
  expect(content_security_policy.to_s).to match("a-custom-key foo")
70
71
  end
72
+
73
+ it "uses 'nonce' in value" do
74
+ content_security_policy[:javascript_src] = "'self' 'nonce'"
75
+
76
+ expect(content_security_policy.nonce?).to be(true)
77
+ end
71
78
  end
72
79
 
73
80
  context "with CSP enabled" do
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami/config"
4
+
5
+ RSpec.describe Hanami::Config, "#console" do
6
+ let(:config) { described_class.new(app_name: app_name, env: :development) }
7
+ let(:app_name) { "MyApp::App" }
8
+
9
+ subject(:console) { config.console }
10
+
11
+ it "is a full console configuration" do
12
+ is_expected.to be_an_instance_of(Hanami::Config::Console)
13
+
14
+ is_expected.to respond_to(:engine)
15
+ is_expected.to respond_to(:include)
16
+ is_expected.to respond_to(:extensions)
17
+ end
18
+
19
+ it "can be finalized" do
20
+ is_expected.to respond_to(:finalize!)
21
+ end
22
+ end
@@ -3,30 +3,27 @@
3
3
  RSpec.describe Hanami, ".env" do
4
4
  subject { described_class.env(e: env) }
5
5
 
6
- context "HANAMI_ENV in ENV" do
7
- let(:env) { {"HANAMI_ENV" => "test"} }
6
+ context "HANAMI_ENV, APP_ENV and RACK_ENV in ENV" do
7
+ let(:env) { { "HANAMI_ENV" => "test", "APP_ENV" => "development", "RACK_ENV" => "production" } }
8
8
 
9
9
  it "is the value of HANAMI_ENV" do
10
10
  is_expected.to eq(:test)
11
11
  end
12
12
  end
13
13
 
14
- context "RACK_ENV in ENV" do
15
- let(:env) { {"HANAMI_ENV" => "test"} }
14
+ context "APP_ENV and RACK_ENV in ENV" do
15
+ let(:env) { {"APP_ENV" => "development", "RACK_ENV" => "production" } }
16
16
 
17
- it "is the value of RACK_ENV" do
18
- is_expected.to eq(:test)
17
+ it "is the value of APP_ENV" do
18
+ is_expected.to eq(:development)
19
19
  end
20
20
  end
21
21
 
22
- context "both HANAMI_ENV and RACK_ENV in ENV" do
23
- let(:env) do
24
- {"HANAMI_ENV" => "test",
25
- "RACK_ENV" => "production"}
26
- end
22
+ context "RACK_ENV in ENV" do
23
+ let(:env) { { "RACK_ENV" => "production" } }
27
24
 
28
- it "is the value of HANAMI_ENV" do
29
- is_expected.to eq(:test)
25
+ it "is the value of RACK_ENV" do
26
+ is_expected.to eq(:production)
30
27
  end
31
28
  end
32
29
 
@@ -65,6 +65,24 @@ RSpec.describe Hanami::Slice, :app_integration do
65
65
  expect { Class.new(described_class).prepare }
66
66
  .to raise_error Hanami::SliceLoadError, /Slice must have a class name/
67
67
  end
68
+
69
+ it "does not allow special characters in slice names" do
70
+ expect { Hanami.app.register_slice(:'test_$lice') }
71
+ .to raise_error(ArgumentError, /must be lowercase alphanumeric text and underscores only/)
72
+ end
73
+
74
+ it "does not allow uppercase characters in slice names" do
75
+ expect { Hanami.app.register_slice(:TEST_slice) }
76
+ .to raise_error(ArgumentError, /must be lowercase alphanumeric text and underscores only/)
77
+ end
78
+
79
+ it "allows lowercase alphanumeric text and underscores only" do
80
+ expect { Hanami.app.register_slice(:test_slice) }.not_to raise_error
81
+ end
82
+
83
+ it "allows single character slice names" do
84
+ expect { Hanami.app.register_slice(:t) }.not_to raise_error
85
+ end
68
86
  end
69
87
 
70
88
  describe ".source_path" do
@@ -2,6 +2,6 @@
2
2
 
3
3
  RSpec.describe "Hanami::VERSION" do
4
4
  it "returns current version" do
5
- expect(Hanami::VERSION).to eq("2.2.0")
5
+ expect(Hanami::VERSION).to eq("2.3.0.beta1")
6
6
  end
7
7
  end
@@ -53,10 +53,17 @@ RSpec.describe Hanami::Web::RackLogger do
53
53
  stream.rewind
54
54
  actual = stream.read
55
55
 
56
- expect(actual).to eql(<<~LOG)
57
- [#{app_name}] [INFO] [#{time}] #{verb} #{status} #{elapsed}µs #{ip} #{path} #{content_length}
58
- {"user"=>{"password"=>"[FILTERED]"}}
59
- LOG
56
+ if RUBY_VERSION < "3.4"
57
+ expect(actual).to eql(<<~LOG)
58
+ [#{app_name}] [INFO] [#{time}] #{verb} #{status} #{elapsed}µs #{ip} #{path} #{content_length}
59
+ {"user"=>{"password"=>"[FILTERED]"}}
60
+ LOG
61
+ else
62
+ expect(actual).to eql(<<~LOG)
63
+ [#{app_name}] [INFO] [#{time}] #{verb} #{status} #{elapsed}µs #{ip} #{path} #{content_length}
64
+ {"user" => {"password" => "[FILTERED]"}}
65
+ LOG
66
+ end
60
67
  end
61
68
 
62
69
  context "ip" do
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hanami
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 2.3.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luca Guidi
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-11-05 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: bundler
@@ -168,14 +167,14 @@ dependencies:
168
167
  requirements:
169
168
  - - "~>"
170
169
  - !ruby/object:Gem::Version
171
- version: '2.2'
170
+ version: 2.3.0.beta1
172
171
  type: :runtime
173
172
  prerelease: false
174
173
  version_requirements: !ruby/object:Gem::Requirement
175
174
  requirements:
176
175
  - - "~>"
177
176
  - !ruby/object:Gem::Version
178
- version: '2.2'
177
+ version: 2.3.0.beta1
179
178
  - !ruby/object:Gem::Dependency
180
179
  name: hanami-utils
181
180
  requirement: !ruby/object:Gem::Requirement
@@ -218,6 +217,20 @@ dependencies:
218
217
  - - "~>"
219
218
  - !ruby/object:Gem::Version
220
219
  version: '2.6'
220
+ - !ruby/object:Gem::Dependency
221
+ name: rack-session
222
+ requirement: !ruby/object:Gem::Requirement
223
+ requirements:
224
+ - - ">="
225
+ - !ruby/object:Gem::Version
226
+ version: '0'
227
+ type: :runtime
228
+ prerelease: false
229
+ version_requirements: !ruby/object:Gem::Requirement
230
+ requirements:
231
+ - - ">="
232
+ - !ruby/object:Gem::Version
233
+ version: '0'
221
234
  - !ruby/object:Gem::Dependency
222
235
  name: rspec
223
236
  requirement: !ruby/object:Gem::Requirement
@@ -238,14 +251,14 @@ dependencies:
238
251
  requirements:
239
252
  - - "~>"
240
253
  - !ruby/object:Gem::Version
241
- version: '1.1'
254
+ version: '2.0'
242
255
  type: :development
243
256
  prerelease: false
244
257
  version_requirements: !ruby/object:Gem::Requirement
245
258
  requirements:
246
259
  - - "~>"
247
260
  - !ruby/object:Gem::Version
248
- version: '1.1'
261
+ version: '2.0'
249
262
  - !ruby/object:Gem::Dependency
250
263
  name: rake
251
264
  requirement: !ruby/object:Gem::Requirement
@@ -282,6 +295,7 @@ files:
282
295
  - lib/hanami/config/actions/cookies.rb
283
296
  - lib/hanami/config/actions/sessions.rb
284
297
  - lib/hanami/config/assets.rb
298
+ - lib/hanami/config/console.rb
285
299
  - lib/hanami/config/db.rb
286
300
  - lib/hanami/config/logger.rb
287
301
  - lib/hanami/config/null_config.rb
@@ -310,6 +324,7 @@ files:
310
324
  - lib/hanami/helpers/form_helper/form_builder.rb
311
325
  - lib/hanami/helpers/form_helper/values.rb
312
326
  - lib/hanami/middleware/assets.rb
327
+ - lib/hanami/middleware/content_security_policy_nonce.rb
313
328
  - lib/hanami/middleware/public_errors_app.rb
314
329
  - lib/hanami/middleware/render_errors.rb
315
330
  - lib/hanami/port.rb
@@ -432,6 +447,7 @@ files:
432
447
  - spec/integration/view/parts/default_rendering_spec.rb
433
448
  - spec/integration/view/slice_configuration_spec.rb
434
449
  - spec/integration/view/views_spec.rb
450
+ - spec/integration/web/content_security_policy_nonce_spec.rb
435
451
  - spec/integration/web/render_detailed_errors_spec.rb
436
452
  - spec/integration/web/render_errors_spec.rb
437
453
  - spec/integration/web/welcome_view_spec.rb
@@ -440,10 +456,6 @@ files:
440
456
  - spec/support/coverage.rb
441
457
  - spec/support/matchers.rb
442
458
  - spec/support/rspec.rb
443
- - spec/support/shared_examples/cli/generate/app.rb
444
- - spec/support/shared_examples/cli/generate/migration.rb
445
- - spec/support/shared_examples/cli/generate/model.rb
446
- - spec/support/shared_examples/cli/new.rb
447
459
  - spec/unit/hanami/config/actions/content_security_policy_spec.rb
448
460
  - spec/unit/hanami/config/actions/cookies_spec.rb
449
461
  - spec/unit/hanami/config/actions/csrf_protection_spec.rb
@@ -451,6 +463,7 @@ files:
451
463
  - spec/unit/hanami/config/actions/sessions_spec.rb
452
464
  - spec/unit/hanami/config/actions_spec.rb
453
465
  - spec/unit/hanami/config/base_url_spec.rb
466
+ - spec/unit/hanami/config/console_spec.rb
454
467
  - spec/unit/hanami/config/db_spec.rb
455
468
  - spec/unit/hanami/config/inflector_spec.rb
456
469
  - spec/unit/hanami/config/logger_spec.rb
@@ -488,7 +501,6 @@ licenses:
488
501
  metadata:
489
502
  rubygems_mfa_required: 'true'
490
503
  allowed_push_host: https://rubygems.org
491
- post_install_message:
492
504
  rdoc_options: []
493
505
  require_paths:
494
506
  - lib
@@ -503,8 +515,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
503
515
  - !ruby/object:Gem::Version
504
516
  version: '0'
505
517
  requirements: []
506
- rubygems_version: 3.5.22
507
- signing_key:
518
+ rubygems_version: 3.6.9
508
519
  specification_version: 4
509
520
  summary: The web, with simplicity
510
521
  test_files:
@@ -593,6 +604,7 @@ test_files:
593
604
  - spec/integration/view/parts/default_rendering_spec.rb
594
605
  - spec/integration/view/slice_configuration_spec.rb
595
606
  - spec/integration/view/views_spec.rb
607
+ - spec/integration/web/content_security_policy_nonce_spec.rb
596
608
  - spec/integration/web/render_detailed_errors_spec.rb
597
609
  - spec/integration/web/render_errors_spec.rb
598
610
  - spec/integration/web/welcome_view_spec.rb
@@ -601,10 +613,6 @@ test_files:
601
613
  - spec/support/coverage.rb
602
614
  - spec/support/matchers.rb
603
615
  - spec/support/rspec.rb
604
- - spec/support/shared_examples/cli/generate/app.rb
605
- - spec/support/shared_examples/cli/generate/migration.rb
606
- - spec/support/shared_examples/cli/generate/model.rb
607
- - spec/support/shared_examples/cli/new.rb
608
616
  - spec/unit/hanami/config/actions/content_security_policy_spec.rb
609
617
  - spec/unit/hanami/config/actions/cookies_spec.rb
610
618
  - spec/unit/hanami/config/actions/csrf_protection_spec.rb
@@ -612,6 +620,7 @@ test_files:
612
620
  - spec/unit/hanami/config/actions/sessions_spec.rb
613
621
  - spec/unit/hanami/config/actions_spec.rb
614
622
  - spec/unit/hanami/config/base_url_spec.rb
623
+ - spec/unit/hanami/config/console_spec.rb
615
624
  - spec/unit/hanami/config/db_spec.rb
616
625
  - spec/unit/hanami/config/inflector_spec.rb
617
626
  - spec/unit/hanami/config/logger_spec.rb