doorkeeper 3.1.0 → 4.4.3

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

Potentially problematic release.


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

Files changed (195) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +1 -0
  3. data/.github/ISSUE_TEMPLATE.md +25 -0
  4. data/.github/PULL_REQUEST_TEMPLATE.md +17 -0
  5. data/.gitignore +6 -1
  6. data/.hound.yml +2 -13
  7. data/.rubocop.yml +17 -0
  8. data/.travis.yml +26 -10
  9. data/Appraisals +18 -0
  10. data/CODE_OF_CONDUCT.md +46 -0
  11. data/CONTRIBUTING.md +2 -0
  12. data/Gemfile +5 -5
  13. data/NEWS.md +141 -2
  14. data/README.md +149 -66
  15. data/RELEASING.md +5 -12
  16. data/Rakefile +1 -1
  17. data/SECURITY.md +15 -0
  18. data/app/controllers/doorkeeper/application_controller.rb +4 -6
  19. data/app/controllers/doorkeeper/application_metal_controller.rb +3 -2
  20. data/app/controllers/doorkeeper/applications_controller.rb +18 -8
  21. data/app/controllers/doorkeeper/authorizations_controller.rb +1 -1
  22. data/app/controllers/doorkeeper/authorized_applications_controller.rb +1 -1
  23. data/app/controllers/doorkeeper/tokens_controller.rb +62 -15
  24. data/app/helpers/doorkeeper/dashboard_helper.rb +14 -10
  25. data/app/validators/redirect_uri_validator.rb +12 -2
  26. data/app/views/doorkeeper/applications/_delete_form.html.erb +1 -2
  27. data/app/views/doorkeeper/applications/_form.html.erb +13 -2
  28. data/app/views/doorkeeper/applications/index.html.erb +2 -0
  29. data/app/views/doorkeeper/applications/show.html.erb +4 -1
  30. data/app/views/doorkeeper/authorizations/new.html.erb +1 -1
  31. data/app/views/doorkeeper/authorized_applications/_delete_form.html.erb +1 -2
  32. data/app/views/doorkeeper/authorized_applications/index.html.erb +0 -1
  33. data/app/views/layouts/doorkeeper/admin.html.erb +1 -1
  34. data/config/locales/en.yml +12 -7
  35. data/doorkeeper.gemspec +16 -11
  36. data/gemfiles/rails_4_2.gemfile +13 -0
  37. data/gemfiles/rails_5_0.gemfile +12 -0
  38. data/gemfiles/rails_5_1.gemfile +12 -0
  39. data/gemfiles/rails_5_2.gemfile +12 -0
  40. data/gemfiles/rails_master.gemfile +14 -0
  41. data/lib/doorkeeper/config.rb +119 -46
  42. data/lib/doorkeeper/engine.rb +11 -7
  43. data/lib/doorkeeper/errors.rb +18 -0
  44. data/lib/doorkeeper/grape/helpers.rb +14 -8
  45. data/lib/doorkeeper/helpers/controller.rb +8 -19
  46. data/lib/doorkeeper/models/access_grant_mixin.rb +10 -21
  47. data/lib/doorkeeper/models/access_token_mixin.rb +147 -43
  48. data/lib/doorkeeper/models/application_mixin.rb +33 -35
  49. data/lib/doorkeeper/models/concerns/accessible.rb +4 -0
  50. data/lib/doorkeeper/models/concerns/expirable.rb +15 -5
  51. data/lib/doorkeeper/models/concerns/orderable.rb +13 -0
  52. data/lib/doorkeeper/models/concerns/ownership.rb +6 -1
  53. data/lib/doorkeeper/models/concerns/revocable.rb +37 -2
  54. data/lib/doorkeeper/oauth/authorization/token.rb +22 -18
  55. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +20 -18
  56. data/lib/doorkeeper/oauth/authorization_code_request.rb +7 -5
  57. data/lib/doorkeeper/oauth/{request_concern.rb → base_request.rb} +9 -2
  58. data/lib/doorkeeper/oauth/base_response.rb +29 -0
  59. data/lib/doorkeeper/oauth/client/credentials.rb +21 -8
  60. data/lib/doorkeeper/oauth/client.rb +2 -3
  61. data/lib/doorkeeper/oauth/client_credentials/creator.rb +1 -1
  62. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +3 -2
  63. data/lib/doorkeeper/oauth/client_credentials/validation.rb +1 -1
  64. data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -8
  65. data/lib/doorkeeper/oauth/code_response.rb +16 -16
  66. data/lib/doorkeeper/oauth/error.rb +2 -2
  67. data/lib/doorkeeper/oauth/error_response.rb +10 -10
  68. data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
  69. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +1 -1
  70. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +17 -1
  71. data/lib/doorkeeper/oauth/invalid_token_response.rb +5 -4
  72. data/lib/doorkeeper/oauth/password_access_token_request.rb +8 -13
  73. data/lib/doorkeeper/oauth/pre_authorization.rb +5 -3
  74. data/lib/doorkeeper/oauth/refresh_token_request.rb +23 -14
  75. data/lib/doorkeeper/oauth/scopes.rb +18 -8
  76. data/lib/doorkeeper/oauth/token.rb +20 -21
  77. data/lib/doorkeeper/oauth/token_introspection.rb +128 -0
  78. data/lib/doorkeeper/oauth/token_request.rb +1 -2
  79. data/lib/doorkeeper/oauth/token_response.rb +1 -1
  80. data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -0
  81. data/lib/doorkeeper/orm/active_record/access_token.rb +34 -8
  82. data/lib/doorkeeper/orm/active_record/application.rb +48 -11
  83. data/lib/doorkeeper/orm/active_record.rb +17 -22
  84. data/lib/doorkeeper/rails/helpers.rb +6 -9
  85. data/lib/doorkeeper/rails/routes/mapper.rb +4 -4
  86. data/lib/doorkeeper/rails/routes/mapping.rb +1 -1
  87. data/lib/doorkeeper/rails/routes.rb +17 -11
  88. data/lib/doorkeeper/request/authorization_code.rb +7 -1
  89. data/lib/doorkeeper/request/password.rb +2 -2
  90. data/lib/doorkeeper/request/refresh_token.rb +1 -1
  91. data/lib/doorkeeper/request.rb +7 -1
  92. data/lib/doorkeeper/server.rb +0 -8
  93. data/lib/doorkeeper/validations.rb +3 -2
  94. data/lib/doorkeeper/version.rb +34 -1
  95. data/lib/doorkeeper.rb +10 -2
  96. data/lib/generators/doorkeeper/add_client_confidentiality_generator.rb +31 -0
  97. data/lib/generators/doorkeeper/application_owner_generator.rb +11 -2
  98. data/lib/generators/doorkeeper/migration_generator.rb +13 -1
  99. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +35 -0
  100. data/lib/generators/doorkeeper/templates/add_confidential_to_application_migration.rb.erb +11 -0
  101. data/{spec/dummy/db/migrate/20130902175349_add_owner_to_application.rb → lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb} +1 -1
  102. data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +11 -0
  103. data/lib/generators/doorkeeper/templates/initializer.rb +38 -6
  104. data/lib/generators/doorkeeper/templates/migration.rb.erb +69 -0
  105. data/spec/controllers/application_metal_controller.rb +10 -0
  106. data/spec/controllers/applications_controller_spec.rb +15 -4
  107. data/spec/controllers/authorizations_controller_spec.rb +74 -27
  108. data/spec/controllers/protected_resources_controller_spec.rb +70 -32
  109. data/spec/controllers/token_info_controller_spec.rb +17 -13
  110. data/spec/controllers/tokens_controller_spec.rb +198 -12
  111. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +4 -4
  112. data/spec/dummy/app/controllers/home_controller.rb +1 -1
  113. data/spec/dummy/app/controllers/metal_controller.rb +1 -1
  114. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +3 -3
  115. data/spec/dummy/app/models/user.rb +0 -4
  116. data/spec/dummy/config/application.rb +2 -36
  117. data/spec/dummy/config/environment.rb +1 -1
  118. data/spec/dummy/config/environments/test.rb +4 -15
  119. data/spec/dummy/config/initializers/doorkeeper.rb +19 -3
  120. data/spec/dummy/config/initializers/new_framework_defaults.rb +6 -0
  121. data/spec/dummy/config/initializers/secret_token.rb +0 -1
  122. data/spec/dummy/db/migrate/20111122132257_create_users.rb +3 -1
  123. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +3 -1
  124. data/{lib/generators/doorkeeper/templates/migration.rb → spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb} +16 -4
  125. data/{lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb → spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb} +4 -2
  126. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +13 -0
  127. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_application.rb +13 -0
  128. data/spec/dummy/db/schema.rb +24 -22
  129. data/spec/factories.rb +4 -2
  130. data/spec/generators/application_owner_generator_spec.rb +24 -5
  131. data/spec/generators/migration_generator_spec.rb +24 -3
  132. data/spec/generators/previous_refresh_token_generator_spec.rb +57 -0
  133. data/spec/grape/grape_integration_spec.rb +135 -0
  134. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
  135. data/spec/lib/config_spec.rb +159 -14
  136. data/spec/lib/doorkeeper_spec.rb +135 -13
  137. data/spec/lib/models/expirable_spec.rb +0 -1
  138. data/spec/lib/models/revocable_spec.rb +27 -4
  139. data/spec/lib/oauth/authorization/uri_builder_spec.rb +1 -2
  140. data/spec/lib/oauth/authorization_code_request_spec.rb +55 -12
  141. data/spec/lib/oauth/base_request_spec.rb +155 -0
  142. data/spec/lib/oauth/base_response_spec.rb +45 -0
  143. data/spec/lib/oauth/client/credentials_spec.rb +45 -2
  144. data/spec/lib/oauth/client_credentials/creator_spec.rb +1 -1
  145. data/spec/lib/oauth/client_credentials_integration_spec.rb +1 -1
  146. data/spec/lib/oauth/client_credentials_request_spec.rb +1 -0
  147. data/spec/lib/oauth/code_request_spec.rb +1 -3
  148. data/spec/lib/oauth/code_response_spec.rb +34 -0
  149. data/spec/lib/oauth/error_response_spec.rb +9 -9
  150. data/spec/lib/oauth/error_spec.rb +1 -1
  151. data/spec/lib/oauth/helpers/uri_checker_spec.rb +115 -1
  152. data/spec/lib/oauth/invalid_token_response_spec.rb +36 -8
  153. data/spec/lib/oauth/password_access_token_request_spec.rb +14 -8
  154. data/spec/lib/oauth/pre_authorization_spec.rb +12 -7
  155. data/spec/lib/oauth/refresh_token_request_spec.rb +52 -9
  156. data/spec/lib/oauth/scopes_spec.rb +28 -2
  157. data/spec/lib/oauth/token_request_spec.rb +6 -8
  158. data/spec/lib/oauth/token_spec.rb +12 -5
  159. data/spec/lib/server_spec.rb +10 -3
  160. data/spec/models/doorkeeper/access_grant_spec.rb +1 -1
  161. data/spec/models/doorkeeper/access_token_spec.rb +116 -48
  162. data/spec/models/doorkeeper/application_spec.rb +145 -29
  163. data/spec/requests/applications/applications_request_spec.rb +5 -5
  164. data/spec/requests/endpoints/authorization_spec.rb +5 -6
  165. data/spec/requests/endpoints/token_spec.rb +8 -1
  166. data/spec/requests/flows/authorization_code_errors_spec.rb +11 -1
  167. data/spec/requests/flows/authorization_code_spec.rb +6 -13
  168. data/spec/requests/flows/client_credentials_spec.rb +29 -1
  169. data/spec/requests/flows/implicit_grant_errors_spec.rb +2 -2
  170. data/spec/requests/flows/password_spec.rb +118 -15
  171. data/spec/requests/flows/refresh_token_spec.rb +89 -19
  172. data/spec/requests/flows/revoke_token_spec.rb +105 -91
  173. data/spec/requests/protected_resources/metal_spec.rb +1 -1
  174. data/spec/requests/protected_resources/private_api_spec.rb +1 -1
  175. data/spec/routing/custom_controller_routes_spec.rb +4 -0
  176. data/spec/routing/default_routes_spec.rb +5 -1
  177. data/spec/spec_helper.rb +2 -0
  178. data/spec/spec_helper_integration.rb +22 -4
  179. data/spec/support/dependencies/factory_girl.rb +2 -2
  180. data/spec/support/helpers/access_token_request_helper.rb +1 -1
  181. data/spec/support/helpers/model_helper.rb +34 -7
  182. data/spec/support/helpers/request_spec_helper.rb +17 -5
  183. data/spec/support/helpers/url_helper.rb +9 -8
  184. data/spec/support/http_method_shim.rb +38 -0
  185. data/spec/support/shared/controllers_shared_context.rb +15 -10
  186. data/spec/support/shared/models_shared_examples.rb +5 -5
  187. data/spec/validators/redirect_uri_validator_spec.rb +51 -6
  188. data/spec/version/version_spec.rb +15 -0
  189. metadata +128 -46
  190. data/lib/doorkeeper/oauth/client/methods.rb +0 -18
  191. data/lib/generators/doorkeeper/application_scopes_generator.rb +0 -34
  192. data/lib/generators/doorkeeper/templates/add_scopes_to_oauth_applications.rb +0 -5
  193. data/spec/dummy/db/migrate/20130902165751_create_doorkeeper_tables.rb +0 -41
  194. data/spec/dummy/db/migrate/20141209001746_add_scopes_to_oauth_applications.rb +0 -5
  195. data/spec/lib/oauth/client/methods_spec.rb +0 -54
