roda 3.7.0 → 3.8.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: d7fe20c8d9a31f311d69cac5c073690374859342d995f97183abeda25e84c2e8
4
- data.tar.gz: d8b584c5768ef36fc60cd495d51285446c9cdd7e94a56668758b9c38253413a4
3
+ metadata.gz: f1f45dc2c17fe99add9644d7ee24bcc83e85f0c4ca5927b7d88b31ddac7c4d35
4
+ data.tar.gz: 654f4aaa9987343d9ff989bc4fc730d2c07d885b4ee57465be845c0876636340
5
5
  SHA512:
6
- metadata.gz: 90e1c33010e0cd7d21fbf434c88bbad41dc069c746bb7eb58b1ae8b982f48320316eabf7f95d8af9376d76cc6d5d88fcb216c3859df5199f6a98bcf86830b5f3
7
- data.tar.gz: 1a2d6dda37a5a49871af93894e5b32e553cdac5baa34d5c0a441481101bbc88353e3b8120deeaf7afcfeaae48c1c7cb48ea525a27c8db8e3d212e7945e75fb8d
6
+ metadata.gz: 9766752c2e4204821986db58bc086080f406770672670179a65bfe91766227f2637c195250d66d0f1b8ad021e6a3593b901a649cd51ab5484e7249cda057498c
7
+ data.tar.gz: e9ad5ba69df715e11e3ee9b258c2e4233631104cbdf972c2c8e0c6ace1bbf1fa5b6bca5cb88d2891e63fb64885ba17623a35760e6b60f49c4e56cebf43a17c1a
data/CHANGELOG CHANGED
@@ -1,3 +1,9 @@
1
+ = 3.8.0 (2018-05-17)
2
+
3
+ * Accept convert_each! :keys option that is Proc or Method in typecast_params plugin (jeremyevans)
4
+
5
+ * Make convert_each! in typecast_params plugin handle hashes with '0'..'N' keys without :keys option (jeremyevans)
6
+
1
7
  = 3.7.0 (2018-04-20)
2
8
 
3
9
  * Make response_request plugin work with error_handler and class_level_routing plugins (jeremyevans)
data/README.rdoc CHANGED
@@ -840,18 +840,40 @@ that all Roda applications that deal with parameters use it or
840
840
  another tool to explicitly convert submitted parameters to the
841
841
  expected types.
842
842
 
843
- === Security Related HTTP Headers
843
+ === Content Security Policy
844
+
845
+ The Content-Security-Policy HTTP header can be used to instruct
846
+ the browser on what types of content to allow and where content
847
+ can be loaded from. Roda ships with a +content_security_policy+
848
+ plugin that allows for the easy configuration of the content
849
+ security policy. Here's an example of a fairly restrictive
850
+ content security policy configuration:
851
+
852
+ class App < Roda
853
+ plugin :content_security_policy do |csp|
854
+ csp.default_src :none # deny everything by default
855
+ csp.style_src :self
856
+ csp.script_src :self
857
+ csp.connect_src :self
858
+ csp.img_src :self
859
+ csp.font_src :self
860
+ csp.form_action :self
861
+ csp.base_uri :none
862
+ csp.frame_ancestors :none
863
+ csp.block_all_mixed_content
864
+ csp.report_uri 'CSP_REPORT_URI'
865
+ end
866
+ end
867
+
868
+ === Other Security Related HTTP Headers
844
869
 
845
870
  You may want to look into setting the following HTTP headers, which
846
871
  can be done at the web server level, but can also be done at the
847
872
  application level using using the +default_headers+ plugin:
848
873
 
849
- Content-Security-Policy/X-Content-Security-Policy :: Defines policy for how javascript and other
850
- types of content can be used on the page.
851
- Frame-Options/X-Frame-Options :: Provides click-jacking protection by not allowing usage inside
852
- a frame.
853
874
  Strict-Transport-Security :: Enforces SSL/TLS Connections to the application.
854
875
  X-Content-Type-Options :: Forces some browsers to respect a declared Content-Type header.
876
+ X-Frame-Options :: Provides click-jacking protection by not allowing usage inside a frame.
855
877
  X-XSS-Protection :: Enables an XSS mitigation filter in some browsers.
