grape 0.17.0 → 0.18.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grape might be problematic. Click here for more details.

Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +22 -3
  3. data/Dangerfile +1 -80
  4. data/Gemfile +1 -1
  5. data/Gemfile.lock +69 -51
  6. data/README.md +42 -1
  7. data/UPGRADING.md +2 -2
  8. data/grape.gemspec +1 -1
  9. data/lib/grape/api.rb +5 -15
  10. data/lib/grape/cookies.rb +1 -1
  11. data/lib/grape/dsl/inside_route.rb +2 -3
  12. data/lib/grape/dsl/request_response.rb +1 -1
  13. data/lib/grape/endpoint.rb +19 -7
  14. data/lib/grape/error_formatter.rb +2 -2
  15. data/lib/grape/exceptions/base.rb +18 -18
  16. data/lib/grape/exceptions/validation.rb +6 -7
  17. data/lib/grape/exceptions/validation_errors.rb +5 -5
  18. data/lib/grape/formatter.rb +2 -2
  19. data/lib/grape/locale/en.yml +1 -0
  20. data/lib/grape/middleware/auth/base.rb +2 -2
  21. data/lib/grape/middleware/base.rb +2 -2
  22. data/lib/grape/middleware/error.rb +1 -1
  23. data/lib/grape/middleware/stack.rb +1 -1
  24. data/lib/grape/middleware/versioner/header.rb +1 -1
  25. data/lib/grape/namespace.rb +1 -1
  26. data/lib/grape/parser.rb +2 -2
  27. data/lib/grape/presenters/presenter.rb +1 -1
  28. data/lib/grape/router.rb +6 -6
  29. data/lib/grape/router/pattern.rb +7 -7
  30. data/lib/grape/router/route.rb +3 -3
  31. data/lib/grape/util/env.rb +1 -1
  32. data/lib/grape/validations/params_scope.rb +15 -7
  33. data/lib/grape/validations/validators/allow_blank.rb +0 -13
  34. data/lib/grape/validations/validators/base.rb +8 -1
  35. data/lib/grape/validations/validators/default.rb +1 -3
  36. data/lib/grape/validations/validators/presence.rb +0 -5
  37. data/lib/grape/validations/validators/values.rb +17 -3
  38. data/lib/grape/version.rb +1 -1
  39. data/pkg/grape-0.18.0.gem +0 -0
  40. data/spec/grape/api_spec.rb +41 -0
  41. data/spec/grape/exceptions/validation_spec.rb +1 -1
  42. data/spec/grape/middleware/stack_spec.rb +20 -0
  43. data/spec/grape/validations/params_scope_spec.rb +190 -58
  44. data/spec/grape/validations/validators/allow_blank_spec.rb +22 -7
  45. data/spec/grape/validations/validators/coerce_spec.rb +6 -6
  46. data/spec/grape/validations/validators/values_spec.rb +146 -0
  47. data/spec/grape/validations_spec.rb +28 -0
  48. metadata +6 -6
@@ -9,7 +9,12 @@ describe Grape::Validations::AllowBlankValidator do
9
9
  params do
10
10
  requires :name, allow_blank: false
11
11
  end
12
- get
12
+ get '/disallow_blank'
13
+
14
+ params do
15
+ optional :name, type: String, allow_blank: false
16
+ end
17
+ get '/opt_disallow_string_blank'
13
18
 
14
19
  params do
15
20
  optional :name, allow_blank: false
@@ -247,7 +252,7 @@ describe Grape::Validations::AllowBlankValidator do
247
252
 
248
253
  context 'invalid input' do
249
254
  it 'refuses empty string' do
250
- get '/', name: ''
255
+ get '/disallow_blank', name: ''
251
256
  expect(last_response.status).to eq(400)
252
257
 
253
258
  get '/disallow_datetime_blank', val: ''
@@ -255,18 +260,23 @@ describe Grape::Validations::AllowBlankValidator do
255
260
  end
256
261
 
257
262
  it 'refuses only whitespaces' do
258
- get '/', name: ' '
263
+ get '/disallow_blank', name: ' '
259
264
  expect(last_response.status).to eq(400)
260
265
 
261
- get '/', name: " \n "
266
+ get '/disallow_blank', name: " \n "
262
267
  expect(last_response.status).to eq(400)
263
268
 
264
- get '/', name: "\n"
269
+ get '/disallow_blank', name: "\n"
265
270
  expect(last_response.status).to eq(400)
