grape_oauth2 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +11 -11
  3. data/Gemfile +23 -23
  4. data/Rakefile +11 -11
  5. data/grape_oauth2.gemspec +26 -27
  6. data/lib/grape_oauth2.rb +129 -129
  7. data/lib/grape_oauth2/configuration.rb +143 -143
  8. data/lib/grape_oauth2/configuration/class_accessors.rb +36 -36
  9. data/lib/grape_oauth2/configuration/validation.rb +71 -71
  10. data/lib/grape_oauth2/endpoints/authorize.rb +34 -34
  11. data/lib/grape_oauth2/endpoints/token.rb +72 -72
  12. data/lib/grape_oauth2/gem_version.rb +24 -24
  13. data/lib/grape_oauth2/generators/authorization.rb +44 -44
  14. data/lib/grape_oauth2/generators/base.rb +26 -26
  15. data/lib/grape_oauth2/generators/token.rb +62 -62
  16. data/lib/grape_oauth2/helpers/access_token_helpers.rb +52 -54
  17. data/lib/grape_oauth2/helpers/oauth_params.rb +41 -41
  18. data/lib/grape_oauth2/mixins/active_record/access_grant.rb +47 -47
  19. data/lib/grape_oauth2/mixins/active_record/access_token.rb +75 -75
  20. data/lib/grape_oauth2/mixins/active_record/client.rb +36 -35
  21. data/lib/grape_oauth2/mixins/mongoid/access_grant.rb +58 -58
  22. data/lib/grape_oauth2/mixins/mongoid/access_token.rb +88 -88
  23. data/lib/grape_oauth2/mixins/mongoid/client.rb +44 -41
  24. data/lib/grape_oauth2/mixins/sequel/access_grant.rb +68 -68
  25. data/lib/grape_oauth2/mixins/sequel/access_token.rb +86 -86
  26. data/lib/grape_oauth2/mixins/sequel/client.rb +54 -46
  27. data/lib/grape_oauth2/responses/authorization.rb +11 -10
  28. data/lib/grape_oauth2/responses/base.rb +56 -56
  29. data/lib/grape_oauth2/responses/token.rb +10 -10
  30. data/lib/grape_oauth2/scopes.rb +74 -74
  31. data/lib/grape_oauth2/strategies/authorization_code.rb +38 -38
  32. data/lib/grape_oauth2/strategies/base.rb +47 -47
  33. data/lib/grape_oauth2/strategies/client_credentials.rb +20 -20
  34. data/lib/grape_oauth2/strategies/password.rb +22 -22
  35. data/lib/grape_oauth2/strategies/refresh_token.rb +47 -47
  36. data/lib/grape_oauth2/unique_token.rb +20 -20
  37. data/lib/grape_oauth2/version.rb +14 -14
  38. data/spec/configuration/config_spec.rb +231 -231
  39. data/spec/configuration/version_spec.rb +12 -12
  40. data/spec/dummy/endpoints/custom_authorization.rb +25 -25
  41. data/spec/dummy/endpoints/custom_token.rb +35 -35
  42. data/spec/dummy/endpoints/status.rb +25 -25
  43. data/spec/dummy/grape_oauth2_config.rb +11 -11
  44. data/spec/dummy/orm/active_record/app/config/db.rb +7 -7
  45. data/spec/dummy/orm/active_record/app/models/access_code.rb +3 -3
  46. data/spec/dummy/orm/active_record/app/models/access_token.rb +3 -3
  47. data/spec/dummy/orm/active_record/app/models/application.rb +3 -3
  48. data/spec/dummy/orm/active_record/app/models/application_record.rb +3 -3
  49. data/spec/dummy/orm/active_record/app/models/user.rb +10 -10
  50. data/spec/dummy/orm/active_record/app/twitter.rb +36 -36
  51. data/spec/dummy/orm/active_record/config.ru +7 -7
  52. data/spec/dummy/orm/active_record/db/schema.rb +53 -53
  53. data/spec/dummy/orm/mongoid/app/config/db.rb +6 -6
  54. data/spec/dummy/orm/mongoid/app/config/mongoid.yml +21 -21
  55. data/spec/dummy/orm/mongoid/app/models/access_code.rb +3 -3
  56. data/spec/dummy/orm/mongoid/app/models/access_token.rb +3 -3
  57. data/spec/dummy/orm/mongoid/app/models/application.rb +3 -3
  58. data/spec/dummy/orm/mongoid/app/models/user.rb +11 -11
  59. data/spec/dummy/orm/mongoid/app/twitter.rb +34 -34
  60. data/spec/dummy/orm/mongoid/config.ru +5 -5
  61. data/spec/dummy/orm/sequel/app/config/db.rb +1 -1
  62. data/spec/dummy/orm/sequel/app/models/access_code.rb +4 -4
  63. data/spec/dummy/orm/sequel/app/models/access_token.rb +4 -4
  64. data/spec/dummy/orm/sequel/app/models/application.rb +4 -4
  65. data/spec/dummy/orm/sequel/app/models/application_record.rb +2 -2
  66. data/spec/dummy/orm/sequel/app/models/user.rb +11 -11
  67. data/spec/dummy/orm/sequel/app/twitter.rb +47 -47
  68. data/spec/dummy/orm/sequel/config.ru +5 -5
  69. data/spec/dummy/orm/sequel/db/schema.rb +50 -50
  70. data/spec/lib/scopes_spec.rb +50 -50
  71. data/spec/mixins/active_record/access_token_spec.rb +185 -185
  72. data/spec/mixins/active_record/client_spec.rb +104 -95
  73. data/spec/mixins/mongoid/access_token_spec.rb +185 -185
  74. data/spec/mixins/mongoid/client_spec.rb +104 -95
  75. data/spec/mixins/sequel/access_token_spec.rb +185 -185
  76. data/spec/mixins/sequel/client_spec.rb +105 -96
  77. data/spec/requests/flows/authorization_code_spec.rb +67 -67
  78. data/spec/requests/flows/client_credentials_spec.rb +101 -101
  79. data/spec/requests/flows/password_spec.rb +210 -210
  80. data/spec/requests/flows/refresh_token_spec.rb +222 -222
  81. data/spec/requests/flows/revoke_token_spec.rb +103 -103
  82. data/spec/requests/protected_resources_spec.rb +64 -64
  83. data/spec/spec_helper.rb +60 -60
  84. data/spec/support/api_helper.rb +11 -11
  85. metadata +50 -52
  86. data/.rspec +0 -2
  87. data/.rubocop.yml +0 -18
  88. data/.travis.yml +0 -42
  89. data/README.md +0 -820
  90. data/gemfiles/active_record.rb +0 -25
  91. data/gemfiles/mongoid.rb +0 -14
  92. data/gemfiles/sequel.rb +0 -24
  93. data/grape_oauth2.png +0 -0
