grape 0.8.0 → 0.9.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 (78) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -2
  3. data/.rubocop_todo.yml +80 -0
  4. data/.travis.yml +2 -2
  5. data/CHANGELOG.md +21 -2
  6. data/Gemfile +1 -6
  7. data/Guardfile +1 -5
  8. data/README.md +110 -27
  9. data/Rakefile +1 -1
  10. data/UPGRADING.md +35 -0
  11. data/grape.gemspec +5 -2
  12. data/lib/grape.rb +20 -4
  13. data/lib/grape/api.rb +25 -467
  14. data/lib/grape/api/helpers.rb +7 -0
  15. data/lib/grape/dsl/callbacks.rb +27 -0
  16. data/lib/grape/dsl/configuration.rb +27 -0
  17. data/lib/grape/dsl/helpers.rb +86 -0
  18. data/lib/grape/dsl/inside_route.rb +227 -0
  19. data/lib/grape/dsl/middleware.rb +33 -0
  20. data/lib/grape/dsl/parameters.rb +79 -0
  21. data/lib/grape/dsl/request_response.rb +152 -0
  22. data/lib/grape/dsl/routing.rb +172 -0
  23. data/lib/grape/dsl/validations.rb +29 -0
  24. data/lib/grape/endpoint.rb +6 -226
  25. data/lib/grape/error_formatter/base.rb +28 -0
  26. data/lib/grape/error_formatter/json.rb +2 -0
  27. data/lib/grape/error_formatter/txt.rb +2 -0
  28. data/lib/grape/error_formatter/xml.rb +2 -0
  29. data/lib/grape/exceptions/base.rb +6 -0
  30. data/lib/grape/exceptions/validation.rb +3 -3
  31. data/lib/grape/exceptions/validation_errors.rb +19 -6
  32. data/lib/grape/locale/en.yml +5 -3
  33. data/lib/grape/middleware/auth/base.rb +28 -12
  34. data/lib/grape/middleware/auth/dsl.rb +35 -0
  35. data/lib/grape/middleware/auth/strategies.rb +24 -0
  36. data/lib/grape/middleware/auth/strategy_info.rb +15 -0
  37. data/lib/grape/validations.rb +3 -92
  38. data/lib/grape/validations/at_least_one_of.rb +25 -0
  39. data/lib/grape/validations/coerce.rb +2 -2
  40. data/lib/grape/validations/exactly_one_of.rb +2 -2
  41. data/lib/grape/validations/mutual_exclusion.rb +2 -2
  42. data/lib/grape/validations/presence.rb +1 -1
  43. data/lib/grape/validations/regexp.rb +1 -1
  44. data/lib/grape/validations/values.rb +1 -1
  45. data/lib/grape/version.rb +1 -1
  46. data/spec/grape/api/helpers_spec.rb +36 -0
  47. data/spec/grape/api_spec.rb +72 -19
  48. data/spec/grape/dsl/callbacks_spec.rb +44 -0
  49. data/spec/grape/dsl/configuration_spec.rb +37 -0
  50. data/spec/grape/dsl/helpers_spec.rb +54 -0
  51. data/spec/grape/dsl/inside_route_spec.rb +222 -0
  52. data/spec/grape/dsl/middleware_spec.rb +40 -0
  53. data/spec/grape/dsl/parameters_spec.rb +108 -0
  54. data/spec/grape/dsl/request_response_spec.rb +123 -0
  55. data/spec/grape/dsl/routing_spec.rb +132 -0
  56. data/spec/grape/dsl/validations_spec.rb +55 -0
  57. data/spec/grape/endpoint_spec.rb +60 -11
  58. data/spec/grape/entity_spec.rb +9 -4
  59. data/spec/grape/exceptions/validation_errors_spec.rb +31 -1
  60. data/spec/grape/middleware/auth/base_spec.rb +34 -0
  61. data/spec/grape/middleware/auth/dsl_spec.rb +53 -0
  62. data/spec/grape/middleware/auth/strategies_spec.rb +81 -0
  63. data/spec/grape/middleware/error_spec.rb +33 -1
  64. data/spec/grape/middleware/exception_spec.rb +13 -0
  65. data/spec/grape/validations/at_least_one_of_spec.rb +63 -0
  66. data/spec/grape/validations/exactly_one_of_spec.rb +1 -1
  67. data/spec/grape/validations/presence_spec.rb +159 -122
  68. data/spec/grape/validations/zh-CN.yml +1 -1
  69. data/spec/grape/validations_spec.rb +77 -15
  70. data/spec/spec_helper.rb +1 -0
  71. data/spec/support/endpoint_faker.rb +23 -0
  72. metadata +93 -15
  73. data/lib/grape/middleware/auth/basic.rb +0 -13
  74. data/lib/grape/middleware/auth/digest.rb +0 -13
  75. data/lib/grape/middleware/auth/oauth2.rb +0 -83
  76. data/spec/grape/middleware/auth/basic_spec.rb +0 -31
  77. data/spec/grape/middleware/auth/digest_spec.rb +0 -47
  78. data/spec/grape/middleware/auth/oauth2_spec.rb +0 -135