266
271
  end
267
272
 
268
273
  it 'refuses nil' do
269
- get '/', name: nil
274
+ get '/disallow_blank', name: nil
275
+ expect(last_response.status).to eq(400)
276
+ end
277
+
278
+ it 'refuses missing' do
279
+ get '/disallow_blank'
270
280
  expect(last_response.status).to eq(400)
271
281
  end
272
282
  end
@@ -432,8 +442,13 @@ describe Grape::Validations::AllowBlankValidator do
432
442
  end
433
443
 
434
444
  context 'valid input' do
445
+ it 'allows missing optional strings' do
446
+ get 'opt_disallow_string_blank'
447
+ expect(last_response.status).to eq(200)
448
+ end
449
+
435
450
  it 'accepts valid input' do
436
- get '/', name: 'bob'
451
+ get '/disallow_blank', name: 'bob'
437
452
  expect(last_response.status).to eq(200)
438
453
  end
439
454
 
@@ -625,7 +625,7 @@ describe Grape::Validations::CoerceValidator do
625
625
 
626
626
  get '/', a: %w(the other)
627
627
  expect(last_response.status).to eq(200)
628
- expect(last_response.body).to eq('["the", "other"]')
628
+ expect(last_response.body).to eq('#<Hashie::Array ["the", "other"]>')
629
629
 
630
630
  get '/', a: { a: 1, b: 2 }
631
631
  expect(last_response.status).to eq(400)
@@ -633,27 +633,27 @@ describe Grape::Validations::CoerceValidator do
633
633
 
634
634
  get '/', a: [1, 2, 3]
635
635
  expect(last_response.status).to eq(200)
636
- expect(last_response.body).to eq('["1", "2", "3"]')
636
+ expect(last_response.body).to eq('#<Hashie::Array ["1", "2", "3"]>')
637
637
  end
638
638
 
639
639
  it 'allows multiple collection types' do
640
640
  get '/', b: [1, 2, 3]
641
641
  expect(last_response.status).to eq(200)
642
- expect(last_response.body).to eq('[1, 2, 3]')
642
+ expect(last_response.body).to eq('#<Hashie::Array [1, 2, 3]>')
643
643
 
644
644
  get '/', b: %w(1 2 3)
645
645
  expect(last_response.status).to eq(200)
646
- expect(last_response.body).to eq('[1, 2, 3]')
646
+ expect(last_response.body).to eq('#<Hashie::Array [1, 2, 3]>')
647
647
 
648
648
  get '/', b: [1, true, 'three']
649
649
  expect(last_response.status).to eq(200)
650
- expect(last_response.body).to eq('["1", "true", "three"]')
650
+ expect(last_response.body).to eq('#<Hashie::Array ["1", "true", "three"]>')
651
651
  end
652
652
 
653
653
  it 'allows collections with multiple types' do
654
654
  get '/', c: [1, '2', true, 'three']
655
655
  expect(last_response.status).to eq(200)
656
- expect(last_response.body).to eq('[1, 2, "true", "three"]')
656
+ expect(last_response.body).to eq('#<Hashie::Array [1, 2, "true", "three"]>')
657
657
 
658
658
  get '/', d: '1'
659
659
  expect(last_response.status).to eq(200)
@@ -4,6 +4,7 @@ describe Grape::Validations::ValuesValidator do
4
4
  module ValidationsSpec
5
5
  class ValuesModel
6
6
  DEFAULT_VALUES = ['valid-type1', 'valid-type2', 'valid-type3'].freeze
7
+ DEFAULT_EXCEPTS = ['invalid-type1', 'invalid-type2', 'invalid-type3'].freeze
7
8
  class << self
8
9
  def values
9
10
  @values ||= []
@@ -14,6 +15,16 @@ describe Grape::Validations::ValuesValidator do
14
15
  @values ||= []
15
16
  @values << value
16
17
  end
18
+
19
+ def excepts
20
+ @excepts ||= []
21
+ [DEFAULT_EXCEPTS + @excepts].flatten.uniq
22
+ end
23
+
24
+ def add_except(except)
25
+ @excepts ||= []
26
+ @excepts << except
27
+ end
17
28
  end
18
29
  end
19
30
 
@@ -35,6 +46,27 @@ describe Grape::Validations::ValuesValidator do
35
46
  get '/lambda' do
36
47
  { type: params[:type] }
37
48
  end