@@ -1,20 +1,20 @@
1
- module Grape
2
- module OAuth2
3
- module Strategies
4
- # Client Credentials strategy class.
5
- # Processes request and respond with Access Token.
6
- class ClientCredentials < Base
7
- class << self
8
- # Processes Client Credentials request.
9
- def process(request)
10
- client = authenticate_client(request)
11
- request.invalid_client! if client.nil?
12
-
13
- token = config.access_token_class.create_for(client, nil, scopes_from(request))
14
- expose_to_bearer_token(token)
15
- end
16
- end
17
- end
18
- end
19
- end
20
- end
1
+ module Grape
2
+ module OAuth2
3
+ module Strategies
4
+ # Client Credentials strategy class.
5
+ # Processes request and respond with Access Token.
6
+ class ClientCredentials < Base
7
+ class << self
8
+ # Processes Client Credentials request.
9
+ def process(request)
10
+ client = authenticate_client(request)
11
+ request.invalid_client! if client.nil?
12
+
13
+ token = config.access_token_class.create_for(client, nil, scopes_from(request))
14
+ expose_to_bearer_token(token)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,22 +1,22 @@
1
- module Grape
2
- module OAuth2
3
- module Strategies
4
- # Resource Owner Password Credentials strategy class.
5
- # Processes request and respond with Access Token.
6
- class Password < Base
7
- class << self
8
- # Processes Password request.
9
- def process(request)
10
- client = authenticate_client(request) || request.invalid_client!
11
- resource_owner = authenticate_resource_owner(client, request)
12
-
13
- request.invalid_grant! if resource_owner.nil?
14
-
15
- token = config.access_token_class.create_for(client, resource_owner, scopes_from(request))
16
- expose_to_bearer_token(token)
17
- end
18
- end
19
- end
20
- end
21
- end
22
- end
1
+ module Grape
2
+ module OAuth2
3
+ module Strategies
4
+ # Resource Owner Password Credentials strategy class.
5
+ # Processes request and respond with Access Token.
6
+ class Password < Base
7
+ class << self
8
+ # Processes Password request.
9
+ def process(request)
10
+ client = authenticate_client(request) || request.invalid_client!
11
+ resource_owner = authenticate_resource_owner(client, request)
12
+
13
+ request.invalid_grant! if resource_owner.nil?
14
+
15
+ token = config.access_token_class.create_for(client, resource_owner, scopes_from(request))
16
+ expose_to_bearer_token(token)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,47 +1,47 @@
1
- module Grape
2
- module OAuth2
3
- module Strategies
4
- # Refresh Token strategy class.
5
- # Processes request and respond with Access Token.
6
- class RefreshToken < Base
7
- class << self
8
- # Processes Refresh Token request.
9
- def process(request)
10
- client = authenticate_client(request)
11
-
12
- request.invalid_client! if client.nil?
13
-
14
- refresh_token = config.access_token_class.authenticate(request.refresh_token, type: :refresh_token)
15
- request.invalid_grant! if refresh_token.nil?
16
- request.unauthorized_client! if refresh_token && refresh_token.client != client
17
-
18
- token = config.access_token_class.create_for(client, refresh_token.resource_owner)
19
- run_on_refresh_callback(refresh_token) if config.on_refresh_runnable?
20
-
21
- expose_to_bearer_token(token)
22
- end
23
-
24
- private
25
-
26
- # Invokes custom callback on Access Token refresh.
27
- # If callback is a proc, then call it with token.
28
- # If access token responds to callback value (symbol for example), then call it from the token.
29
- #
30
- # @param access_token [Object] Access Token instance
31
- #
32
- def run_on_refresh_callback(access_token)
33
- callback = config.on_refresh
34
-
35
- if callback.respond_to?(:call)
36
- callback.call(access_token)
37
- elsif access_token.respond_to?(callback)
38
- access_token.send(callback)
39
- else
40
- raise ArgumentError, ":on_refresh is not a block and Access Token class doesn't respond to #{callback}!"
41
- end
42
- end
43
- end
44
- end
45
- end
46
- end
47
- end
1
+ module Grape
2
+ module OAuth2
3
+ module Strategies
4
+ # Refresh Token strategy class.
5
+ # Processes request and respond with Access Token.
6
+ class RefreshToken < Base
7
+ class << self
8
+ # Processes Refresh Token request.
9
+ def process(request)
10
+ client = authenticate_client(request)
11
+
12
+ request.invalid_client! if client.nil?
13
+
14
+ refresh_token = config.access_token_class.authenticate(request.refresh_token, type: :refresh_token)
15
+ request.invalid_grant! if refresh_token.nil?
16
+ request.unauthorized_client! if refresh_token && refresh_token.client != client
17
+
18
+ token = config.access_token_class.create_for(client, refresh_token.resource_owner)
19
+ run_on_refresh_callback(refresh_token) if config.on_refresh_runnable?
20
+
21
+ expose_to_bearer_token(token)
22
+ end
23
+
24
+ private
25
+
26
+ # Invokes custom callback on Access Token refresh.
27
+ # If callback is a proc, then call it with token.
28
+ # If access token responds to callback value (symbol for example), then call it from the token.
29
+ #
30
+ # @param access_token [Object] Access Token instance
31
+ #
32
+ def run_on_refresh_callback(access_token)
33
+ callback = config.on_refresh
34
+
35
+ if callback.respond_to?(:call)
36
+ callback.call(access_token)
37
+ elsif access_token.respond_to?(callback)
38
+ access_token.send(callback)
39
+ else
40
+ raise ArgumentError, ":on_refresh is not a block and Access Token class doesn't respond to #{callback}!"
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -1,20 +1,20 @@
1
- module Grape
2
- module OAuth2
3
- # OAuth2 helper for generation of unique token values.
4
- # Can process custom payload and options.
5
- module UniqueToken
6
- # Generates unique token value.
7
- #
8
- # @param _payload [Hash]
9
- # payload
10
- # @param options [Hash]
11
- # options for generator
12
- #
13
- # @return [String]
14
- # unique token value
15
- def self.generate(_payload = {}, options = {})
16
- SecureRandom.hex(options.delete(:size) || 32)
17
- end
18
- end
19
- end
20
- end
1
+ module Grape
2
+ module OAuth2
3
+ # OAuth2 helper for generation of unique token values.
4
+ # Can process custom payload and options.
5
+ module UniqueToken
6
+ # Generates unique token value.
7
+ #
8
+ # @param _payload [Hash]
9
+ # payload
10
+ # @param options [Hash]
11
+ # options for generator
12
+ #
13
+ # @return [String]
14
+ # unique token value
15
+ def self.generate(_payload = {}, options = {})
16
+ SecureRandom.hex(options.delete(:size) || 32)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,14 +1,14 @@
1
- require_relative 'gem_version'
2
-
3
- module Grape
4
- module OAuth2
5
- # Grape::OAuth2 gem version.
6
- #
7
- # @return [Gem::Version]
8
- # version value
9
- #
10
- def self.version
11
- gem_version
12
- end
13
- end
14
- end
1
+ require_relative 'gem_version'
2
+
3
+ module Grape
4
+ module OAuth2
5
+ # Grape::OAuth2 gem version.
6
+ #
7
+ # @return [Gem::Version]
8
+ # version value
9
+ #
10
+ def self.version
11
+ gem_version
12
+ end
13
+ end
14
+ end
@@ -1,231 +1,231 @@
1
- require 'spec_helper'
2
-
3
- describe Grape::OAuth2::Configuration do
4
- let(:config) { described_class.new }
5
-
6
- # Refactor: Mock it
7
- class CustomClient
8
- def self.authenticate(key, secret = nil)
9
- 'Test'
10
- end
11
- end
12
-
13
- class CustomAccessToken
14
- def self.create_for(client, resource_owner, scopes = nil)
15
- end
16
-
17
- def self.authenticate(token, type: :access_token)
18
- 'Test'
19
- end
20
-
21
- def client
22
- end
23
-
24
- def resource_owner
25
- end
26
-
27
- def expired?
28
- end
29
-
30
- def revoked?
31
- end
32
-
33
- def revoke!(revoked_at = Time.now)
34
- end
35
-
36
- def to_bearer_token
37
- end
38
- end
39
-
40
- class CustomResourceOwner
41
- def self.oauth_authenticate(client, username, password)
42
- 'Test'
43
- end
44
- end
45
-
46
- context 'default config' do
47
- it 'setup config with default values' do
48
- expect(config.access_token_lifetime).to eq(7200)
49
- expect(config.authorization_code_lifetime).to eq(1800)
50
-
51
- expect(config.realm).to eq(Grape::OAuth2::Configuration::DEFAULT_REALM)
52
- expect(config.allowed_grant_types).to eq(%w(password client_credentials))
53
-
54
- expect(config.issue_refresh_token).to be_falsey
55
- expect(config.on_refresh).to eq(:nothing)
56
-
57
- expect(config.scopes_validator_class_name).to eq(Grape::OAuth2::Scopes.name)
58
- end
59
- end
60
-
61
- context 'custom config' do
62
- class CustomScopesValidator
63
- def initialize(scopes)
64
- @scopes = scopes
65
- end
66
-
67
- def valid_for?(access_token)
68
- false
69
- end
70
- end
71
-
72
- class CustomTokenGenerator
73
- def self.generate(options = {})
74
- if options[:custom]
75
- 'custom_token'
76
- else
77
- 'default_token'
78
- end
79
- end
80
- end
81
-
82
- before do
83
- config.access_token_class_name = 'CustomAccessToken'
84
- config.resource_owner_class_name = 'CustomResourceOwner'
85
- config.client_class_name = 'CustomClient'
86
- config.access_grant_class_name = 'Object'
87
- config.scopes_validator_class_name = 'CustomScopesValidator'
88
- end
89
-
90
- it 'invokes custom scopes validator' do
91
- expect(config.scopes_validator.new([]).valid_for?(nil)).to be_falsey
92
- end
93
-
94
- it 'works with custom Access Token class' do
95
- expect(config.access_token_class.authenticate('')).to eq('Test')
96
- end
97
-
98
- it 'works with custom Client class' do
99
- expect(config.client_class.authenticate('')).to eq('Test')
100
- end
101
-
102
- it 'works with custom Resource Owner class' do
103
- expect(config.resource_owner_class.oauth_authenticate('', '', '')).to eq('Test')
104
- end
105
-
106
- it 'works with custom token authenticator' do
107
- # before
108
- Grape::OAuth2.configure do |config|
109
- config.token_authenticator do |request|
110
- raise ArgumentError, 'Test'
111
- end
112
- end
113
-
114
- expect { config.token_authenticator.call }.to raise_error(ArgumentError)
115
-
116
- # after
117
- Grape::OAuth2.configure do |config|
118
- config.token_authenticator = config.default_token_authenticator
119
- end
120
- end
121
-
122
- it 'works with custom token generator' do
123
- # before
124
- Grape::OAuth2.configure do |config|
125
- config.token_generator_class_name = 'CustomTokenGenerator'
126
- end
127
-
128
- expect(Grape::OAuth2.config.token_generator.generate).to eq('default_token')
129
- expect(Grape::OAuth2.config.token_generator.generate(custom: true)).to eq('custom_token')
130
-
131
- # after
132
- Grape::OAuth2.configure do |config|
133
- config.token_generator_class_name = Grape::OAuth2::UniqueToken.name
134
- end
135
- end
136
-
137
- it 'works with custom on_refresh callback' do
138
- token = AccessToken.create
139
-
140
- # before
141
- Grape::OAuth2.configure do |config|
142
- config.on_refresh do |access_token|
143
- access_token.update(scopes: 'test')
144
- end
145
- end
146
-
147
- expect {
148
- Grape::OAuth2::Strategies::RefreshToken.send(:run_on_refresh_callback, token)
149
- }.to change { token.scopes }.to('test')
150
-
151
- # after
152
- Grape::OAuth2.configure do |config|
153
- config.on_refresh = :nothing
154
- end
155
- end
156
-
157
- it 'raises an error with invalid on_refresh callback' do
158
- # before
159
- Grape::OAuth2.configure do |config|
160
- config.on_refresh = 'invalid'
161
- end
162
-
163
- expect {
164
- Grape::OAuth2::Strategies::RefreshToken.send(:run_on_refresh_callback, nil)
165
- }.to raise_error(ArgumentError)
166
-
167
- # after
168
- Grape::OAuth2.configure do |config|
169
- config.on_refresh = :nothing
170
- end
171
- end
172
- end
173
-
174
- context 'validation' do
175
- context 'with invalid config options' do
176
- it 'raises an error for default configuration' do
177
- expect { config.check! }.to raise_error(Grape::OAuth2::Configuration::Error)
178
- end
179
-
180
- it "raises an error if configured classes doesn't have an instance methods" do
181
- class InvalidAccessToken
182
- # Only class methods
183
- def self.create_for(client, resource_owner, scopes = nil)
184
- end
185
-
186
- def self.authenticate(token, type: :access_token)
187
- 'Test'
188
- end
189
- end
190
-
191
- config.access_token_class_name = 'InvalidAccessToken'
192
- config.resource_owner_class_name = 'CustomResourceOwner'
193
- config.client_class_name = 'CustomClient'
194
- config.access_grant_class_name = 'Object'
195
-
196
- expect { config.check! }.to raise_error(Grape::OAuth2::Configuration::APIMissing) do |error|
197
- expect(error.message).to include('access_token_class')
198
- expect(error.message).to include('Instance method')
199
- end
200
- end
201
-
202
- it "raises an error if configured classes doesn't have a class methods" do
203
- class InvalidClient
204
- end
205
-
206
- config.access_token_class_name = 'CustomAccessToken'
207
- config.resource_owner_class_name = 'CustomResourceOwner'
208
- config.client_class_name = 'InvalidClient'
209
- config.access_grant_class_name = 'Object'
210
-
211
- expect { config.check! }.to raise_error(Grape::OAuth2::Configuration::APIMissing) do |error|
212
- expect(error.message).to include('client_class')
213
- expect(error.message).to include('Class method')
214
- end
215
- end
216
- end
217
-
218
- context 'with valid config options' do
219
- before do
220
- config.access_token_class_name = 'CustomAccessToken'
221
- config.resource_owner_class_name = 'CustomResourceOwner'
222
- config.client_class_name = 'CustomClient'
223
- config.access_grant_class_name = 'Object'
224
- end
225
-
226
- it 'successfully pass' do
227
- expect { config.check! }.not_to raise_error
228
- end
229
- end
230
- end
231
- end
1
+ require 'spec_helper'
2
+
3
+ describe Grape::OAuth2::Configuration do
4
+ let(:config) { described_class.new }
5
+
6
+ # Refactor: Mock it
7
+ class CustomClient
8
+ def self.authenticate(key, secret = nil)
9
+ 'Test'
10
+ end
11
+ end
12
+
13
+ class CustomAccessToken
14
+ def self.create_for(client, resource_owner, scopes = nil)
15
+ end
16
+
17
+ def self.authenticate(token, type: :access_token)
18
+ 'Test'
19
+ end
20
+
21
+ def client
22
+ end
23
+
24
+ def resource_owner
25
+ end
26
+
27
+ def expired?
28
+ end
29
+
30
+ def revoked?
31
+ end
32
+
33
+ def revoke!(revoked_at = Time.now)
34
+ end
35
+
36
+ def to_bearer_token
37
+ end
38
+ end
39
+
40
+ class CustomResourceOwner
41
+ def self.oauth_authenticate(client, username, password)
42
+ 'Test'
43
+ end
44
+ end
45
+
46
+ context 'default config' do
47
+ it 'setup config with default values' do
48
+ expect(config.access_token_lifetime).to eq(7200)
49
+ expect(config.authorization_code_lifetime).to eq(1800)
50
+
51
+ expect(config.realm).to eq(Grape::OAuth2::Configuration::DEFAULT_REALM)
52
+ expect(config.allowed_grant_types).to eq(%w[password client_credentials])
53
+
54
+ expect(config.issue_refresh_token).to be_falsey
55
+ expect(config.on_refresh).to eq(:nothing)
56
+
57
+ expect(config.scopes_validator_class_name).to eq(Grape::OAuth2::Scopes.name)
58
+ end
59
+ end
60
+
61
+ context 'custom config' do
62
+ class CustomScopesValidator
63
+ def initialize(scopes)
64
+ @scopes = scopes
65
+ end
66
+
67
+ def valid_for?(*)
68
+ false
69
+ end
70
+ end
71
+
72
+ class CustomTokenGenerator
73
+ def self.generate(options = {})
74
+ if options[:custom]
75
+ 'custom_token'
76
+ else
77
+ 'default_token'
78
+ end
79
+ end
80
+ end
81
+
82
+ before do
83
+ config.access_token_class_name = 'CustomAccessToken'
84
+ config.resource_owner_class_name = 'CustomResourceOwner'
85
+ config.client_class_name = 'CustomClient'
86
+ config.access_grant_class_name = 'Object'
87
+ config.scopes_validator_class_name = 'CustomScopesValidator'
88
+ end
89
+
90
+ it 'invokes custom scopes validator' do
91
+ expect(config.scopes_validator.new([]).valid_for?(nil)).to be_falsey
92
+ end
93
+
94
+ it 'works with custom Access Token class' do
95
+ expect(config.access_token_class.authenticate('')).to eq('Test')
96
+ end
97
+
98
+ it 'works with custom Client class' do
99
+ expect(config.client_class.authenticate('')).to eq('Test')
100
+ end
101
+
102
+ it 'works with custom Resource Owner class' do
103
+ expect(config.resource_owner_class.oauth_authenticate('', '', '')).to eq('Test')
104
+ end
105
+
106
+ it 'works with custom token authenticator' do
107
+ # before
108
+ Grape::OAuth2.configure do |config|
109
+ config.token_authenticator do |request|
110
+ raise ArgumentError, 'Test'
111
+ end
112
+ end
113
+
114
+ expect { config.token_authenticator.call }.to raise_error(ArgumentError)
115
+
116
+ # after
117
+ Grape::OAuth2.configure do |config|
118
+ config.token_authenticator = config.default_token_authenticator
119
+ end
120
+ end
121
+
122
+ it 'works with custom token generator' do
123
+ # before
124
+ Grape::OAuth2.configure do |config|
125
+ config.token_generator_class_name = 'CustomTokenGenerator'
126
+ end
127
+
128
+ expect(Grape::OAuth2.config.token_generator.generate).to eq('default_token')
129
+ expect(Grape::OAuth2.config.token_generator.generate(custom: true)).to eq('custom_token')
130
+
131
+ # after
132
+ Grape::OAuth2.configure do |config|
133
+ config.token_generator_class_name = Grape::OAuth2::UniqueToken.name
134
+ end
135
+ end
136
+
137
+ it 'works with custom on_refresh callback' do
138
+ token = AccessToken.create
139
+
140
+ # before
141
+ Grape::OAuth2.configure do |config|
142
+ config.on_refresh do |access_token|
143
+ access_token.update(scopes: 'test')
144
+ end
145
+ end
146
+
147
+ expect {
148
+ Grape::OAuth2::Strategies::RefreshToken.send(:run_on_refresh_callback, token)
149
+ }.to change { token.scopes }.to('test')
150
+
151
+ # after
152
+ Grape::OAuth2.configure do |config|
153
+ config.on_refresh = :nothing
154
+ end
155
+ end
156
+
157
+ it 'raises an error with invalid on_refresh callback' do
158
+ # before
159
+ Grape::OAuth2.configure do |config|
160
+ config.on_refresh = 'invalid'
161
+ end
162
+
163
+ expect {
164
+ Grape::OAuth2::Strategies::RefreshToken.send(:run_on_refresh_callback, nil)
165
+ }.to raise_error(ArgumentError)
166
+
167
+ # after
168
+ Grape::OAuth2.configure do |config|
169
+ config.on_refresh = :nothing
170
+ end
171
+ end
172
+ end
173
+
174
+ context 'validation' do
175
+ context 'with invalid config options' do
176
+ it 'raises an error for default configuration' do
177
+ expect { config.check! }.to raise_error(Grape::OAuth2::Configuration::Error)
178
+ end
179
+
180
+ it "raises an error if configured classes doesn't have an instance methods" do
181
+ class InvalidAccessToken
182
+ # Only class methods
183
+ def self.create_for(client, resource_owner, scopes = nil)
184
+ end
185
+
186
+ def self.authenticate(token, type: :access_token)
187
+ 'Test'
188
+ end
189
+ end
190
+
191
+ config.access_token_class_name = 'InvalidAccessToken'
192
+ config.resource_owner_class_name = 'CustomResourceOwner'
193
+ config.client_class_name = 'CustomClient'
194
+ config.access_grant_class_name = 'Object'
195
+
196
+ expect { config.check! }.to raise_error(Grape::OAuth2::Configuration::APIMissing) do |error|
197
+ expect(error.message).to include('access_token_class')
198
+ expect(error.message).to include('Instance method')
199
+ end
200
+ end
201
+
202
+ it "raises an error if configured classes doesn't have a class methods" do
203
+ class InvalidClient
204
+ end
205
+
206
+ config.access_token_class_name = 'CustomAccessToken'
207
+ config.resource_owner_class_name = 'CustomResourceOwner'
208
+ config.client_class_name = 'InvalidClient'
209
+ config.access_grant_class_name = 'Object'
210
+
211
+ expect { config.check! }.to raise_error(Grape::OAuth2::Configuration::APIMissing) do |error|
212
+ expect(error.message).to include('client_class')
213
+ expect(error.message).to include('Class method')
214
+ end
215
+ end
216
+ end
217
+
218
+ context 'with valid config options' do
219
+ before do
220
+ config.access_token_class_name = 'CustomAccessToken'
221
+ config.resource_owner_class_name = 'CustomResourceOwner'
222
+ config.client_class_name = 'CustomClient'
223
+ config.access_grant_class_name = 'Object'
224
+ end
225
+
226
+ it 'successfully pass' do
227
+ expect { config.check! }.not_to raise_error
228
+ end
229
+ end
230
+ end
231
+ end