forme 2.4.1 → 2.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 +8 -0
- data/README.rdoc +18 -2
- data/lib/forme/template.rb +4 -4
- data/lib/forme/transformers/formatter.rb +6 -0
- data/lib/forme/version.rb +2 -2
- data/lib/roda/plugins/forme_erubi_capture.rb +2 -2
- data/lib/roda/plugins/forme_route_csrf.rb +18 -1
- data/lib/roda/plugins/forme_set.rb +14 -1
- data/lib/sequel/plugins/forme.rb +16 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 79c0b3986af69becb74de866d9027eafb1af2b148056c60963e8c8c6af04ad3d
|
4
|
+
data.tar.gz: 8478ef6951317b7a33bf7c3b2630291bcd94bb94fcbb2820ef89d08c0addfaec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c63cedc392288fba47d26da036ed2ad145acf4493683600cbad71238f66fd61dfeb91cadc1db68ab2211ff3cf6cd69622f17934f9ea0be4e4006a53c2baa0a07
|
7
|
+
data.tar.gz: ef4a1d7b5bfdd0dc83d5f52b87f8dbc0785f03ccdfdb8d7e1bdfe160e85636fc2165fae7916489c8d22ba082293a64b3e0a466c67e4a4fe3a90726f4d228ffb1
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
=== 2.5.0 (2024-02-13)
|
2
|
+
|
3
|
+
* Add hidden inputs to work with formaction/formmethod support in Roda 3.77+ route_csrf plugin (jeremyevans)
|
4
|
+
|
5
|
+
* Support :formaction option on buttons (jeremyevans)
|
6
|
+
|
7
|
+
* Support emit: false option for non-rails template forms allowing block based form use without appending to template (jeremyevans)
|
8
|
+
|
1
9
|
=== 2.4.1 (2023-09-19)
|
2
10
|
|
3
11
|
* Add dependency on bigdecimal, as bigdecimal is moving from standard library to bundled gem in Ruby 3.4 (jeremyevans)
|
data/README.rdoc
CHANGED
@@ -800,7 +800,7 @@ For new code, it is recommended to use forme_route_csrf, as that uses Roda's rou
|
|
800
800
|
plugin, which supports more secure request-specific CSRF tokens. In both cases, usage in ERB
|
801
801
|
templates is the same:
|
802
802
|
|
803
|
-
<% form(@obj, :
|
803
|
+
<% form(@obj, action: '/foo') do |f| %>
|
804
804
|
<%= f.input(:field) %>
|
805
805
|
<% f.tag(:fieldset) do %>
|
806
806
|
<%= f.input(:field_two) %>
|
@@ -810,6 +810,8 @@ templates is the same:
|
|
810
810
|
The forme_route_csrf plugin's +form+ method supports the following options
|
811
811
|
in addition to the default +Forme.form+ options:
|
812
812
|
|
813
|
+
:emit :: Set to false to not emit implicit tags into template. This should only be
|
814
|
+
used if you are not modifying the template inside the block.
|
813
815
|
:csrf :: Set to force whether a CSRF tag should be included. By default, a CSRF
|
814
816
|
tag is included if the form's method is one of the request methods checked
|
815
817
|
by the Roda route_csrf plugin.
|
@@ -818,6 +820,19 @@ in addition to the default +Forme.form+ options:
|
|
818
820
|
CSRF token unless the Roda route_csrf plugin has been
|
819
821
|
configured to support non-request specific tokens.
|
820
822
|
|
823
|
+
The <tt>emit: false</tt> option allows you to do:
|
824
|
+
|
825
|
+
<%= form(@obj, {action: '/foo'}, emit: false) do |f|
|
826
|
+
f.input(:field)
|
827
|
+
f.tag(:fieldset) do
|
828
|
+
f.input(:field_two)
|
829
|
+
end
|
830
|
+
end %>
|
831
|
+
|
832
|
+
This is useful if you are calling some method that calls +form+ with a block,
|
833
|
+
where the resulting entire Forme::Forme object will be literalized into the
|
834
|
+
template. The form will include the CSRF token and forme_set metadata as appropriate.
|
835
|
+
|
821
836
|
The forme plugin does not require any csrf plugin, but will transparently use
|
822
837
|
Rack::Csrf if it is available. If Rack::Csrf is available a CSRF tag if the form's
|
823
838
|
method is +POST+, with no configuration ability.
|
@@ -856,7 +871,8 @@ It allows you to use the following API in your erb templates:
|
|
856
871
|
<% end %>
|
857
872
|
|
858
873
|
In order to this to work transparently, the ERB outvar needs to be <tt>@_out_buf</tt> (this is the
|
859
|
-
default in Sinatra).
|
874
|
+
default in Sinatra). The Sinatra extension also supports the <tt>emit: false</tt> option to not
|
875
|
+
directly modify the related template (see example in the Roda section for usage).
|
860
876
|
|
861
877
|
= Rails Support
|
862
878
|
|
data/lib/forme/template.rb
CHANGED
@@ -72,9 +72,9 @@ module Forme
|
|
72
72
|
private
|
73
73
|
|
74
74
|
def _forme_form(obj, attr, opts, &block)
|
75
|
-
if
|
75
|
+
if block && opts[:emit] != false
|
76
76
|
erb_form = buffer = offset = nil
|
77
|
-
|
77
|
+
form_block = proc do
|
78
78
|
wrapped_form = erb_form.instance_variable_get(:@form)
|
79
79
|
buffer = wrapped_form.to_s
|
80
80
|
offset = buffer.length
|
@@ -83,9 +83,9 @@ module Forme
|
|
83
83
|
offset = buffer.length
|
84
84
|
end
|
85
85
|
|
86
|
-
f, attr,
|
86
|
+
f, attr, form_block = _forme_wrapped_form_class.form_args(obj, attr, opts, &form_block)
|
87
87
|
erb_form = _forme_form_class.new(f, self)
|
88
|
-
erb_form.form(attr, &
|
88
|
+
erb_form.form(attr, &form_block)
|
89
89
|
erb_form.emit(buffer[offset, buffer.length])
|
90
90
|
else
|
91
91
|
_forme_wrapped_form_class.form(obj, attr, opts, &block)
|
@@ -268,6 +268,12 @@ module Forme
|
|
268
268
|
ret
|
269
269
|
end
|
270
270
|
|
271
|
+
# Formats a submit input. Respects :formaction option.
|
272
|
+
def format_submit
|
273
|
+
copy_options_to_attributes([:formaction])
|
274
|
+
_format_input(:submit)
|
275
|
+
end
|
276
|
+
|
271
277
|
# Formats a textarea. Respects the following options:
|
272
278
|
# :value :: Sets value as the child of the textarea.
|
273
279
|
def format_textarea
|
data/lib/forme/version.rb
CHANGED
@@ -6,11 +6,11 @@ module Forme
|
|
6
6
|
MAJOR = 2
|
7
7
|
|
8
8
|
# The minor version of Forme, updated for new feature releases of Forme.
|
9
|
-
MINOR =
|
9
|
+
MINOR = 5
|
10
10
|
|
11
11
|
# The patch version of Forme, updated only for bug fixes from the last
|
12
12
|
# feature release.
|
13
|
-
TINY =
|
13
|
+
TINY = 0
|
14
14
|
|
15
15
|
# Version constant, use <tt>Forme.version</tt> instead.
|
16
16
|
VERSION = "#{MAJOR}.#{MINOR}.#{TINY}".freeze
|
@@ -36,7 +36,7 @@ class Roda
|
|
36
36
|
end
|
37
37
|
|
38
38
|
if apply_csrf
|
39
|
-
token = if opts.fetch(:use_request_specific_token){use_request_specific_csrf_tokens?}
|
39
|
+
token = if use_request_specific_token = opts.fetch(:use_request_specific_token){use_request_specific_csrf_tokens?}
|
40
40
|
csrf_token(csrf_path(attr[:action]), method)
|
41
41
|
else
|
42
42
|
csrf_token
|
@@ -46,6 +46,23 @@ class Roda
|
|
46
46
|
opts[:_before] = lambda do |form|
|
47
47
|
form.tag(:input, :type=>:hidden, :name=>csrf_field, :value=>token)
|
48
48
|
end
|
49
|
+
|
50
|
+
if use_request_specific_token && (formaction_field = csrf_options[:formaction_field])
|
51
|
+
formactions = opts[:formactions] = []
|
52
|
+
formaction_tokens = opts[:formaction_tokens] = {}
|
53
|
+
_after = opts[:_after]
|
54
|
+
opts[:formaction_csrfs] = [formaction_field, formaction_tokens]
|
55
|
+
formaction_field = csrf_options[:formaction_field]
|
56
|
+
opts[:_after] = lambda do |form|
|
57
|
+
formactions.each do |action, method|
|
58
|
+
path = csrf_path(action)
|
59
|
+
fa_token = csrf_token(path, method)
|
60
|
+
formaction_tokens[path] = fa_token
|
61
|
+
form.tag(:input, :type=>:hidden, :name=>"#{formaction_field}[#{path}]", :value=>fa_token)
|
62
|
+
end
|
63
|
+
_after.call(form) if _after
|
64
|
+
end
|
65
|
+
end
|
49
66
|
end
|
50
67
|
end
|
51
68
|
end
|
@@ -102,7 +102,9 @@ class Roda
|
|
102
102
|
def _forme_form_options(obj, attr, opts)
|
103
103
|
super
|
104
104
|
|
105
|
+
_after = opts[:_after]
|
105
106
|
opts[:_after] = lambda do |form|
|
107
|
+
_after.call(form) if _after
|
106
108
|
if (obj = form.opts[:obj]) && obj.respond_to?(:forme_inputs) && (forme_inputs = obj.forme_inputs)
|
107
109
|
columns = []
|
108
110
|
valid_values = {}
|
@@ -129,6 +131,9 @@ class Roda
|
|
129
131
|
data['columns'] = columns
|
130
132
|
data['namespaces'] = form.opts[:namespace]
|
131
133
|
data['csrf'] = form.opts[:csrf]
|
134
|
+
if (formactions = form.opts[:formaction_csrfs]) && !formactions[1].empty?
|
135
|
+
data['formaction_csrfs'] = formactions
|
136
|
+
end
|
132
137
|
data['valid_values'] = valid_values unless valid_values.empty?
|
133
138
|
data['form_version'] = form.opts[:form_version] if form.opts[:form_version]
|
134
139
|
|
@@ -154,8 +159,16 @@ class Roda
|
|
154
159
|
|
155
160
|
data = JSON.parse(data)
|
156
161
|
csrf_field, hmac_csrf_value = data['csrf']
|
162
|
+
formaction_csrf_field, formaction_values = data['formaction_csrfs']
|
163
|
+
|
157
164
|
if csrf_field
|
158
|
-
|
165
|
+
formaction_params = params[formaction_csrf_field]
|
166
|
+
if formaction_csrf_field && (formaction_params = params[formaction_csrf_field]).is_a?(Hash) && (csrf_value = formaction_params[request.path])
|
167
|
+
hmac_csrf_value = formaction_values[request.path]
|
168
|
+
else
|
169
|
+
csrf_value = params[csrf_field].to_s
|
170
|
+
end
|
171
|
+
|
159
172
|
hmac_csrf_value = hmac_csrf_value.to_s
|
160
173
|
unless Rack::Utils.secure_compare(csrf_value.ljust(hmac_csrf_value.length), hmac_csrf_value) && csrf_value.length == hmac_csrf_value.length
|
161
174
|
return _forme_parse_error(:csrf_mismatch, obj)
|
data/lib/sequel/plugins/forme.rb
CHANGED
@@ -17,6 +17,22 @@ module Sequel # :nodoc:
|
|
17
17
|
# that use a <tt>Sequel::Model</tt> instance as the form's
|
18
18
|
# +obj+.
|
19
19
|
module SequelForm
|
20
|
+
# If the form has the :formactions option and the button has the
|
21
|
+
# formaction option or attribute, append the action and method
|
22
|
+
# for this button to the formactions. This is used by the
|
23
|
+
# Roda forme_route_csrf and forme_set plugins so that formaction
|
24
|
+
# can work as expected.
|
25
|
+
def button(opts={})
|
26
|
+
if opts.is_a?(Hash) && (formactions = self.opts[:formactions]) &&
|
27
|
+
(formaction = opts[:formaction] || ((attr = opts[:attr]) && (attr[:formaction] || attr['formaction'])))
|
28
|
+
formmethod = opts[:formmethod] ||
|
29
|
+
((attr = opts[:attr]) && (attr[:formmethod] || attr['formmethod'])) ||
|
30
|
+
((attr = form_tag_attributes) && (attr[:method] || attr['method']))
|
31
|
+
formactions << [formaction, formmethod]
|
32
|
+
end
|
33
|
+
super
|
34
|
+
end
|
35
|
+
|
20
36
|
# Use the post method by default for Sequel forms, unless
|
21
37
|
# overridden with the :method attribute.
|
22
38
|
def form(attr={}, &block)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: forme
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.5.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:
|
11
|
+
date: 2024-02-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bigdecimal
|
@@ -239,7 +239,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
239
239
|
- !ruby/object:Gem::Version
|
240
240
|
version: '0'
|
241
241
|
requirements: []
|
242
|
-
rubygems_version: 3.
|
242
|
+
rubygems_version: 3.5.3
|
243
243
|
signing_key:
|
244
244
|
specification_version: 4
|
245
245
|
summary: HTML forms library
|