roda 3.80.0 → 3.81.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0cebe935d536e1f903b212075108ba9cbcade4aa2e8d2abf1c5e0d6e6f539ce8
4
- data.tar.gz: 9b0c576aaa36c5a05596c1bc1bec23d3ab0f37c56dc72342bfa962b10442928f
3
+ metadata.gz: a9d94f31e568bd2774c3e582152f0bcdbffdf3fcd7e5a95241e73b3fd5b7ac3c
4
+ data.tar.gz: b9ad44642acdbaa0035cbd6ece521ca3432d2e7c23d75a331172ecd6c6288c60
5
5
  SHA512:
6
- metadata.gz: 0e83d0fe8e1f70bb196ea5f285f7a00590ab1669e4b1d686f859d1e5c65a8e760d1320b345306740d00c7d063f0f6bada1af88433b3b04c6b429f439bb7e2521
7
- data.tar.gz: e9b0ffd5b5fb7e976a971f11fbed4f0beb35868dcb7aa70c41c005046a9053cb6c62caf29f669c02cd53e67cd5db51a28076f058824c90a1c1b917a9b7f0f4fb
6
+ metadata.gz: 1cd64e84b47a1a7a01d9165d16e14d95d2c43287b58f2557d9492a201832c1388157152eab1fd12052c7691e3969e5ce1cb9c0ad706e73ad6de822dcc29e1590
7
+ data.tar.gz: 86320c603d0c9b90e2c82f16cc5229b76afe66dde5bdbccce9b28ce076e80808a35410098fe0eae5cb3f5b3180b79f4265b3d525e7861a9dd65890315d274fad
data/CHANGELOG CHANGED
@@ -1,3 +1,11 @@
1
+ = 3.81.0 (2024-06-12)
2
+
3
+ * Make assets plugin :early_hints option follow Rack 3 SPEC if using Rack 3 (jeremyevans)
4
+
5
+ * Correctly parse Ruby 3.4 backtraces in exception_page plugin (jeremyevans)
6
+
7
+ * Support :until and :seconds option in hmac_paths plugin, for paths valid only until a specific time (jeremyevans)
8
+
1
9
  = 3.80.0 (2024-05-10)
2
10
 
3
11
  * Support :namespace option in hmac_paths plugin, allowing for easy per-user/per-group HMAC paths (jeremyevans)
@@ -0,0 +1,24 @@
1
+ = New Features
2
+
3
+ * The hmac_paths plugin now supports :until and :seconds options for
4
+ hmac_path, to create a path that is only valid for a specific amount of
5
+ time. :until sets a specific time that the path will be valid until,
6
+ and :seconds makes the path only valid for the given number of seconds.
7
+
8
+ hmac_path('/widget/1', until: Time.utc(2100))
9
+ # => "/dc8b6e56e4cbe7815df7880d42f0e02956b2e4c49881b6060ceb0e49745a540d/t/4102444800/widget/1"
10
+
11
+ Requests for the path after the given time will not be matched by
12
+ r.hmac_path.
13
+
14
+ = Other Improvements
15
+
16
+ * The early_hints plugin now correctly follows the Rack 3 SPEC when
17
+ using Rack 3. This was not caught previously because Rack only
18
+ added official support for early_hints in the last month.
19
+
20
+ * Ruby 3.4 backtraces are now parsed correctly in the exception_page
21
+ plugin.
22
+
23
+ * Some plugins that accept a block no longer issue an unused block
24
+ warning on Ruby 3.4.
@@ -736,7 +736,9 @@ class Roda
736
736
  paths = assets_paths(type)
737
737
  if o[:early_hints]
738
738
  early_hint_as = ltype == :js ? 'script' : 'style'
739
- send_early_hints('Link'=>paths.map{|p| "<#{p}>; rel=preload; as=#{early_hint_as}"}.join("\n"))
739
+ early_hints = paths.map{|p| "<#{p}>; rel=preload; as=#{early_hint_as}"}
740
+ early_hints = early_hints.join("\n") if Rack.release < '3'
741
+ send_early_hints(RodaResponseHeaders::LINK=>early_hints)
740
742
  end