49
+
50
+ params do
51
+ requires :type, values: { except: ValuesModel.excepts, except_message: 'value is on exclusions list', message: 'default exclude message' }
52
+ end
53
+ get '/exclude/exclude_message' do
54
+ { type: params[:type] }
55
+ end
56
+
57
+ params do
58
+ requires :type, values: { except: -> { ValuesModel.excepts }, except_message: 'value is on exclusions list' }
59
+ end
60
+ get '/exclude/lambda/exclude_message' do
61
+ { type: params[:type] }
62
+ end
63
+
64
+ params do
65
+ requires :type, values: { except: ValuesModel.excepts, message: 'default exclude message' }
66
+ end
67
+ get '/exclude/fallback_message' do
68
+ { type: params[:type] }
69
+ end
38
70
  end
39
71
 
40
72
  params do
@@ -99,6 +131,34 @@ describe Grape::Validations::ValuesValidator do
99
131
  end
100
132
  end
101
133
  get '/optional_with_required_values'
134
+
135
+ params do
136
+ requires :type, values: { except: ValuesModel.excepts }
137
+ end
138
+ get '/except/exclusive' do
139
+ { type: params[:type] }
140
+ end
141
+
142
+ params do
143
+ requires :type, values: { except: -> { ValuesModel.excepts } }
144
+ end
145
+ get '/except/exclusive/lambda' do
146
+ { type: params[:type] }
147
+ end
148
+
149
+ params do
150
+ requires :type, type: Integer, values: { except: -> { [3, 4, 5] } }
151
+ end
152
+ get '/except/exclusive/lambda/coercion' do
153
+ { type: params[:type] }
154
+ end
155
+
156
+ params do
157
+ requires :type, type: Integer, values: { value: 1..5, except: [3] }
158
+ end
159
+ get '/mixed/value/except' do
160
+ { type: params[:type] }
161
+ end
102
162
  end
103
163
  end
104
164
  end
@@ -135,6 +195,30 @@ describe Grape::Validations::ValuesValidator do
135
195
  end
136
196
  end
137
197
 
198
+ context 'with a custom exclude validation message' do
199
+ it 'does not allow an invalid value for a parameter' do
200
+ get('/custom_message/exclude/exclude_message', type: 'invalid-type1')
201
+ expect(last_response.status).to eq 400
202
+ expect(last_response.body).to eq({ error: 'type value is on exclusions list' }.to_json)
203
+ end
204
+ end
205
+
206
+ context 'with a custom exclude validation message' do
207
+ it 'does not allow an invalid value for a parameter' do
208
+ get('/custom_message/exclude/lambda/exclude_message', type: 'invalid-type1')
209
+ expect(last_response.status).to eq 400
210
+ expect(last_response.body).to eq({ error: 'type value is on exclusions list' }.to_json)
211
+ end
212
+ end
213
+
214
+ context 'exclude with a standard custom validation message' do
215
+ it 'does not allow an invalid value for a parameter' do
216
+ get('/custom_message/exclude/fallback_message', type: 'invalid-type1')
217
+ expect(last_response.status).to eq 400
218
+ expect(last_response.body).to eq({ error: 'type default exclude message' }.to_json)
219
+ end
220
+ end
221
+
138
222
  it 'allows a valid value for a parameter' do
139
223
  get('/', type: 'valid-type1')
140
224
  expect(last_response.status).to eq 200
@@ -321,4 +405,66 @@ describe Grape::Validations::ValuesValidator do
321
405
  expect(last_response.body).to eq('values does not have a valid value')
322
406
  end
323
407
  end
