committee 2.0.0.pre8 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/committee/middleware/request_validation.rb +10 -23
- data/lib/committee/parameter_coercer.rb +46 -14
- data/lib/committee/request_unpacker.rb +1 -4
- data/lib/committee/string_params_coercer.rb +74 -25
- data/test/middleware/request_validation_test.rb +197 -4
- data/test/parameter_coercer_test.rb +84 -6
- data/test/string_params_coercer_test.rb +89 -32
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0719ce2f2d3336816d822c41eace6161265ab86b
|
4
|
+
data.tar.gz: 8eaf8c70a09ed4ef5b6613897e54d370f8523ea6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c94926b7b0f4a0e92b99d448d5eb186c751b5b29fe7734038027f824ae2d892e8d93939d9c0d6f738b11d21926ef4235ac8a0818b2a03d8b4f421cbab5d396cf
|
7
|
+
data.tar.gz: 5df57d46e4d3f639705339a88c0464eb9c1677d314eccf1ea877d8449b13fb9f8d3da3d56f865fe1da5fcfe038eb1d3b2c43754de064a825a05ff4062447e5d6
|
@@ -9,6 +9,7 @@ module Committee::Middleware
|
|
9
9
|
@optimistic_json = options.fetch(:optimistic_json, false)
|
10
10
|
@strict = options[:strict]
|
11
11
|
@coerce_date_times = options.fetch(:coerce_date_times, false)
|
12
|
+
@coerce_recursive = options.fetch(:coerce_recursive, true)
|
12
13
|
|
13
14
|
@coerce_form_params = options.fetch(:coerce_form_params,
|
14
15
|
@schema.driver.default_coerce_form_params)
|
@@ -23,29 +24,18 @@ module Committee::Middleware
|
|
23
24
|
|
24
25
|
def handle(request)
|
25
26
|
link, param_matches = @router.find_request_link(request)
|
26
|
-
path_params = {}
|
27
27
|
|
28
28
|
if link
|
29
29
|
# Attempts to coerce parameters that appear in a link's URL to Ruby
|
30
30
|
# types that can be validated with a schema.
|
31
31
|
if @coerce_path_params
|
32
|
-
|
33
|
-
Committee::StringParamsCoercer.new(
|
34
|
-
param_matches,
|
35
|
-
link.schema
|
36
|
-
).call
|
37
|
-
)
|
32
|
+
Committee::StringParamsCoercer.new(param_matches, link.schema, coerce_recursive: @coerce_recursive).call!
|
38
33
|
end
|
39
34
|
|
40
35
|
# Attempts to coerce parameters that appear in a query string to Ruby
|
41
36
|
# types that can be validated with a schema.
|
42
37
|
if @coerce_query_params && !request.GET.nil? && !link.schema.nil?
|
43
|
-
request.
|
44
|
-
Committee::StringParamsCoercer.new(
|
45
|
-
request.GET,
|
46
|
-
link.schema
|
47
|
-
).call
|
48
|
-
)
|
38
|
+
Committee::StringParamsCoercer.new(request.GET, link.schema, coerce_recursive: @coerce_recursive).call!
|
49
39
|
end
|
50
40
|
end
|
51
41
|
|
@@ -58,14 +48,14 @@ module Committee::Middleware
|
|
58
48
|
schema: link ? link.schema : nil
|
59
49
|
).call
|
60
50
|
|
61
|
-
request.env[@params_key].merge!(
|
51
|
+
request.env[@params_key].merge!(param_matches) if param_matches
|
62
52
|
|
63
53
|
if link
|
64
54
|
validator = Committee::RequestValidator.new(link, check_content_type: @check_content_type)
|
65
55
|
validator.call(request, request.env[@params_key])
|
66
56
|
|
67
|
-
parameter_coerce(request, link, @params_key)
|
68
|
-
parameter_coerce(request, link, "rack.request.query_hash") if !request.GET.nil? && !link.schema.nil?
|
57
|
+
parameter_coerce!(request, link, @params_key)
|
58
|
+
parameter_coerce!(request, link, "rack.request.query_hash") if !request.GET.nil? && !link.schema.nil?
|
69
59
|
|
70
60
|
@app.call(request.env)
|
71
61
|
elsif @strict
|
@@ -90,13 +80,10 @@ module Committee::Middleware
|
|
90
80
|
|
91
81
|
private
|
92
82
|
|
93
|
-
def parameter_coerce(request, link, coerce_key)
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
coerce_date_times: @coerce_date_times)
|
98
|
-
.call
|
99
|
-
)
|
83
|
+
def parameter_coerce!(request, link, coerce_key)
|
84
|
+
Committee::ParameterCoercer.
|
85
|
+
new(request.env[coerce_key], link.schema, coerce_date_times: @coerce_date_times, coerce_recursive: @coerce_recursive).
|
86
|
+
call!
|
100
87
|
end
|
101
88
|
end
|
102
89
|
end
|
@@ -5,31 +5,63 @@ module Committee
|
|
5
5
|
@schema = schema
|
6
6
|
|
7
7
|
@coerce_date_times = options.fetch(:coerce_date_times, false)
|
8
|
+
@coerce_recursive = options.fetch(:coerce_recursive, false)
|
8
9
|
end
|
9
10
|
|
10
|
-
def call
|
11
|
-
|
12
|
-
|
11
|
+
def call!
|
12
|
+
coerce_object!(@params, @schema)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
13
16
|
|
14
|
-
|
15
|
-
|
17
|
+
def coerce_object!(hash, schema)
|
18
|
+
return false unless schema.respond_to?(:properties)
|
16
19
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
20
|
+
is_coerced = false
|
21
|
+
schema.properties.each do |k, s|
|
22
|
+
original_val = hash[k]
|
23
|
+
unless original_val.nil?
|
24
|
+
new_value, is_changed = coerce_value!(original_val, s)
|
25
|
+
if is_changed
|
26
|
+
hash[k] = new_value
|
27
|
+
is_coerced = true
|
22
28
|
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
is_coerced
|
33
|
+
end
|
23
34
|
|
24
|
-
|
35
|
+
def coerce_value!(original_val, s)
|
36
|
+
s.type.each do |to_type|
|
37
|
+
if @coerce_date_times && to_type == "string" && s.format == "date-time"
|
38
|
+
coerced_val = parse_date_time(original_val)
|
39
|
+
return coerced_val, true if coerced_val
|
25
40
|
end
|
41
|
+
|
42
|
+
return original_val, true if @coerce_recursive && (to_type == "array") && coerce_array_data!(original_val, s)
|
43
|
+
|
44
|
+
return original_val, true if @coerce_recursive && (to_type == "object") && coerce_object!(original_val, s)
|
26
45
|
end
|
46
|
+
return nil, false
|
27
47
|
end
|
28
48
|
|
29
|
-
|
30
|
-
|
49
|
+
def coerce_array_data!(original_val, schema)
|
50
|
+
return false unless schema.respond_to?(:items)
|
51
|
+
return false unless original_val.is_a?(Array)
|
52
|
+
|
53
|
+
is_coerced = false
|
54
|
+
original_val.each_with_index do |d, index|
|
55
|
+
new_value, is_changed = coerce_value!(d, schema.items)
|
56
|
+
if is_changed
|
57
|
+
original_val[index] = new_value
|
58
|
+
is_coerced = true
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
is_coerced
|
63
|
+
end
|
31
64
|
|
32
|
-
private
|
33
65
|
def parse_date_time(original_val)
|
34
66
|
begin
|
35
67
|
DateTime.parse(original_val)
|
@@ -10,41 +10,90 @@ module Committee
|
|
10
10
|
# errors are simply ignored and expected to be handled later by schema
|
11
11
|
# validation.
|
12
12
|
class StringParamsCoercer
|
13
|
-
def initialize(query_hash, schema)
|
13
|
+
def initialize(query_hash, schema, options = {})
|
14
14
|
@query_hash = query_hash
|
15
15
|
@schema = schema
|
16
|
+
|
17
|
+
@coerce_recursive = options.fetch(:coerce_recursive, false)
|
18
|
+
end
|
19
|
+
|
20
|
+
def call!
|
21
|
+
coerce_object!(@query_hash, @schema)
|
16
22
|
end
|
17
23
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
24
|
+
private
|
25
|
+
|
26
|
+
def coerce_object!(hash, schema)
|
27
|
+
return false unless schema.respond_to?(:properties)
|
28
|
+
|
29
|
+
is_coerced = false
|
30
|
+
schema.properties.each do |k, s|
|
31
|
+
original_val = hash[k]
|
32
|
+
unless original_val.nil?
|
33
|
+
new_value, is_changed = coerce_value!(original_val, s)
|
34
|
+
if is_changed
|
35
|
+
hash[k] = new_value
|
36
|
+
is_coerced = true
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
is_coerced
|
42
|
+
end
|
43
|
+
|
44
|
+
def coerce_value!(original_val, s)
|
22
45
|
unless original_val.nil?
|
23
46
|
s.type.each do |to_type|
|
24
47
|
case to_type
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
48
|
+
when "null"
|
49
|
+
return nil, true if original_val.empty?
|
50
|
+
when "integer"
|
51
|
+
begin
|
52
|
+
return Integer(original_val), true
|
53
|
+
rescue ArgumentError => e
|
54
|
+
raise e unless e.message =~ /invalid value for Integer/
|
55
|
+
end
|
56
|
+
when "number"
|
57
|
+
begin
|
58
|
+
return Float(original_val), true
|
59
|
+
rescue ArgumentError => e
|
60
|
+
raise e unless e.message =~ /invalid value for Float/
|
61
|
+
end
|
62
|
+
when "boolean"
|
63
|
+
if original_val == "true" || original_val == "1"
|
64
|
+
return true, true
|
65
|
+
end
|
66
|
+
if original_val == "false" || original_val == "0"
|
67
|
+
return false, true
|
68
|
+
end
|
69
|
+
when "array"
|
70
|
+
if @coerce_recursive && coerce_array_data!(original_val, s)
|
71
|
+
return original_val, true # change original value
|
72
|
+
end
|
73
|
+
when "object"
|
74
|
+
if @coerce_recursive && coerce_object!(original_val, s)
|
75
|
+
return original_val, true # change original value
|
76
|
+
end
|
42
77
|
end
|
43
|
-
break if coerced.key?(k)
|
44
78
|
end
|
45
79
|
end
|
80
|
+
return nil, false
|
81
|
+
end
|
82
|
+
|
83
|
+
def coerce_array_data!(original_val, schema)
|
84
|
+
return false unless schema.respond_to?(:items)
|
85
|
+
return false unless original_val.is_a?(Array)
|
86
|
+
|
87
|
+
is_coerced = false
|
88
|
+
original_val.each_with_index do |d, index|
|
89
|
+
new_value, is_changed = coerce_value!(d, schema.items)
|
90
|
+
if is_changed
|
91
|
+
original_val[index] = new_value
|
92
|
+
is_coerced = true
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
is_coerced
|
46
97
|
end
|
47
|
-
coerced
|
48
|
-
end
|
49
98
|
end
|
50
99
|
end
|
@@ -7,6 +7,50 @@ describe Committee::Middleware::RequestValidation do
|
|
7
7
|
@app
|
8
8
|
end
|
9
9
|
|
10
|
+
ARRAY_PROPERTY = [
|
11
|
+
{
|
12
|
+
"update_time" => "2016-04-01T16:00:00.000+09:00",
|
13
|
+
"per_page" => 1,
|
14
|
+
"nested_coercer_object" => {
|
15
|
+
"update_time" => "2016-04-01T16:00:00.000+09:00",
|
16
|
+
"threshold" => 1.5
|
17
|
+
},
|
18
|
+
"nested_no_coercer_object" => {
|
19
|
+
"per_page" => 1,
|
20
|
+
"threshold" => 1.5
|
21
|
+
},
|
22
|
+
"nested_coercer_array" => [
|
23
|
+
{
|
24
|
+
"update_time" => "2016-04-01T16:00:00.000+09:00",
|
25
|
+
"threshold" => 1.5
|
26
|
+
}
|
27
|
+
],
|
28
|
+
"nested_no_coercer_array" => [
|
29
|
+
{
|
30
|
+
"per_page" => 1,
|
31
|
+
"threshold" => 1.5
|
32
|
+
}
|
33
|
+
],
|
34
|
+
"integer_array" => [
|
35
|
+
1, 2, 3
|
36
|
+
],
|
37
|
+
"datetime_array" => [
|
38
|
+
"2016-04-01T16:00:00.000+09:00",
|
39
|
+
"2016-04-01T17:00:00.000+09:00",
|
40
|
+
"2016-04-01T18:00:00.000+09:00"
|
41
|
+
]
|
42
|
+
},
|
43
|
+
{
|
44
|
+
"update_time" => "2016-04-01T16:00:00.000+09:00",
|
45
|
+
"per_page" => 1,
|
46
|
+
"threshold" => 1.5
|
47
|
+
},
|
48
|
+
{
|
49
|
+
"threshold" => 1.5,
|
50
|
+
"per_page" => 1
|
51
|
+
}
|
52
|
+
]
|
53
|
+
|
10
54
|
it "passes through a valid request" do
|
11
55
|
@app = new_rack_app(schema: hyper_schema)
|
12
56
|
params = {
|
@@ -35,18 +79,162 @@ describe Committee::Middleware::RequestValidation do
|
|
35
79
|
assert_equal 200, last_response.status
|
36
80
|
end
|
37
81
|
|
38
|
-
it "passes
|
82
|
+
it "passes a nested object with recursive option" do
|
39
83
|
key_name = "update_time"
|
40
84
|
params = {
|
41
|
-
key_name => "2016-04-01T16:00:00.000+09:00"
|
85
|
+
key_name => "2016-04-01T16:00:00.000+09:00",
|
86
|
+
"query" => "cloudnasium",
|
87
|
+
"array_property" => ARRAY_PROPERTY
|
42
88
|
}
|
43
89
|
|
44
90
|
check_parameter = lambda { |env|
|
91
|
+
hash = env['rack.request.query_hash']
|
92
|
+
assert_equal DateTime, hash['array_property'].first['update_time'].class
|
93
|
+
assert_equal 1, hash['array_property'].first['per_page']
|
94
|
+
assert_equal DateTime, hash['array_property'].first['nested_coercer_object']['update_time'].class
|
95
|
+
assert_equal 1, hash['array_property'].first['nested_no_coercer_object']['per_page']
|
96
|
+
assert_equal 2, hash['array_property'].first['integer_array'][1]
|
97
|
+
assert_equal DateTime, hash['array_property'].first['datetime_array'][0].class
|
98
|
+
assert_equal DateTime, hash[key_name].class
|
99
|
+
[200, {}, []]
|
100
|
+
}
|
101
|
+
|
102
|
+
@app = new_rack_app_with_lambda(check_parameter,
|
103
|
+
coerce_query_params: true,
|
104
|
+
coerce_recursive: true,
|
105
|
+
coerce_date_times: true,
|
106
|
+
schema: hyper_schema)
|
107
|
+
|
108
|
+
get "/search/apps", params
|
109
|
+
assert_equal 200, last_response.status
|
110
|
+
end
|
111
|
+
|
112
|
+
it "passes a nested object with coerce_recursive false" do
|
113
|
+
key_name = "update_time"
|
114
|
+
params = {
|
115
|
+
key_name => "2016-04-01T16:00:00.000+09:00",
|
116
|
+
"query" => "cloudnasium",
|
117
|
+
"array_property" => ARRAY_PROPERTY
|
118
|
+
}
|
119
|
+
|
120
|
+
@app = new_rack_app(coerce_query_params: true, coerce_date_times: true, coerce_recursive: false, schema: hyper_schema)
|
121
|
+
|
122
|
+
get "/search/apps", params
|
123
|
+
assert_equal 400, last_response.status # schema expect integer but we don't convert string to integer, so 400
|
124
|
+
end
|
125
|
+
|
126
|
+
it "passes a nested object with coerce_recursive default(true)" do
|
127
|
+
key_name = "update_time"
|
128
|
+
params = {
|
129
|
+
key_name => "2016-04-01T16:00:00.000+09:00",
|
130
|
+
"query" => "cloudnasium",
|
131
|
+
"array_property" => ARRAY_PROPERTY
|
132
|
+
}
|
133
|
+
|
134
|
+
@app = new_rack_app(coerce_query_params: true, coerce_date_times: true, schema: hyper_schema)
|
135
|
+
|
136
|
+
get "/search/apps", params
|
137
|
+
assert_equal 200, last_response.status # schema expect integer but we don't convert string to integer, so 400
|
138
|
+
end
|
139
|
+
|
140
|
+
it "passes given a nested datetime and with coerce_recursive=true and coerce_date_times=true on POST endpoint" do
|
141
|
+
key_name = "update_time"
|
142
|
+
params = {
|
143
|
+
key_name => "2016-04-01T16:00:00.000+09:00",
|
144
|
+
"array_property" => ARRAY_PROPERTY
|
145
|
+
}
|
146
|
+
|
147
|
+
check_parameter = lambda { |env|
|
148
|
+
hash = env['committee.params']
|
149
|
+
assert_equal DateTime, hash['array_property'].first['update_time'].class
|
150
|
+
assert_equal 1, hash['array_property'].first['per_page']
|
151
|
+
assert_equal DateTime, hash['array_property'].first['nested_coercer_object']['update_time'].class
|
152
|
+
assert_equal 1, hash['array_property'].first['nested_no_coercer_object']['per_page']
|
153
|
+
assert_equal 2, hash['array_property'].first['integer_array'][1]
|
154
|
+
assert_equal DateTime, hash['array_property'].first['datetime_array'][0].class
|
45
155
|
assert_equal DateTime, env['committee.params'][key_name].class
|
46
156
|
[200, {}, []]
|
47
157
|
}
|
48
158
|
|
49
|
-
@app = new_rack_app_with_lambda(check_parameter, coerce_date_times: true, schema: hyper_schema)
|
159
|
+
@app = new_rack_app_with_lambda(check_parameter, coerce_date_times: true, coerce_recursive: true, schema: hyper_schema)
|
160
|
+
|
161
|
+
header "Content-Type", "application/json"
|
162
|
+
post "/apps", JSON.generate(params)
|
163
|
+
assert_equal 200, last_response.status
|
164
|
+
end
|
165
|
+
|
166
|
+
it "passes given a nested datetime and with coerce_recursive=true and coerce_date_times=true on POST endpoint" do
|
167
|
+
key_name = "update_time"
|
168
|
+
params = {
|
169
|
+
key_name => "2016-04-01T16:00:00.000+09:00",
|
170
|
+
"array_property" => ARRAY_PROPERTY
|
171
|
+
}
|
172
|
+
|
173
|
+
check_parameter = lambda { |env|
|
174
|
+
hash = env['committee.params']
|
175
|
+
assert_equal String, hash['array_property'].first['update_time'].class
|
176
|
+
assert_equal 1, hash['array_property'].first['per_page']
|
177
|
+
assert_equal String, hash['array_property'].first['nested_coercer_object']['update_time'].class
|
178
|
+
assert_equal 1, hash['array_property'].first['nested_no_coercer_object']['per_page']
|
179
|
+
assert_equal 2, hash['array_property'].first['integer_array'][1]
|
180
|
+
assert_equal String, hash['array_property'].first['datetime_array'][0].class
|
181
|
+
assert_equal String, env['committee.params'][key_name].class
|
182
|
+
[200, {}, []]
|
183
|
+
}
|
184
|
+
|
185
|
+
@app = new_rack_app_with_lambda(check_parameter, schema: hyper_schema)
|
186
|
+
|
187
|
+
header "Content-Type", "application/json"
|
188
|
+
post "/apps", JSON.generate(params)
|
189
|
+
assert_equal 200, last_response.status
|
190
|
+
end
|
191
|
+
|
192
|
+
it "passes given a nested datetime and with coerce_recursive=false and coerce_date_times=true on POST endpoint" do
|
193
|
+
key_name = "update_time"
|
194
|
+
params = {
|
195
|
+
key_name => "2016-04-01T16:00:00.000+09:00",
|
196
|
+
"array_property" => ARRAY_PROPERTY
|
197
|
+
}
|
198
|
+
|
199
|
+
check_parameter = lambda { |env|
|
200
|
+
hash = env['committee.params']
|
201
|
+
assert_equal String, hash['array_property'].first['update_time'].class
|
202
|
+
assert_equal 1, hash['array_property'].first['per_page']
|
203
|
+
assert_equal String, hash['array_property'].first['nested_coercer_object']['update_time'].class
|
204
|
+
assert_equal 1, hash['array_property'].first['nested_no_coercer_object']['per_page']
|
205
|
+
assert_equal 2, hash['array_property'].first['integer_array'][1]
|
206
|
+
assert_equal String, hash['array_property'].first['datetime_array'][0].class
|
207
|
+
assert_equal DateTime, env['committee.params'][key_name].class
|
208
|
+
[200, {}, []]
|
209
|
+
}
|
210
|
+
|
211
|
+
@app = new_rack_app_with_lambda(check_parameter, coerce_date_times: true, coerce_recursive: false, schema: hyper_schema)
|
212
|
+
|
213
|
+
header "Content-Type", "application/json"
|
214
|
+
post "/apps", JSON.generate(params)
|
215
|
+
assert_equal 200, last_response.status
|
216
|
+
end
|
217
|
+
|
218
|
+
it "passes given a nested datetime and with coerce_recursive=false and coerce_date_times=false on POST endpoint" do
|
219
|
+
key_name = "update_time"
|
220
|
+
params = {
|
221
|
+
key_name => "2016-04-01T16:00:00.000+09:00",
|
222
|
+
"array_property" => ARRAY_PROPERTY
|
223
|
+
}
|
224
|
+
|
225
|
+
check_parameter = lambda { |env|
|
226
|
+
hash = env['committee.params']
|
227
|
+
assert_equal String, hash['array_property'].first['update_time'].class
|
228
|
+
assert_equal 1, hash['array_property'].first['per_page']
|
229
|
+
assert_equal String, hash['array_property'].first['nested_coercer_object']['update_time'].class
|
230
|
+
assert_equal 1, hash['array_property'].first['nested_no_coercer_object']['per_page']
|
231
|
+
assert_equal 2, hash['array_property'].first['integer_array'][1]
|
232
|
+
assert_equal String, hash['array_property'].first['datetime_array'][0].class
|
233
|
+
assert_equal String, env['committee.params'][key_name].class
|
234
|
+
[200, {}, []]
|
235
|
+
}
|
236
|
+
|
237
|
+
@app = new_rack_app_with_lambda(check_parameter, schema: hyper_schema)
|
50
238
|
|
51
239
|
header "Content-Type", "application/json"
|
52
240
|
post "/apps", JSON.generate(params)
|
@@ -153,7 +341,12 @@ describe Committee::Middleware::RequestValidation do
|
|
153
341
|
end
|
154
342
|
|
155
343
|
it "passes through a valid request for OpenAPI" do
|
156
|
-
|
344
|
+
check_parameter = lambda { |env|
|
345
|
+
assert_equal 3, env['rack.request.query_hash']['limit']
|
346
|
+
[200, {}, []]
|
347
|
+
}
|
348
|
+
|
349
|
+
@app = new_rack_app_with_lambda(check_parameter, schema: open_api_2_schema)
|
157
350
|
get "/api/pets?limit=3"
|
158
351
|
assert_equal 200, last_response.status
|
159
352
|
end
|
@@ -12,22 +12,100 @@ describe Committee::ParameterCoercer do
|
|
12
12
|
|
13
13
|
it "pass datetime string" do
|
14
14
|
params = { "update_time" => "2016-04-01T16:00:00.000+09:00"}
|
15
|
-
|
15
|
+
call(params, coerce_date_times: true)
|
16
16
|
|
17
|
-
assert_kind_of DateTime,
|
17
|
+
assert_kind_of DateTime, params["update_time"]
|
18
|
+
end
|
19
|
+
|
20
|
+
it "don't change object type" do
|
21
|
+
params = HashLikeObject.new
|
22
|
+
params["update_time"] = "2016-04-01T16:00:00.000+09:00"
|
23
|
+
call(params, coerce_date_times: true)
|
24
|
+
|
25
|
+
assert_kind_of DateTime, params["update_time"]
|
26
|
+
assert_kind_of HashLikeObject, params
|
18
27
|
end
|
19
28
|
|
20
29
|
it "pass invalid datetime string, not convert" do
|
21
|
-
|
22
|
-
|
30
|
+
invalid_datetime = "llmfllmf"
|
31
|
+
params = { "update_time" => invalid_datetime}
|
32
|
+
call(params, coerce_date_times: true)
|
23
33
|
|
24
|
-
|
34
|
+
assert_equal invalid_datetime, params["update_time"]
|
35
|
+
end
|
36
|
+
|
37
|
+
it "pass array property" do
|
38
|
+
params = {
|
39
|
+
"array_property" => [
|
40
|
+
{
|
41
|
+
"update_time" => "2016-04-01T16:00:00.000+09:00",
|
42
|
+
"per_page" => 1,
|
43
|
+
"nested_coercer_object" => {
|
44
|
+
"update_time" => "2016-04-01T16:00:00.000+09:00",
|
45
|
+
"threshold" => 1.5
|
46
|
+
},
|
47
|
+
"nested_no_coercer_object" => {
|
48
|
+
"per_page" => 1,
|
49
|
+
"threshold" => 1.5
|
50
|
+
},
|
51
|
+
"nested_coercer_array" => [
|
52
|
+
{
|
53
|
+
"update_time" => "2016-04-01T16:00:00.000+09:00",
|
54
|
+
"threshold" => 1.5
|
55
|
+
}
|
56
|
+
],
|
57
|
+
"nested_no_coercer_array" => [
|
58
|
+
{
|
59
|
+
"per_page" => 1,
|
60
|
+
"threshold" => 1.5
|
61
|
+
}
|
62
|
+
]
|
63
|
+
},
|
64
|
+
{
|
65
|
+
"update_time" => "2016-04-01T16:00:00.000+09:00",
|
66
|
+
"per_page" => 1,
|
67
|
+
"threshold" => 1.5
|
68
|
+
},
|
69
|
+
{
|
70
|
+
"threshold" => 1.5,
|
71
|
+
"per_page" => 1
|
72
|
+
}
|
73
|
+
],
|
74
|
+
}
|
75
|
+
call(params, coerce_date_times: true, coerce_recursive: true)
|
76
|
+
|
77
|
+
first_data = params["array_property"][0]
|
78
|
+
assert_kind_of DateTime, first_data["update_time"]
|
79
|
+
assert_kind_of Integer, first_data["per_page"]
|
80
|
+
|
81
|
+
second_data = params["array_property"][1]
|
82
|
+
assert_kind_of DateTime, second_data["update_time"]
|
83
|
+
assert_kind_of Integer, second_data["per_page"]
|
84
|
+
assert_kind_of Float, second_data["threshold"]
|
85
|
+
|
86
|
+
third_data = params["array_property"][1]
|
87
|
+
assert_kind_of Integer, third_data["per_page"]
|
88
|
+
assert_kind_of Float, third_data["threshold"]
|
89
|
+
|
90
|
+
assert_kind_of DateTime, first_data["nested_coercer_object"]["update_time"]
|
91
|
+
assert_kind_of Float, first_data["nested_coercer_object"]["threshold"]
|
92
|
+
|
93
|
+
assert_kind_of Integer, first_data["nested_no_coercer_object"]["per_page"]
|
94
|
+
assert_kind_of Float, first_data["nested_no_coercer_object"]["threshold"]
|
95
|
+
|
96
|
+
assert_kind_of DateTime, first_data["nested_coercer_array"].first["update_time"]
|
97
|
+
assert_kind_of Float, first_data["nested_coercer_array"].first["threshold"]
|
98
|
+
|
99
|
+
assert_kind_of Integer, first_data["nested_no_coercer_array"].first["per_page"]
|
100
|
+
assert_kind_of Float, first_data["nested_no_coercer_array"].first["threshold"]
|
25
101
|
end
|
26
102
|
|
27
103
|
private
|
28
104
|
|
105
|
+
class HashLikeObject < Hash; end
|
106
|
+
|
29
107
|
def call(params, options={})
|
30
108
|
link = Committee::Drivers::HyperSchema::Link.new(@link)
|
31
|
-
Committee::ParameterCoercer.new(params, link.schema, options).call
|
109
|
+
Committee::ParameterCoercer.new(params, link.schema, options).call!
|
32
110
|
end
|
33
111
|
end
|
@@ -9,65 +9,122 @@ describe Committee::StringParamsCoercer do
|
|
9
9
|
end
|
10
10
|
|
11
11
|
it "doesn't coerce params not in the schema" do
|
12
|
-
|
13
|
-
assert_equal({}, call(data))
|
12
|
+
check_convert("onwer", "admin", "admin")
|
14
13
|
end
|
15
14
|
|
16
15
|
it "skips values for string param" do
|
17
|
-
|
18
|
-
assert_equal({}, call(data))
|
16
|
+
check_convert("name", "foo", "foo")
|
19
17
|
end
|
20
18
|
|
21
19
|
it "coerces valid values for boolean param" do
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
data = {"deleted" => "1"}
|
27
|
-
assert_equal({"deleted" => true}, call(data))
|
28
|
-
data = {"deleted" => "0"}
|
29
|
-
assert_equal({"deleted" => false}, call(data))
|
20
|
+
check_convert("deleted", "true", true)
|
21
|
+
check_convert("deleted", "false", false)
|
22
|
+
check_convert("deleted", "1", true)
|
23
|
+
check_convert("deleted", "0", false)
|
30
24
|
end
|
31
25
|
|
32
26
|
it "skips invalid values for boolean param" do
|
33
|
-
|
34
|
-
assert_equal({}, call(data))
|
27
|
+
check_convert("deleted", "foo", "foo")
|
35
28
|
end
|
36
29
|
|
37
30
|
it "coerces valid values for integer param" do
|
38
|
-
|
39
|
-
assert_equal({"per_page" => 3}, call(data))
|
31
|
+
check_convert("per_page", "3", 3)
|
40
32
|
end
|
41
33
|
|
42
34
|
it "skips invalid values for integer param" do
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
assert_equal({}, call(data))
|
47
|
-
data = {"per_page" => ""}
|
48
|
-
assert_equal({}, call(data))
|
35
|
+
check_convert("per_page", "3.5", "3.5")
|
36
|
+
check_convert("per_page", "false", "false")
|
37
|
+
check_convert("per_page", "", "")
|
49
38
|
end
|
50
39
|
|
51
40
|
it "coerces valid values for number param" do
|
52
|
-
|
53
|
-
|
54
|
-
data = {"threshold" => "3.5"}
|
55
|
-
assert_equal({"threshold" => 3.5}, call(data))
|
41
|
+
check_convert("threshold", "3", 3.0)
|
42
|
+
check_convert("threshold", "3.5", 3.5)
|
56
43
|
end
|
57
44
|
|
58
45
|
it "skips invalid values for number param" do
|
59
|
-
|
60
|
-
assert_equal({}, call(data))
|
46
|
+
check_convert("threshold", "false", "false")
|
61
47
|
end
|
62
48
|
|
63
49
|
it "coerces valid values for null param" do
|
64
|
-
|
65
|
-
|
50
|
+
check_convert("threshold", "", nil)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "pass array property" do
|
54
|
+
params = {
|
55
|
+
"array_property" => [
|
56
|
+
{
|
57
|
+
"update_time" => "2016-04-01T16:00:00.000+09:00",
|
58
|
+
"per_page" => "1",
|
59
|
+
"nested_coercer_object" => {
|
60
|
+
"update_time" => "2016-04-01T16:00:00.000+09:00",
|
61
|
+
"threshold" => "1.5"
|
62
|
+
},
|
63
|
+
"nested_no_coercer_object" => {
|
64
|
+
"per_page" => "1",
|
65
|
+
"threshold" => "1.5"
|
66
|
+
},
|
67
|
+
"nested_coercer_array" => [
|
68
|
+
{
|
69
|
+
"update_time" => "2016-04-01T16:00:00.000+09:00",
|
70
|
+
"threshold" => "1.5"
|
71
|
+
}
|
72
|
+
],
|
73
|
+
"nested_no_coercer_array" => [
|
74
|
+
{
|
75
|
+
"per_page" => "1",
|
76
|
+
"threshold" => "1.5"
|
77
|
+
}
|
78
|
+
]
|
79
|
+
},
|
80
|
+
{
|
81
|
+
"update_time" => "2016-04-01T16:00:00.000+09:00",
|
82
|
+
"per_page" => "1",
|
83
|
+
"threshold" => "1.5"
|
84
|
+
},
|
85
|
+
{
|
86
|
+
"threshold" => "1.5",
|
87
|
+
"per_page" => "1"
|
88
|
+
}
|
89
|
+
],
|
90
|
+
}
|
91
|
+
call(params, coerce_recursive: true)
|
92
|
+
|
93
|
+
first_data = params["array_property"][0]
|
94
|
+
assert_kind_of String, first_data["update_time"]
|
95
|
+
assert_kind_of Integer, first_data["per_page"]
|
96
|
+
|
97
|
+
second_data = params["array_property"][1]
|
98
|
+
assert_kind_of String, second_data["update_time"]
|
99
|
+
assert_kind_of Integer, second_data["per_page"]
|
100
|
+
assert_kind_of Float, second_data["threshold"]
|
101
|
+
|
102
|
+
third_data = params["array_property"][1]
|
103
|
+
assert_kind_of Integer, third_data["per_page"]
|
104
|
+
assert_kind_of Float, third_data["threshold"]
|
105
|
+
|
106
|
+
assert_kind_of String, first_data["nested_coercer_object"]["update_time"]
|
107
|
+
assert_kind_of Float, first_data["nested_coercer_object"]["threshold"]
|
108
|
+
|
109
|
+
assert_kind_of Integer, first_data["nested_no_coercer_object"]["per_page"]
|
110
|
+
assert_kind_of Float, first_data["nested_no_coercer_object"]["threshold"]
|
111
|
+
|
112
|
+
assert_kind_of String, first_data["nested_coercer_array"].first["update_time"]
|
113
|
+
assert_kind_of Float, first_data["nested_coercer_array"].first["threshold"]
|
114
|
+
|
115
|
+
assert_kind_of Integer, first_data["nested_no_coercer_array"].first["per_page"]
|
116
|
+
assert_kind_of Float, first_data["nested_no_coercer_array"].first["threshold"]
|
66
117
|
end
|
67
118
|
|
68
119
|
private
|
69
120
|
|
70
|
-
def
|
71
|
-
|
121
|
+
def check_convert(key, before_value, after_value)
|
122
|
+
data = {key => before_value}
|
123
|
+
call(data)
|
124
|
+
assert_equal(data[key], after_value)
|
125
|
+
end
|
126
|
+
|
127
|
+
def call(data, options={})
|
128
|
+
Committee::StringParamsCoercer.new(data, @link.schema, options).call!
|
72
129
|
end
|
73
130
|
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: 2.0.0
|
4
|
+
version: 2.0.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: 2017-05
|
12
|
+
date: 2017-09-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: json_schema
|
@@ -207,12 +207,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
207
207
|
version: '0'
|
208
208
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
209
209
|
requirements:
|
210
|
-
- - "
|
210
|
+
- - ">="
|
211
211
|
- !ruby/object:Gem::Version
|
212
|
-
version:
|
212
|
+
version: '0'
|
213
213
|
requirements: []
|
214
214
|
rubyforge_project:
|
215
|
-
rubygems_version: 2.
|
215
|
+
rubygems_version: 2.6.12
|
216
216
|
signing_key:
|
217
217
|
specification_version: 4
|
218
218
|
summary: A collection of Rack middleware to support JSON Schema.
|