741
743
  paths.map{|p| "#{tag_start}#{h(p)}#{tag_end}"}.join("\n")
742
744
  end
@@ -245,7 +245,7 @@ END
245
245
 
246
246
  frames = exception.backtrace.map.with_index do |line, i|
247
247
  frame = {:id=>i}
248
- if line =~ /\A(.*?):(\d+)(?::in `(.*)')?\Z/
248
+ if line =~ /\A(.*?):(\d+)(?::in [`'](.*)')?\Z/
249
249
  filename = frame[:filename] = $1
250
250
  lineno = frame[:lineno] = $2.to_i
251
251
  frame[:function] = $3
@@ -21,7 +21,7 @@ class Roda
21
21
  # !request.path.start_with?('/admin/')
22
22
  # end
23
23
  module FilterCommonLogger
24
- def self.load_dependencies(app)
24
+ def self.load_dependencies(app, &_)
25
25
  app.plugin :common_logger
26
26
  end
27
27
 
@@ -112,6 +112,16 @@ class Roda
112
112
  # this for POST requests (or other HTTP verbs that can have request bodies), use +r.GET+
113
113
  # instead of +r.params+ to specifically check query string parameters.
114
114
  #
115
+ # The generated paths can be timestamped, so that they are only valid until a given time
116
+ # or for a given number of seconds after they are generated, using the :until or :seconds
117
+ # options:
118
+ #
119
+ # hmac_path('/widget/1', until: Time.utc(2100))
120
+ # # => "/dc8b6e56e4cbe7815df7880d42f0e02956b2e4c49881b6060ceb0e49745a540d/t/4102444800/widget/1"
121
+ #
122
+ # hmac_path('/widget/1', seconds: Time.utc(2100).to_i - Time.now.to_i)
123
+ # # => "/dc8b6e56e4cbe7815df7880d42f0e02956b2e4c49881b6060ceb0e49745a540d/t/4102444800/widget/1"
124
+ #
115
125
  # The :namespace option, if provided, should be a string, and it modifies the generated HMACs
116
126
  # to only match those in the same namespace. This can be used to provide different paths to
117
127
  # different users or groups of users.
@@ -190,6 +200,11 @@ class Roda
190
200
  # r.hmac_path('/1', params: {k: 2})
191
201
  # HMAC_hex(HMAC_hex(secret, ''), '/p/1?k=2')
192
202
  #
203
+ # The +:until+ and +:seconds+ option include the timestamp in the HMAC:
204
+ #
205
+ # r.hmac_path('/1', until: Time.utc(2100))
206
+ # HMAC_hex(HMAC_hex(secret, ''), '/t/4102444800/1')
207
+ #
193
208
  # If a +:namespace+ option is provided, the original secret used before the +:root+ option is
194
209
  # an HMAC of the +:secret+ plugin option and the given namespace.
195
210
  #
@@ -232,6 +247,8 @@ class Roda
232
247
  # the already matched path of the routing tree using r.hmac_path. Defaults
233
248
  # to the empty string, which will returns paths valid for r.hmac_path at
234
249
  # the top level of the routing tree.
250
+ # :seconds :: Make the given path valid for the given integer number of seconds.
251
+ # :until :: Make the given path valid until the given Time.
235
252
  def hmac_path(path, opts=OPTS)
236
253
  unless path.is_a?(String) && path.getbyte(0) == 47
237
254
  raise RodaError, "path must be a string starting with /"
@@ -242,6 +259,12 @@ class Roda
242
259
  raise RodaError, "root must be empty string or string starting with /"
243
260
  end
244
261
 
262
+ if valid_until = opts[:until]
263
+ valid_until = valid_until.to_i
264
+ elsif seconds = opts[:seconds]
265
+ valid_until = Time.now.to_i + seconds
266
+ end
267
+
245
268
  flags = String.new
246
269
  path = path.dup
247
270
 