@@ -2,7 +2,7 @@ require 'spec_helper_integration'
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
 
@@ -12,15 +12,24 @@ module Doorkeeper
12
12
  let(:factory_name) { :access_token }
13
13
  end
14
14
 
15
+ module CustomGeneratorArgs
16
+ def self.generate
17
+ end
18
+ end
19
+
15
20
  describe :generate_token do
16
21
  it 'generates a token using the default method' do
17
- FactoryGirl.create :access_token
22
+ FactoryBot.create :access_token
18
23
 
19
- token = FactoryGirl.create :access_token
24
+ token = FactoryBot.create :access_token
20
25
  expect(token.token).to be_a(String)
21
26
  end
22
27
 
23
28
  it 'generates a token using a custom object' do
29
+ eigenclass = class << CustomGeneratorArgs; self; end
30
+ eigenclass.class_eval do
31
+ remove_method :generate
32
+ end
24
33
  module CustomGeneratorArgs
25
34
  def self.generate(opts = {})
26
35
  "custom_generator_token_#{opts[:resource_owner_id]}"
@@ -32,11 +41,15 @@ module Doorkeeper
32
41
  access_token_generator "Doorkeeper::CustomGeneratorArgs"
33
42
  end
34
43
 
35
- token = FactoryGirl.create :access_token
44
+ token = FactoryBot.create :access_token
36
45
  expect(token.token).to match(%r{custom_generator_token_\d+})
