doorkeeper 4.2.5 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE.md +25 -0
  3. data/.github/PULL_REQUEST_TEMPLATE.md +17 -0
  4. data/.gitignore +2 -1
  5. data/.gitlab-ci.yml +16 -0
  6. data/.hound.yml +2 -13
  7. data/.rubocop.yml +17 -0
  8. data/.travis.yml +19 -4
  9. data/Appraisals +8 -4
  10. data/CODE_OF_CONDUCT.md +46 -0
  11. data/Gemfile +1 -1
  12. data/NEWS.md +115 -0
  13. data/README.md +175 -39
  14. data/RELEASING.md +5 -12
  15. data/Rakefile +6 -0
  16. data/SECURITY.md +15 -0
  17. data/UPGRADE.md +2 -0
  18. data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
  19. data/app/controllers/doorkeeper/application_controller.rb +2 -5
  20. data/app/controllers/doorkeeper/application_metal_controller.rb +4 -0
  21. data/app/controllers/doorkeeper/applications_controller.rb +47 -13
  22. data/app/controllers/doorkeeper/authorizations_controller.rb +55 -12
  23. data/app/controllers/doorkeeper/authorized_applications_controller.rb +19 -2
  24. data/app/controllers/doorkeeper/tokens_controller.rb +24 -17
  25. data/app/helpers/doorkeeper/dashboard_helper.rb +8 -6
  26. data/app/validators/redirect_uri_validator.rb +13 -2
  27. data/app/views/doorkeeper/applications/_delete_form.html.erb +3 -1
  28. data/app/views/doorkeeper/applications/_form.html.erb +31 -19
  29. data/app/views/doorkeeper/applications/edit.html.erb +1 -1
  30. data/app/views/doorkeeper/applications/index.html.erb +18 -6
  31. data/app/views/doorkeeper/applications/new.html.erb +1 -1
  32. data/app/views/doorkeeper/applications/show.html.erb +8 -5
  33. data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
  34. data/app/views/doorkeeper/authorizations/new.html.erb +5 -1
  35. data/app/views/doorkeeper/authorized_applications/index.html.erb +0 -1
  36. data/app/views/layouts/doorkeeper/admin.html.erb +15 -15
  37. data/config/locales/en.yml +19 -6
  38. data/doorkeeper.gemspec +20 -20
  39. data/gemfiles/rails_4_2.gemfile +6 -4
  40. data/gemfiles/rails_5_0.gemfile +4 -4
  41. data/gemfiles/rails_5_1.gemfile +6 -7
  42. data/gemfiles/rails_5_2.gemfile +12 -0
  43. data/gemfiles/rails_master.gemfile +17 -0
  44. data/lib/doorkeeper/config.rb +123 -71
  45. data/lib/doorkeeper/engine.rb +7 -3
  46. data/lib/doorkeeper/errors.rb +20 -5
  47. data/lib/doorkeeper/grape/helpers.rb +14 -9
  48. data/lib/doorkeeper/helpers/controller.rb +16 -22
  49. data/lib/doorkeeper/models/access_grant_mixin.rb +67 -23
  50. data/lib/doorkeeper/models/access_token_mixin.rb +54 -55
  51. data/lib/doorkeeper/models/application_mixin.rb +16 -30
  52. data/lib/doorkeeper/models/concerns/expirable.rb +7 -5
  53. data/lib/doorkeeper/models/concerns/orderable.rb +13 -0
  54. data/lib/doorkeeper/models/concerns/scopes.rb +1 -1
  55. data/lib/doorkeeper/oauth/authorization/code.rb +31 -8
  56. data/lib/doorkeeper/oauth/authorization/context.rb +15 -0
  57. data/lib/doorkeeper/oauth/authorization/token.rb +46 -20
  58. data/lib/doorkeeper/oauth/authorization_code_request.rb +33 -3
  59. data/lib/doorkeeper/oauth/base_request.rb +23 -7
  60. data/lib/doorkeeper/oauth/client/credentials.rb +6 -4
  61. data/lib/doorkeeper/oauth/client.rb +2 -4
  62. data/lib/doorkeeper/oauth/client_credentials/creator.rb +2 -1
  63. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +6 -3
  64. data/lib/doorkeeper/oauth/client_credentials/validation.rb +4 -6
  65. data/lib/doorkeeper/oauth/client_credentials_request.rb +0 -4
  66. data/lib/doorkeeper/oauth/error.rb +2 -2
  67. data/lib/doorkeeper/oauth/error_response.rb +11 -4
  68. data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
  69. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +0 -8
  70. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +15 -0
  71. data/lib/doorkeeper/oauth/invalid_token_response.rb +3 -4
  72. data/lib/doorkeeper/oauth/password_access_token_request.rb +8 -4
  73. data/lib/doorkeeper/oauth/pre_authorization.rb +45 -13
  74. data/lib/doorkeeper/oauth/refresh_token_request.rb +7 -1
  75. data/lib/doorkeeper/oauth/scopes.rb +19 -9
  76. data/lib/doorkeeper/oauth/token.rb +6 -3
  77. data/lib/doorkeeper/oauth/token_introspection.rb +128 -0
  78. data/lib/doorkeeper/oauth/token_response.rb +4 -2
  79. data/lib/doorkeeper/oauth.rb +13 -0
  80. data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -0
  81. data/lib/doorkeeper/orm/active_record/access_token.rb +21 -20
  82. data/lib/doorkeeper/orm/active_record/application.rb +45 -0
  83. data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +26 -0
  84. data/lib/doorkeeper/orm/active_record.rb +21 -8
  85. data/lib/doorkeeper/rails/helpers.rb +7 -10
  86. data/lib/doorkeeper/rails/routes.rb +21 -7
  87. data/lib/doorkeeper/rake/db.rake +40 -0
  88. data/lib/doorkeeper/rake/setup.rake +6 -0
  89. data/lib/doorkeeper/rake.rb +14 -0
  90. data/lib/doorkeeper/request/authorization_code.rb +0 -2
  91. data/lib/doorkeeper/request/client_credentials.rb +0 -2
  92. data/lib/doorkeeper/request/code.rb +0 -2
  93. data/lib/doorkeeper/request/password.rb +1 -13
  94. data/lib/doorkeeper/request/refresh_token.rb +0 -2
  95. data/lib/doorkeeper/request/token.rb +0 -2
  96. data/lib/doorkeeper/request.rb +29 -30
  97. data/lib/doorkeeper/validations.rb +3 -2
  98. data/lib/doorkeeper/version.rb +14 -1
  99. data/lib/doorkeeper.rb +21 -17
  100. data/lib/generators/doorkeeper/application_owner_generator.rb +26 -12
  101. data/lib/generators/doorkeeper/confidential_applications_generator.rb +32 -0
  102. data/lib/generators/doorkeeper/install_generator.rb +17 -9
  103. data/lib/generators/doorkeeper/migration_generator.rb +26 -9
  104. data/lib/generators/doorkeeper/pkce_generator.rb +32 -0
  105. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +31 -20
  106. data/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
  107. data/lib/generators/doorkeeper/templates/{add_owner_to_application_migration.rb → add_owner_to_application_migration.rb.erb} +1 -1
  108. data/lib/generators/doorkeeper/templates/{add_previous_refresh_token_to_access_tokens.rb → add_previous_refresh_token_to_access_tokens.rb.erb} +1 -1
  109. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +6 -0
  110. data/lib/generators/doorkeeper/templates/initializer.rb +104 -12
  111. data/lib/generators/doorkeeper/templates/{migration.rb → migration.rb.erb} +2 -1
  112. data/lib/generators/doorkeeper/views_generator.rb +3 -1
  113. data/spec/controllers/application_metal_controller_spec.rb +50 -0
  114. data/spec/controllers/applications_controller_spec.rb +141 -17
  115. data/spec/controllers/authorizations_controller_spec.rb +304 -27
  116. data/spec/controllers/protected_resources_controller_spec.rb +44 -35
  117. data/spec/controllers/token_info_controller_spec.rb +17 -21
  118. data/spec/controllers/tokens_controller_spec.rb +201 -17
  119. data/spec/dummy/app/assets/config/manifest.js +2 -0
  120. data/spec/dummy/config/environments/test.rb +4 -5
  121. data/spec/dummy/config/initializers/doorkeeper.rb +23 -2
  122. data/spec/dummy/config/initializers/{active_record_belongs_to_required_by_default.rb → new_framework_defaults.rb} +5 -1
  123. data/spec/dummy/config/initializers/secret_token.rb +0 -1
  124. data/spec/dummy/config/routes.rb +3 -42
  125. data/spec/dummy/db/migrate/20111122132257_create_users.rb +3 -1
  126. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +3 -1
  127. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +3 -1
  128. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +3 -1
  129. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +3 -1
  130. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +6 -0
  131. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +13 -0
  132. data/spec/dummy/db/schema.rb +38 -37
  133. data/spec/factories.rb +1 -1
  134. data/spec/generators/application_owner_generator_spec.rb +25 -6
  135. data/spec/generators/confidential_applications_generator_spec.rb +45 -0
  136. data/spec/generators/install_generator_spec.rb +1 -1
  137. data/spec/generators/migration_generator_spec.rb +25 -4
  138. data/spec/generators/pkce_generator_spec.rb +43 -0
  139. data/spec/generators/previous_refresh_token_generator_spec.rb +57 -0
  140. data/spec/generators/views_generator_spec.rb +1 -1
  141. data/spec/grape/grape_integration_spec.rb +135 -0
  142. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +2 -2
  143. data/spec/lib/config_spec.rb +199 -22
  144. data/spec/lib/doorkeeper_spec.rb +1 -126
  145. data/spec/lib/models/expirable_spec.rb +0 -4
  146. data/spec/lib/models/revocable_spec.rb +2 -4
  147. data/spec/lib/models/scopes_spec.rb +0 -4
  148. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -4
  149. data/spec/lib/oauth/authorization_code_request_spec.rb +63 -13
  150. data/spec/lib/oauth/base_request_spec.rb +43 -10
  151. data/spec/lib/oauth/base_response_spec.rb +1 -1
  152. data/spec/lib/oauth/client/credentials_spec.rb +5 -5
  153. data/spec/lib/oauth/client_credentials/creator_spec.rb +6 -2
  154. data/spec/lib/oauth/client_credentials/issuer_spec.rb +26 -7
  155. data/spec/lib/oauth/client_credentials/validation_spec.rb +2 -3
  156. data/spec/lib/oauth/client_credentials_integration_spec.rb +2 -2
  157. data/spec/lib/oauth/client_credentials_request_spec.rb +4 -5
  158. data/spec/lib/oauth/client_spec.rb +0 -3
  159. data/spec/lib/oauth/code_request_spec.rb +5 -5
  160. data/spec/lib/oauth/error_response_spec.rb +0 -3
  161. data/spec/lib/oauth/error_spec.rb +1 -3
  162. data/spec/lib/oauth/forbidden_token_response_spec.rb +1 -4
  163. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -3
  164. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -1
  165. data/spec/lib/oauth/helpers/uri_checker_spec.rb +115 -3
  166. data/spec/lib/oauth/invalid_token_response_spec.rb +2 -5
  167. data/spec/lib/oauth/password_access_token_request_spec.rb +46 -5
  168. data/spec/lib/oauth/pre_authorization_spec.rb +40 -6
  169. data/spec/lib/oauth/refresh_token_request_spec.rb +30 -14
  170. data/spec/lib/oauth/scopes_spec.rb +28 -4
  171. data/spec/lib/oauth/token_request_spec.rb +10 -13
  172. data/spec/lib/oauth/token_response_spec.rb +0 -1
  173. data/spec/lib/oauth/token_spec.rb +37 -14
  174. data/spec/lib/orm/active_record/stale_records_cleaner_spec.rb +79 -0
  175. data/spec/lib/request/strategy_spec.rb +0 -1
  176. data/spec/lib/server_spec.rb +10 -0
  177. data/spec/models/doorkeeper/access_grant_spec.rb +45 -2
  178. data/spec/models/doorkeeper/access_token_spec.rb +132 -64
  179. data/spec/models/doorkeeper/application_spec.rb +114 -23
  180. data/spec/requests/applications/applications_request_spec.rb +139 -6
  181. data/spec/requests/applications/authorized_applications_spec.rb +1 -1
  182. data/spec/requests/endpoints/authorization_spec.rb +1 -1
  183. data/spec/requests/endpoints/token_spec.rb +15 -6
  184. data/spec/requests/flows/authorization_code_errors_spec.rb +12 -2
  185. data/spec/requests/flows/authorization_code_spec.rb +199 -2
  186. data/spec/requests/flows/client_credentials_spec.rb +73 -5
  187. data/spec/requests/flows/implicit_grant_errors_spec.rb +3 -3
  188. data/spec/requests/flows/implicit_grant_spec.rb +38 -11
  189. data/spec/requests/flows/password_spec.rb +160 -24
  190. data/spec/requests/flows/refresh_token_spec.rb +6 -6
  191. data/spec/requests/flows/revoke_token_spec.rb +26 -26
  192. data/spec/requests/flows/skip_authorization_spec.rb +16 -11
  193. data/spec/requests/protected_resources/metal_spec.rb +2 -2
  194. data/spec/requests/protected_resources/private_api_spec.rb +2 -2
  195. data/spec/routing/custom_controller_routes_spec.rb +63 -7
  196. data/spec/routing/default_routes_spec.rb +6 -2
  197. data/spec/routing/scoped_routes_spec.rb +16 -2
  198. data/spec/spec_helper.rb +54 -3
  199. data/spec/spec_helper_integration.rb +2 -64
  200. data/spec/support/dependencies/factory_bot.rb +2 -0
  201. data/spec/support/doorkeeper_rspec.rb +19 -0
  202. data/spec/support/helpers/access_token_request_helper.rb +1 -1
  203. data/spec/support/helpers/authorization_request_helper.rb +4 -4
  204. data/spec/support/helpers/model_helper.rb +9 -4
  205. data/spec/support/helpers/request_spec_helper.rb +18 -6
  206. data/spec/support/helpers/url_helper.rb +15 -10
  207. data/spec/support/http_method_shim.rb +12 -16
  208. data/spec/support/shared/controllers_shared_context.rb +2 -6
  209. data/spec/support/shared/models_shared_examples.rb +4 -4
  210. data/spec/validators/redirect_uri_validator_spec.rb +58 -7
  211. data/spec/version/version_spec.rb +15 -0
  212. data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
  213. metadata +75 -33
  214. data/spec/controllers/application_metal_controller.rb +0 -10
  215. data/spec/support/dependencies/factory_girl.rb +0 -2
