wine_bouncer 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/CHANGELOG.md +10 -5
- data/README.md +11 -4
- data/lib/wine_bouncer/auth_strategies/protected.rb +9 -1
- data/lib/wine_bouncer/extension.rb +3 -3
- data/lib/wine_bouncer/version.rb +1 -1
- data/spec/dummy/app/api/default_api.rb +18 -3
- data/spec/dummy/app/api/protected_api.rb +15 -0
- data/spec/dummy/app/api/swagger_api.rb +14 -2
- data/spec/dummy/config/initializers/doorkeeper.rb +1 -1
- data/spec/intergration/oauth2_default_strategy_spec.rb +49 -5
- data/spec/intergration/oauth2_protected_strategy_spec.rb +54 -4
- data/spec/intergration/oauth2_swagger_strategy_spec.rb +40 -4
- data/wine_bouncer.gemspec +2 -2
- metadata +10 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1d520f0842f9978dde501b13eecd7ec124f30a57
|
4
|
+
data.tar.gz: 4f74158125be0303fb0e4c3efb28407190c3628d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 752d4043b4360f1e8baa23457e611d6cdb3fea714e07e518652adc51a8e95099f798576cc36acc4e550201722e42adc437c3ad68435c6fae499f9a7d5b0db83f
|
7
|
+
data.tar.gz: e160c6f796b00889e233d6da793754c7053ddc3bc296b6471fe81fcff13ef8cf9781829bcacd43377e42ec59a9076a8b874768c003321b7fb40cb8e839801d62
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,17 +1,22 @@
|
|
1
1
|
Changelog
|
2
2
|
=========
|
3
|
+
## 0.3.1
|
4
|
+
[#31](https://github.com/antek-drzewiecki/wine_bouncer/pull/31): Improves support for default scopes trough DSL.
|
5
|
+
[#30](https://github.com/antek-drzewiecki/wine_bouncer/pull/30): Restricted grape dependencies to the next minor level of grape.
|
6
|
+
[#29](https://github.com/antek-drzewiecki/wine_bouncer/pull/29): Doorkeepers dependencies are restricted to minor levels. Thanks @nickcharlton
|
7
|
+
[#27](https://github.com/antek-drzewiecki/wine_bouncer/pull/27): Fixes DSL default and protected strategy. Fixes #24 and #26.
|
3
8
|
|
4
9
|
## 0.3.0
|
5
10
|
[#21](https://github.com/antek-drzewiecki/wine_bouncer/pull/21): Added an Easy DSL for WineBouncer. Thanks @masarakki .
|
6
11
|
[#23](https://github.com/antek-drzewiecki/wine_bouncer/pull/23): Added support for Doorkeeper 2.1.1 and refactored strategies.
|
7
12
|
|
8
13
|
## 0.2.2
|
9
|
-
|
14
|
+
[#17](https://github.com/antek-drzewiecki/wine_bouncer/pull/17): Added a new protected strategy. Thanks @whatasunnyday .
|
10
15
|
|
11
16
|
## 0.2.1
|
12
|
-
|
13
|
-
|
17
|
+
[#12](https://github.com/antek-drzewiecki/wine_bouncer/pull/12): Added a rails generator to generate the WineBouncer configuration file. Thanks @whatasunnyday.
|
18
|
+
[#7](https://github.com/antek-drzewiecki/wine_bouncer/pull/7): Added support for Doorkeeper 2.0.0 and 2.0.1. Thanks @whatasunnyday .
|
14
19
|
|
15
20
|
## 0.2.0
|
16
|
-
|
17
|
-
|
21
|
+
[#4](https://github.com/antek-drzewiecki/wine_bouncer/pull/4): Support for newer versions of grape ( > 0.8 ).
|
22
|
+
[#6](https://github.com/antek-drzewiecki/wine_bouncer/pull/6): Added the option to configure the resource owner.
|
data/README.md
CHANGED
@@ -13,20 +13,22 @@ Table of Contents
|
|
13
13
|
* [Installation](#installation)
|
14
14
|
* [Upgrading](#upgrading)
|
15
15
|
* [Usage](#usage)
|
16
|
+
* [Easy DSL](#easy-dsl)
|
16
17
|
* [Authentication strategies](#authentication-strategies)
|
17
18
|
* [Default](#default)
|
18
19
|
* [Swagger](#swagger)
|
19
20
|
* [Protected](#protected)
|
20
21
|
* [Token information](#token-information)
|
21
22
|
* [Exceptions and Exception handling](#exceptions-and-exception-handling)
|
23
|
+
* [Example Application](#example-application)
|
22
24
|
* [Development](#development)
|
23
25
|
* [Contributing](#contributing)
|
24
26
|
|
25
27
|
|
26
28
|
## Requirements
|
27
29
|
- Ruby > 1.9.3
|
28
|
-
- Doorkeeper > 1.4.0 and
|
29
|
-
- Grape > 0.8 and
|
30
|
+
- Doorkeeper > 1.4.0 and < 2.2
|
31
|
+
- Grape > 0.8 and < 0.12
|
30
32
|
|
31
33
|
## Installation
|
32
34
|
|
@@ -174,8 +176,9 @@ The Swagger strategy uses scopes and injects them in the authorizations descript
|
|
174
176
|
|
175
177
|
#### Protected
|
176
178
|
|
177
|
-
The protected strategy is very similar to the default strategy except any public
|
178
|
-
If the authorization is not set, the end point is assumed to be
|
179
|
+
The protected strategy is very similar to the default strategy except any public endpoint must explicitly set. To make an end point public, use `oauth2 false`.
|
180
|
+
If the authorization method is not set, the end point is assumed to be __protected with Doorkeeper's default scopes__ (which is the same as `oauth2 nil `.)
|
181
|
+
To protect your endpoint with other scopes append the following method `oauth2 'first scope', 'second scope'`.
|
179
182
|
|
180
183
|
|
181
184
|
### Token information
|
@@ -191,6 +194,10 @@ This gem raises the following exceptions which can be handled in your Grape API,
|
|
191
194
|
* `WineBouncer::Errors::OAuthForbiddenError`
|
192
195
|
when the token is found but scopes do not match.
|
193
196
|
|
197
|
+
## Example Application
|
198
|
+
|
199
|
+
A full working sample app can be found on [sethherr page](https://github.com/sethherr/grape-doorkeeper) and can be accessed on [heroku](https://grape-doorkeeper.herokuapp.com/)
|
200
|
+
|
194
201
|
## Development
|
195
202
|
|
196
203
|
Since we want the gem tested against several rails versions we use the same way to prepare our development environment as Doorkeeper.
|
@@ -23,8 +23,16 @@ module WineBouncer
|
|
23
23
|
end
|
24
24
|
|
25
25
|
|
26
|
+
# returns true if an authorization hash has been found
|
27
|
+
# First it checks for the old syntax, then for the new.
|
26
28
|
def has_authorizations?
|
27
|
-
nil_authorizations? || endpoint_authorizations
|
29
|
+
(nil_authorizations? || !!endpoint_authorizations) && scope_keys?
|
30
|
+
end
|
31
|
+
|
32
|
+
# if false or nil scopes are entered the authorization should be skipped.
|
33
|
+
# nil_authorizations? is used to check against the legacy hash.
|
34
|
+
def scope_keys?
|
35
|
+
nil_authorizations? || endpoint_authorizations[:scopes] != [false]
|
28
36
|
end
|
29
37
|
|
30
38
|
def endpoint_authorizations
|
@@ -1,15 +1,15 @@
|
|
1
1
|
module WineBouncer
|
2
2
|
module Extension
|
3
3
|
def oauth2(*scopes)
|
4
|
-
scopes =
|
4
|
+
scopes = Doorkeeper.configuration.default_scopes.all if scopes.all? { |x| x.nil? }
|
5
5
|
description = if respond_to?(:route_setting) # >= grape-0.10.0
|
6
|
-
route_setting(:description)
|
6
|
+
route_setting(:description) || route_setting(:description, {})
|
7
7
|
else
|
8
8
|
@last_description ||= {}
|
9
9
|
end
|
10
10
|
# case WineBouncer.configuration.auth_strategy
|
11
11
|
# when :default
|
12
|
-
description[:auth] = {
|
12
|
+
description[:auth] = { scopes: scopes }
|
13
13
|
# when :swagger
|
14
14
|
description[:authorizations] = { oauth2: scopes.map{|x| {scope: x}} }
|
15
15
|
# end
|
data/lib/wine_bouncer/version.rb
CHANGED
@@ -14,6 +14,11 @@ module Api
|
|
14
14
|
{ hello: 'scoped world' }
|
15
15
|
end
|
16
16
|
|
17
|
+
desc 'Protected method with custom scope', auth: { scopes: ['custom_scope'] }
|
18
|
+
get '/oauth2_custom_scope' do
|
19
|
+
{ hello: 'oauth2_custom_scope' }
|
20
|
+
end
|
21
|
+
|
17
22
|
desc 'Unprotected method'
|
18
23
|
get '/unprotected' do
|
19
24
|
{ hello: 'unprotected world' }
|
@@ -29,14 +34,24 @@ module Api
|
|
29
34
|
{ hello: 'protected unscoped world' }
|
30
35
|
end
|
31
36
|
|
37
|
+
get '/not_described_world' do
|
38
|
+
{ hello: 'non described world' }
|
39
|
+
end
|
40
|
+
|
32
41
|
desc 'oauth2_dsl'
|
33
42
|
oauth2 'public'
|
34
43
|
get '/oauth2_dsl' do
|
35
|
-
{ hello: '
|
44
|
+
{ hello: 'oauth2 dsl' }
|
36
45
|
end
|
37
46
|
|
38
|
-
|
39
|
-
|
47
|
+
oauth2 'custom_scope'
|
48
|
+
get '/oauth2_dsl_custom_scope' do
|
49
|
+
{ hello: 'oauth2 dsl custom scope' }
|
50
|
+
end
|
51
|
+
|
52
|
+
oauth2
|
53
|
+
get '/oauth2_dsl_default_scopes' do
|
54
|
+
{ hello: 'oauth dsl default scopes' }
|
40
55
|
end
|
41
56
|
|
42
57
|
end
|
@@ -35,6 +35,21 @@ module Api
|
|
35
35
|
{ hello: 'oauth2_dsl' }
|
36
36
|
end
|
37
37
|
|
38
|
+
oauth2 'custom_scope'
|
39
|
+
get '/oauth2_dsl_custom_scope' do
|
40
|
+
{ hello: 'custom scope' }
|
41
|
+
end
|
42
|
+
|
43
|
+
oauth2
|
44
|
+
get '/oauth2_protected_with_default_scopes' do
|
45
|
+
{ hello: 'default oauth2 dsl' }
|
46
|
+
end
|
47
|
+
|
48
|
+
oauth2 false
|
49
|
+
get '/unprotected_endpoint' do
|
50
|
+
{ hello: 'public oauth2 dsl' }
|
51
|
+
end
|
52
|
+
|
38
53
|
get '/not_described_world' do
|
39
54
|
{ hello: 'non described world' }
|
40
55
|
end
|
@@ -29,15 +29,27 @@ module Api
|
|
29
29
|
{ hello: 'protected unscoped world' }
|
30
30
|
end
|
31
31
|
|
32
|
+
get '/not_described_world' do
|
33
|
+
{ hello: 'non described world' }
|
34
|
+
end
|
35
|
+
|
36
|
+
|
32
37
|
desc 'oauth2 dsl'
|
33
38
|
oauth2 'public'
|
34
39
|
get '/oauth2_dsl' do
|
35
40
|
{ hello: 'oauth2_dsl' }
|
36
41
|
end
|
37
42
|
|
38
|
-
|
39
|
-
|
43
|
+
oauth2
|
44
|
+
get '/oauth2_dsl_default_scopes' do
|
45
|
+
{ hello: 'oauth dsl default scopes' }
|
40
46
|
end
|
47
|
+
|
48
|
+
oauth2 'custom_scope'
|
49
|
+
get '/oauth2_dsl_custom_scopes' do
|
50
|
+
{ hello: 'oauth dsl custom scopes' }
|
51
|
+
end
|
52
|
+
|
41
53
|
end
|
42
54
|
|
43
55
|
class SwaggerApiUnderTest < Grape::API
|
@@ -41,7 +41,7 @@ Doorkeeper.configure do
|
|
41
41
|
# Define access token scopes for your provider
|
42
42
|
# For more information go to
|
43
43
|
# https://github.com/doorkeeper-gem/doorkeeper/wiki/Using-Scopes
|
44
|
-
default_scopes :public
|
44
|
+
default_scopes :public, :default
|
45
45
|
optional_scopes :write, :update
|
46
46
|
|
47
47
|
# Change the way client credentials are retrieved from the request object.
|
@@ -4,8 +4,9 @@ require 'json'
|
|
4
4
|
describe Api::MountedDefaultApiUnderTest, type: :api do
|
5
5
|
|
6
6
|
let(:user) { FactoryGirl.create :user }
|
7
|
-
let(:token) { FactoryGirl.create :clientless_access_token, resource_owner_id: user.id, scopes:
|
8
|
-
let(:unscoped_token) { FactoryGirl.create :clientless_access_token, resource_owner_id: user.id, scopes:
|
7
|
+
let(:token) { FactoryGirl.create :clientless_access_token, resource_owner_id: user.id, scopes: 'public' }
|
8
|
+
let(:unscoped_token) { FactoryGirl.create :clientless_access_token, resource_owner_id: user.id, scopes: '' }
|
9
|
+
let(:custom_scope) { FactoryGirl.create :clientless_access_token, resource_owner_id: user.id, scopes: 'custom_scope' } #not a default scope
|
9
10
|
|
10
11
|
before (:example) do
|
11
12
|
WineBouncer.configure do |c|
|
@@ -26,6 +27,15 @@ describe Api::MountedDefaultApiUnderTest, type: :api do
|
|
26
27
|
expect(json).to have_key('hello')
|
27
28
|
end
|
28
29
|
|
30
|
+
it 'gives access when tokens are correct and an non doorkeeper default scope is used.' do
|
31
|
+
get '/default_api/oauth2_custom_scope', nil, 'HTTP_AUTHORIZATION' => "Bearer #{custom_scope.token}"
|
32
|
+
|
33
|
+
expect(last_response.status).to eq(200)
|
34
|
+
json = JSON.parse(last_response.body)
|
35
|
+
expect(json).to have_key('hello')
|
36
|
+
expect(json['hello']).to eq('oauth2_custom_scope')
|
37
|
+
end
|
38
|
+
|
29
39
|
it 'raises an authentication error when the token is invalid' do
|
30
40
|
expect { get '/default_api/protected', nil, 'HTTP_AUTHORIZATION' => "Bearer #{token.token}-invalid" }.to raise_exception(WineBouncer::Errors::OAuthUnauthorizedError)
|
31
41
|
end
|
@@ -87,15 +97,49 @@ describe Api::MountedDefaultApiUnderTest, type: :api do
|
|
87
97
|
expect(last_response.status).to eq(200)
|
88
98
|
json = JSON.parse(last_response.body)
|
89
99
|
expect(json).to have_key('hello')
|
90
|
-
expect(json['hello']).to eq('
|
91
|
-
|
100
|
+
expect(json['hello']).to eq('oauth2 dsl')
|
92
101
|
end
|
93
102
|
|
94
103
|
it 'raises an error when an protected endpoint without scopes is called without token ' do
|
95
104
|
expect { get '/default_api/oauth2_dsl' }.to raise_exception(WineBouncer::Errors::OAuthUnauthorizedError)
|
96
105
|
end
|
97
|
-
end
|
98
106
|
|
107
|
+
context 'without parameters' do
|
108
|
+
it 'accepts tokens with default scopes' do
|
109
|
+
get '/swagger_api/oauth2_dsl_default_scopes', nil, 'HTTP_AUTHORIZATION' => "Bearer #{token.token}"
|
110
|
+
expect(last_response.status).to eq(200)
|
111
|
+
json = JSON.parse(last_response.body)
|
112
|
+
expect(json).to have_key('hello')
|
113
|
+
expect(json['hello']).to eq('oauth dsl default scopes')
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'raises an error when an protected endpoint without scopes is called without token ' do
|
117
|
+
expect { get '/default_api/oauth2_dsl_default_scopes' }.to raise_exception(WineBouncer::Errors::OAuthUnauthorizedError)
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'raises an error when token scopes are not default scopes ' do
|
121
|
+
expect { get '/default_api/oauth2_dsl_default_scopes', nil, 'HTTP_AUTHORIZATION' => "Bearer #{custom_scope.token}" }.to raise_exception(WineBouncer::Errors::OAuthForbiddenError)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context 'custom scopes' do
|
126
|
+
it 'allows to call custom scopes' do
|
127
|
+
get '/default_api/oauth2_dsl_custom_scope', nil, 'HTTP_AUTHORIZATION' => "Bearer #{custom_scope.token}"
|
128
|
+
expect(last_response.status).to eq(200)
|
129
|
+
json = JSON.parse(last_response.body)
|
130
|
+
expect(json).to have_key('hello')
|
131
|
+
expect(json['hello']).to eq('oauth2 dsl custom scope')
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'raises an error when an protected endpoint without scopes is called without token ' do
|
135
|
+
expect { get '/default_api/oauth2_dsl_custom_scope' }.to raise_exception(WineBouncer::Errors::OAuthUnauthorizedError)
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'raises an error when token scopes do not match' do
|
139
|
+
expect { get '/default_api/oauth2_dsl_custom_scope', nil, 'HTTP_AUTHORIZATION' => "Bearer #{token.token}" }.to raise_exception(WineBouncer::Errors::OAuthForbiddenError)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
99
143
|
|
100
144
|
context 'not_described_world' do
|
101
145
|
it 'allows to call an endpoint without description' do
|
@@ -4,8 +4,9 @@ require 'json'
|
|
4
4
|
describe Api::MountedProtectedApiUnderTest, type: :api do
|
5
5
|
|
6
6
|
let(:user) { FactoryGirl.create :user }
|
7
|
-
let(:token) { FactoryGirl.create :clientless_access_token, resource_owner_id: user.id, scopes:
|
8
|
-
let(:unscoped_token) { FactoryGirl.create :clientless_access_token, resource_owner_id: user.id, scopes:
|
7
|
+
let(:token) { FactoryGirl.create :clientless_access_token, resource_owner_id: user.id, scopes: 'public' }
|
8
|
+
let(:unscoped_token) { FactoryGirl.create :clientless_access_token, resource_owner_id: user.id, scopes: '' }
|
9
|
+
let(:custom_scope) { FactoryGirl.create :clientless_access_token, resource_owner_id: user.id, scopes: 'custom_scope' } #not a default scope
|
9
10
|
|
10
11
|
before (:example) do
|
11
12
|
WineBouncer.configure do |c|
|
@@ -91,12 +92,61 @@ describe Api::MountedProtectedApiUnderTest, type: :api do
|
|
91
92
|
json = JSON.parse(last_response.body)
|
92
93
|
expect(json).to have_key('hello')
|
93
94
|
expect(json['hello']).to eq('oauth2_dsl')
|
94
|
-
|
95
95
|
end
|
96
96
|
|
97
|
-
it 'raises an error when an protected endpoint
|
97
|
+
it 'raises an error when an protected endpoint is called without token' do
|
98
98
|
expect { get '/protected_api/oauth2_dsl' }.to raise_exception(WineBouncer::Errors::OAuthUnauthorizedError)
|
99
99
|
end
|
100
|
+
|
101
|
+
context 'without parameters' do
|
102
|
+
it 'allows to call an endpoint with default scopes' do
|
103
|
+
get '/protected_api/oauth2_protected_with_default_scopes', nil, 'HTTP_AUTHORIZATION' => "Bearer #{token.token}"
|
104
|
+
expect(last_response.status).to eq(200)
|
105
|
+
json = JSON.parse(last_response.body)
|
106
|
+
expect(json).to have_key('hello')
|
107
|
+
expect(json['hello']).to eq('default oauth2 dsl')
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'raises an error when an protected endpoint without scopes is called without token ' do
|
111
|
+
expect { get '/protected_api/oauth2_protected_with_default_scopes' }.to raise_exception(WineBouncer::Errors::OAuthUnauthorizedError)
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'raises an error when token scopes are not default scopes ' do
|
115
|
+
expect { get '/protected_api/oauth2_protected_with_default_scopes', nil, 'HTTP_AUTHORIZATION' => "Bearer #{custom_scope.token}" }.to raise_exception(WineBouncer::Errors::OAuthForbiddenError)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context 'custom scopes' do
|
120
|
+
it 'protects endpoints with custom scopes' do
|
121
|
+
get '/protected_api/oauth2_dsl_custom_scope', nil, 'HTTP_AUTHORIZATION' => "Bearer #{custom_scope.token}"
|
122
|
+
expect(last_response.status).to eq(200)
|
123
|
+
json = JSON.parse(last_response.body)
|
124
|
+
expect(json).to have_key('hello')
|
125
|
+
expect(json['hello']).to eq('custom scope')
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'raises an error when an protected endpoint without scopes is called without token ' do
|
129
|
+
expect { get '/protected_api/oauth2_dsl_custom_scope' }.to raise_exception(WineBouncer::Errors::OAuthUnauthorizedError)
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'raises an error when token scopes do not match' do
|
133
|
+
expect { get '/protected_api/oauth2_dsl_custom_scope', nil, 'HTTP_AUTHORIZATION' => "Bearer #{token.token}" }.to raise_exception(WineBouncer::Errors::OAuthForbiddenError)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
context 'public endpoint' do
|
138
|
+
it 'allows to call an unprotected endpoint without token' do
|
139
|
+
get '/protected_api/unprotected_endpoint'
|
140
|
+
expect(last_response.status).to eq(200)
|
141
|
+
json = JSON.parse(last_response.body)
|
142
|
+
expect(json).to have_key('hello')
|
143
|
+
expect(json['hello']).to eq('public oauth2 dsl')
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'allows requests with tokens to public endpoints with tokens' do
|
147
|
+
expect { get '/protected_api/oauth2_protected_with_default_scopes', nil, 'HTTP_AUTHORIZATION' => "Bearer #{token.token}" }.not_to raise_error
|
148
|
+
end
|
149
|
+
end
|
100
150
|
end
|
101
151
|
|
102
152
|
context 'not_described_world' do
|
@@ -4,8 +4,9 @@ require 'json'
|
|
4
4
|
describe Api::MountedSwaggerApiUnderTest, type: :api do
|
5
5
|
|
6
6
|
let(:user) { FactoryGirl.create :user }
|
7
|
-
let(:token) { FactoryGirl.create :clientless_access_token, resource_owner_id: user.id, scopes:
|
8
|
-
let(:unscoped_token) { FactoryGirl.create :clientless_access_token, resource_owner_id: user.id, scopes:
|
7
|
+
let(:token) { FactoryGirl.create :clientless_access_token, resource_owner_id: user.id, scopes: 'public' }
|
8
|
+
let(:unscoped_token) { FactoryGirl.create :clientless_access_token, resource_owner_id: user.id, scopes: '' }
|
9
|
+
let(:custom_scope) { FactoryGirl.create :clientless_access_token, resource_owner_id: user.id, scopes: 'custom_scope' } #not a default scope
|
9
10
|
|
10
11
|
|
11
12
|
before (:example) do
|
@@ -82,7 +83,7 @@ describe Api::MountedSwaggerApiUnderTest, type: :api do
|
|
82
83
|
end
|
83
84
|
end
|
84
85
|
|
85
|
-
context '
|
86
|
+
context 'oauth2 dsl' do
|
86
87
|
it 'allows to call an protected endpoint without scopes' do
|
87
88
|
get '/swagger_api/oauth2_dsl', nil, 'HTTP_AUTHORIZATION' => "Bearer #{token.token}"
|
88
89
|
|
@@ -90,12 +91,47 @@ describe Api::MountedSwaggerApiUnderTest, type: :api do
|
|
90
91
|
json = JSON.parse(last_response.body)
|
91
92
|
expect(json).to have_key('hello')
|
92
93
|
expect(json['hello']).to eq('oauth2_dsl')
|
93
|
-
|
94
94
|
end
|
95
95
|
|
96
96
|
it 'raises an error when an protected endpoint without scopes is called without token ' do
|
97
97
|
expect { get '/swagger_api/oauth2_dsl' }.to raise_exception(WineBouncer::Errors::OAuthUnauthorizedError)
|
98
98
|
end
|
99
|
+
|
100
|
+
context 'without parameters' do
|
101
|
+
it 'accepts tokens with default scopes' do
|
102
|
+
get '/swagger_api/oauth2_dsl_default_scopes', nil, 'HTTP_AUTHORIZATION' => "Bearer #{token.token}"
|
103
|
+
expect(last_response.status).to eq(200)
|
104
|
+
json = JSON.parse(last_response.body)
|
105
|
+
expect(json).to have_key('hello')
|
106
|
+
expect(json['hello']).to eq('oauth dsl default scopes')
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'raises an error when an protected endpoint without scopes is called without token ' do
|
110
|
+
expect { get '/swagger_api/oauth2_dsl_default_scopes' }.to raise_exception(WineBouncer::Errors::OAuthUnauthorizedError)
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'raises an error when token scopes are not default scopes ' do
|
114
|
+
expect { get '/swagger_api/oauth2_dsl_default_scopes', nil, 'HTTP_AUTHORIZATION' => "Bearer #{custom_scope.token}" }.to raise_exception(WineBouncer::Errors::OAuthForbiddenError)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
context 'custom scopes' do
|
119
|
+
it 'accepts tokens with default scopes' do
|
120
|
+
get '/swagger_api/oauth2_dsl_custom_scopes', nil, 'HTTP_AUTHORIZATION' => "Bearer #{custom_scope.token}"
|
121
|
+
expect(last_response.status).to eq(200)
|
122
|
+
json = JSON.parse(last_response.body)
|
123
|
+
expect(json).to have_key('hello')
|
124
|
+
expect(json['hello']).to eq('oauth dsl custom scopes')
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'raises an error when an protected endpoint without scopes is called without token ' do
|
128
|
+
expect { get '/swagger_api/oauth2_dsl_custom_scopes' }.to raise_exception(WineBouncer::Errors::OAuthUnauthorizedError)
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'raises an error when token scopes do not match' do
|
132
|
+
expect { get '/swagger_api/oauth2_dsl_custom_scopes', nil, 'HTTP_AUTHORIZATION' => "Bearer #{token.token}" }.to raise_exception(WineBouncer::Errors::OAuthForbiddenError)
|
133
|
+
end
|
134
|
+
end
|
99
135
|
end
|
100
136
|
|
101
137
|
context 'not_described_world' do
|
data/wine_bouncer.gemspec
CHANGED
@@ -17,8 +17,8 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
18
|
spec.require_paths = ["lib"]
|
19
19
|
|
20
|
-
spec.add_runtime_dependency 'grape', '~> 0.8', '
|
21
|
-
spec.add_runtime_dependency 'doorkeeper', '>= 1.4', '
|
20
|
+
spec.add_runtime_dependency 'grape', '~> 0.8', '< 0.12'
|
21
|
+
spec.add_runtime_dependency 'doorkeeper', '>= 1.4', '< 2.2'
|
22
22
|
|
23
23
|
spec.add_development_dependency "railties"
|
24
24
|
spec.add_development_dependency "bundler", "~> 1.7"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wine_bouncer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Antek Drzewiecki
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-03-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: grape
|
@@ -17,9 +17,9 @@ dependencies:
|
|
17
17
|
- - ~>
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0.8'
|
20
|
-
- -
|
20
|
+
- - <
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: 0.
|
22
|
+
version: '0.12'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -27,9 +27,9 @@ dependencies:
|
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '0.8'
|
30
|
-
- -
|
30
|
+
- - <
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: 0.
|
32
|
+
version: '0.12'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: doorkeeper
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -37,9 +37,9 @@ dependencies:
|
|
37
37
|
- - '>='
|
38
38
|
- !ruby/object:Gem::Version
|
39
39
|
version: '1.4'
|
40
|
-
- -
|
40
|
+
- - <
|
41
41
|
- !ruby/object:Gem::Version
|
42
|
-
version: 2.
|
42
|
+
version: '2.2'
|
43
43
|
type: :runtime
|
44
44
|
prerelease: false
|
45
45
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -47,9 +47,9 @@ dependencies:
|
|
47
47
|
- - '>='
|
48
48
|
- !ruby/object:Gem::Version
|
49
49
|
version: '1.4'
|
50
|
-
- -
|
50
|
+
- - <
|
51
51
|
- !ruby/object:Gem::Version
|
52
|
-
version: 2.
|
52
|
+
version: '2.2'
|
53
53
|
- !ruby/object:Gem::Dependency
|
54
54
|
name: railties
|
55
55
|
requirement: !ruby/object:Gem::Requirement
|