roda 3.75.0 → 3.77.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: 4ebdbc5b5707ba21044b5f4c83445ff8fca6a3925488c72a5176cc662c2ad15b
4
- data.tar.gz: ac528e50bfe1e778b5b4d32d16d12e117e87dc55b2f7cad1170b682e2f979586
3
+ metadata.gz: 8afa46b8055c19e63e1efeebf444b422cd810701c759936d476797515630245d
4
+ data.tar.gz: 4e857447435707de1d586857126795e2a1191f685ca8893e99cd1c78aeb50c02
5
5
  SHA512:
6
- metadata.gz: b7d13975d6c7705f1d7b184f27430320e1dfd5fea96e532f119f86b4c09fdb5c7e460107033d8d099c6ef8da354a514289981163d74cdb293b89074299a57eda
7
- data.tar.gz: d16c1b3a2edd401a73b104bf9458fcb865e441f4de649dcfcb8144eb3102abcd6abee741ecbbbf1cad3b13d8efca7260d7785b7e5a2505f29541ad001de9b1e4
6
+ metadata.gz: 2ecfeb211d574d46bdc31995c3551afb97af50acf8567cce83b46808e87ff797a5ef7c769e42c0477ed6a6d9271040b818da72e77c91e4f91f9760201d2cd5ca
7
+ data.tar.gz: 45e67fbd1da64839c6dc5a8dc0975a0dca5f67a77c83ae79a62ab22e7d9cf0002cb8b8f6a22661bdaf97ad973b6bc6ff928af2e416a96c35b12150e9fe0eaf4d
data/CHANGELOG CHANGED
@@ -1,3 +1,15 @@
1
+ = 3.77.0 (2024-02-12)
2
+
3
+ * Support formaction/formmethod attributes in forms in route_csrf plugin (jeremyevans)
4
+
5
+ = 3.76.0 (2024-01-12)
6
+
7
+ * Support :filter plugin option in error_mail and error_email for filtering parameters, environment variables, and session values (jeremyevans) (#346)
8
+
9
+ * Set temporary name on Ruby 3.3 in middleware plugin for middleware class created (janko) (#344)
10
+
11
+ * Add break plugin, for using break inside a routing block to return from the block and keep routing (jeremyevans)
12
+
1
13
  = 3.75.0 (2023-12-14)
2
14
 
3
15
  * Add cookie_flags plugin, for overriding, warning, or raising for incorrect cookie flags (jeremyevans)
@@ -0,0 +1,18 @@
1
+ = New Features
2
+
3
+ * A break plugin has been added, allowing you to use break from
4
+ inside a routing block and continue routing after the block. This
5
+ offers the same feature as the pass plugin, but using the standard
6
+ break keyword instead of the r.pass method.
7
+
8
+ * The error_mail and error_email features now both accept a :filter
9
+ plugin option. The value should respond to call with two arguments.
10
+ The first arguments is the key, and the second is the value, and
11
+ should return a truthy value if the value should be filtered. This
12
+ will be used for filtering parameter values, ENV values, and session
13
+ values in the generated emails.
14
+
15
+ = Other Improvements
16
+
17
+ * On Ruby 3.3+, the middleware plugin sets a temporary class name for
18
+ the created middleware, based on the class name of the Roda app.
@@ -0,0 +1,8 @@
1
+ = New Features
2
+
3
+ * The route_csrf plugin now supports formaction/formmethod attributes
4
+ in forms. A csrf_formaction_tag method has been added for creating
5
+ a hidden input for a particular path and method. When a form is
6
+ submitted, the check_csrf! method will fix check for a path-specific
7
+ csrf token (set by the hidden tag added by the csrf_formaction_tag
8
+ method), before checking for the default csrf token.
@@ -0,0 +1,43 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # The break plugin supports calling break inside a match block, to
7
+ # return from the block and continue in the routing tree, restoring
8
+ # the remaining path so that future matchers operating on the path
9
+ # operate as expected.
10
+ #
11
+ # plugin :break
12
+ #
13
+ # route do |r|
14
+ # r.on "foo", :bar do |bar|
15
+ # break if bar == 'baz'
16
+ # "/foo/#{bar} (not baz)"
17
+ # end
18
+ #
19
+ # r.on "foo/baz" do
20
+ # "/foo/baz"
21
+ # end
22
+ # end
23
+ #
24
+ # This provides the same basic feature as the pass plugin, but
25
+ # uses Ruby's standard control flow primative instead of a
26
+ # separate method.
27
+ module Break
28
+ module RequestMethods
29
+ private
30
+
31
+ # Handle break inside match blocks, restoring remaining path.
32
+ def if_match(_)
33
+ rp = @remaining_path
34
+ super
35
+ ensure
36
+ @remaining_path = rp
37
+ end
38
+ end
39
+ end
40
+
41
+ register_plugin(:break, Break)
42
+ end
43
+ end
@@ -21,6 +21,9 @@ class Roda
21
21
  #
22
22
  # Options:
23
23
  #
24
+ # :filter :: Callable called with the key and value for each parameter, environment
25
+ # variable, and session value. If it returns true, the value of the
26
+ # parameter is filtered in the email.
24
27
  # :from :: The From address to use in the email (required)
25
28
  # :headers :: A hash of additional headers to use in the email (default: empty hash)
26
29
  # :host :: The SMTP server to use to send the email (default: localhost)
@@ -38,6 +41,7 @@ class Roda
38
41
  # use an error reporting service instead of this plugin.
39
42
  module ErrorEmail
40
43
  DEFAULTS = {
44
+ :filter=>lambda{|k,v| false},
41
45
  :headers=>OPTS,
42
46
  :host=>'localhost',
43
47
  # :nocov:
@@ -52,7 +56,12 @@ class Roda
52
56
  {'From'=>h[:from], 'To'=>h[:to], 'Subject'=>"#{h[:prefix]}#{subject}"}
53
57
  end,
54
58
  :body=>lambda do |s, e|
55
- format = lambda{|h| h.map{|k, v| "#{k.inspect} => #{v.inspect}"}.sort.join("\n")}
59
+ filter = s.opts[:error_email][:filter]
60
+ format = lambda do |h|
61
+ h = h.map{|k, v| "#{k.inspect} => #{filter.call(k, v) ? 'FILTERED' : v.inspect}"}
62
+ h.sort!
63
+ h.join("\n")
64
+ end
56
65
 
57
66
  begin
58
67
  params = s.request.params
@@ -21,6 +21,9 @@ class Roda
21
21
  #
22
22
  # Options:
23
23
  #
24
+ # :filter :: Callable called with the key and value for each parameter, environment
25
+ # variable, and session value. If it returns true, the value of the
26
+ # parameter is filtered in the email.
24
27
  # :from :: The From address to use in the email (required)
25
28
  # :headers :: A hash of additional headers to use in the email (default: empty hash)
26
29
  # :prefix :: A prefix to use in the email's subject line (default: no prefix)
@@ -36,9 +39,12 @@ class Roda
36
39
  # for low traffic web applications. For high traffic web applications,
37
40
  # use an error reporting service instead of this plugin.
38
41
  module ErrorMail
42
+ DEFAULT_FILTER = lambda{|k,v| false}
43
+ private_constant :DEFAULT_FILTER
44
+
39
45
  # Set default opts for plugin. See ErrorEmail module RDoc for options.
40
46
  def self.configure(app, opts=OPTS)
41
- app.opts[:error_mail] = email_opts = (app.opts[:error_mail] || OPTS).merge(opts).freeze
47
+ app.opts[:error_mail] = email_opts = (app.opts[:error_mail] || {:filter=>DEFAULT_FILTER}).merge(opts).freeze
42
48
  unless email_opts[:to] && email_opts[:from]
43
49
  raise RodaError, "must provide :to and :from options to error_mail plugin"
44
50
  end
@@ -68,8 +74,13 @@ class Roda
68
74
  e.to_s
69
75
  end
70
76
  subject = "#{email_opts[:prefix]}#{subject}"
77
+ filter = email_opts[:filter]
71
78
 
72
- format = lambda{|h| h.map{|k, v| "#{k.inspect} => #{v.inspect}"}.sort.join("\n")}
79
+ format = lambda do |h|
80
+ h = h.map{|k, v| "#{k.inspect} => #{filter.call(k, v) ? 'FILTERED' : v.inspect}"}
81
+ h.sort!
82
+ h.join("\n")
83
+ end
73
84
 
74
85
  begin
75
86
  params = request.params
@@ -134,6 +134,9 @@ class Roda
134
134
  # and store +app+ as the next middleware to call.
135
135
  def initialize(mid, app, *args, &block)
136
136
  @mid = Class.new(mid)
137
+ # :nocov:
138
+ @mid.set_temporary_name("#{mid.name}(middleware)") if mid.name && RUBY_VERSION >= "3.3"
139
+ # :nocov:
137
140
  if @mid.opts[:middleware_next_if_not_found]
138
141
  @mid.plugin(:not_found, &NEXT_PROC)
139
142
  end
@@ -42,6 +42,9 @@ class Roda
42
42
  # This plugin supports the following options:
43
43
  #
44
44
  # :field :: Form input parameter name for CSRF token (default: '_csrf')
45
+ # :formaction_field :: Form input parameter name for path-specific CSRF tokens (used by the
46
+ # +csrf_formaction_tag+ method). If present, this parameter should be
47
+ # submitted as a hash, keyed by path, with CSRF token values.
45
48
  # :header :: HTTP header name for CSRF token (default: 'X-CSRF-Token')
46
49
  # :key :: Session key for CSRF secret (default: '_roda_csrf_secret')
47
50
  # :require_request_specific_tokens :: Whether request-specific tokens are required (default: true).
@@ -86,6 +89,10 @@ class Roda
86
89
  # override any of the plugin options for this specific call.
87
90
  # The :token option can be used to specify the provided CSRF token
88
91
  # (instead of looking for the token in the submitted parameters).
92
+ # csrf_formaction_tag(path, method='POST') :: An HTML hidden input tag string containing the CSRF token, suitable
93
+ # for placing in an HTML form that has inputs that use formaction
94
+ # attributes to change the endpoint to which the form is submitted.
95
+ # Takes the same arguments as csrf_token.
89
96
  # csrf_field :: The field name to use for the hidden tag containing the CSRF token.
90
97
  # csrf_path(action) :: This takes an argument that would be the value of the HTML form's
91
98
  # action attribute, and returns a path you can pass to csrf_token
@@ -152,6 +159,7 @@ class Roda
152
159
  # Default CSRF option values
153
160
  DEFAULTS = {
154
161
  :field => '_csrf'.freeze,
162
+ :formaction_field => '_csrfs'.freeze,
155
163
  :header => 'X-CSRF-Token'.freeze,
156
164
  :key => '_roda_csrf_secret'.freeze,
157
165
  :require_request_specific_tokens => true,
@@ -252,6 +260,14 @@ class Roda
252
260
  end
253
261
  end
254
262
 
263
+ # An HTML hidden input tag string containing the CSRF token, used for inputs
264
+ # with formaction, so the same form can be used to submit to multiple endpoints
265
+ # depending on which button was clicked. See csrf_token for arguments, but the
266
+ # path argument is required.
267
+ def csrf_formaction_tag(path, *args)
268
+ "<input type=\"hidden\" name=\"#{csrf_options[:formaction_field]}[#{Rack::Utils.escape_html(path)}]\" value=\"#{csrf_token(path, *args)}\" \/>"
269
+ end
270
+
255
271
  # An HTML hidden input tag string containing the CSRF token. See csrf_token for
256
272
  # arguments.
257
273
  def csrf_tag(*args)
@@ -291,6 +307,8 @@ class Roda
291
307
  return
292
308
  end
293
309
 
310
+ path = @_request.path
311
+
294
312
  unless encoded_token = opts[:token]
295
313
  encoded_token = case opts[:check_header]
296
314
  when :only
@@ -298,7 +316,8 @@ class Roda
298
316
  when true
299
317
  return (csrf_invalid_message(opts.merge(:check_header=>false)) && csrf_invalid_message(opts.merge(:check_header=>:only)))
300
318
  else
301
- @_request.params[opts[:field]]
319
+ params = @_request.params
320
+ ((formactions = params[opts[:formaction_field]]).is_a?(Hash) && (formactions[path])) || params[opts[:field]]
302
321
  end
303
322
  end
304
323
 
@@ -326,7 +345,7 @@ class Roda
326
345
 
327
346
  random_data = submitted_hmac.slice!(0...31)
328
347
 
329
- if csrf_compare(csrf_hmac(random_data, method, @_request.path), submitted_hmac)
348
+ if csrf_compare(csrf_hmac(random_data, method, path), submitted_hmac)
330
349
  return
331
350
  end
332
351
 
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 = 75
7
+ RodaMinorVersion = 77
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.75.0
4
+ version: 3.77.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: 2023-12-14 00:00:00.000000000 Z
11
+ date: 2024-02-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -249,6 +249,8 @@ extra_rdoc_files:
249
249
  - doc/release_notes/3.73.0.txt
250
250
  - doc/release_notes/3.74.0.txt
251
251
  - doc/release_notes/3.75.0.txt
252
+ - doc/release_notes/3.76.0.txt
253
+ - doc/release_notes/3.77.0.txt
252
254
  - doc/release_notes/3.8.0.txt
253
255
  - doc/release_notes/3.9.0.txt
254
256
  files:
@@ -331,6 +333,8 @@ files:
331
333
  - doc/release_notes/3.73.0.txt
332
334
  - doc/release_notes/3.74.0.txt
333
335
  - doc/release_notes/3.75.0.txt
336
+ - doc/release_notes/3.76.0.txt
337
+ - doc/release_notes/3.77.0.txt
334
338
  - doc/release_notes/3.8.0.txt
335
339
  - doc/release_notes/3.9.0.txt
336
340
  - lib/roda.rb
@@ -351,6 +355,7 @@ files:
351
355
  - lib/roda/plugins/autoload_named_routes.rb
352
356
  - lib/roda/plugins/backtracking_array.rb
353
357
  - lib/roda/plugins/branch_locals.rb
358
+ - lib/roda/plugins/break.rb
354
359
  - lib/roda/plugins/caching.rb
355
360
  - lib/roda/plugins/capture_erb.rb
356
361
  - lib/roda/plugins/chunked.rb
@@ -494,7 +499,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
494
499
  - !ruby/object:Gem::Version
495
500
  version: '0'
496
501
  requirements: []
497
- rubygems_version: 3.4.10
502
+ rubygems_version: 3.5.3
498
503
  signing_key:
499
504
  specification_version: 4
500
505
  summary: Routing tree web toolkit