@@ -1,8 +1,8 @@
1
- require 'spec_helper_integration'
1
+ require 'spec_helper'
2
2
 
3
3
  module Doorkeeper
4
4
  describe AccessToken do
5
- subject { FactoryGirl.build(:access_token) }
5
+ subject { FactoryBot.build(:access_token) }
6
6
 
7
7
  it { expect(subject).to be_valid }
8
8
 
@@ -19,9 +19,9 @@ module Doorkeeper
19
19
 
20
20
  describe :generate_token do
21
21
  it 'generates a token using the default method' do
22
- FactoryGirl.create :access_token
22
+ FactoryBot.create :access_token
23
23
 
24
- token = FactoryGirl.create :access_token
24
+ token = FactoryBot.create :access_token
25
25
  expect(token.token).to be_a(String)
26
26
  end
27
27
 
@@ -41,7 +41,7 @@ module Doorkeeper
41
41
  access_token_generator "Doorkeeper::CustomGeneratorArgs"
42
42
  end
43
43
 
44
- token = FactoryGirl.create :access_token
44
+ token = FactoryBot.create :access_token
45
45
  expect(token.token).to match(%r{custom_generator_token_\d+})
46
46
  end
47
47
 
@@ -61,7 +61,7 @@ module Doorkeeper
61
61
  access_token_generator "Doorkeeper::CustomGeneratorArgs"
62
62
  end
63
63
 
64
- token = FactoryGirl.create :access_token
64
+ token = FactoryBot.create :access_token
65
65
  expect(token.token).to match(%r{custom_generator_token_Application \d+})
66
66
  end
67
67
 
@@ -81,7 +81,7 @@ module Doorkeeper
81
81
  access_token_generator "Doorkeeper::CustomGeneratorArgs"
82
82
  end
83
83
 
84
- token = FactoryGirl.create :access_token, scopes: 'public write'
84
+ token = FactoryBot.create :access_token, scopes: 'public write'
85
85
 
86
86
  expect(token.token).to eq 'custom_generator_token_2_public write'
87
87
  end
@@ -102,7 +102,7 @@ module Doorkeeper
102
102
  access_token_generator "Doorkeeper::CustomGeneratorArgs"
103
103
  end
104
104
 
105
- token = FactoryGirl.create :access_token
105
+ token = FactoryBot.create :access_token
106
106
  expect(token.token).to eq 'custom_generator_token_7200'
107
107
  end
108
108
 
@@ -118,7 +118,7 @@ module Doorkeeper
118
118
  access_token_generator "Doorkeeper::CustomGeneratorArgs"
119
119
  end
120
120
 
121
- token = FactoryGirl.create :access_token
121
+ token = FactoryBot.create :access_token
122
122
  created_at = token.created_at
123
123
  expect(token.token).to eq "custom_generator_token_#{created_at.to_i}"
124
124
  end
@@ -132,8 +132,31 @@ module Doorkeeper
132
132
  access_token_generator "Doorkeeper::NoGenerate"
133
133
  end
134
134
 
135
- expect { FactoryGirl.create :access_token }.to(
136
- raise_error(Doorkeeper::Errors::UnableToGenerateToken))
135
+ expect { FactoryBot.create :access_token }.to(
136
+ raise_error(Doorkeeper::Errors::UnableToGenerateToken)
137
+ )
138
+ end
139
+
140
+ it 'raises original error if something went wrong in custom generator' do
141
+ eigenclass = class << CustomGeneratorArgs; self; end
142
+ eigenclass.class_eval do
143
+ remove_method :generate
144
+ end
145
+
146
+ module CustomGeneratorArgs
147
+ def self.generate(_opts = {})
148
+ raise LoadError, 'custom behaviour'
149
+ end
150
+ end
151
+
152
+ Doorkeeper.configure do
153
+ orm DOORKEEPER_ORM
154
+ access_token_generator "Doorkeeper::CustomGeneratorArgs"
155
+ end
156
+
157
+ expect { FactoryBot.create :access_token }.to(
158
+ raise_error(LoadError)
159
+ )
137
160
  end
138
161
 
139
162
  it 'raises an error if the custom object does not exist' do
@@ -142,32 +165,33 @@ module Doorkeeper
142
165
  access_token_generator "Doorkeeper::NotReal"
143
166
  end
144
167
 
145
- expect { FactoryGirl.create :access_token }.to(
146
- raise_error(Doorkeeper::Errors::TokenGeneratorNotFound))
168
+ expect { FactoryBot.create :access_token }.to(
169
+ raise_error(Doorkeeper::Errors::TokenGeneratorNotFound, /NotReal/)
170
+ )
147
171
  end
148
172
  end
149
173
 
150
174
  describe :refresh_token do
151
175
  it 'has empty refresh token if it was not required' do
152
- token = FactoryGirl.create :access_token
176
+ token = FactoryBot.create :access_token
153
177
  expect(token.refresh_token).to be_nil
154
178
  end
155
179
 
156
180
  it 'generates a refresh token if it was requested' do
157
- token = FactoryGirl.create :access_token, use_refresh_token: true
181
+ token = FactoryBot.create :access_token, use_refresh_token: true
158
182
  expect(token.refresh_token).not_to be_nil
159
183
  end
160
184
 
161
185
  it 'is not valid if token exists' do
162
- token1 = FactoryGirl.create :access_token, use_refresh_token: true
163
- token2 = FactoryGirl.create :access_token, use_refresh_token: true
186
+ token1 = FactoryBot.create :access_token, use_refresh_token: true
187
+ token2 = FactoryBot.create :access_token, use_refresh_token: true
164
188
  token2.refresh_token = token1.refresh_token
165
189
  expect(token2).not_to be_valid
166
190
  end
167
191
 
168
192
  it 'expects database to raise an error if refresh tokens are the same' do
169
- token1 = FactoryGirl.create :access_token, use_refresh_token: true
170
- token2 = FactoryGirl.create :access_token, use_refresh_token: true
193
+ token1 = FactoryBot.create :access_token, use_refresh_token: true
194
+ token2 = FactoryBot.create :access_token, use_refresh_token: true
171
195
  expect do
172
196
  token2.refresh_token = token1.refresh_token
173
197
  token2.save(validate: false)
@@ -194,22 +218,22 @@ module Doorkeeper
194
218
  context 'with default parameters' do
195
219
 
196
220
  let(:resource_owner_id) { 100 }
197
- let(:application) { FactoryGirl.create :application }
221
+ let(:application) { FactoryBot.create :application }
198
222
  let(:default_attributes) do
199
223
  { application: application, resource_owner_id: resource_owner_id }
200
224
  end
201
- let(:access_token1) { FactoryGirl.create :access_token, default_attributes }
225
+ let(:access_token1) { FactoryBot.create :access_token, default_attributes }
202
226
 
203
227
  context 'the second token has the same owner and same app' do
204
- let(:access_token2) { FactoryGirl.create :access_token, default_attributes }
228
+ let(:access_token2) { FactoryBot.create :access_token, default_attributes }
205
229
  it 'success' do
206
230
  expect(access_token1.same_credential?(access_token2)).to be_truthy
207
231
  end
208
232
  end
209
233
 
210
234
  context 'the second token has same owner and different app' do
211
- let(:other_application) { FactoryGirl.create :application }
212
- let(:access_token2) { FactoryGirl.create :access_token, application: other_application, resource_owner_id: resource_owner_id }
235
+ let(:other_application) { FactoryBot.create :application }
236
+ let(:access_token2) { FactoryBot.create :access_token, application: other_application, resource_owner_id: resource_owner_id }
213
237
 
214
238
  it 'fail' do
215
239
  expect(access_token1.same_credential?(access_token2)).to be_falsey
@@ -218,8 +242,8 @@ module Doorkeeper
218
242
 
219
243
  context 'the second token has different owner and different app' do
220
244
 
221
- let(:other_application) { FactoryGirl.create :application }
222
- let(:access_token2) { FactoryGirl.create :access_token, application: other_application, resource_owner_id: 42 }
245
+ let(:other_application) { FactoryBot.create :application }
246
+ let(:access_token2) { FactoryBot.create :access_token, application: other_application, resource_owner_id: 42 }
223
247
 
224
248
  it 'fail' do
225
249
  expect(access_token1.same_credential?(access_token2)).to be_falsey
@@ -227,7 +251,7 @@ module Doorkeeper
227
251
  end
228
252
 
229
253
  context 'the second token has different owner and same app' do
230
- let(:access_token2) { FactoryGirl.create :access_token, application: application, resource_owner_id: 42 }
254
+ let(:access_token2) { FactoryBot.create :access_token, application: application, resource_owner_id: 42 }
231
255
 
232
256
  it 'fail' do
233
257
  expect(access_token1.same_credential?(access_token2)).to be_falsey
@@ -238,7 +262,7 @@ module Doorkeeper
238
262
 
239
263
  describe '#acceptable?' do
240
264
  context 'a token that is not accessible' do
241
- let(:token) { FactoryGirl.create(:access_token, created_at: 6.hours.ago) }
265
+ let(:token) { FactoryBot.create(:access_token, created_at: 6.hours.ago) }
242
266
 
243
267
  it 'should return false' do
244
268
  expect(token.acceptable?(nil)).to be false
@@ -246,7 +270,7 @@ module Doorkeeper
246
270
  end
247
271
 
248
272
  context 'a token that has the incorrect scopes' do
249
- let(:token) { FactoryGirl.create(:access_token) }
273
+ let(:token) { FactoryBot.create(:access_token) }
250
274
 
251
275
  it 'should return false' do
252
276
  expect(token.acceptable?(['public'])).to be false
@@ -255,7 +279,7 @@ module Doorkeeper
255
279
 
256
280
  context 'a token is acceptable with the correct scopes' do
257
281
  let(:token) do
258
- token = FactoryGirl.create(:access_token)
282
+ token = FactoryBot.create(:access_token)
259
283
  token[:scopes] = 'public'
260
284
  token
261
285
  end
@@ -268,13 +292,13 @@ module Doorkeeper
268
292
 
269
293
  describe '.revoke_all_for' do
270
294
  let(:resource_owner) { double(id: 100) }
271
- let(:application) { FactoryGirl.create :application }
295
+ let(:application) { FactoryBot.create :application }
272
296
  let(:default_attributes) do
273
297
  { application: application, resource_owner_id: resource_owner.id }
274
298
  end
275
299
 
276
300
  it 'revokes all tokens for given application and resource owner' do
277
- FactoryGirl.create :access_token, default_attributes
301
+ FactoryBot.create :access_token, default_attributes
278
302
  AccessToken.revoke_all_for application.id, resource_owner
279
303
  AccessToken.all.each do |token|
280
304
  expect(token).to be_revoked
@@ -282,21 +306,31 @@ module Doorkeeper
282
306
  end
283
307
 
284
308
  it 'matches application' do
285
- FactoryGirl.create :access_token, default_attributes.merge(application: FactoryGirl.create(:application))
309
+ access_token_for_different_app = FactoryBot.create(
310
+ :access_token,
311
+ default_attributes.merge(application: FactoryBot.create(:application))
312
+ )
313
+
286
314
  AccessToken.revoke_all_for application.id, resource_owner
287
- expect(AccessToken.all).not_to be_empty
315
+
316
+ expect(access_token_for_different_app.reload).not_to be_revoked
288
317
  end
289
318
 
290
319
  it 'matches resource owner' do
291
- FactoryGirl.create :access_token, default_attributes.merge(resource_owner_id: 90)
320
+ access_token_for_different_owner = FactoryBot.create(
321
+ :access_token,
322
+ default_attributes.merge(resource_owner_id: 90)
323
+ )
324
+
292
325
  AccessToken.revoke_all_for application.id, resource_owner
293
- expect(AccessToken.all).not_to be_empty
326
+
327
+ expect(access_token_for_different_owner.reload).not_to be_revoked
294
328
  end
295
329
  end
296
330
 
297
331
  describe '.matching_token_for' do
298
332
  let(:resource_owner_id) { 100 }
299
- let(:application) { FactoryGirl.create :application }
333
+ let(:application) { FactoryBot.create :application }
300
334
  let(:scopes) { Doorkeeper::OAuth::Scopes.from_string('public write') }
301
335
  let(:default_attributes) do
302
336
  {
@@ -306,89 +340,123 @@ module Doorkeeper
306
340
  }
307
341
  end
308
342
 
343
+ before do
344
+ default_scopes_exist(*scopes.all)
345
+ end
346
+
309
347
  it 'returns only one token' do
310
- token = FactoryGirl.create :access_token, default_attributes
348
+ token = FactoryBot.create :access_token, default_attributes
311
349
  last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
312
350
  expect(last_token).to eq(token)
313
351
  end
314
352
 
315
353
  it 'accepts resource owner as object' do
316
354
  resource_owner = double(to_key: true, id: 100)
317
- token = FactoryGirl.create :access_token, default_attributes
355
+ token = FactoryBot.create :access_token, default_attributes
318
356
  last_token = AccessToken.matching_token_for(application, resource_owner, scopes)
319
357
  expect(last_token).to eq(token)
320
358
  end
321
359
 
322
360
  it 'accepts nil as resource owner' do
323
- token = FactoryGirl.create :access_token, default_attributes.merge(resource_owner_id: nil)
361
+ token = FactoryBot.create :access_token, default_attributes.merge(resource_owner_id: nil)
324
362
  last_token = AccessToken.matching_token_for(application, nil, scopes)
325
363
  expect(last_token).to eq(token)
326
364
  end
327
365
 
328
366
  it 'excludes revoked tokens' do
329
- FactoryGirl.create :access_token, default_attributes.merge(revoked_at: 1.day.ago)
367
+ FactoryBot.create :access_token, default_attributes.merge(revoked_at: 1.day.ago)
330
368
  last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
331
369
  expect(last_token).to be_nil
332
370
  end
333
371
 
334
- it 'matches the application' do
335
- FactoryGirl.create :access_token, default_attributes.merge(application: FactoryGirl.create(:application))
372
+ it "excludes tokens with a different application" do
373
+ FactoryBot.create :access_token, default_attributes.merge(application: FactoryBot.create(:application))
336
374
  last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
337
375
  expect(last_token).to be_nil
338
376
  end
339
377
 
340
- it 'matches the resource owner' do
341
- FactoryGirl.create :access_token, default_attributes.merge(resource_owner_id: 2)
378
+ it "excludes tokens with a different resource owner" do
379
+ FactoryBot.create :access_token, default_attributes.merge(resource_owner_id: 2)
342
380
  last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
343
381
  expect(last_token).to be_nil
344
382
  end
345
383
 
346
- it 'matches token with fewer scopes' do
347
- FactoryGirl.create :access_token, default_attributes.merge(scopes: 'public')
384
+ it "excludes tokens with fewer scopes" do
385
+ FactoryBot.create :access_token, default_attributes.merge(scopes: 'public')
348
386
  last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
349
387
  expect(last_token).to be_nil
350
388
  end
351
389
 
352
- it 'matches token with different scopes' do
353
- FactoryGirl.create :access_token, default_attributes.merge(scopes: 'public email')
390
+ it 'excludes tokens with different scopes' do
391
+ FactoryBot.create :access_token, default_attributes.merge(scopes: 'public email')
354
392
  last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
355
393
  expect(last_token).to be_nil
356
394
  end
357
395
 
358
- it 'matches token with more scopes' do
359
- FactoryGirl.create :access_token, default_attributes.merge(scopes: 'public write email')
396
+ it 'excludes tokens with additional scopes' do
397
+ FactoryBot.create :access_token, default_attributes.merge(scopes: 'public write email')
360
398
  last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
361
399
  expect(last_token).to be_nil
362
400
  end
363
401
 
364
- it 'matches application scopes' do
365
- application = FactoryGirl.create :application, scopes: "private read"
366
- FactoryGirl.create :access_token, default_attributes.merge(
367
- application: application
402
+ it 'excludes tokens with scopes that are not present in server scopes' do
403
+ FactoryBot.create :access_token, default_attributes.merge(
404
+ application: application, scopes: 'public read'
368
405
  )
369
406
  last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
370
407
  expect(last_token).to be_nil
371
408
  end
372
409
 
373
- it 'returns the last created token' do
374
- FactoryGirl.create :access_token, default_attributes.merge(created_at: 1.day.ago)
375
- token = FactoryGirl.create :access_token, default_attributes
410
+ it 'excludes tokens with scopes that are not present in application scopes' do
411
+ application = FactoryBot.create :application, scopes: "private read"
412
+ FactoryBot.create :access_token, default_attributes.merge(
413
+ application: application
414
+ )
376
415
  last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
416
+ expect(last_token).to be_nil
417
+ end
418
+
419
+ it 'does not match token if empty scope requested and token/app scopes present' do
420
+ application = FactoryBot.create :application, scopes: "sample:scope"
421
+ app_params = {
422
+ application_id: application.id, scopes: "sample:scope",
423
+ resource_owner_id: 100
424
+ }
425
+ FactoryBot.create :access_token, app_params
426
+ empty_scopes = Doorkeeper::OAuth::Scopes.from_string("")
427
+ last_token = AccessToken.matching_token_for(application, 100, empty_scopes)
428
+ expect(last_token).to be_nil
429
+ end
430
+
431
+ it 'matches token if empty scope requested and no token scopes present' do
432
+ empty_scopes = Doorkeeper::OAuth::Scopes.from_string("")
433
+ token = FactoryBot.create :access_token, default_attributes.merge(scopes: empty_scopes)
434
+ last_token = AccessToken.matching_token_for(application, 100, empty_scopes)
377
435
  expect(last_token).to eq(token)
378
436
  end
379
437
 
380
- it 'returns as_json hash' do
381
- token = FactoryGirl.create :access_token, default_attributes
438
+ it 'returns the last matching token' do
439
+ FactoryBot.create :access_token, default_attributes.merge(created_at: 1.day.ago)
440
+ matching_token = FactoryBot.create :access_token, default_attributes
441
+ FactoryBot.create :access_token, default_attributes.merge(scopes: 'public')
442
+
443
+ last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
444
+ expect(last_token).to eq(matching_token)
445
+ end
446
+ end
447
+
448
+ describe "#as_json" do
449
+ it "returns as_json hash" do
450
+ token = FactoryBot.create :access_token
382
451
  token_hash = {
383
452
  resource_owner_id: token.resource_owner_id,
384
- scopes: token.scopes,
385
- expires_in_seconds: token.expires_in_seconds,
453
+ scope: token.scopes,
454
+ expires_in: token.expires_in_seconds,
386
455
  application: { uid: token.application.uid },
387
- created_at: token.created_at.to_i,
456
+ created_at: token.created_at.to_i
388
457
  }
389
458
  expect(token.as_json).to eq token_hash
390
459
  end
391
460
  end
392
-
393
461
  end
394
462
  end
@@ -1,10 +1,10 @@
1
- require 'spec_helper_integration'
1
+ require 'spec_helper'
2
2
 
3
3
  module Doorkeeper
4
4
  describe Application do
5
5
  let(:require_owner) { Doorkeeper.configuration.instance_variable_set('@confirm_application_owner', true) }
6
6
  let(:unset_require_owner) { Doorkeeper.configuration.instance_variable_set('@confirm_application_owner', false) }
7
- let(:new_application) { FactoryGirl.build(:application) }
7
+ let(:new_application) { FactoryBot.build(:application) }
8
8
 
9
9
  let(:uid) { SecureRandom.hex(8) }
10
10
  let(:secret) { SecureRandom.hex(8) }
@@ -30,7 +30,7 @@ module Doorkeeper
30
30
  context 'application owner is required' do
31
31
  before(:each) do
32
32
  require_owner
33
- @owner = FactoryGirl.build_stubbed(:doorkeeper_testing_user)
33
+ @owner = FactoryBot.build_stubbed(:doorkeeper_testing_user)
34
34
  end
35
35
 
36
36
  it 'is invalid without an owner' do
@@ -49,6 +49,11 @@ module Doorkeeper
49
49
  expect(new_application).not_to be_valid
50
50
  end
51
51
 
52
+ it 'is invalid without determining confidentiality' do
53
+ new_application.confidential = nil
54
+ expect(new_application).not_to be_valid
55
+ end
56
+
52
57
  it 'generates uid on create' do
53
58
  expect(new_application.uid).to be_nil
54
59
  new_application.save
@@ -80,15 +85,15 @@ module Doorkeeper
80
85
  end
81
86
 
82
87
  it 'checks uniqueness of uid' do
83
- app1 = FactoryGirl.create(:application)
84
- app2 = FactoryGirl.create(:application)
88
+ app1 = FactoryBot.create(:application)
89
+ app2 = FactoryBot.create(:application)
85
90
  app2.uid = app1.uid
86
91
  expect(app2).not_to be_valid
87
92
  end
88
93
 
89
94
  it 'expects database to throw an error when uids are the same' do
90
- app1 = FactoryGirl.create(:application)
91
- app2 = FactoryGirl.create(:application)
95
+ app1 = FactoryBot.create(:application)
96
+ app2 = FactoryBot.create(:application)
92
97
  app2.uid = app1.uid
93
98
  expect { app2.save!(validate: false) }.to raise_error(uniqueness_error)
94
99
  end
@@ -123,19 +128,52 @@ module Doorkeeper
123
128
  end
124
129
 
125
130
  it 'should destroy its access grants' do
126
- FactoryGirl.create(:access_grant, application: new_application)
131
+ FactoryBot.create(:access_grant, application: new_application)
127
132
  expect { new_application.destroy }.to change { Doorkeeper::AccessGrant.count }.by(-1)
128
133
  end
129
134
 
130
135
  it 'should destroy its access tokens' do
131
- FactoryGirl.create(:access_token, application: new_application)
132
- FactoryGirl.create(:access_token, application: new_application, revoked_at: Time.now.utc)
136
+ FactoryBot.create(:access_token, application: new_application)
137
+ FactoryBot.create(:access_token, application: new_application, revoked_at: Time.now.utc)
133
138
  expect do
134
139
  new_application.destroy
135
140
  end.to change { Doorkeeper::AccessToken.count }.by(-2)
136
141
  end
137
142
  end
138
143
 
144
+ describe :ordered_by do
145
+ let(:applications) { FactoryBot.create_list(:application, 5) }
146
+
147
+ context 'when a direction is not specified' do
148
+ it 'calls order with a default order of asc' do
149
+ names = applications.map(&:name).sort
150
+ expect(Application.ordered_by(:name).map(&:name)).to eq(names)
151
+ end
152
+ end
153
+
154
+ context 'when a direction is specified' do
155
+ it 'calls order with specified direction' do
156
+ names = applications.map(&:name).sort.reverse
157
+ expect(Application.ordered_by(:name, :desc).map(&:name)).to eq(names)
158
+ end
159
+ end
160
+ end
161
+
162
+ describe "#redirect_uri=" do
163
+ context "when array of valid redirect_uris" do
164
+ it "should join by newline" do
165
+ new_application.redirect_uri = ['http://localhost/callback1', 'http://localhost/callback2']
166
+ expect(new_application.redirect_uri).to eq("http://localhost/callback1\nhttp://localhost/callback2")
167
+ end
168
+ end
169
+ context "when string of valid redirect_uris" do
170
+ it "should store as-is" do
171
+ new_application.redirect_uri = "http://localhost/callback1\nhttp://localhost/callback2"
172
+ expect(new_application.redirect_uri).to eq("http://localhost/callback1\nhttp://localhost/callback2")
173
+ end
174
+ end
175
+ end
176
+
139
177
  describe :authorized_for do
140
178
  let(:resource_owner) { double(:resource_owner, id: 10) }
141
179
 
@@ -144,35 +182,88 @@ module Doorkeeper
144
182
  end
145
183
 
146
184
  it 'returns only application for a specific resource owner' do
147
- FactoryGirl.create(:access_token, resource_owner_id: resource_owner.id + 1)
148
- token = FactoryGirl.create(:access_token, resource_owner_id: resource_owner.id)
185
+ FactoryBot.create(:access_token, resource_owner_id: resource_owner.id + 1)
186
+ token = FactoryBot.create(:access_token, resource_owner_id: resource_owner.id)
149
187
  expect(Application.authorized_for(resource_owner)).to eq([token.application])
150
188
  end
151
189
 
152
190
  it 'excludes revoked tokens' do
153
- FactoryGirl.create(:access_token, resource_owner_id: resource_owner.id, revoked_at: 2.days.ago)
191
+ FactoryBot.create(:access_token, resource_owner_id: resource_owner.id, revoked_at: 2.days.ago)
154
192
  expect(Application.authorized_for(resource_owner)).to be_empty
155
193
  end
156
194
 
157
195
  it 'returns all applications that have been authorized' do
158
- token1 = FactoryGirl.create(:access_token, resource_owner_id: resource_owner.id)
159
- token2 = FactoryGirl.create(:access_token, resource_owner_id: resource_owner.id)
196
+ token1 = FactoryBot.create(:access_token, resource_owner_id: resource_owner.id)
197
+ token2 = FactoryBot.create(:access_token, resource_owner_id: resource_owner.id)
160
198
  expect(Application.authorized_for(resource_owner)).to eq([token1.application, token2.application])
161
199
  end
162
200
 
163
201
  it 'returns only one application even if it has been authorized twice' do
164
- application = FactoryGirl.create(:application)
165
- FactoryGirl.create(:access_token, resource_owner_id: resource_owner.id, application: application)
166
- FactoryGirl.create(:access_token, resource_owner_id: resource_owner.id, application: application)
202
+ application = FactoryBot.create(:application)
203
+ FactoryBot.create(:access_token, resource_owner_id: resource_owner.id, application: application)
204
+ FactoryBot.create(:access_token, resource_owner_id: resource_owner.id, application: application)
167
205
  expect(Application.authorized_for(resource_owner)).to eq([application])
168
206
  end
169
207
  end
170
208
 
171
- describe :authenticate do
172
- it 'finds the application via uid/secret' do
173
- app = FactoryGirl.create :application
174
- authenticated = Application.by_uid_and_secret(app.uid, app.secret)
175
- expect(authenticated).to eq(app)
209
+ describe :revoke_tokens_and_grants_for do
210
+ it 'revokes all access tokens and access grants' do
211
+ application_id = 42
212
+ resource_owner = double
213
+ expect(Doorkeeper::AccessToken).
214
+ to receive(:revoke_all_for).with(application_id, resource_owner)
215
+ expect(Doorkeeper::AccessGrant).
216
+ to receive(:revoke_all_for).with(application_id, resource_owner)
217
+
218
+ Application.revoke_tokens_and_grants_for(application_id, resource_owner)
219
+ end
220
+ end
221
+
222
+ describe :by_uid_and_secret do
223
+ context "when application is private/confidential" do
224
+ it "finds the application via uid/secret" do
225
+ app = FactoryBot.create :application
226
+ authenticated = Application.by_uid_and_secret(app.uid, app.secret)
227
+ expect(authenticated).to eq(app)
228
+ end
229
+ context "when secret is wrong" do
230
+ it "should not find the application" do
231
+ app = FactoryBot.create :application
232
+ authenticated = Application.by_uid_and_secret(app.uid, 'bad')
233
+ expect(authenticated).to eq(nil)
234
+ end
235
+ end
236
+ end
237
+
238
+ context "when application is public/non-confidential" do
239
+ context "when secret is blank" do
240
+ it "should find the application" do
241
+ app = FactoryBot.create :application, confidential: false
242
+ authenticated = Application.by_uid_and_secret(app.uid, nil)
243
+ expect(authenticated).to eq(app)
244
+ end
245
+ end
246
+ context "when secret is wrong" do
247
+ it "should not find the application" do
248
+ app = FactoryBot.create :application, confidential: false
249
+ authenticated = Application.by_uid_and_secret(app.uid, 'bad')
250
+ expect(authenticated).to eq(nil)
251
+ end
252
+ end
253
+ end
254
+ end
255
+
256
+ describe :confidential? do
257
+ subject { FactoryBot.create(:application, confidential: confidential).confidential? }
258
+
259
+ context 'when application is private/confidential' do
260
+ let(:confidential) { true }
261
+ it { expect(subject).to eq(true) }
262
+ end
263
+
264
+ context 'when application is public/non-confidential' do
265
+ let(:confidential) { false }
266
+ it { expect(subject).to eq(false) }
176
267
  end
177
268
  end
178
269
  end