37
46
  end
38
47
 
39
48
  it 'allows the custom generator to access the application details' do
49
+ eigenclass = class << CustomGeneratorArgs; self; end
50
+ eigenclass.class_eval do
51
+ remove_method :generate
52
+ end
40
53
  module CustomGeneratorArgs
41
54
  def self.generate(opts = {})
42
55
  "custom_generator_token_#{opts[:application].name}"
@@ -48,11 +61,15 @@ module Doorkeeper
48
61
  access_token_generator "Doorkeeper::CustomGeneratorArgs"
49
62
  end
50
63
 
51
- token = FactoryGirl.create :access_token
64
+ token = FactoryBot.create :access_token
52
65
  expect(token.token).to match(%r{custom_generator_token_Application \d+})
53
66
  end
54
67
 
55
68
  it 'allows the custom generator to access the scopes' do
69
+ eigenclass = class << CustomGeneratorArgs; self; end
70
+ eigenclass.class_eval do
71
+ remove_method :generate
72
+ end
56
73
  module CustomGeneratorArgs
57
74
  def self.generate(opts = {})
58
75
  "custom_generator_token_#{opts[:scopes].count}_#{opts[:scopes]}"
@@ -64,12 +81,16 @@ module Doorkeeper
64
81
  access_token_generator "Doorkeeper::CustomGeneratorArgs"
65
82
  end
66
83
 
67
- token = FactoryGirl.create :access_token, scopes: 'public write'
84
+ token = FactoryBot.create :access_token, scopes: 'public write'
68
85
 
69
86
  expect(token.token).to eq 'custom_generator_token_2_public write'
70
87
  end
71
88
 
72
89
  it 'allows the custom generator to access the expiry length' do
90
+ eigenclass = class << CustomGeneratorArgs; self; end
91
+ eigenclass.class_eval do
92
+ remove_method :generate
93
+ end
73
94
  module CustomGeneratorArgs
74
95
  def self.generate(opts = {})
75
96
  "custom_generator_token_#{opts[:expires_in]}"
@@ -81,10 +102,27 @@ module Doorkeeper
81
102
  access_token_generator "Doorkeeper::CustomGeneratorArgs"
82
103
  end
83
104
 
84
- token = FactoryGirl.create :access_token
105
+ token = FactoryBot.create :access_token
85
106
  expect(token.token).to eq 'custom_generator_token_7200'
86
107
  end
87
108
 
109
+ it 'allows the custom generator to access the created time' do
110
+ module CustomGeneratorArgs
111
+ def self.generate(opts = {})
112
+ "custom_generator_token_#{opts[:created_at].to_i}"
113
+ end
114
+ end
115
+
116
+ Doorkeeper.configure do
117
+ orm DOORKEEPER_ORM
118
+ access_token_generator "Doorkeeper::CustomGeneratorArgs"
119
+ end
120
+
121
+ token = FactoryBot.create :access_token
122
+ created_at = token.created_at
123
+ expect(token.token).to eq "custom_generator_token_#{created_at.to_i}"
124
+ end
125
+
88
126
  it 'raises an error if the custom object does not support generate' do
89
127
  module NoGenerate
90
128
  end
@@ -94,8 +132,31 @@ module Doorkeeper
94
132
  access_token_generator "Doorkeeper::NoGenerate"
95
133
  end
96
134
 
97
- expect { FactoryGirl.create :access_token }.to(
98
- 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
+ )
99
160
  end
100
161
 
101
162
  it 'raises an error if the custom object does not exist' do
@@ -104,36 +165,37 @@ module Doorkeeper
104
165
  access_token_generator "Doorkeeper::NotReal"
105
166
  end
106
167
 
107
- expect { FactoryGirl.create :access_token }.to(
108
- raise_error(Doorkeeper::Errors::TokenGeneratorNotFound))
168
+ expect { FactoryBot.create :access_token }.to(
169
+ raise_error(Doorkeeper::Errors::TokenGeneratorNotFound, /NotReal/)
170
+ )
109
171
  end
110
172
  end
111
173
 
112
174
  describe :refresh_token do
113
175
  it 'has empty refresh token if it was not required' do
114
- token = FactoryGirl.create :access_token
176
+ token = FactoryBot.create :access_token
115
177
  expect(token.refresh_token).to be_nil
116
178
  end
117
179
 
118
180
  it 'generates a refresh token if it was requested' do
119
- token = FactoryGirl.create :access_token, use_refresh_token: true
181
+ token = FactoryBot.create :access_token, use_refresh_token: true
120
182
  expect(token.refresh_token).not_to be_nil
121
183
  end
122
184
 
123
185
  it 'is not valid if token exists' do
124
- token1 = FactoryGirl.create :access_token, use_refresh_token: true
125
- 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
126
188
  token2.refresh_token = token1.refresh_token
127
189
  expect(token2).not_to be_valid
128
190
  end
129
191
 
130
192
  it 'expects database to raise an error if refresh tokens are the same' do
131
- token1 = FactoryGirl.create :access_token, use_refresh_token: true
132
- 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
133
195
  expect do
134
196
  token2.refresh_token = token1.refresh_token
135
197
  token2.save(validate: false)
136
- end.to raise_error(ActiveRecord::RecordNotUnique)
198
+ end.to raise_error(uniqueness_error)
137
199
  end
138
200
  end
139
201
 
@@ -143,6 +205,12 @@ module Doorkeeper
143
205
  subject.resource_owner_id = nil
144
206
  expect(subject).to be_valid
145
207
  end
208
+
209
+ it 'is valid without application_id' do
210
+ # For resource owner credentials flow
211
+ subject.application_id = nil
212
+ expect(subject).to be_valid
213
+ end
146
214
  end
147
215
 
148
216
  describe '#same_credential?' do
@@ -150,22 +218,22 @@ module Doorkeeper
150
218
  context 'with default parameters' do
151
219
 
152
220
  let(:resource_owner_id) { 100 }
153
- let(:application) { FactoryGirl.create :application }
221
+ let(:application) { FactoryBot.create :application }
154
222
  let(:default_attributes) do
155
223
  { application: application, resource_owner_id: resource_owner_id }
156
224
  end
157
- let(:access_token1) { FactoryGirl.create :access_token, default_attributes }
225
+ let(:access_token1) { FactoryBot.create :access_token, default_attributes }
158
226
 
159
227
  context 'the second token has the same owner and same app' do
160
- let(:access_token2) { FactoryGirl.create :access_token, default_attributes }
228
+ let(:access_token2) { FactoryBot.create :access_token, default_attributes }
161
229
  it 'success' do
162
230
  expect(access_token1.same_credential?(access_token2)).to be_truthy
163
231
  end