408
+
409
+ context 'exclusive excepts' do
410
+ it 'allows any other value outside excepts' do
411
+ get '/except/exclusive', type: 'value'
412
+ expect(last_response.status).to eq 200
413
+ expect(last_response.body).to eq({ type: 'value' }.to_json)
414
+ end
415
+
416
+ it 'rejects values that matches except' do
417
+ get '/except/exclusive', type: 'invalid-type1'
418
+ expect(last_response.status).to eq 400
419
+ expect(last_response.body).to eq({ error: 'type has a value not allowed' }.to_json)
420
+ end
421
+ end
422
+
423
+ context 'exclusive excepts with lambda' do
424
+ it 'allows any other value outside excepts' do
425
+ get '/except/exclusive/lambda', type: 'value'
426
+ expect(last_response.status).to eq 200
427
+ expect(last_response.body).to eq({ type: 'value' }.to_json)
428
+ end
429
+
430
+ it 'rejects values that matches except' do
431
+ get '/except/exclusive/lambda', type: 'invalid-type1'
432
+ expect(last_response.status).to eq 400
433
+ expect(last_response.body).to eq({ error: 'type has a value not allowed' }.to_json)
434
+ end
435
+ end
436
+
437
+ context 'exclusive excepts with lambda and coercion' do
438
+ it 'allows any other value outside excepts' do
439
+ get '/except/exclusive/lambda/coercion', type: '10010000'
440
+ expect(last_response.status).to eq 200
441
+ expect(last_response.body).to eq({ type: 10_010_000 }.to_json)
442
+ end
443
+
444
+ it 'rejects values that matches except' do
445
+ get '/except/exclusive/lambda/coercion', type: '3'
446
+ expect(last_response.status).to eq 400
447
+ expect(last_response.body).to eq({ error: 'type has a value not allowed' }.to_json)
448
+ end
449
+ end
450
+
451
+ context 'with mixed values and excepts' do
452
+ it 'allows value, but not in except' do
453
+ get '/mixed/value/except', type: 2
454
+ expect(last_response.status).to eq 200
455
+ expect(last_response.body).to eq({ type: 2 }.to_json)
456
+ end
457
+
458
+ it 'rejects except' do
459
+ get '/mixed/value/except', type: 3
460
+ expect(last_response.status).to eq 400
461
+ expect(last_response.body).to eq({ error: 'type has a value not allowed' }.to_json)
462
+ end
463
+
464
+ it 'rejects outside except and outside value' do
465
+ get '/mixed/value/except', type: 10
466
+ expect(last_response.status).to eq 400
467
+ expect(last_response.body).to eq({ error: 'type does not have a valid value' }.to_json)
468
+ end
469
+ end
324
470
  end
@@ -274,6 +274,28 @@ describe Grape::Validations do
274
274
  end
275
275
  end
276
276
 
277
+ # Ensure there is no leakage between declared Array types and
278
+ # subsequent Hash types
279
+ context 'required with an Array and a Hash block' do
280
+ before do
281
+ subject.params do
282
+ requires :cats, type: Array[String], default: []
283
+ requires :items, type: Hash do
284
+ requires :key
285
+ end
286
+ end
287
+ subject.get '/required' do
288
+ 'required works'
289
+ end
290
+ end
291
+
292
+ it 'does not output index [0] for Hash types' do
293
+ get '/required', cats: ['Garfield'], items: { foo: 'bar' }
294
+ expect(last_response.status).to eq(400)
295
+ expect(last_response.body).to eq('items[key] is missing')
296
+ end
297
+ end
298
+
277
299
  context 'required with a Hash block' do
278
300
  before do
279
301
  subject.params do
@@ -292,6 +314,12 @@ describe Grape::Validations do
292
314
  expect(last_response.body).to eq('items is missing, items[key] is missing')
293
315
  end
294
316
 
317
+ it 'errors when nested param not present' do
318
+ get '/required', items: { foo: 'bar' }
319
+ expect(last_response.status).to eq(400)
320
+ expect(last_response.body).to eq('items[key] is missing')
321
+ end
322
+
295
323
  it 'errors when param is not a Hash' do
296
324
  get '/required', items: 'hello'
297
325
  expect(last_response.status).to eq(400)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grape
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.17.0
4
+ version: 0.18.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Bleigh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-07-29 00:00:00.000000000 Z
11
+ date: 2016-10-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -25,19 +25,19 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: 1.3.0
27
27
  - !ruby/object:Gem::Dependency
28
- name: mustermann19
28
+ name: mustermann-grape
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.4.3
33
+ version: 0.4.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.4.3
40
+ version: 0.4.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rack-accept
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -275,6 +275,7 @@ files:
275
275
  - lib/grape/validations/validators/regexp.rb
276
276
  - lib/grape/validations/validators/values.rb
277
277
  - lib/grape/version.rb
278
+ - pkg/grape-0.18.0.gem
278
279
  - spec/grape/api/custom_validations_spec.rb
279
280
  - spec/grape/api/deeply_included_options_spec.rb
280
281
  - spec/grape/api/invalid_format_spec.rb
@@ -474,4 +475,3 @@ test_files:
474
475
  - spec/support/endpoint_faker.rb
475
476
  - spec/support/file_streamer.rb
476
477
  - spec/support/versioned_helpers.rb
477
- has_rdoc: