committee 1.14.1 → 1.15.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
  SHA1:
3
- metadata.gz: 6b93ed460e34afc046f016a0b28c53c221bb4eb5
4
- data.tar.gz: 0670a4037229f06312799901ade0e94bf416a95e
3
+ metadata.gz: d5fcb82a192f894e1baec1dcab89f081782d222f
4
+ data.tar.gz: 54d056b8be5b297b6a524166363f955db7a1bd15
5
5
  SHA512:
6
- metadata.gz: c64af87f69eeeb24ba0b6dd0e9baa873c436d67e452dfde3c432e318d3cf583ec536dd1faed3c136ce1e4d0a2b90aac17083b861492ce0ed518d24ea2ede4f36
7
- data.tar.gz: 9fcc322cc7e10fa8299fc0025dada82a5222c3546988737ed344f06d9e809ccf1c6a010a193d1e49378ba3c2767b0e340652793bcd8f22edf0d7c2590795a96e
6
+ metadata.gz: f22924efd2696d884eb499978cdb2a9f6e81ead9d25dacbe3ea331b9fb4d771886a4ccea1926fe2d09256886433a451fdbe25ef47cbe8d4c80a07a4157e0b9bc
7
+ data.tar.gz: db8d1aa50e4f4fa854bda1d5484df09e7262801bd845195c1340a718fc6d0792666360698ea2fe8722f1c57a287fcfb4b1f0258706032f47a2ef7cceaffd7df9
data/lib/committee.rb CHANGED
@@ -3,6 +3,7 @@ require "json_schema"
3
3
  require "rack"
4
4
 
5
5
  require_relative "committee/errors"
6
+ require_relative "committee/query_params_coercer"
6
7
  require_relative "committee/request_unpacker"
7
8
  require_relative "committee/request_validator"
8
9
  require_relative "committee/response_generator"
@@ -2,17 +2,29 @@ module Committee::Middleware
2
2
  class RequestValidation < Base
3
3
  def initialize(app, options={})
4
4
  super
5
- @allow_form_params = options.fetch(:allow_form_params, true)
6
- @allow_query_params = options.fetch(:allow_query_params, true)
7
- @check_content_type = options.fetch(:check_content_type, true)
8
- @optimistic_json = options.fetch(:optimistic_json, false)
9
- @strict = options[:strict]
5
+ @allow_form_params = options.fetch(:allow_form_params, true)
6
+ @allow_query_params = options.fetch(:allow_query_params, true)
7
+ @check_content_type = options.fetch(:check_content_type, true)
8
+ @optimistic_json = options.fetch(:optimistic_json, false)
9
+ @coerce_query_params = options.fetch(:coerce_query_params, false)
10
+ @strict = options[:strict]
10
11
 
11
12
  # deprecated
12
13
  @allow_extra = options[:allow_extra]
13
14
  end
14
15
 
15
16
  def handle(request)
17
+ link = @router.find_request_link(request)
18
+
19
+ if link && @coerce_query_params && !request.GET.nil? && !link.schema.nil?
20
+ request.env["rack.request.query_hash"].merge!(
21
+ Committee::QueryParamsCoercer.new(
22
+ request.GET,
23
+ link.schema
24
+ ).call
25
+ )
26
+ end
27
+
16
28
  request.env[@params_key] = Committee::RequestUnpacker.new(
17
29
  request,
18
30
  allow_form_params: @allow_form_params,
@@ -20,7 +32,7 @@ module Committee::Middleware
20
32
  optimistic_json: @optimistic_json
21
33
  ).call
22
34
 
23
- if link = @router.find_request_link(request)
35
+ if link
24
36
  validator = Committee::RequestValidator.new(link, check_content_type: @check_content_type)
25
37
  validator.call(request, request.env[@params_key])
26
38
  @app.call(request.env)
@@ -0,0 +1,45 @@
1
+ # Attempts to coerce params given in the query hash (which are all strings) into
2
+ # the types specified by the schema.
3
+ # Currently supported types: null, integer, number and boolean.
4
+ # +call+ returns a hash of all params which could be coerced - coercion errors
5
+ # are simply ignored and expected to be handled later by schema validation.
6
+ module Committee
7
+ class QueryParamsCoercer
8
+ def initialize(query_hash, schema)
9
+ @query_hash = query_hash
10
+ @schema = schema
11
+ end
12
+
13
+ def call
14
+ coerced = {}
15
+ @schema.properties.each do |k, s|
16
+ original_val = @query_hash[k]
17
+ unless original_val.nil?
18
+ s.type.each do |to_type|
19
+ case to_type
20
+ when "null"
21
+ coerced[k] = nil if original_val.empty?
22
+ when "integer"
23
+ begin
24
+ coerced[k] = Integer(original_val)
25
+ rescue ArgumentError => e
26
+ raise e unless e.message =~ /invalid value for Integer/
27
+ end
28
+ when "number"
29
+ begin
30
+ coerced[k] = Float(original_val)
31
+ rescue ArgumentError => e
32
+ raise e unless e.message =~ /invalid value for Float/
33
+ end
34
+ when "boolean"
35
+ coerced[k] = true if original_val == "true"
36
+ coerced[k] = false if original_val == "false"
37
+ end
38
+ break if coerced.key?(k)
39
+ end
40
+ end
41
+ end
42
+ coerced
43
+ end
44
+ end
45
+ end
@@ -94,6 +94,21 @@ describe Committee::Middleware::RequestValidation do
94
94
  assert_equal 200, last_response.status
95
95
  end
96
96
 
97
+ it "optionally coerces query params" do
98
+ @app = new_rack_app(coerce_query_params: true)
99
+ header "Content-Type", "application/json"
100
+ get "/search/apps", {"per_page" => "10", "query" => "cloudnasium"}
101
+ assert_equal 200, last_response.status
102
+ end
103
+
104
+ it "still raises an error if query param coercion is not possible" do
105
+ @app = new_rack_app(coerce_query_params: true)
106
+ header "Content-Type", "application/json"
107
+ get "/search/apps", {"per_page" => "foo", "query" => "cloudnasium"}
108
+ assert_equal 400, last_response.status
109
+ assert_match /invalid request/i, last_response.body
110
+ end
111
+
97
112
  private
98
113
 
99
114
  def new_rack_app(options = {})
@@ -0,0 +1,70 @@
1
+ require_relative "test_helper"
2
+
3
+ describe Committee::QueryParamsCoercer do
4
+ before do
5
+ @schema =
6
+ JsonSchema.parse!(JSON.parse(File.read("./test/data/schema.json")))
7
+ @schema.expand_references!
8
+ # GET /search/apps
9
+ @link = @link = @schema.properties["app"].links[5]
10
+ end
11
+
12
+ it "doesn't coerce params not in the schema" do
13
+ data = {"owner" => "admin"}
14
+ assert_equal({}, call(data))
15
+ end
16
+
17
+ it "skips values for string param" do
18
+ data = {"name" => "foo"}
19
+ assert_equal({}, call(data))
20
+ end
21
+
22
+ it "coerces valid values for boolean param" do
23
+ data = {"deleted" => "true"}
24
+ assert_equal({"deleted" => true}, call(data))
25
+ data = {"deleted" => "false"}
26
+ assert_equal({"deleted" => false}, call(data))
27
+ end
28
+
29
+ it "skips invalid values for boolean param" do
30
+ data = {"deleted" => "foo"}
31
+ assert_equal({}, call(data))
32
+ end
33
+
34
+ it "coerces valid values for integer param" do
35
+ data = {"per_page" => "3"}
36
+ assert_equal({"per_page" => 3}, call(data))
37
+ end
38
+
39
+ it "skips invalid values for integer param" do
40
+ data = {"per_page" => "3.5"}
41
+ assert_equal({}, call(data))
42
+ data = {"per_page" => "false"}
43
+ assert_equal({}, call(data))
44
+ data = {"per_page" => ""}
45
+ assert_equal({}, call(data))
46
+ end
47
+
48
+ it "coerces valid values for number param" do
49
+ data = {"threshold" => "3"}
50
+ assert_equal({"threshold" => 3.0}, call(data))
51
+ data = {"threshold" => "3.5"}
52
+ assert_equal({"threshold" => 3.5}, call(data))
53
+ end
54
+
55
+ it "skips invalid values for number param" do
56
+ data = {"threshold" => "false"}
57
+ assert_equal({}, call(data))
58
+ end
59
+
60
+ it "coerces valid values for null param" do
61
+ data = {"threshold" => ""}
62
+ assert_equal({"threshold" => nil}, call(data))
63
+ end
64
+
65
+ private
66
+
67
+ def call(data)
68
+ Committee::QueryParamsCoercer.new(data, @link.schema).call
69
+ end
70
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: committee
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.14.1
4
+ version: 1.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brandur
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-05-26 00:00:00.000000000 Z
12
+ date: 2016-09-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json_schema
@@ -117,6 +117,7 @@ files:
117
117
  - lib/committee/middleware/request_validation.rb
118
118
  - lib/committee/middleware/response_validation.rb
119
119
  - lib/committee/middleware/stub.rb
120
+ - lib/committee/query_params_coercer.rb
120
121
  - lib/committee/request_unpacker.rb
121
122
  - lib/committee/request_validator.rb
122
123
  - lib/committee/response_generator.rb
@@ -128,6 +129,7 @@ files:
128
129
  - test/middleware/request_validation_test.rb
129
130
  - test/middleware/response_validation_test.rb
130
131
  - test/middleware/stub_test.rb
132
+ - test/query_params_coercer_test.rb
131
133
  - test/request_unpacker_test.rb
132
134
  - test/request_validator_test.rb
133
135
  - test/response_generator_test.rb