164
232
  end
165
233
 
166
234
  context 'the second token has same owner and different app' do
167
- let(:other_application) { FactoryGirl.create :application }
168
- 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 }
169
237
 
170
238
  it 'fail' do
171
239
  expect(access_token1.same_credential?(access_token2)).to be_falsey
@@ -174,8 +242,8 @@ module Doorkeeper
174
242
 
175
243
  context 'the second token has different owner and different app' do
176
244
 
177
- let(:other_application) { FactoryGirl.create :application }
178
- 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 }
179
247
 
180
248
  it 'fail' do
181
249
  expect(access_token1.same_credential?(access_token2)).to be_falsey
@@ -183,7 +251,7 @@ module Doorkeeper
183
251
  end
184
252
 
185
253
  context 'the second token has different owner and same app' do
186
- 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 }
187
255
 
188
256
  it 'fail' do
189
257
  expect(access_token1.same_credential?(access_token2)).to be_falsey
@@ -194,7 +262,7 @@ module Doorkeeper
194
262
 
195
263
  describe '#acceptable?' do
196
264
  context 'a token that is not accessible' do
197
- let(:token) { FactoryGirl.create(:access_token, created_at: 6.hours.ago) }
265
+ let(:token) { FactoryBot.create(:access_token, created_at: 6.hours.ago) }
198
266
 
199
267
  it 'should return false' do
200
268
  expect(token.acceptable?(nil)).to be false
@@ -202,7 +270,7 @@ module Doorkeeper
202
270
  end
203
271
 
204
272
  context 'a token that has the incorrect scopes' do
205
- let(:token) { FactoryGirl.create(:access_token) }
273
+ let(:token) { FactoryBot.create(:access_token) }
206
274
 
207
275
  it 'should return false' do
208
276
  expect(token.acceptable?(['public'])).to be false
@@ -211,7 +279,7 @@ module Doorkeeper
211
279
 
212
280
  context 'a token is acceptable with the correct scopes' do
213
281
  let(:token) do
214
- token = FactoryGirl.create(:access_token)
282
+ token = FactoryBot.create(:access_token)
215
283
  token[:scopes] = 'public'
216
284
  token
217
285
  end
@@ -224,13 +292,13 @@ module Doorkeeper
224
292
 
225
293
  describe '.revoke_all_for' do
226
294
  let(:resource_owner) { double(id: 100) }
227
- let(:application) { FactoryGirl.create :application }
295
+ let(:application) { FactoryBot.create :application }
228
296
  let(:default_attributes) do
229
297
  { application: application, resource_owner_id: resource_owner.id }
230
298
  end
231
299
 
232
300
  it 'revokes all tokens for given application and resource owner' do
233
- FactoryGirl.create :access_token, default_attributes
301
+ FactoryBot.create :access_token, default_attributes
234
302
  AccessToken.revoke_all_for application.id, resource_owner
235
303
  AccessToken.all.each do |token|
236
304
  expect(token).to be_revoked
@@ -238,13 +306,13 @@ module Doorkeeper
238
306
  end
239
307
 
240
308
  it 'matches application' do
241
- FactoryGirl.create :access_token, default_attributes.merge(application: FactoryGirl.create(:application))
309
+ FactoryBot.create :access_token, default_attributes.merge(application: FactoryBot.create(:application))
242
310
  AccessToken.revoke_all_for application.id, resource_owner
243
311
  expect(AccessToken.all).not_to be_empty
244
312
  end
245
313
 
246
314
  it 'matches resource owner' do
247
- FactoryGirl.create :access_token, default_attributes.merge(resource_owner_id: 90)
315
+ FactoryBot.create :access_token, default_attributes.merge(resource_owner_id: 90)
248
316
  AccessToken.revoke_all_for application.id, resource_owner
249
317
  expect(AccessToken.all).not_to be_empty
250
318
  end
@@ -252,7 +320,7 @@ module Doorkeeper
252
320
 
253
321
  describe '.matching_token_for' do
254
322
  let(:resource_owner_id) { 100 }
255
- let(:application) { FactoryGirl.create :application }
323
+ let(:application) { FactoryBot.create :application }
256
324
  let(:scopes) { Doorkeeper::OAuth::Scopes.from_string('public write') }
257
325
  let(:default_attributes) do