856
878
 
857
879
  Example:
@@ -859,10 +881,9 @@ Example:
859
881
  class App < Roda
860
882
  plugin :default_headers,
861
883
  'Content-Type'=>'text/html',
862
- 'Content-Security-Policy'=>"default-src 'self'",
863
884
  'Strict-Transport-Security'=>'max-age=16070400;',
864
- 'X-Frame-Options'=>'deny',
865
885
  'X-Content-Type-Options'=>'nosniff',
886
+ 'X-Frame-Options'=>'deny',
866
887
  'X-XSS-Protection'=>'1; mode=block'
867
888
  end
868
889
 
@@ -876,8 +897,6 @@ location on the file system that users can write files to).
876
897
  You can specify which directories are allowed using the +:allowed_paths+ render plugin
877
898
  option. If you really want to turn path checking off, you can do so via the
878
899
  <tt>check_paths: false</tt> render plugin option.
879
- not check paths, as it assumes that users and libraries that use this option will be checking
880
- such paths manually.
881
900
 
882
901
  == Code Reloading
883
902
 
@@ -0,0 +1,27 @@
1
+ = New Features
2
+
3
+ * The convert_each! method in the typecast_params plugin now
4
+ accepts a Proc or Method value for the :keys option. The proc
5
+ or method is called with the current array or hash that
6
+ typecast params is operating on, and should return an
7
+ array of keys to use for the conversion.
8
+
9
+ * The convert_each! method in the typecast_params plugin will
10
+ now automatically handle hashes with keys from '0'..'N',
11
+ without a :keys option being provided.
12
+
13
+ This makes it possible to handle parameter names such as
14
+ foo[0][bar], foo[0][baz], foo[1][bar], and foo[1][baz], if you
15
+ want to avoid the issues related to rack's issues when parsing
16
+ array parameters.
17
+
18
+ = Other Improvements
19
+
20
+ * The Roda::RodaVersionNumber constant has been added for easier
21
+ version comparisons. It is 30080 for version 3.8.0.
22
+
23
+ = Backwards Compatibility
24
+
25
+ * When an unsupported type is given as value of the :keys option
26
+ to the convert_each! method in the typecast_params plugin, a
27
+ ProgrammerError exception is now raised.
@@ -162,7 +162,7 @@ class Roda
162
162
  # tp.pos_int!('artist_id')
163
163
  # tp.array!(:pos_int, 'album_ids')
164
164
  # tp.convert!('sales') do |stp|
165
- # tp.pos_int!(['num_sold', 'num_shipped'])
165
+ # stp.pos_int!(['num_sold', 'num_shipped'])
166
166
  # end
167
167
  # tp.convert!('members') do |mtp|
168
168
  # mtp.convert_each! do |stp|
@@ -197,7 +197,7 @@ class Roda
197
197
  # tp.pos_int!('artist_id')
198
198
  # tp.array!(:pos_int, 'album_ids')
199
199
  # tp.convert!('sales') do |stp|
200
- # tp.pos_int!(['num_sold', 'num_shipped'])
200
+ # stp.pos_int!(['num_sold', 'num_shipped'])
201
201
  # end
202
202
  # tp.convert!('members') do |mtp|
203
203
  # mtp.convert_each! do |stp|
@@ -295,7 +295,7 @@ class Roda
295
295
 
296
296
  # An array of all other errors that were raised with this error. If the error
297
297
  # was not raised inside Params#convert! or Params#convert_each!, this will just be
298
- # an array containing the current the receiver.
298
+ # an array containing the current receiver.
299
299
  #
300
300
  # This allows you to use Params#convert! to process a form input, and if any
301
301
  # conversion errors occur inside the block, it can provide an array of all parameter
@@ -574,22 +574,43 @@ class Roda
574
574
  end
575
575
  end
576
576
 
577
- # Runs convert! for each key specified by the :keys option. If no :keys option is given and the object is an array,
578
- # runs convert! for all entries in the array.
579
- # Raises an Error if the current object is not an array and :keys option is not specified.
577
+ # Runs convert! for each key specified by the :keys option. If :keys option is not given
578
+ # and the object is an array, runs convert! for all entries in the array. If the :keys
579
+ # option is not given and the object is a Hash with string keys '0', '1', ..., 'N' (with
580
+ # no skipped keys), runs convert! for all entries in the hash. If :keys option is a Proc
581
+ # or a Method, calls the proc/method with the current object, which should return an
582
+ # array of keys to use.
580
583
  # Passes any options given to #convert!. Options:
581
584
  #
582
- # :keys :: The keys to extract from the object
585
+ # :keys :: The keys to extract from the object. If a proc or method,
586
+ # calls the value with the current object, which should return the array of keys
587
+ # to use.
583
588
  def convert_each!(opts=OPTS, &block)
584
589
  np = !@capture
585
590
 
586
591
  _capture!(nil, opts) do
587
- unless keys = opts[:keys]
588
- unless @obj.is_a?(Array)
589
- handle_error(nil, :invalid_type, "convert_each! called on non-array")
592
+ case keys = opts[:keys]
593
+ when nil
594
+ keys = (0...@obj.length)
595
+
596
+ valid = case @obj
597
+ when Array
598
+ true
599
+ when Hash
600
+ keys = keys.map(&:to_s)
601
+ keys.all?{|k| @obj.has_key?(k)}
602
+ end
603
+
604
+ unless valid
605
+ handle_error(nil, :invalid_type, "convert_each! called on object not an array or hash with keys '0'..'N'")
590
606
  next
591
607
  end
592
- keys = (0...@obj.length)
608
+ when Array
609
+ # nothing to do
610
+ when Proc, Method
611
+ keys = keys.call(@obj)
612
+ else
613
+ raise ProgrammerError, "unsupported convert_each! :keys option: #{keys.inspect}"
593
614
  end
594
615
 
595
616
  keys.map do |i|
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 = 7
7
+ RodaMinorVersion = 8
8
8
 
9
9
  # The patch version of Roda, updated only for bug fixes from the last
10
10
  # feature release.
@@ -12,4 +12,7 @@ class Roda
12
12
 
13
13
  # The full version of Roda as a string.
14
14
  RodaVersion = "#{RodaMajorVersion}.#{RodaMinorVersion}.#{RodaPatchVersion}".freeze
15
+
16
+ # The full version of Roda as a number (3.7.0 => 30070)
17
+ RodaVersionNumber = RodaMajorVersion*10000 + RodaMinorVersion*10 + RodaPatchVersion
15
18
  end
@@ -581,13 +581,27 @@ describe "typecast_params plugin" do
581
581
  end.must_equal [{'b'=>1, 'c'=>2}, {'b'=>3, 'c'=>4}]
582
582
  end
583
583
 
584
- it "#convert_each! with :keys option should convert each named entry in a hash" do
584
+ it "#convert_each! without :keys option should convert each named entry in a hash when keys are '0'..'N'" do
585
+ tp = tp('a[0][b]=1&a[0][c]=2&a[1][b]=3&a[1][c]=4')
586
+ tp['a'].convert_each! do |tp0|
587
+ tp0.int(%w'b c')
588
+ end.must_equal [{'b'=>1, 'c'=>2}, {'b'=>3, 'c'=>4}]
589
+ end
590
+
591
+ it "#convert_each! with :keys option should convert each named entry in a hash when keys are '0'..'N'" do
585
592
  tp = tp('a[0][b]=1&a[0][c]=2&a[1][b]=3&a[1][c]=4')
586
593
  tp['a'].convert_each!(:keys=>%w'0 1') do |tp0|
587
594
  tp0.int(%w'b c')
588
595
  end.must_equal [{'b'=>1, 'c'=>2}, {'b'=>3, 'c'=>4}]
589
596
  end
590
597
 
598
+ it "#convert_each! with :keys option should convert each named entry in a hash" do
599
+ tp = tp('a[d][b]=1&a[d][c]=2&a[e][b]=3&a[e][c]=4')
600
+ tp['a'].convert_each!(:keys=>%w'd e') do |tp0|
601
+ tp0.int(%w'b c')
602
+ end.must_equal [{'b'=>1, 'c'=>2}, {'b'=>3, 'c'=>4}]
603
+ end
604
+
591
605
  it "#convert_each! with :keys option should store entries when called inside convert" do
592
606
  tp('a[0][b]=1&a[0][c]=2&a[1][b]=3&a[1][c]=4').convert! do |tp|
593
607
  tp['a'].convert_each!(:keys=>%w'0 1') do |tp0|
@@ -596,10 +610,33 @@ describe "typecast_params plugin" do
596
610
  end.must_equal("a"=>{"0"=>{'b'=>1, 'c'=>2}, "1"=>{'b'=>3, 'c'=>4}})
597
611
  end
598
612
 
599
- it "#convert_each! should raise if obj is not an array" do
613
+ it "#convert_each! :keys option should accept a Proc" do
614
+ tp('a[0][b]=1&a[0][c]=2&a[1][b]=3&a[1][c]=4').convert! do |tp|
615
+ tp['a'].convert_each!(:keys=>proc{|obj| obj.keys}) do |tp0|
616
+ tp0.int(%w'b c')
617
+ end
618
+ end.must_equal("a"=>{"0"=>{'b'=>1, 'c'=>2}, "1"=>{'b'=>3, 'c'=>4}})
619
+ end
620
+
621
+ it "#convert_each! should raise if :keys option is given and not an Array/Proc/Method" do
622
+ tp = tp('a[0][b]=1&a[0][c]=2&a[2][b]=3&a[2][c]=4')
623
+ lambda{tp['a'].convert_each!(:keys=>Object.new){}}.must_raise Roda::RodaPlugins::TypecastParams::ProgrammerError
624
+ end
625
+
626
+ it "#convert_each! should raise if obj is a hash without '0' keys" do
600
627
  lambda{tp.convert_each!{}}.must_raise @tp_error
601
628
  end
602
629
 
630
+ it "#convert_each! should raise if obj is not a hash with '0' but not '0'..'N' keys" do
631
+ tp = tp('a[0][b]=1&a[0][c]=2&a[2][b]=3&a[2][c]=4')
632
+ lambda{tp['b'].convert_each!{}}.must_raise @tp_error
633
+ end
634
+
635
+ it "#convert_each! should raise if obj is a scalar" do
636
+ tp = tp('a[d][b]=1&a[d][c]=2&a[e][b]=3&a[e][c]=4')
637
+ lambda{tp['d']['b'].convert_each!{}}.must_raise @tp_error
638
+ end
639
+
603
640
  it "#convert_each! should raise if obj is a array of non-hashes" do
604
641
  lambda{tp['b'].convert_each!{}}.must_raise @tp_error
605
642
  end
data/spec/version_spec.rb CHANGED
@@ -5,10 +5,10 @@ describe "Roda version constants" do
5
5
  Roda::RodaVersion.must_match(/\A\d+\.\d+\.\d+\z/)
6
6
  end
7
7
 
8
- it "Roda*Version should be integers" do
8
+ it "Roda*Version and RodaVersionNumber should be integers" do
9
9
  Roda::RodaMajorVersion.must_be_kind_of(Integer)
10
10
  Roda::RodaMinorVersion.must_be_kind_of(Integer)
11
11
  Roda::RodaPatchVersion.must_be_kind_of(Integer)
12
+ Roda::RodaVersionNumber.must_be_kind_of(Integer)
12
13
  end
13
14
  end
14
-
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.7.0
4
+ version: 3.8.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: 2018-04-20 00:00:00.000000000 Z
11
+ date: 2018-05-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -203,6 +203,7 @@ extra_rdoc_files:
203
203
  - doc/release_notes/3.4.0.txt
204
204
  - doc/release_notes/3.5.0.txt
205
205
  - doc/release_notes/3.6.0.txt
206
+ - doc/release_notes/3.8.0.txt
206
207
  files:
207
208
  - CHANGELOG
208
209
  - MIT-LICENSE
@@ -252,6 +253,7 @@ files:
252
253
  - doc/release_notes/3.5.0.txt
253
254
  - doc/release_notes/3.6.0.txt
254
255
  - doc/release_notes/3.7.0.txt
256
+ - doc/release_notes/3.8.0.txt
255
257
  - lib/roda.rb
256
258
  - lib/roda/plugins/_symbol_regexp_matchers.rb
257
259
  - lib/roda/plugins/all_verbs.rb