@@ -258,6 +281,11 @@ class Roda
258
281
  flags << 'n'
259
282
  end
260
283
 
284
+ if valid_until
285
+ flags << 't'
286
+ path = "/#{valid_until}#{path}"
287
+ end
288
+
261
289
  flags << '0' if flags.empty?
262
290
 
263
291
  hmac_path = if method
@@ -335,7 +363,19 @@ class Roda
335
363
  end
336
364
 
337
365
  if hmac_path_valid?(mpath, rpath, submitted_hmac, opts)
338
- always(&block)
366
+ if flags.include?('t')
367
+ on Integer do |int|
368
+ if int >= Time.now.to_i
369
+ always(&block)
370
+ else
371
+ # Return from method without matching
372
+ @remaining_path = orig_path
373
+ return
374
+ end
375
+ end
376
+ else
377
+ always(&block)
378
+ end
339
379
  end
340
380
  end
341
381
 
@@ -53,13 +53,10 @@ class Roda
53
53
 
54
54
  class Params < Rack::QueryParser::Params
55
55
  if Rack.release >= '3'
56
- # rack main branch compatibility
57
- # :nocov:
58
56
  if Params < Hash
59
57
  def initialize
60
58
  super(&INDIFFERENT_PROC)
61
59
  end
62
- # :nocov:
63
60
  else
64
61
  def initialize
65
62
  @size = 0
@@ -31,7 +31,7 @@ class Roda
31
31
  # still exists mainly for backward compatibility.
32
32
  module NotFound
33
33
  # Require the status_handler plugin
34
- def self.load_dependencies(app)
34
+ def self.load_dependencies(app, &_)
35
35
  app.plugin :status_handler
36
36
  end
37
37
 
@@ -172,7 +172,7 @@ class Roda
172
172
  # a valid CSRF token was not provided.
173
173
  class InvalidToken < RodaError; end
174
174
 
175
- def self.load_dependencies(app, opts=OPTS)
175
+ def self.load_dependencies(app, opts=OPTS, &_)
176
176
  app.plugin :_base64
177
177
  end
178
178
 
@@ -476,7 +476,7 @@ class Roda
476
476
  serialized_data << json_data
477
477
 
478
478
  cipher_secret = opts[:cipher_secret]
479
- if per_cookie_secret = opts[:per_cookie_cipher_secret]
479
+ if opts[:per_cookie_cipher_secret]
480
480
  version = "\1"
481
481
  per_cookie_secret_base = SecureRandom.random_bytes(32)
482
482
  cipher_secret = OpenSSL::HMAC.digest(OpenSSL::Digest::SHA256.new, cipher_secret, per_cookie_secret_base)
data/lib/roda/version.rb CHANGED
@@ -4,7 +4,7 @@ class Roda
4
4
  RodaMajorVersion = 3
5
5
 
6
6
  # The minor version of Roda, updated for new feature releases of Roda.
7
- RodaMinorVersion = 80
7
+ RodaMinorVersion = 81
8
8
 
9
9
  # The patch version of Roda, updated only for bug fixes from the last
10
10
  # feature release.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: roda
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.80.0
4
+ version: 3.81.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Evans
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-10 00:00:00.000000000 Z
11
+ date: 2024-06-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -255,6 +255,7 @@ extra_rdoc_files:
255
255
  - doc/release_notes/3.79.0.txt
256
256
  - doc/release_notes/3.8.0.txt
257
257
  - doc/release_notes/3.80.0.txt
258
+ - doc/release_notes/3.81.0.txt
258
259
  - doc/release_notes/3.9.0.txt
259
260
  files:
260
261
  - CHANGELOG
@@ -342,6 +343,7 @@ files:
342
343
  - doc/release_notes/3.79.0.txt
343
344
  - doc/release_notes/3.8.0.txt
344
345
  - doc/release_notes/3.80.0.txt
346
+ - doc/release_notes/3.81.0.txt
345
347
  - doc/release_notes/3.9.0.txt
346
348
  - lib/roda.rb
347
349
  - lib/roda/cache.rb