258
326
  {
@@ -263,63 +331,63 @@ module Doorkeeper
263
331
  end
264
332
 
265
333
  it 'returns only one token' do
266
- token = FactoryGirl.create :access_token, default_attributes
334
+ token = FactoryBot.create :access_token, default_attributes
267
335
  last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
268
336
  expect(last_token).to eq(token)
269
337
  end
270
338
 
271
339
  it 'accepts resource owner as object' do
272
340
  resource_owner = double(to_key: true, id: 100)
273
- token = FactoryGirl.create :access_token, default_attributes
341
+ token = FactoryBot.create :access_token, default_attributes
274
342
  last_token = AccessToken.matching_token_for(application, resource_owner, scopes)
275
343
  expect(last_token).to eq(token)
276
344
  end
277
345
 
278
346
  it 'accepts nil as resource owner' do
279
- token = FactoryGirl.create :access_token, default_attributes.merge(resource_owner_id: nil)
347
+ token = FactoryBot.create :access_token, default_attributes.merge(resource_owner_id: nil)
280
348
  last_token = AccessToken.matching_token_for(application, nil, scopes)
281
349
  expect(last_token).to eq(token)
282
350
  end
283
351
 
284
352
  it 'excludes revoked tokens' do
285
- FactoryGirl.create :access_token, default_attributes.merge(revoked_at: 1.day.ago)
353
+ FactoryBot.create :access_token, default_attributes.merge(revoked_at: 1.day.ago)
286
354
  last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
287
355
  expect(last_token).to be_nil
288
356
  end
289
357
 
290
358
  it 'matches the application' do
291
- FactoryGirl.create :access_token, default_attributes.merge(application: FactoryGirl.create(:application))
359
+ FactoryBot.create :access_token, default_attributes.merge(application: FactoryBot.create(:application))
292
360
  last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
293
361
  expect(last_token).to be_nil
294
362
  end
295
363
 
296
364
  it 'matches the resource owner' do
297
- FactoryGirl.create :access_token, default_attributes.merge(resource_owner_id: 2)
365
+ FactoryBot.create :access_token, default_attributes.merge(resource_owner_id: 2)
298
366
  last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
299
367
  expect(last_token).to be_nil
300
368
  end
301
369
 
302
370
  it 'matches token with fewer scopes' do
303
- FactoryGirl.create :access_token, default_attributes.merge(scopes: 'public')
371
+ FactoryBot.create :access_token, default_attributes.merge(scopes: 'public')
304
372
  last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
305
373
  expect(last_token).to be_nil
306
374
  end
307
375
 
308
376
  it 'matches token with different scopes' do
309
- FactoryGirl.create :access_token, default_attributes.merge(scopes: 'public email')
377
+ FactoryBot.create :access_token, default_attributes.merge(scopes: 'public email')
310
378
  last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
311
379
  expect(last_token).to be_nil
312
380
  end
313
381
 
314
382
  it 'matches token with more scopes' do
315
- FactoryGirl.create :access_token, default_attributes.merge(scopes: 'public write email')
383
+ FactoryBot.create :access_token, default_attributes.merge(scopes: 'public write email')
316
384
  last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
317
385
  expect(last_token).to be_nil
318
386
  end
319
387
 
320
388
  it 'matches application scopes' do
321
- application = FactoryGirl.create :application, scopes: "private read"
322
- FactoryGirl.create :access_token, default_attributes.merge(
389
+ application = FactoryBot.create :application, scopes: "private read"
390
+ FactoryBot.create :access_token, default_attributes.merge(
323
391
  application: application
324
392
  )
325
393
  last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
@@ -327,14 +395,14 @@ module Doorkeeper
327
395
  end
328
396
 
329
397
  it 'returns the last created token' do
330
- FactoryGirl.create :access_token, default_attributes.merge(created_at: 1.day.ago)
331
- token = FactoryGirl.create :access_token, default_attributes
398
+ FactoryBot.create :access_token, default_attributes.merge(created_at: 1.day.ago)
399
+ token = FactoryBot.create :access_token, default_attributes
332
400
  last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
333
401
  expect(last_token).to eq(token)
334
402
  end
335
403
 
336
404
  it 'returns as_json hash' do
337
- token = FactoryGirl.create :access_token, default_attributes
405
+ token = FactoryBot.create :access_token, default_attributes
338
406
  token_hash = {
339
407
  resource_owner_id: token.resource_owner_id,
340
408
  scopes: token.scopes,
@@ -4,7 +4,7 @@ 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(: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,17 +85,17 @@ 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
- expect { app2.save!(validate: false) }.to raise_error(ActiveRecord::RecordNotUnique)
98
+ expect { app2.save!(validate: false) }.to raise_error(uniqueness_error)
94
99
  end
95
100
 
96
101
  it 'generate secret on create' do
@@ -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)
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,43 +182,121 @@ 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
207
+ end
169
208
 
170
- it 'should fail to mass assign a new application', if: ::Rails::VERSION::MAJOR < 4 do
171
- mass_assign = { name: 'Something',
172
- redirect_uri: 'http://somewhere.com/something',
173
- uid: 123,
174
- secret: 'something' }
175
- expect(Application.create(mass_assign).uid).not_to eq(123)
209
+ describe :by_uid_and_secret do
210
+ context "when application is private/confidential" do
211
+ it "finds the application via uid/secret" do
212
+ app = FactoryBot.create :application
213
+ authenticated = Application.by_uid_and_secret(app.uid, app.secret)
214
+ expect(authenticated).to eq(app)
215
+ end
216
+ context "when secret is wrong" do
217
+ it "should not find the application" do
218
+ app = FactoryBot.create :application
219
+ authenticated = Application.by_uid_and_secret(app.uid, 'bad')
220
+ expect(authenticated).to eq(nil)
221
+ end
222
+ end
223
+ end
224
+
225
+ context "when application is public/non-confidential" do
226
+ context "when secret is blank" do
227
+ it "should find the application" do
228
+ app = FactoryBot.create :application, confidential: false
229
+ authenticated = Application.by_uid_and_secret(app.uid, nil)
230
+ expect(authenticated).to eq(app)
231
+ end
232
+ end
233
+ context "when secret is wrong" do
234
+ it "should not find the application" do
235
+ app = FactoryBot.create :application, confidential: false
236
+ authenticated = Application.by_uid_and_secret(app.uid, 'bad')
237
+ expect(authenticated).to eq(nil)
238
+ end
239
+ end
240
+ end
241
+ end
242
+
243
+ describe :confidential? do
244
+ subject { FactoryBot.create(:application, confidential: confidential).confidential? }
245
+
246
+ context 'when application is private/confidential' do
247
+ let(:confidential) { true }
248
+ it { expect(subject).to eq(true) }
249
+ end
250
+
251
+ context 'when application is public/non-confidential' do
252
+ let(:confidential) { false }
253
+ it { expect(subject).to eq(false) }
254
+ end
255
+ end
256
+
257
+ describe :confidential do
258
+ subject { FactoryBot.create(:application, confidential: confidential).confidential }
259
+
260
+ context 'when application is private/confidential' do
261
+ let(:confidential) { true }
262
+ it { expect(subject).to eq(true) }
263
+ end
264
+
265
+ context 'when application is public/non-confidential' do
266
+ let(:confidential) { false }
267
+ it { expect(subject).to eq(false) }
268
+ end
269
+
270
+ context 'when the application does not support confidentiality' do
271
+ let(:confidential) { false }
272
+
273
+ before { allow(Application).to receive(:supports_confidentiality?).and_return(false) }
274
+
275
+ it 'warns of the CVE' do
276
+ expect(ActiveSupport::Deprecation).to receive(:warn).with(
277
+ 'You are susceptible to security bug ' \
278
+ 'CVE-2018-1000211. Please follow instructions outlined in ' \
279
+ 'Doorkeeper::CVE_2018_1000211_WARNING'
280
+ )
281
+ Application.new.confidential
282
+ end
283
+
284
+ it { expect(subject).to eq(true) }
176
285
  end
177
286
  end
178
287
 
179
- describe :authenticate do
180
- it 'finds the application via uid/secret' do
181
- app = FactoryGirl.create :application
182
- authenticated = Application.by_uid_and_secret(app.uid, app.secret)
183
- expect(authenticated).to eq(app)
288
+ describe :supports_confidentiality? do
289
+ context 'when no column' do
290
+ it 'returns false' do
291
+ expect(Application).to receive(:column_names).and_return(%w[foo bar])
292
+ expect(Application.supports_confidentiality?).to eq(false)
293
+ end
294
+ end
295
+ context 'when column' do
296
+ it 'returns true' do
297
+ expect(Application).to receive(:column_names).and_return(%w[foo bar confidential])
298
+ expect(Application.supports_confidentiality?).to eq(true)
299
+ end
184
300
  end
185
301
  end
186
302
  end