@@ -1,83 +0,0 @@
1
- module Grape
2
- module Middleware
3
- module Auth
4
- # OAuth 2.0 authorization for Grape APIs.
5
- class OAuth2 < Grape::Middleware::Base
6
- def default_options
7
- {
8
- token_class: 'AccessToken',
9
- realm: 'OAuth API',
10
- parameter: %w(bearer_token oauth_token access_token),
11
- accepted_headers: %w(HTTP_AUTHORIZATION X_HTTP_AUTHORIZATION X-HTTP_AUTHORIZATION REDIRECT_X_HTTP_AUTHORIZATION),
12
- header: [/Bearer (.*)/i, /OAuth (.*)/i],
13
- required: true
14
- }
15
- end
16
-
17
- def before
18
- verify_token(token_parameter || token_header)
19
- end
20
-
21
- def request
22
- @request ||= Grape::Request.new(env)
23
- end
24
-
25
- def params
26
- @params ||= request.params
27
- end
28
-
29
- def token_parameter
30
- Array(options[:parameter]).each do |p|
31
- return params[p] if params[p]
32
- end
33
- nil
34
- end
35
-
36
- def token_header
37
- return false unless authorization_header
38
- Array(options[:header]).each do |regexp|
39
- return $1 if authorization_header =~ regexp
40
- end
41
- nil
42
- end
43
-
44
- def authorization_header
45
- options[:accepted_headers].each do |head|
46
- return env[head] if env[head]
47
- end
48
- nil
49
- end
50
-
51
- def token_class
52
- @klass ||= eval(options[:token_class]) # rubocop:disable Eval
53
- end
54
-
55
- def verify_token(token)
56
- token = token_class.verify(token)
57
- if token
58
- if token.respond_to?(:expired?) && token.expired?
59
- error_out(401, 'invalid_grant')
60
- else
61
- if !token.respond_to?(:permission_for?) || token.permission_for?(env)
62
- env['api.token'] = token
63
- else
64
- error_out(403, 'insufficient_scope')
65
- end
66
- end
67
- elsif !!options[:required]
68
- error_out(401, 'invalid_grant')
69
- end
70
- end
71
-
72
- def error_out(status, error)
73
- throw :error,
74
- message: error,
75
- status: status,
76
- headers: {
77
- 'WWW-Authenticate' => "OAuth realm='#{options[:realm]}', error='#{error}'"
78
- }
79
- end
80
- end
81
- end
82
- end
83
- end
@@ -1,31 +0,0 @@
1
- require 'spec_helper'
2
-
3
- require 'base64'
4
-
5
- describe Grape::Middleware::Auth::Basic do
6
- def app
7
- Rack::Builder.new do |b|
8
- b.use Grape::Middleware::Error
9
- b.use(Grape::Middleware::Auth::Basic) do |u, p|
10
- u && p && u == p
11
- end
12
- b.run lambda { |env| [200, {}, ["Hello there."]] }
13
- end
14
- end
15
-
16
- it 'throws a 401 if no auth is given' do
17
- @proc = lambda { false }
18
- get '/whatever'
19
- expect(last_response.status).to eq(401)
20
- end
21
-
22
- it 'authenticates if given valid creds' do
23
- get '/whatever', {}, 'HTTP_AUTHORIZATION' => encode_basic_auth('admin', 'admin')
24
- expect(last_response.status).to eq(200)
25
- end
26
-
27
- it 'throws a 401 is wrong auth is given' do
28
- get '/whatever', {}, 'HTTP_AUTHORIZATION' => encode_basic_auth('admin', 'wrong')
29
- expect(last_response.status).to eq(401)
30
- end
31
- end
@@ -1,47 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec::Matchers.define :be_challenge do
4
- match do |actual_response|
5
- actual_response.status == 401 &&
6
- actual_response['WWW-Authenticate'] =~ /^Digest / &&
7
- actual_response.body.empty?
8
- end
9
- end
10
-
11
- class Test < Grape::API
12
- http_digest(realm: 'Test Api', opaque: 'secret') do |username|
13
- { 'foo' => 'bar' }[username]
14
- end
15
-
16
- get '/test' do
17
- [{ hey: 'you' }, { there: 'bar' }, { foo: 'baz' }]
18
- end
19
- end
20
-
21
- describe Grape::Middleware::Auth::Digest do
22
- def app
23
- Test
24
- end
25
-
26
- it 'is a digest authentication challenge' do
27
- get '/test'
28
- expect(last_response).to be_challenge
29
- end
30
-
31
- it 'throws a 401 if no auth is given' do
32
- get '/test'
33
- expect(last_response.status).to eq(401)
34
- end
35
-
36
- it 'authenticates if given valid creds' do
37
- digest_authorize "foo", "bar"
38
- get '/test'
39
- expect(last_response.status).to eq(200)
40
- end
41
-
42
- it 'throws a 401 if given invalid creds' do
43
- digest_authorize "bar", "foo"
44
- get '/test'
45
- expect(last_response.status).to eq(401)
46
- end
47
- end
@@ -1,135 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Grape::Middleware::Auth::OAuth2 do
4
- class FakeToken
5
- attr_accessor :token
6
-
7
- def self.verify(token)
8
- FakeToken.new(token) if !!token && %w(g e).include?(token[0..0])
9
- end
10
-
11
- def initialize(token)
12
- @token = token
13
- end
14
-
15
- def expired?
16
- @token[0..0] == 'e'
17
- end
18
-
19
- def permission_for?(env)
20
- env['PATH_INFO'] == '/forbidden' ? false : true
21
- end
22
- end
23
-
24
- def app
25
- Rack::Builder.app do
26
- use Grape::Middleware::Auth::OAuth2, token_class: 'FakeToken'
27
- run lambda { |env| [200, {}, [(env['api.token'].token if env['api.token'])]] }
28
- end
29
- end
30
-
31
- context 'with the token in the query string' do
32
- context 'and a valid token' do
33
- before { get '/awesome?access_token=g123' }
34
-
35
- it 'sets env["api.token"]' do
36
- expect(last_response.body).to eq('g123')
37
- end
38
- end
39
-
40
- context 'and an invalid token' do
41
- before do
42
- @err = catch :error do
43
- get '/awesome?access_token=b123'
44
- end
45
- end
46
-
47
- it 'throws an error' do
48
- expect(@err[:status]).to eq(401)
49
- end
50
-
51
- it 'sets the WWW-Authenticate header in the response' do
52
- expect(@err[:headers]['WWW-Authenticate']).to eq("OAuth realm='OAuth API', error='invalid_grant'")
53
- end
54
- end
55
- end
56
-
57
- context 'with an expired token' do
58
- before do
59
- @err = catch :error do
60
- get '/awesome?access_token=e123'
61
- end
62
- end
63
-
64
- it 'throws an error' do
65
- expect(@err[:status]).to eq(401)
66
- end
67
-
68
- it 'sets the WWW-Authenticate header in the response to error' do
69
- expect(@err[:headers]['WWW-Authenticate']).to eq("OAuth realm='OAuth API', error='invalid_grant'")
70
- end
71
- end
72
-
73
- %w(HTTP_AUTHORIZATION X_HTTP_AUTHORIZATION X-HTTP_AUTHORIZATION REDIRECT_X_HTTP_AUTHORIZATION).each do |head|
74
- context "with the token in the #{head} header" do
75
- before do
76
- get '/awesome', {}, head => 'OAuth g123'
77
- end
78
-
79
- it 'sets env["api.token"]' do
80
- expect(last_response.body).to eq('g123')
81
- end
82
- end
83
- end
84
-
85
- context 'with the token in the POST body' do
86
- before do
87
- post '/awesome', 'access_token' => 'g123'
88
- end
89
-
90
- it 'sets env["api.token"]' do
91
- expect(last_response.body).to eq('g123')
92
- end
93
- end
94
-
95
- context 'when accessing something outside its scope' do
96
- before do
97
- @err = catch :error do
98
- get '/forbidden?access_token=g123'
99
- end
100
- end
101
-
102
- it 'throws an error' do
103
- expect(@err[:status]).to eq(403)
104
- end
105
-
106
- it 'sets the WWW-Authenticate header in the response to error' do
107
- expect(@err[:headers]['WWW-Authenticate']).to eq("OAuth realm='OAuth API', error='insufficient_scope'")
108
- end
109
- end
110
-
111
- context 'when authorization is not required' do
112
- def app
113
- Rack::Builder.app do
114
- use Grape::Middleware::Auth::OAuth2, token_class: 'FakeToken', required: false
115
- run lambda { |env| [200, {}, [(env['api.token'].token if env['api.token'])]] }
116
- end
117
- end
118
-
119
- context 'with no token' do
120
- before { post '/awesome' }
121
-
122
- it 'succeeds anyway' do
123
- expect(last_response.status).to eq(200)
124
- end
125
- end
126
-
127
- context 'with a valid token' do
128
- before { get '/awesome?access_token=g123' }
129
-
130
- it 'sets env["api.token"]' do
131
- expect(last_response.body).to eq('g123')
132
- end
133
- end
134
- end
135
- end